diff options
author | David Mitchell <davem@iabyn.com> | 2014-09-02 17:11:42 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2014-09-10 14:25:05 +0100 |
commit | f3574cc66412a684ced323c9c3183b20381c3f58 (patch) | |
tree | 21a6ba05b8811dc488327cb841953e49971d1b1e | |
parent | 738ec38010d319318456d2882cb13e00547853de (diff) | |
download | perl-f3574cc66412a684ced323c9c3183b20381c3f58.tar.gz |
Automate processing of op_private flags
Add a new config file, regen/op_private, which contains all the
information about the flags and descriptions for the OP op_private field.
Previously, the flags themselves were defined in op.h, accompanied by
textual descriptions (sometimes inaccurate or incomplete).
For display purposes, there were short labels for each flag found in
Concise.pm, and another set of labels for Perl_do_op_dump() in dump.c.
These two sets of labels differed from each other in spelling (e.g.
REFC verses REFCOUNT), and differed in completeness and accuracy.
With this commit, all the data to generate the defines and the labels is
derived from a single source, and are generated automatically by 'make
regen'. It also contains complete data on which bits are used for what by
each op. So any attempt to add a new flag for a particular op where that
bit is already in use, will raise an error in make regen. This compares
to the previous practice of reading the descriptions in op.h and hoping
for the best.
It also makes use of data in regen/opcodes: for example, regen/op_private
specifies that all ops flagged as 'T' get the OPpTARGET_MY flag.
Since the set of labels used by Concise and Perl_do_op_dump() differed,
I've standardised on the Concise version. Thus this commit changes the
output produced by Concise only marginally, while Perl_do_op_dump() is
considerably different. As well as the change in labels (and missing
labels), Perl_do_op_dump() formerly had a bug whereby any unrecognised
bits would not be shown if there was at least one recognised bit.
So while Concise displayed (and still does) "LVINTRO,2", Perl_do_op_dump()
has changed:
- PRIVATE = (INTRO)
+ PRIVATE = (LVINTRO,0x2)
Concise has mainly changed in that a few op/bit combinations weren't being
shown symbolically, and now are. I've avoiding fixing the ones that would
break tests; they'll be fixed up in the next few commits.
A few new OPp* flags have been added:
OPpARG1_MASK
OPpARG2_MASK
OPpARG3_MASK
OPpARG4_MASK
OPpHINT_M_VMSISH_STATUS
OPpHINT_M_VMSISH_TIME
OPpHINT_STRICT_REFS
The last three are analogues for existing HINT_* flags. The former four
reflect that many ops some of the lower few bits of op_private to indicate
how many args the op expects. While (for now) this is still displayed as,
e.g. "LVINTRO,2", the definitions in regen/op_private now fully account
for which ops use which bits for the arg count.
There is a new module, B::Op_private, which allows this new data to be
accessed from Perl. For example,
use B::Op_private;
my $name = $B::Op_private::bits{aelem}{7}; # OPpLVAL_INTRO
my $value = $B::Op_private::defines{$name}; # 128
my $label = $B::Op_private::labels{$name}; # LVINTRO
There are several new constant PL_* tables. PL_op_private_valid[]
specifies for each op number, which bits are valid for that op. In a
couple of commits' time, op_free() will use this on debugging builds to
assert that no ops gained any private flags which we don't know about.
In fact it was by using such a temporary assert repeatedly against the
test suite, that I tracked down most of the inconsistencies and errors in
the current flag data.
The other PL_op_private_* tables contain a compact representation of all
the ops/bits/labels in a format suitable for Perl_do_op_dump() to decode
Op_private. Overall, the perl binary is about 500 bytes smaller on my
system.
-rw-r--r-- | MANIFEST | 2 | ||||
-rwxr-xr-x | Porting/Maintainers.pl | 1 | ||||
-rw-r--r-- | dump.c | 274 | ||||
-rw-r--r-- | ext/B/B/Concise.pm | 160 | ||||
-rw-r--r-- | ext/B/Makefile.PL | 1 | ||||
-rw-r--r-- | ext/Devel-Peek/t/Peek.t | 4 | ||||
-rw-r--r-- | globvar.sym | 5 | ||||
-rw-r--r-- | lib/B/Op_private.pm | 695 | ||||
-rw-r--r-- | op.h | 203 | ||||
-rw-r--r-- | opcode.h | 1352 | ||||
-rw-r--r-- | pp.h | 2 | ||||
-rw-r--r-- | pp_sys.c | 2 | ||||
-rw-r--r-- | regen/op_private | 668 | ||||
-rwxr-xr-x | regen/opcode.pl | 744 | ||||
-rw-r--r-- | t/porting/regen.t | 2 |
15 files changed, 3626 insertions, 489 deletions
@@ -4008,6 +4008,7 @@ lib/Benchmark.pm Measure execution time lib/Benchmark.t See if Benchmark works lib/blib.pm For "use blib" lib/blib.t blib.pm test +lib/B/Op_private.pm Definitions of OP op_private flags lib/bytes_heavy.pl Support routines for byte pragma lib/bytes.pm Pragma to enable byte operations lib/bytes.t bytes.pm test @@ -4696,6 +4697,7 @@ regen/mk_invlists.pl Generates charclass_invlists.h regen/mk_PL_charclass.pl Populate the PL_charclass table regen/opcode.pl Opcode header generator regen/opcodes Opcode data +regen/op_private Definitions of bits in an OP's op_private field regen/overload.pl generate overload.h regen_perly.pl generate perly.{act,h,tab} from perly.y regen.pl Run all scripts that (re)generate files diff --git a/Porting/Maintainers.pl b/Porting/Maintainers.pl index 2015edd033..6e494f2dc7 100755 --- a/Porting/Maintainers.pl +++ b/Porting/Maintainers.pl @@ -1351,6 +1351,7 @@ use File::Glob qw(:case); lib/AnyDBM_File.{pm,t} lib/Benchmark.{pm,t} lib/B/Deparse{.pm,.t,-core.t} + lib/B/Op_private.pm lib/CORE.pod lib/Class/Struct.{pm,t} lib/Config.t @@ -751,6 +751,10 @@ S_sequence_num(pTHX_ const OP *o) return PL_op_seq; } + + + + const struct flag_to_name op_flags_names[] = { {OPf_KIDS, ",KIDS"}, {OPf_PARENS, ",PARENS"}, @@ -760,125 +764,6 @@ const struct flag_to_name op_flags_names[] = { {OPf_SPECIAL, ",SPECIAL"} }; -const struct flag_to_name op_trans_names[] = { - {OPpTRANS_FROM_UTF, ",FROM_UTF"}, - {OPpTRANS_TO_UTF, ",TO_UTF"}, - {OPpTRANS_IDENTICAL, ",IDENTICAL"}, - {OPpTRANS_SQUASH, ",SQUASH"}, - {OPpTRANS_COMPLEMENT, ",COMPLEMENT"}, - {OPpTRANS_GROWS, ",GROWS"}, - {OPpTRANS_DELETE, ",DELETE"} -}; - -const struct flag_to_name op_entersub_names[] = { - {OPpENTERSUB_DB, ",DB"}, - {OPpENTERSUB_HASTARG, ",HASTARG"}, - {OPpENTERSUB_AMPER, ",AMPER"}, - {OPpENTERSUB_NOPAREN, ",NOPAREN"}, - {OPpENTERSUB_INARGS, ",INARGS"} -}; - -const struct flag_to_name op_const_names[] = { - {OPpCONST_NOVER, ",NOVER"}, - {OPpCONST_SHORTCIRCUIT, ",SHORTCIRCUIT"}, - {OPpCONST_STRICT, ",STRICT"}, - {OPpCONST_ENTERED, ",ENTERED"}, - {OPpCONST_BARE, ",BARE"} -}; - -const struct flag_to_name op_sort_names[] = { - {OPpSORT_NUMERIC, ",NUMERIC"}, - {OPpSORT_INTEGER, ",INTEGER"}, - {OPpSORT_REVERSE, ",REVERSE"}, - {OPpSORT_INPLACE, ",INPLACE"}, - {OPpSORT_DESCEND, ",DESCEND"}, - {OPpSORT_QSORT, ",QSORT"}, - {OPpSORT_STABLE, ",STABLE"} -}; - -const struct flag_to_name op_open_names[] = { - {OPpOPEN_IN_RAW, ",IN_RAW"}, - {OPpOPEN_IN_CRLF, ",IN_CRLF"}, - {OPpOPEN_OUT_RAW, ",OUT_RAW"}, - {OPpOPEN_OUT_CRLF, ",OUT_CRLF"} -}; - -const struct flag_to_name op_sassign_names[] = { - {OPpASSIGN_BACKWARDS, ",BACKWARDS"}, - {OPpASSIGN_CV_TO_GV, ",CV2GV"} -}; - -const struct flag_to_name op_leave_names[] = { - {OPpREFCOUNTED, ",REFCOUNTED"}, - {OPpLVALUE, ",LVALUE"} -}; - -#define OP_PRIVATE_ONCE(op, flag, name) \ - const struct flag_to_name CAT2(op, _names)[] = { \ - {(flag), (name)} \ - } - -OP_PRIVATE_ONCE(op_leavesub, OPpREFCOUNTED, ",REFCOUNTED"); -OP_PRIVATE_ONCE(op_repeat, OPpREPEAT_DOLIST, ",DOLIST"); -OP_PRIVATE_ONCE(op_reverse, OPpREVERSE_INPLACE, ",INPLACE"); -OP_PRIVATE_ONCE(op_rv2cv, OPpLVAL_INTRO, ",INTRO"); -OP_PRIVATE_ONCE(op_flip, OPpFLIP_LINENUM, ",LINENUM"); -OP_PRIVATE_ONCE(op_gv, OPpEARLY_CV, ",EARLY_CV"); -OP_PRIVATE_ONCE(op_list, OPpLIST_GUESSED, ",GUESSED"); -OP_PRIVATE_ONCE(op_delete, OPpSLICE, ",SLICE"); -OP_PRIVATE_ONCE(op_exists, OPpEXISTS_SUB, ",EXISTS_SUB"); -OP_PRIVATE_ONCE(op_die, OPpHUSH_VMSISH, ",HUSH_VMSISH"); -OP_PRIVATE_ONCE(op_split, OPpSPLIT_IMPLIM, ",IMPLIM"); -OP_PRIVATE_ONCE(op_dbstate, OPpHUSH_VMSISH, ",HUSH_VMSISH"); - -struct op_private_by_op { - U16 op_type; - U16 len; - const struct flag_to_name *start; -}; - -const struct op_private_by_op op_private_names[] = { - {OP_LEAVESUB, C_ARRAY_LENGTH(op_leavesub_names), op_leavesub_names }, - {OP_LEAVE, C_ARRAY_LENGTH(op_leave_names), op_leave_names }, - {OP_LEAVESUBLV, C_ARRAY_LENGTH(op_leavesub_names), op_leavesub_names }, - {OP_LEAVEWRITE, C_ARRAY_LENGTH(op_leavesub_names), op_leavesub_names }, - {OP_DIE, C_ARRAY_LENGTH(op_die_names), op_die_names }, - {OP_DELETE, C_ARRAY_LENGTH(op_delete_names), op_delete_names }, - {OP_EXISTS, C_ARRAY_LENGTH(op_exists_names), op_exists_names }, - {OP_FLIP, C_ARRAY_LENGTH(op_flip_names), op_flip_names }, - {OP_FLOP, C_ARRAY_LENGTH(op_flip_names), op_flip_names }, - {OP_GV, C_ARRAY_LENGTH(op_gv_names), op_gv_names }, - {OP_LIST, C_ARRAY_LENGTH(op_list_names), op_list_names }, - {OP_SASSIGN, C_ARRAY_LENGTH(op_sassign_names), op_sassign_names }, - {OP_REPEAT, C_ARRAY_LENGTH(op_repeat_names), op_repeat_names }, - {OP_RV2CV, C_ARRAY_LENGTH(op_rv2cv_names), op_rv2cv_names }, - {OP_TRANS, C_ARRAY_LENGTH(op_trans_names), op_trans_names }, - {OP_CONST, C_ARRAY_LENGTH(op_const_names), op_const_names }, - {OP_SORT, C_ARRAY_LENGTH(op_sort_names), op_sort_names }, - {OP_OPEN, C_ARRAY_LENGTH(op_open_names), op_open_names }, - {OP_SPLIT, C_ARRAY_LENGTH(op_split_names), op_split_names }, - {OP_DBSTATE, C_ARRAY_LENGTH(op_dbstate_names), op_dbstate_names }, - {OP_NEXTSTATE, C_ARRAY_LENGTH(op_dbstate_names), op_dbstate_names }, - {OP_BACKTICK, C_ARRAY_LENGTH(op_open_names), op_open_names } -}; - -static bool -S_op_private_to_names(pTHX_ SV *tmpsv, U32 optype, U32 op_private) { - const struct op_private_by_op *start = op_private_names; - const struct op_private_by_op *const end = C_ARRAY_END(op_private_names); - - /* This is a linear search, but no worse than the code that it replaced. - It's debugging code - size is more important than speed. */ - do { - if (optype == start->op_type) { - S_append_flags(aTHX_ tmpsv, op_private, start->start, - start->start + start->len); - return TRUE; - } - } while (++start < end); - return FALSE; -} - void Perl_do_op_dump(pTHX_ I32 level, PerlIO *file, const OP *o) @@ -966,95 +851,88 @@ Perl_do_op_dump(pTHX_ I32 level, PerlIO *file, const OP *o) } if (o->op_private) { - U32 optype = o->op_type; - U32 oppriv = o->op_private; - SV * const tmpsv = newSVpvs(""); - if (PL_opargs[optype] & OA_TARGLEX) { - if (oppriv & OPpTARGET_MY) - sv_catpv(tmpsv, ",TARGET_MY"); - } - else if (optype == OP_ENTERSUB || - optype == OP_RV2SV || - optype == OP_GVSV || - optype == OP_RV2AV || - optype == OP_RV2HV || - optype == OP_RV2GV || - optype == OP_AELEM || - optype == OP_HELEM ) - { - if (optype == OP_ENTERSUB) { - append_flags(tmpsv, oppriv, op_entersub_names); - } - else { - switch (oppriv & OPpDEREF) { - case OPpDEREF_SV: - sv_catpv(tmpsv, ",SV"); - break; - case OPpDEREF_AV: - sv_catpv(tmpsv, ",AV"); - break; - case OPpDEREF_HV: - sv_catpv(tmpsv, ",HV"); - break; + U16 oppriv = o->op_private; + I16 op_ix = PL_op_private_bitdef_ix[o->op_type]; + SV * tmpsv = NULL; + + if (op_ix != -1) { + U16 stop = 0; + tmpsv = newSVpvs(""); + for (; !stop; op_ix++) { + U16 entry = PL_op_private_bitdefs[op_ix]; + U16 bit = (entry >> 2) & 7; + U16 ix = entry >> 5; + + stop = (entry & 1); + + if (entry & 2) { + /* bitfield */ + I16 const *p = &PL_op_private_bitfields[ix]; + U16 bitmin = (U16) *p++; + I16 label = *p++; + I16 enum_label; + U16 mask = 0; + U16 i; + U16 val; + + for (i = bitmin; i<= bit; i++) + mask |= (1<<i); + bit = bitmin; + val = (oppriv & mask); + + if ( label != -1 + && PL_op_private_labels[label] == '-' + && PL_op_private_labels[label+1] == '\0' + ) + /* display as raw number */ + continue; + + oppriv -= val; + val >>= bit; + enum_label = -1; + while (*p != -1) { + if (val == *p++) { + enum_label = *p; + break; + } + p++; + } + if (val == 0 && enum_label == -1) + /* don't display anonymous zero values */ + continue; + + sv_catpv(tmpsv, ","); + if (label != -1) { + sv_catpv(tmpsv, &PL_op_private_labels[label]); + sv_catpv(tmpsv, "="); + } + sv_catpv(tmpsv, &PL_op_private_labels[enum_label]); + + } + else { + /* bit flag */ + if ( oppriv & (1<<bit) + && !(PL_op_private_labels[ix] == '-' + && PL_op_private_labels[ix+1] == '\0')) + { + oppriv -= (1<<bit); + sv_catpv(tmpsv, ","); + sv_catpv(tmpsv, &PL_op_private_labels[ix]); + } } - if (oppriv & OPpMAYBE_LVSUB) - sv_catpv(tmpsv, ",MAYBE_LVSUB"); - } - if (optype == OP_AELEM || optype == OP_HELEM) { - if (oppriv & OPpLVAL_DEFER) - sv_catpv(tmpsv, ",LVAL_DEFER"); - } - else if (optype == OP_RV2HV || optype == OP_PADHV) { - if (oppriv & OPpMAYBE_TRUEBOOL) - sv_catpvs(tmpsv, ",OPpMAYBE_TRUEBOOL"); - if (oppriv & OPpTRUEBOOL) - sv_catpvs(tmpsv, ",OPpTRUEBOOL"); } - else { - if (oppriv & HINT_STRICT_REFS) - sv_catpv(tmpsv, ",STRICT_REFS"); - if (oppriv & OPpOUR_INTRO) - sv_catpv(tmpsv, ",OUR_INTRO"); + if (oppriv) { + sv_catpv(tmpsv, ","); + Perl_sv_catpvf(aTHX_ tmpsv, "0x%"UVxf, (UV)oppriv); } } - else if (S_op_private_to_names(aTHX_ tmpsv, optype, oppriv)) { - } - else if (OP_IS_FILETEST(o->op_type)) { - if (oppriv & OPpFT_ACCESS) - sv_catpv(tmpsv, ",FT_ACCESS"); - if (oppriv & OPpFT_STACKED) - sv_catpv(tmpsv, ",FT_STACKED"); - if (oppriv & OPpFT_STACKING) - sv_catpv(tmpsv, ",FT_STACKING"); - if (oppriv & OPpFT_AFTER_t) - sv_catpv(tmpsv, ",AFTER_t"); - } - else if (o->op_type == OP_AASSIGN) { - if (oppriv & OPpASSIGN_COMMON) - sv_catpvs(tmpsv, ",COMMON"); - if (oppriv & OPpMAYBE_LVSUB) - sv_catpvs(tmpsv, ",MAYBE_LVSUB"); - } - if (o->op_flags & OPf_MOD && oppriv & OPpLVAL_INTRO) - sv_catpv(tmpsv, ",INTRO"); - if (o->op_type == OP_PADRANGE) - Perl_sv_catpvf(aTHX_ tmpsv, ",COUNT=%"UVuf, - (UV)(oppriv & OPpPADRANGE_COUNTMASK)); - if ( (o->op_type == OP_RV2HV || o->op_type == OP_RV2AV || - o->op_type == OP_PADAV || o->op_type == OP_PADHV || - o->op_type == OP_ASLICE || o->op_type == OP_HSLICE) - && oppriv & OPpSLICEWARNING ) - sv_catpvs(tmpsv, ",SLICEWARNING"); - if (SvCUR(tmpsv)) { + if (tmpsv && SvCUR(tmpsv)) { Perl_dump_indent(aTHX_ level, file, "PRIVATE = (%s)\n", SvPVX_const(tmpsv) + 1); } else Perl_dump_indent(aTHX_ level, file, "PRIVATE = (0x%"UVxf")\n", (UV)oppriv); } - - - switch (optype) { case OP_AELEMFAST: case OP_GVSV: diff --git a/ext/B/B/Concise.pm b/ext/B/B/Concise.pm index 53790db967..b531ce85af 100644 --- a/ext/B/B/Concise.pm +++ b/ext/B/B/Concise.pm @@ -592,73 +592,13 @@ sub fmt_line { # generate text-line for op. return $text; # suppress empty lines } -our %priv; # used to display each opcode's BASEOP.op_private values - -$priv{$_}{128} = "LVINTRO" - for qw(pos substr vec threadsv gvsv rv2sv rv2hv rv2gv rv2av rv2arylen - aelem helem aslice hslice padsv padav padhv enteriter entersub - padrange pushmark); -$priv{$_}{64} = "REFC" for qw(leave leavesub leavesublv leavewrite); -$priv{$_}{128} = "LV" for qw(leave leaveloop); -@{$priv{aassign}}{32,64} = qw(STATE COMMON); -@{$priv{sassign}}{32,64,128} = qw(STATE BKWARD CV2GV); -$priv{$_}{64} = "RTIME" for qw(match subst substcont qr); -@{$priv{$_}}{1,2,4,8,16,64} = qw(<UTF >UTF IDENT SQUASH DEL COMPL GROWS) - for qw(trans transr); -$priv{repeat}{64} = "DOLIST"; -$priv{leaveloop}{64} = "CONT"; -@{$priv{$_}}{32,64,96} = qw(DREFAV DREFHV DREFSV) - for qw(rv2gv rv2sv padsv aelem helem); -$priv{$_}{16} = "STATE" for qw(padav padhv padsv); -@{$priv{rv2gv}}{4,16} = qw(NOINIT FAKE); -@{$priv{entersub}}{1,4,16,32,64} = qw(INARGS TARG DBG DEREF); -@{$priv{rv2cv}}{64,8,128} = qw(CONST AMPER NO()); -$priv{gv}{32} = "EARLYCV"; -$priv{$_}{16} = "LVDEFER" for qw(aelem helem); -$priv{$_}{16} = "OURINTR" for qw(gvsv rv2sv rv2av rv2hv r2gv enteriter); -$priv{$_}{8} = "LVSUB" - for qw(rv2av rv2gv rv2hv padav padhv aelem helem aslice hslice - av2arylen keys rkeys substr pos vec); -$priv{$_}{4} = "SLICEWARN" - for qw(rv2hv rv2av padav padhv hslice aslice); -@{$priv{$_}}{32,64} = qw(BOOL BOOL?) for qw(rv2hv padhv); -$priv{substr}{16} = "REPL1ST"; -$priv{$_}{16} = "TARGMY" - for map(($_,"s$_"), qw(chop chomp)), - map(($_,"i_$_"), qw(postinc postdec multiply divide modulo add - subtract negate)), - qw(pow concat stringify left_shift right_shift bit_and bit_xor - bit_or complement atan2 sin cos rand exp log sqrt int hex oct - abs length index rindex sprintf ord chr crypt quotemeta join - push unshift flock chdir chown chroot unlink chmod utime rename - link symlink mkdir rmdir wait waitpid system exec kill getppid - getpgrp setpgrp getpriority setpriority time sleep); -$priv{$_}{4} = "REVERSED" for qw(enteriter iter); -@{$priv{const}}{2,4,8,16,64} = qw(NOVER SHORT STRICT ENTERED BARE); -$priv{$_}{64} = "LINENUM" for qw(flip flop); -$priv{list}{64} = "GUESSED"; -$priv{delete}{64} = "SLICE"; -$priv{exists}{64} = "SUB"; -@{$priv{sort}}{1,2,4,8,16,32,64} = qw(NUM INT REV INPLACE DESC QSORT STABLE); -$priv{reverse}{8} = "INPLACE"; -$priv{threadsv}{64} = "SVREFd"; -@{$priv{$_}}{16,32,64,128} = qw(INBIN INCR OUTBIN OUTCR) - for qw(open backtick); -$priv{$_}{32} = "HUSH" for qw(nextstate dbstate); -$priv{$_}{2} = "FTACCESS" - for qw(ftrread ftrwrite ftrexec fteread ftewrite fteexec); -@{$priv{entereval}}{2,4,8,16} = qw(HAS_HH UNI BYTES COPHH); -@{$priv{$_}}{4,8,16} = qw(FTSTACKED FTSTACKING FTAFTERt) - for qw(ftrread ftrwrite ftrexec fteread ftewrite fteexec ftis fteowned - ftrowned ftzero ftsize ftmtime ftatime ftctime ftsock ftchr - ftblk ftfile ftdir ftpipe ftlink ftsuid ftsgid ftsvtx fttty - fttext ftbinary); -$priv{$_}{2} = "GREPLEX" - for qw(mapwhile mapstart grepwhile grepstart); -$priv{$_}{128} = "+1" for qw(caller wantarray runcv); -@{$priv{coreargs}}{1,2,64,128} = qw(DREF1 DREF2 $MOD MARK); -$priv{$_}{128} = "UTF" for qw(last redo next goto dump); -$priv{split}{128} = "IMPLIM"; + + +# use require rather than use here to avoid disturbing tests that dump +# BEGIN blocks +require B::Op_private; + + our %hints; # used to display each COP's op_hints values @@ -688,9 +628,61 @@ sub _flags { return join(",", @s); } +# return a string like 'LVINTRO,1' for the op $name with op_private +# value $x + sub private_flags { my($name, $x) = @_; - _flags($priv{$name}, $x); + my $entry = $B::Op_private::bits{$name}; + return $x ? "$x" : '' unless $entry; + + my @flags; + my $bit; + for ($bit = 7; $bit >= 0; $bit--) { + next unless exists $entry->{$bit}; + my $e = $entry->{$bit}; + if (ref($e) eq 'HASH') { + # bit field + + my ($bitmin, $bitmax, $bitmask, $enum, $label) = + @{$e}{qw(bitmin bitmax bitmask enum label)}; + $bit = $bitmin; + next if defined $label && $label eq '-'; # display as raw number + + my $val = $x & $bitmask; + $x &= ~$bitmask; + $val >>= $bitmin; + + if (defined $enum) { + # try to convert numeric $val into symbolic + my @enum = @$enum; + while (@enum) { + my $ix = shift @enum; + my $name = shift @enum; + my $label = shift @enum; + if ($val == $ix) { + $val = $label; + last; + } + } + } + next if $val eq '0'; # don't display anonymous zero values + push @flags, defined $label ? "$label=$val" : $val; + + } + else { + # flag bit + my $label = $B::Op_private::labels{$e}; + next if defined $label && $label eq '-'; # display as raw number + if ($x & (1<<$bit)) { + $x -= (1<<$bit); + push @flags, $label; + } + } + } + + push @flags, $x if $x; # display unknown bits numerically + return join ",", @flags; } sub hints_flags { @@ -779,18 +771,25 @@ sub concise_op { $h{class} = class($op); $h{extarg} = $h{targ} = $op->targ; $h{extarg} = "" unless $h{extarg}; + $h{privval} = $op->private; + $h{private} = private_flags($h{name}, $op->private); + if ($op->folded) { + $h{private} &&= "$h{private},"; + $h{private} .= "FOLD"; + } + if ($h{name} eq "null" and $h{targ}) { # targ holds the old type $h{exname} = "ex-" . substr(ppname($h{targ}), 3); $h{extarg} = ""; - } elsif ($op->name =~ /^leave(sub(lv)?|write)?$/) { - # targ potentially holds a reference count - if ($op->private & 64) { - my $refs = "ref" . ($h{targ} != 1 ? "s" : ""); - $h{targarglife} = $h{targarg} = "$h{targ} $refs"; - } + } elsif ($h{private} =~ /\bREFC\b/) { + # targ holds a reference count + my $refs = "ref" . ($h{targ} != 1 ? "s" : ""); + $h{targarglife} = $h{targarg} = "$h{targ} $refs"; } elsif ($h{targ}) { - my $count = $h{name} eq 'padrange' ? ($op->private & 127) : 1; + my $count = $h{name} eq 'padrange' + ? ($op->private & $B::Op_private::defines{'OPpPADRANGE_COUNTMASK'}) + : 1; my (@targarg, @targarglife); for my $i (0..$count-1) { my ($targarg, $targarglife); @@ -916,12 +915,6 @@ sub concise_op { $h{classsym} = $opclass{$h{class}}; $h{flagval} = $op->flags; $h{flags} = op_flags($op->flags); - $h{privval} = $op->private; - $h{private} = private_flags($h{name}, $op->private); - if ($op->folded) { - $h{private} &&= "$h{private},"; - $h{private} .= "FOLD"; - } if ($op->can("hints")) { $h{hintsval} = $op->hints; $h{hints} = hints_flags($h{hintsval}); @@ -1413,10 +1406,7 @@ Private flags, if any are set for an opcode, are displayed after a '/' They're opcode specific, and occur less often than the public ones, so they're represented by short mnemonics instead of single-chars; see -F<op.h> for gory details, or try this quick 2-liner: - - $> perl -MB::Concise -de 1 - DB<1> |x \%B::Concise::priv +B::Op_private and F<regen/op_private> for more details. =head1 FORMATTING SPECIFICATIONS diff --git a/ext/B/Makefile.PL b/ext/B/Makefile.PL index 8767b5e3dd..308b015a31 100644 --- a/ext/B/Makefile.PL +++ b/ext/B/Makefile.PL @@ -32,6 +32,7 @@ foreach my $tuple (['cop.h'], ['cv.h', 'CVf'], ['gv.h', 'GVf'], ['op.h'], + ['opcode.h', 'OPp'], ['op_reg_common.h','(?:(?:RXf_)?PMf_)'], ['regexp.h','RXf_'], ['sv.h', 'SV(?:[fps]|pad)_'], diff --git a/ext/Devel-Peek/t/Peek.t b/ext/Devel-Peek/t/Peek.t index 52dc1757e2..ce777da4e9 100644 --- a/ext/Devel-Peek/t/Peek.t +++ b/ext/Devel-Peek/t/Peek.t @@ -1529,7 +1529,7 @@ dumpindent is 4 at - line 1. 1 TYPE = leave ===> NULL TARG = 1 FLAGS = (VOID,KIDS,PARENS,SLABBED,LASTSIB) - PRIVATE = (REFCOUNTED) + PRIVATE = (REFC) REFCNT = 1 { 2 TYPE = enter ===> 3 @@ -1545,7 +1545,7 @@ dumpindent is 4 at - line 1. 5 TYPE = entersub ===> 1 TARG = 1 FLAGS = (VOID,KIDS,STACKED,SLABBED,LASTSIB) - PRIVATE = (HASTARG) + PRIVATE = (TARG) { 6 TYPE = null ===> (5) (was list) diff --git a/globvar.sym b/globvar.sym index 3cab4bf725..3e66db91c3 100644 --- a/globvar.sym +++ b/globvar.sym @@ -39,6 +39,11 @@ no_usym no_wrongref op_desc op_name +op_private_bitdef_ix +op_private_bitdefs +op_private_bitfields +op_private_labels +op_private_valid opargs phase_names ppaddr diff --git a/lib/B/Op_private.pm b/lib/B/Op_private.pm new file mode 100644 index 0000000000..08ab0f4b38 --- /dev/null +++ b/lib/B/Op_private.pm @@ -0,0 +1,695 @@ +# -*- buffer-read-only: t -*- +# +# lib/B/Op_private.pm +# +# Copyright (C) 2014 by Larry Wall and others +# +# You may distribute under the terms of either the GNU General Public +# License or the Artistic License, as specified in the README file. +# +# !!!!!!! DO NOT EDIT THIS FILE !!!!!!! +# This file is built by regen/opcode.pl from data in regen/op_private. +# Any changes made here will be lost! + +=head1 NAME + +B::Op_private - OP op_private flag definitions + +=head1 SYNOPSIS + + use B::Op_private; + + # flag details for bit 7 of OP_AELEM's op_private: + my $name = $B::Op_private::bits{aelem}{7}; # OPpLVAL_INTRO + my $value = $B::Op_private::defines{$name}; # 128 + my $label = $B::Op_private::labels{$name}; # LVINTRO + + # the bit field at bits 5..6 of OP_AELEM's op_private: + my $bf = $B::Op_private::bits{aelem}{6}; + my $mask = $bf->{bitmask}; # etc + +=head1 DESCRIPTION + +This module provides three global hashes: + + %B::Op_private::bits + %B::Op_private::defines + %B::Op_private::labels + +which contain information about the per-op meanings of the bits in the +op_private field. + +=head2 C<%bits> + +This is indexed by op name and then bit number (0..7). For single bit flags, +it returns the name of the define (if any) for that bit: + + $B::Op_private::bits{aelem}{7} eq 'OPpLVAL_INTRO'; + +For bit fields, it returns a hash ref containing details about the field. +The same reference will be returned for all bit positions that make +up the bit field; so for example these both return the same hash ref: + + $bitfield = $B::Op_private::bits{aelem}{5}; + $bitfield = $B::Op_private::bits{aelem}{6}; + +The general format of this hash ref is + + { + # The bit range and mask; these are always present. + bitmin => 5, + bitmax => 6, + bitmask => 0x60, + + # (The remaining keys are optional) + + # The names of any defines that were requested: + mask_def => 'OPpFOO_MASK', + baseshift_def => 'OPpFOO_SHIFT', + bitcount_def => 'OPpFOO_BITS', + + # If present, Concise etc will display the value with a 'FOO=' + # prefix. If it equals '-', then Concise will treat the bit field + # as raw bits and not try to interpret it. + label => 'FOO', + + # If present, specifies the names of some defines and the display + # labels that are used to assign meaning to particular integer + # values within the bit field; e.g. 3 is displayed as 'C'. + enum => [ qw( + 1 OPpFOO_A A + 2 OPpFOO_B B + 3 OPpFOO_C C + )], + + }; + + +=head2 C<%defines> + +This gives the value of every C<OPp> define, e.g. + + $B::Op_private::defines{OPpLVAL_INTRO} == 128; + +=head2 C<%labels> + +This gives the short display label for each define, as used by C<B::Concise> +and C<perl -Dx>, e.g. + + $B::Op_private::labels{OPpLVAL_INTRO} eq 'LVINTRO'; + +If the label equals '-', then Concise will treat the bit as a raw bit and +not try to display it symbolically. + +=cut + +package B::Op_private; + +our %bits; + +$bits{$_}{3} = 'OPpENTERSUB_AMPER' for qw(entersub rv2cv); +$bits{$_}{4} = 'OPpENTERSUB_DB' for qw(entersub rv2cv); +$bits{$_}{2} = 'OPpENTERSUB_HASTARG' for qw(entersub rv2cv); +$bits{$_}{6} = 'OPpFLIP_LINENUM' for qw(flip flop); +$bits{$_}{1} = 'OPpFT_ACCESS' for qw(fteexec fteread ftewrite ftrexec ftrread ftrwrite); +$bits{$_}{4} = 'OPpFT_AFTER_t' for qw(ftatime ftbinary ftblk ftchr ftctime ftdir fteexec fteowned fteread ftewrite ftfile ftis ftlink ftmtime ftpipe ftrexec ftrowned ftrread ftrwrite ftsgid ftsize ftsock ftsuid ftsvtx fttext fttty ftzero); +$bits{$_}{2} = 'OPpFT_STACKED' for qw(ftatime ftbinary ftblk ftchr ftctime ftdir fteexec fteowned fteread ftewrite ftfile ftis ftlink ftmtime ftpipe ftrexec ftrowned ftrread ftrwrite ftsgid ftsize ftsock ftsuid ftsvtx fttext fttty ftzero); +$bits{$_}{3} = 'OPpFT_STACKING' for qw(ftatime ftbinary ftblk ftchr ftctime ftdir fteexec fteowned fteread ftewrite ftfile ftis ftlink ftmtime ftpipe ftrexec ftrowned ftrread ftrwrite ftsgid ftsize ftsock ftsuid ftsvtx fttext fttty ftzero); +$bits{$_}{1} = 'OPpGREP_LEX' for qw(grepstart grepwhile mapstart mapwhile); +$bits{$_}{6} = 'OPpHINT_M_VMSISH_STATUS' for qw(dbstate nextstate); +$bits{$_}{7} = 'OPpHINT_M_VMSISH_TIME' for qw(dbstate nextstate); +$bits{$_}{1} = 'OPpHINT_STRICT_REFS' for qw(entersub rv2av rv2cv rv2gv rv2hv rv2sv); +$bits{$_}{5} = 'OPpHUSH_VMSISH' for qw(dbstate nextstate); +$bits{$_}{2} = 'OPpITER_REVERSED' for qw(enteriter iter); +$bits{$_}{7} = 'OPpLVALUE' for qw(leave leaveloop); +$bits{$_}{4} = 'OPpLVAL_DEFER' for qw(aelem helem); +$bits{$_}{7} = 'OPpLVAL_INTRO' for qw(aelem aslice cond_expr delete enteriter entersub gvsv helem hslice list padav padhv padrange padsv pos pushmark rv2av rv2gv rv2hv rv2sv substr vec); +$bits{$_}{3} = 'OPpMAYBE_LVSUB' for qw(aassign aelem aslice av2arylen helem hslice keys kvaslice kvhslice padav padhv pos rkeys rv2av rv2gv rv2hv substr vec); +$bits{$_}{6} = 'OPpMAYBE_TRUEBOOL' for qw(padhv rv2hv); +$bits{$_}{7} = 'OPpOFFBYONE' for qw(caller runcv wantarray); +$bits{$_}{5} = 'OPpOPEN_IN_CRLF' for qw(backtick open); +$bits{$_}{4} = 'OPpOPEN_IN_RAW' for qw(backtick open); +$bits{$_}{7} = 'OPpOPEN_OUT_CRLF' for qw(backtick open); +$bits{$_}{6} = 'OPpOPEN_OUT_RAW' for qw(backtick open); +$bits{$_}{4} = 'OPpOUR_INTRO' for qw(enteriter gvsv rv2av rv2hv rv2sv); +$bits{$_}{4} = 'OPpPAD_STATE' for qw(padav padhv padsv pushmark); +$bits{$_}{7} = 'OPpPV_IS_UTF8' for qw(dump goto last next redo); +$bits{$_}{6} = 'OPpREFCOUNTED' for qw(leave leaveeval leavesub leavesublv leavewrite); +$bits{$_}{6} = 'OPpRUNTIME' for qw(match pushre qr subst substcont); +$bits{$_}{2} = 'OPpSLICEWARNING' for qw(aslice hslice padav padhv rv2av rv2hv); +$bits{$_}{4} = 'OPpTARGET_MY' for qw(abs add atan2 chdir chmod chomp chown chr chroot concat cos crypt divide exec exp flock getpgrp getppid getpriority hex i_add i_divide i_modulo i_multiply i_negate i_postdec i_postinc i_subtract index int kill left_shift length link log match mkdir modulo multiply oct ord pow push rand rename right_shift rindex rmdir schomp setpgrp setpriority sin sleep sqrt srand stringify subst subtract symlink system time trans transr unlink unshift utime wait waitpid); +$bits{$_}{5} = 'OPpTRANS_COMPLEMENT' for qw(trans transr); +$bits{$_}{7} = 'OPpTRANS_DELETE' for qw(trans transr); +$bits{$_}{0} = 'OPpTRANS_FROM_UTF' for qw(trans transr); +$bits{$_}{6} = 'OPpTRANS_GROWS' for qw(trans transr); +$bits{$_}{2} = 'OPpTRANS_IDENTICAL' for qw(trans transr); +$bits{$_}{3} = 'OPpTRANS_SQUASH' for qw(trans transr); +$bits{$_}{1} = 'OPpTRANS_TO_UTF' for qw(trans transr); +$bits{$_}{5} = 'OPpTRUEBOOL' for qw(padhv rv2hv); + +my @bf = ( + { + label => '-', + mask_def => 'OPpARG1_MASK', + bitmin => 0, + bitmax => 0, + bitmask => 1, + }, + { + label => '-', + mask_def => 'OPpARG2_MASK', + bitmin => 0, + bitmax => 1, + bitmask => 3, + }, + { + label => '-', + mask_def => 'OPpARG3_MASK', + bitmin => 0, + bitmax => 2, + bitmask => 7, + }, + { + label => '-', + mask_def => 'OPpARG4_MASK', + bitmin => 0, + bitmax => 3, + bitmask => 15, + }, + { + label => '-', + mask_def => 'OPpPADRANGE_COUNTMASK', + bitcount_def => 'OPpPADRANGE_COUNTSHIFT', + bitmin => 0, + bitmax => 6, + bitmask => 127, + }, + { + label => '-', + bitmin => 0, + bitmax => 7, + bitmask => 255, + }, + { + mask_def => 'OPpDEREF', + bitmin => 5, + bitmax => 6, + bitmask => 96, + enum => [ + 1, 'OPpDEREF_AV', 'DREFAV', + 2, 'OPpDEREF_HV', 'DREFHV', + 3, 'OPpDEREF_SV', 'DREFSV', + ], + }, +); + +@{$bits{aassign}}{6,1,0} = ('OPpASSIGN_COMMON', $bf[1], $bf[1]); +$bits{abs}{0} = $bf[0]; +@{$bits{accept}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{add}}{1,0} = ($bf[1], $bf[1]); +$bits{aeach}{0} = $bf[0]; +@{$bits{aelem}}{6,5,1,0} = ($bf[6], $bf[6], $bf[1], $bf[1]); +@{$bits{aelemfast}}{7,6,5,4,3,2,1,0} = ($bf[5], $bf[5], $bf[5], $bf[5], $bf[5], $bf[5], $bf[5], $bf[5]); +@{$bits{aelemfast_lex}}{7,6,5,4,3,2,1,0} = ($bf[5], $bf[5], $bf[5], $bf[5], $bf[5], $bf[5], $bf[5], $bf[5]); +$bits{akeys}{0} = $bf[0]; +$bits{alarm}{0} = $bf[0]; +$bits{and}{0} = $bf[0]; +$bits{andassign}{0} = $bf[0]; +@{$bits{anonhash}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{anonlist}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{atan2}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{av2arylen}{0} = $bf[0]; +$bits{avalues}{0} = $bf[0]; +$bits{backtick}{0} = $bf[0]; +@{$bits{bind}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{binmode}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{bit_and}}{1,0} = ($bf[1], $bf[1]); +@{$bits{bit_or}}{1,0} = ($bf[1], $bf[1]); +@{$bits{bit_xor}}{1,0} = ($bf[1], $bf[1]); +@{$bits{bless}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{caller}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{chdir}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{chmod}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{chomp}{0} = $bf[0]; +$bits{chop}{0} = $bf[0]; +@{$bits{chown}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{chr}{0} = $bf[0]; +$bits{chroot}{0} = $bf[0]; +@{$bits{close}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{closedir}{0} = $bf[0]; +$bits{complement}{0} = $bf[0]; +@{$bits{concat}}{1,0} = ($bf[1], $bf[1]); +$bits{cond_expr}{0} = $bf[0]; +@{$bits{connect}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{const}}{6,4,3,2,1} = ('OPpCONST_BARE', 'OPpCONST_ENTERED', 'OPpCONST_STRICT', 'OPpCONST_SHORTCIRCUIT', 'OPpCONST_NOVER'); +@{$bits{coreargs}}{7,6,1,0} = ('OPpCOREARGS_PUSHMARK', 'OPpCOREARGS_SCALARMOD', 'OPpCOREARGS_DEREF2', 'OPpCOREARGS_DEREF1'); +$bits{cos}{0} = $bf[0]; +@{$bits{crypt}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{dbmclose}{0} = $bf[0]; +@{$bits{dbmopen}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{defined}{0} = $bf[0]; +@{$bits{delete}}{6,0} = ('OPpSLICE', $bf[0]); +@{$bits{die}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{divide}}{1,0} = ($bf[1], $bf[1]); +$bits{dofile}{0} = $bf[0]; +$bits{dor}{0} = $bf[0]; +$bits{dorassign}{0} = $bf[0]; +$bits{dump}{0} = $bf[0]; +$bits{each}{0} = $bf[0]; +@{$bits{entereval}}{5,4,3,2,1,0} = ('OPpEVAL_RE_REPARSING', 'OPpEVAL_COPHH', 'OPpEVAL_BYTES', 'OPpEVAL_UNICODE', 'OPpEVAL_HAS_HH', $bf[0]); +$bits{entergiven}{0} = $bf[0]; +$bits{enteriter}{3} = 'OPpITER_DEF'; +@{$bits{entersub}}{6,5,0} = ($bf[6], $bf[6], 'OPpENTERSUB_INARGS'); +$bits{entertry}{0} = $bf[0]; +$bits{enterwhen}{0} = $bf[0]; +@{$bits{enterwrite}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{eof}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{eq}}{1,0} = ($bf[1], $bf[1]); +@{$bits{exec}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{exists}}{6,0} = ('OPpEXISTS_SUB', $bf[0]); +@{$bits{exit}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{exp}{0} = $bf[0]; +$bits{fc}{0} = $bf[0]; +@{$bits{fcntl}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{fileno}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{flip}{0} = $bf[0]; +@{$bits{flock}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{flop}{0} = $bf[0]; +@{$bits{formline}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{ftatime}{0} = $bf[0]; +$bits{ftbinary}{0} = $bf[0]; +$bits{ftblk}{0} = $bf[0]; +$bits{ftchr}{0} = $bf[0]; +$bits{ftctime}{0} = $bf[0]; +$bits{ftdir}{0} = $bf[0]; +$bits{fteexec}{0} = $bf[0]; +$bits{fteowned}{0} = $bf[0]; +$bits{fteread}{0} = $bf[0]; +$bits{ftewrite}{0} = $bf[0]; +$bits{ftfile}{0} = $bf[0]; +$bits{ftis}{0} = $bf[0]; +$bits{ftlink}{0} = $bf[0]; +$bits{ftmtime}{0} = $bf[0]; +$bits{ftpipe}{0} = $bf[0]; +$bits{ftrexec}{0} = $bf[0]; +$bits{ftrowned}{0} = $bf[0]; +$bits{ftrread}{0} = $bf[0]; +$bits{ftrwrite}{0} = $bf[0]; +$bits{ftsgid}{0} = $bf[0]; +$bits{ftsize}{0} = $bf[0]; +$bits{ftsock}{0} = $bf[0]; +$bits{ftsuid}{0} = $bf[0]; +$bits{ftsvtx}{0} = $bf[0]; +$bits{fttext}{0} = $bf[0]; +$bits{fttty}{0} = $bf[0]; +$bits{ftzero}{0} = $bf[0]; +@{$bits{ge}}{1,0} = ($bf[1], $bf[1]); +@{$bits{gelem}}{1,0} = ($bf[1], $bf[1]); +@{$bits{getc}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{getpeername}{0} = $bf[0]; +@{$bits{getpgrp}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{getpriority}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{getsockname}{0} = $bf[0]; +$bits{ggrgid}{0} = $bf[0]; +$bits{ggrnam}{0} = $bf[0]; +@{$bits{ghbyaddr}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{ghbyname}{0} = $bf[0]; +@{$bits{glob}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{gmtime}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{gnbyaddr}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{gnbyname}{0} = $bf[0]; +$bits{goto}{0} = $bf[0]; +$bits{gpbyname}{0} = $bf[0]; +@{$bits{gpbynumber}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{gpwnam}{0} = $bf[0]; +$bits{gpwuid}{0} = $bf[0]; +$bits{grepwhile}{0} = $bf[0]; +@{$bits{gsbyname}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{gsbyport}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{gsockopt}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{gt}}{1,0} = ($bf[1], $bf[1]); +$bits{gv}{5} = 'OPpEARLY_CV'; +@{$bits{helem}}{6,5,1,0} = ($bf[6], $bf[6], $bf[1], $bf[1]); +$bits{hex}{0} = $bf[0]; +@{$bits{i_add}}{1,0} = ($bf[1], $bf[1]); +@{$bits{i_divide}}{1,0} = ($bf[1], $bf[1]); +@{$bits{i_eq}}{1,0} = ($bf[1], $bf[1]); +@{$bits{i_ge}}{1,0} = ($bf[1], $bf[1]); +@{$bits{i_gt}}{1,0} = ($bf[1], $bf[1]); +@{$bits{i_le}}{1,0} = ($bf[1], $bf[1]); +@{$bits{i_lt}}{1,0} = ($bf[1], $bf[1]); +@{$bits{i_modulo}}{1,0} = ($bf[1], $bf[1]); +@{$bits{i_multiply}}{1,0} = ($bf[1], $bf[1]); +@{$bits{i_ncmp}}{1,0} = ($bf[1], $bf[1]); +@{$bits{i_ne}}{1,0} = ($bf[1], $bf[1]); +$bits{i_negate}{0} = $bf[0]; +$bits{i_postdec}{0} = $bf[0]; +$bits{i_postinc}{0} = $bf[0]; +$bits{i_predec}{0} = $bf[0]; +$bits{i_preinc}{0} = $bf[0]; +@{$bits{i_subtract}}{1,0} = ($bf[1], $bf[1]); +@{$bits{index}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{int}{0} = $bf[0]; +@{$bits{ioctl}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{join}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{keys}{0} = $bf[0]; +@{$bits{kill}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{last}{0} = $bf[0]; +$bits{lc}{0} = $bf[0]; +$bits{lcfirst}{0} = $bf[0]; +@{$bits{le}}{1,0} = ($bf[1], $bf[1]); +$bits{leaveeval}{0} = $bf[0]; +$bits{leavegiven}{0} = $bf[0]; +@{$bits{leaveloop}}{1,0} = ($bf[1], $bf[1]); +$bits{leavesub}{0} = $bf[0]; +$bits{leavesublv}{0} = $bf[0]; +$bits{leavewhen}{0} = $bf[0]; +$bits{leavewrite}{0} = $bf[0]; +@{$bits{left_shift}}{1,0} = ($bf[1], $bf[1]); +$bits{length}{0} = $bf[0]; +@{$bits{link}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{list}{6} = 'OPpLIST_GUESSED'; +@{$bits{listen}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{localtime}{0} = $bf[0]; +$bits{lock}{0} = $bf[0]; +$bits{log}{0} = $bf[0]; +@{$bits{lslice}}{1,0} = ($bf[1], $bf[1]); +$bits{lstat}{0} = $bf[0]; +@{$bits{lt}}{1,0} = ($bf[1], $bf[1]); +$bits{mapwhile}{0} = $bf[0]; +$bits{method}{0} = $bf[0]; +@{$bits{mkdir}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{modulo}}{1,0} = ($bf[1], $bf[1]); +@{$bits{msgctl}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{msgget}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{msgrcv}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{msgsnd}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{multiply}}{1,0} = ($bf[1], $bf[1]); +@{$bits{ncmp}}{1,0} = ($bf[1], $bf[1]); +@{$bits{ne}}{1,0} = ($bf[1], $bf[1]); +$bits{negate}{0} = $bf[0]; +$bits{next}{0} = $bf[0]; +$bits{not}{0} = $bf[0]; +$bits{oct}{0} = $bf[0]; +$bits{once}{0} = $bf[0]; +@{$bits{open}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{open_dir}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{or}{0} = $bf[0]; +$bits{orassign}{0} = $bf[0]; +$bits{ord}{0} = $bf[0]; +@{$bits{pack}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{padrange}}{6,5,4,3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4], $bf[4], $bf[4], $bf[4]); +@{$bits{padsv}}{6,5} = ($bf[6], $bf[6]); +@{$bits{pipe_op}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{pop}{0} = $bf[0]; +$bits{pos}{0} = $bf[0]; +$bits{postdec}{0} = $bf[0]; +$bits{postinc}{0} = $bf[0]; +@{$bits{pow}}{1,0} = ($bf[1], $bf[1]); +$bits{predec}{0} = $bf[0]; +$bits{preinc}{0} = $bf[0]; +$bits{prototype}{0} = $bf[0]; +@{$bits{push}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{quotemeta}{0} = $bf[0]; +@{$bits{rand}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{range}{0} = $bf[0]; +$bits{reach}{0} = $bf[0]; +@{$bits{read}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{readdir}{0} = $bf[0]; +$bits{readline}{0} = $bf[0]; +$bits{readlink}{0} = $bf[0]; +@{$bits{recv}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{redo}{0} = $bf[0]; +$bits{ref}{0} = $bf[0]; +$bits{refgen}{0} = $bf[0]; +$bits{regcmaybe}{0} = $bf[0]; +$bits{regcomp}{0} = $bf[0]; +$bits{regcreset}{0} = $bf[0]; +@{$bits{rename}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{repeat}}{6,1,0} = ('OPpREPEAT_DOLIST', $bf[1], $bf[1]); +$bits{require}{0} = $bf[0]; +@{$bits{reset}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{reverse}}{3,0} = ('OPpREVERSE_INPLACE', $bf[0]); +$bits{rewinddir}{0} = $bf[0]; +@{$bits{right_shift}}{1,0} = ($bf[1], $bf[1]); +@{$bits{rindex}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{rkeys}{0} = $bf[0]; +$bits{rmdir}{0} = $bf[0]; +$bits{rv2av}{0} = $bf[0]; +@{$bits{rv2cv}}{7,6,0} = ('OPpENTERSUB_NOPAREN', 'OPpMAY_RETURN_CONSTANT', $bf[0]); +@{$bits{rv2gv}}{6,5,4,2,0} = ($bf[6], $bf[6], 'OPpALLOW_FAKE', 'OPpDONT_INIT_GV', $bf[0]); +$bits{rv2hv}{0} = $bf[0]; +@{$bits{rv2sv}}{6,5,0} = ($bf[6], $bf[6], $bf[0]); +$bits{rvalues}{0} = $bf[0]; +@{$bits{sassign}}{7,6,1,0} = ('OPpASSIGN_CV_TO_GV', 'OPpASSIGN_BACKWARDS', $bf[1], $bf[1]); +$bits{scalar}{0} = $bf[0]; +$bits{schomp}{0} = $bf[0]; +$bits{schop}{0} = $bf[0]; +@{$bits{scmp}}{1,0} = ($bf[1], $bf[1]); +@{$bits{seek}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{seekdir}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{select}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{semctl}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{semget}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{semop}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{send}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{seq}}{1,0} = ($bf[1], $bf[1]); +@{$bits{setpgrp}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{setpriority}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{sge}}{1,0} = ($bf[1], $bf[1]); +@{$bits{sgt}}{1,0} = ($bf[1], $bf[1]); +$bits{shift}{0} = $bf[0]; +@{$bits{shmctl}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{shmget}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{shmread}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{shmwrite}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{shostent}{0} = $bf[0]; +@{$bits{shutdown}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{sin}{0} = $bf[0]; +@{$bits{sle}}{1,0} = ($bf[1], $bf[1]); +@{$bits{sleep}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{slt}}{1,0} = ($bf[1], $bf[1]); +@{$bits{smartmatch}}{1,0} = ($bf[1], $bf[1]); +@{$bits{sne}}{1,0} = ($bf[1], $bf[1]); +$bits{snetent}{0} = $bf[0]; +@{$bits{socket}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{sockpair}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{sort}}{6,5,4,3,2,1,0} = ('OPpSORT_STABLE', 'OPpSORT_QSORT', 'OPpSORT_DESCEND', 'OPpSORT_INPLACE', 'OPpSORT_REVERSE', 'OPpSORT_INTEGER', 'OPpSORT_NUMERIC'); +@{$bits{splice}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{split}{7} = 'OPpSPLIT_IMPLIM'; +@{$bits{sprintf}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{sprotoent}{0} = $bf[0]; +$bits{sqrt}{0} = $bf[0]; +@{$bits{srand}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{srefgen}{0} = $bf[0]; +@{$bits{sselect}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{sservent}{0} = $bf[0]; +@{$bits{ssockopt}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{stat}{0} = $bf[0]; +@{$bits{stringify}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{study}{0} = $bf[0]; +$bits{substcont}{0} = $bf[0]; +@{$bits{substr}}{4,2,1,0} = ('OPpSUBSTR_REPL_FIRST', $bf[2], $bf[2], $bf[2]); +@{$bits{subtract}}{1,0} = ($bf[1], $bf[1]); +@{$bits{symlink}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{syscall}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{sysopen}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{sysread}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{sysseek}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{system}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{syswrite}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{tell}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{telldir}{0} = $bf[0]; +@{$bits{tie}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{tied}{0} = $bf[0]; +@{$bits{truncate}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{uc}{0} = $bf[0]; +$bits{ucfirst}{0} = $bf[0]; +@{$bits{umask}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{undef}{0} = $bf[0]; +@{$bits{unlink}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{unpack}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{unshift}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{untie}{0} = $bf[0]; +@{$bits{utime}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +$bits{values}{0} = $bf[0]; +@{$bits{vec}}{1,0} = ($bf[1], $bf[1]); +@{$bits{waitpid}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{warn}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]); +@{$bits{xor}}{1,0} = ($bf[1], $bf[1]); + + +our %defines = ( + OPpALLOW_FAKE => 16, + OPpARG1_MASK => 1, + OPpARG2_MASK => 3, + OPpARG3_MASK => 7, + OPpARG4_MASK => 15, + OPpASSIGN_BACKWARDS => 64, + OPpASSIGN_COMMON => 64, + OPpASSIGN_CV_TO_GV => 128, + OPpCONST_BARE => 64, + OPpCONST_ENTERED => 16, + OPpCONST_NOVER => 2, + OPpCONST_SHORTCIRCUIT => 4, + OPpCONST_STRICT => 8, + OPpCOREARGS_DEREF1 => 1, + OPpCOREARGS_DEREF2 => 2, + OPpCOREARGS_PUSHMARK => 128, + OPpCOREARGS_SCALARMOD => 64, + OPpDEREF => 96, + OPpDEREF_AV => 32, + OPpDEREF_HV => 64, + OPpDEREF_SV => 96, + OPpDONT_INIT_GV => 4, + OPpEARLY_CV => 32, + OPpENTERSUB_AMPER => 8, + OPpENTERSUB_DB => 16, + OPpENTERSUB_HASTARG => 4, + OPpENTERSUB_INARGS => 1, + OPpENTERSUB_NOPAREN => 128, + OPpEVAL_BYTES => 8, + OPpEVAL_COPHH => 16, + OPpEVAL_HAS_HH => 2, + OPpEVAL_RE_REPARSING => 32, + OPpEVAL_UNICODE => 4, + OPpEXISTS_SUB => 64, + OPpFLIP_LINENUM => 64, + OPpFT_ACCESS => 2, + OPpFT_AFTER_t => 16, + OPpFT_STACKED => 4, + OPpFT_STACKING => 8, + OPpGREP_LEX => 2, + OPpHINT_M_VMSISH_STATUS => 64, + OPpHINT_M_VMSISH_TIME => 128, + OPpHINT_STRICT_REFS => 2, + OPpHUSH_VMSISH => 32, + OPpITER_DEF => 8, + OPpITER_REVERSED => 4, + OPpLIST_GUESSED => 64, + OPpLVALUE => 128, + OPpLVAL_DEFER => 16, + OPpLVAL_INTRO => 128, + OPpMAYBE_LVSUB => 8, + OPpMAYBE_TRUEBOOL => 64, + OPpMAY_RETURN_CONSTANT => 64, + OPpOFFBYONE => 128, + OPpOPEN_IN_CRLF => 32, + OPpOPEN_IN_RAW => 16, + OPpOPEN_OUT_CRLF => 128, + OPpOPEN_OUT_RAW => 64, + OPpOUR_INTRO => 16, + OPpPADRANGE_COUNTMASK => 127, + OPpPADRANGE_COUNTSHIFT => 7, + OPpPAD_STATE => 16, + OPpPV_IS_UTF8 => 128, + OPpREFCOUNTED => 64, + OPpREPEAT_DOLIST => 64, + OPpREVERSE_INPLACE => 8, + OPpRUNTIME => 64, + OPpSLICE => 64, + OPpSLICEWARNING => 4, + OPpSORT_DESCEND => 16, + OPpSORT_INPLACE => 8, + OPpSORT_INTEGER => 2, + OPpSORT_NUMERIC => 1, + OPpSORT_QSORT => 32, + OPpSORT_REVERSE => 4, + OPpSORT_STABLE => 64, + OPpSPLIT_IMPLIM => 128, + OPpSUBSTR_REPL_FIRST => 16, + OPpTARGET_MY => 16, + OPpTRANS_COMPLEMENT => 32, + OPpTRANS_DELETE => 128, + OPpTRANS_FROM_UTF => 1, + OPpTRANS_GROWS => 64, + OPpTRANS_IDENTICAL => 4, + OPpTRANS_SQUASH => 8, + OPpTRANS_TO_UTF => 2, + OPpTRUEBOOL => 32, +); + +our %labels = ( + OPpALLOW_FAKE => 'FAKE', + OPpASSIGN_BACKWARDS => 'BKWARD', + OPpASSIGN_COMMON => 'COMMON', + OPpASSIGN_CV_TO_GV => 'CV2GV', + OPpCONST_BARE => 'BARE', + OPpCONST_ENTERED => 'ENTERED', + OPpCONST_NOVER => 'NOVER', + OPpCONST_SHORTCIRCUIT => 'SHORT', + OPpCONST_STRICT => 'STRICT', + OPpCOREARGS_DEREF1 => 'DEREF1', + OPpCOREARGS_DEREF2 => 'DEREF2', + OPpCOREARGS_PUSHMARK => 'MARK', + OPpCOREARGS_SCALARMOD => '$MOD', + OPpDEREF_AV => 'DREFAV', + OPpDEREF_HV => 'DREFHV', + OPpDEREF_SV => 'DREFSV', + OPpDONT_INIT_GV => 'NOINIT', + OPpEARLY_CV => 'EARLYCV', + OPpENTERSUB_AMPER => 'AMPER', + OPpENTERSUB_DB => 'DBG', + OPpENTERSUB_HASTARG => 'TARG', + OPpENTERSUB_INARGS => 'INARGS', + OPpENTERSUB_NOPAREN => 'NO()', + OPpEVAL_BYTES => 'BYTES', + OPpEVAL_COPHH => 'COPHH', + OPpEVAL_HAS_HH => 'HAS_HH', + OPpEVAL_RE_REPARSING => '-', + OPpEVAL_UNICODE => 'UNI', + OPpEXISTS_SUB => 'SUB', + OPpFLIP_LINENUM => 'LINENUM', + OPpFT_ACCESS => 'FTACCESS', + OPpFT_AFTER_t => 'FTAFTERt', + OPpFT_STACKED => 'FTSTACKED', + OPpFT_STACKING => 'FTSTACKING', + OPpGREP_LEX => 'GREPLEX', + OPpHINT_M_VMSISH_STATUS => 'VMSISH_STATUS', + OPpHINT_M_VMSISH_TIME => 'VMSISH_TIME', + OPpHINT_STRICT_REFS => '-', + OPpHUSH_VMSISH => 'HUSH', + OPpITER_DEF => '-', + OPpITER_REVERSED => 'REVERSED', + OPpLIST_GUESSED => 'GUESSED', + OPpLVALUE => 'LV', + OPpLVAL_DEFER => 'LVDEFER', + OPpLVAL_INTRO => 'LVINTRO', + OPpMAYBE_LVSUB => 'LVSUB', + OPpMAYBE_TRUEBOOL => 'BOOL?', + OPpMAY_RETURN_CONSTANT => 'CONST', + OPpOFFBYONE => '+1', + OPpOPEN_IN_CRLF => 'INCR', + OPpOPEN_IN_RAW => 'INBIN', + OPpOPEN_OUT_CRLF => 'OUTCR', + OPpOPEN_OUT_RAW => 'OUTBIN', + OPpOUR_INTRO => 'OURINTR', + OPpPAD_STATE => 'STATE', + OPpPV_IS_UTF8 => 'UTF', + OPpREFCOUNTED => 'REFC', + OPpREPEAT_DOLIST => 'DOLIST', + OPpREVERSE_INPLACE => 'INPLACE', + OPpRUNTIME => 'RTIME', + OPpSLICE => 'SLICE', + OPpSLICEWARNING => 'SLICEWARN', + OPpSORT_DESCEND => 'DESC', + OPpSORT_INPLACE => 'INPLACE', + OPpSORT_INTEGER => 'INT', + OPpSORT_NUMERIC => 'NUM', + OPpSORT_QSORT => 'QSORT', + OPpSORT_REVERSE => 'REV', + OPpSORT_STABLE => 'STABLE', + OPpSPLIT_IMPLIM => 'IMPLIM', + OPpSUBSTR_REPL_FIRST => 'REPL1ST', + OPpTARGET_MY => 'TARGMY', + OPpTRANS_COMPLEMENT => 'COMPL', + OPpTRANS_DELETE => 'DEL', + OPpTRANS_FROM_UTF => '<UTF', + OPpTRANS_GROWS => 'GROWS', + OPpTRANS_IDENTICAL => 'IDENT', + OPpTRANS_SQUASH => 'SQUASH', + OPpTRANS_TO_UTF => '>UTF', + OPpTRUEBOOL => 'BOOL', +); + +# ex: set ro: @@ -150,213 +150,22 @@ Deprecated. Use C<GIMME_V> instead. : G_SCALAR) \ : dowantarray()) -/* Lower bits of op_private often carry the number of arguments, as - * set by newBINOP, newUNOP and ck_fun */ -/* NOTE: OP_NEXTSTATE and OP_DBSTATE (i.e. COPs) carry NATIVE_HINTS - * in op_private */ +/* NOTE: OPp* flags are now auto-generated and defined in opcode.h, + * from data in regen/op_private */ -/* Private for lvalues */ -#define OPpLVAL_INTRO 128 /* Lvalue must be localized or lvalue sub */ -/* Private for OPs with TARGLEX */ - /* (lower bits may carry MAXARG) */ -#define OPpTARGET_MY 16 /* Target is PADMY. */ - -/* Private for OP_LEAVE, OP_LEAVESUB, OP_LEAVESUBLV and OP_LEAVEWRITE */ -#define OPpREFCOUNTED 64 /* op_targ carries a refcount */ - -/* Private for OP_LEAVE and OP_LEAVELOOP */ -#define OPpLVALUE 128 /* Do not copy return value */ - -/* Private for OP_AASSIGN */ -#define OPpASSIGN_COMMON 64 /* Left & right have syms in common. */ - -/* Private for OP_SASSIGN */ -#define OPpASSIGN_BACKWARDS 64 /* Left & right switched. */ -#define OPpASSIGN_CV_TO_GV 128 /* Possible optimisation for constants. */ - -/* Private for OP_MATCH and OP_SUBST{,CONT} */ -#define OPpRUNTIME 64 /* Pattern coming in on the stack */ - -/* Private for OP_TRANS */ -#define OPpTRANS_FROM_UTF 1 -#define OPpTRANS_TO_UTF 2 -#define OPpTRANS_IDENTICAL 4 /* right side is same as left */ -#define OPpTRANS_SQUASH 8 - /* 16 is used for OPpTARGET_MY */ -#define OPpTRANS_COMPLEMENT 32 -#define OPpTRANS_GROWS 64 -#define OPpTRANS_DELETE 128 #define OPpTRANS_ALL (OPpTRANS_FROM_UTF|OPpTRANS_TO_UTF|OPpTRANS_IDENTICAL|OPpTRANS_SQUASH|OPpTRANS_COMPLEMENT|OPpTRANS_GROWS|OPpTRANS_DELETE) -/* Private for OP_REPEAT */ -#define OPpREPEAT_DOLIST 64 /* List replication. */ - -/* Private for OP_RV2GV, OP_RV2SV, OP_AELEM, OP_HELEM, OP_PADSV */ -#define OPpDEREF (32|64) /* autovivify: Want ref to something: */ -#define OPpDEREF_AV 32 /* Want ref to AV. */ -#define OPpDEREF_HV 64 /* Want ref to HV. */ -#define OPpDEREF_SV (32|64) /* Want ref to SV. */ - -/* OP_ENTERSUB and OP_RV2CV flags - -Flags are set on entersub and rv2cv in three phases: - parser - the parser passes the flag to the op constructor - check - the check routine called by the op constructor sets the flag - context - application of scalar/ref/lvalue context applies the flag - -In the third stage, an entersub op might turn into an rv2cv op (undef &foo, -\&foo, lock &foo, exists &foo, defined &foo). The two places where that -happens (op_lvalue_flags and doref in op.c) need to make sure the flags do -not conflict. Flags applied in the context phase are only set when there -is no conversion of op type. - - bit entersub flag phase rv2cv flag phase - --- ------------- ----- ---------- ----- - 1 OPpENTERSUB_INARGS context - 2 HINT_STRICT_REFS check HINT_STRICT_REFS check - 4 OPpENTERSUB_HASTARG check - 8 OPpENTERSUB_AMPER parser - 16 OPpENTERSUB_DB check - 32 OPpDEREF_AV context - 64 OPpDEREF_HV context OPpMAY_RETURN_CONSTANT context - 128 OPpLVAL_INTRO context OPpENTERSUB_NOPAREN parser -*/ - /* OP_ENTERSUB only */ -#define OPpENTERSUB_DB 16 /* Debug subroutine. */ -#define OPpENTERSUB_HASTARG 4 /* Called from OP tree. */ -#define OPpENTERSUB_INARGS 1 /* Lval used as arg to a sub. */ -/* used by OPpDEREF (32|64) */ -/* used by HINT_STRICT_REFS 2 */ - /* Mask for OP_ENTERSUB flags, the absence of which must be propagated - in dynamic context */ +/* Mask for OP_ENTERSUB flags, the absence of which must be propagated + in dynamic context */ #define OPpENTERSUB_LVAL_MASK (OPpLVAL_INTRO|OPpENTERSUB_INARGS) - /* OP_RV2CV only */ -#define OPpENTERSUB_AMPER 8 /* Used & form to call. */ -#define OPpENTERSUB_NOPAREN 128 /* bare sub call (without parens) */ -#define OPpMAY_RETURN_CONSTANT 64 /* If a constant sub, return the constant */ - - /* OP_GV only */ -#define OPpEARLY_CV 32 /* foo() called before sub foo was parsed */ - /* OP_?ELEM only */ -#define OPpLVAL_DEFER 16 /* Defer creation of array/hash elem */ - /* OP_RV2[AH]V OP_[AH]SLICE */ -#define OPpSLICEWARNING 4 /* warn about @hash{$scalar} */ - /* OP_RV2[SAH]V, OP_GVSV, OP_ENTERITER only */ -#define OPpOUR_INTRO 16 /* Variable was in an our() */ - /* OP_RV2[AGH]V, OP_PAD[AH]V, OP_[AH]ELEM, OP_[AH]SLICE OP_AV2ARYLEN, - OP_R?KEYS, OP_SUBSTR, OP_POS, OP_VEC */ -#define OPpMAYBE_LVSUB 8 /* We might be an lvalue to return */ - /* OP_RV2HV and OP_PADHV */ -#define OPpTRUEBOOL 32 /* %hash in (%hash || $foo) in - void context */ -#define OPpMAYBE_TRUEBOOL 64 /* %hash in (%hash || $foo) where - cx is not known till run time */ - - /* OP_SUBSTR only */ -#define OPpSUBSTR_REPL_FIRST 16 /* 1st arg is replacement string */ - - /* OP_PADSV only */ -#define OPpPAD_STATE 16 /* is a "state" pad */ - /* for OP_RV2?V, lower bits carry hints (currently only HINT_STRICT_REFS) */ - - /* OP_PADRANGE only */ - /* bit 7 is OPpLVAL_INTRO */ -#define OPpPADRANGE_COUNTMASK 127 /* bits 6..0 hold target range, */ -#define OPpPADRANGE_COUNTSHIFT 7 /* 7 bits in total */ - - /* OP_RV2GV only */ -#define OPpDONT_INIT_GV 4 /* Call gv_fetchpv with GV_NOINIT */ -/* (Therefore will return whatever is currently in the symbol table, not - guaranteed to be a PVGV) */ -#define OPpALLOW_FAKE 16 /* OK to return fake glob */ - -/* Private for OP_ENTERITER and OP_ITER */ -#define OPpITER_REVERSED 4 /* for (reverse ...) */ -#define OPpITER_DEF 8 /* for $_ or for my $_ */ - -/* Private for OP_CONST */ -#define OPpCONST_NOVER 2 /* no 6; */ -#define OPpCONST_SHORTCIRCUIT 4 /* eg the constant 5 in (5 || foo) */ -#define OPpCONST_STRICT 8 /* bareword subject to strict 'subs' */ -#define OPpCONST_ENTERED 16 /* Has been entered as symbol. */ -#define OPpCONST_BARE 64 /* Was a bare word (filehandle?). */ - -/* Private for OP_FLIP/FLOP */ -#define OPpFLIP_LINENUM 64 /* Range arg potentially a line num. */ - -/* Private for OP_LIST */ -#define OPpLIST_GUESSED 64 /* Guessed that pushmark was needed. */ - -/* Private for OP_DELETE */ -#define OPpSLICE 64 /* Operating on a list of keys */ -/* Also OPpLVAL_INTRO (128) */ - -/* Private for OP_EXISTS */ -#define OPpEXISTS_SUB 64 /* Checking for &sub, not {} or []. */ - -/* Private for OP_SORT */ -#define OPpSORT_NUMERIC 1 /* Optimized away { $a <=> $b } */ -#define OPpSORT_INTEGER 2 /* Ditto while under "use integer" */ -#define OPpSORT_REVERSE 4 /* Reversed sort */ -#define OPpSORT_INPLACE 8 /* sort in-place; eg @a = sort @a */ -#define OPpSORT_DESCEND 16 /* Descending sort */ -#define OPpSORT_QSORT 32 /* Use quicksort (not mergesort) */ -#define OPpSORT_STABLE 64 /* Use a stable algorithm */ - -/* Private for OP_REVERSE */ -#define OPpREVERSE_INPLACE 8 /* reverse in-place (@a = reverse @a) */ - -/* Private for OP_OPEN and OP_BACKTICK */ -#define OPpOPEN_IN_RAW 16 /* binmode(F,":raw") on input fh */ -#define OPpOPEN_IN_CRLF 32 /* binmode(F,":crlf") on input fh */ -#define OPpOPEN_OUT_RAW 64 /* binmode(F,":raw") on output fh */ -#define OPpOPEN_OUT_CRLF 128 /* binmode(F,":crlf") on output fh */ - -/* Private for COPs */ -#define OPpHUSH_VMSISH 32 /* hush DCL exit msg vmsish mode*/ -/* Note: Used for NATIVE_HINTS (shifted from the values in PL_hints), - currently defined by vms/vmsish.h: - 64 - 128 - */ -/* Private for OP_FTXXX */ -#define OPpFT_ACCESS 2 /* use filetest 'access' */ -#define OPpFT_STACKED 4 /* stacked filetest, as "-f" in "-f -x $f" */ -#define OPpFT_STACKING 8 /* stacking filetest, as "-x" in "-f -x $f" */ -#define OPpFT_AFTER_t 16 /* previous op was -t */ - -/* Private for OP_(MAP|GREP)(WHILE|START) */ -#define OPpGREP_LEX 2 /* iterate over lexical $_ */ - -/* Private for OP_ENTEREVAL */ -#define OPpEVAL_HAS_HH 2 /* Does it have a copy of %^H */ -#define OPpEVAL_UNICODE 4 -#define OPpEVAL_BYTES 8 -#define OPpEVAL_COPHH 16 /* Construct %^H from cop hints */ -#define OPpEVAL_RE_REPARSING 32 /* eval_sv(..., G_RE_REPARSING) */ - -/* Private for OP_CALLER, OP_WANTARRAY and OP_RUNCV */ -#define OPpOFFBYONE 128 /* Treat caller(1) as caller(2) */ - -/* Private for OP_COREARGS */ -/* These must not conflict with OPpDONT_INIT_GV or OPpALLOW_FAKE. - See pp.c:S_rv2gv. */ -#define OPpCOREARGS_DEREF1 1 /* Arg 1 is a handle constructor */ -#define OPpCOREARGS_DEREF2 2 /* Arg 2 is a handle constructor */ -#define OPpCOREARGS_SCALARMOD 64 /* \$ rather than \[$@%*] */ -#define OPpCOREARGS_PUSHMARK 128 /* Call pp_pushmark */ - -/* Private for OP_(LAST|REDO|NEXT|GOTO|DUMP) */ -#define OPpPV_IS_UTF8 128 /* label is in UTF8 */ - -/* Private for OP_SPLIT */ -#define OPpSPLIT_IMPLIM 128 /* implicit limit */ + + struct op { BASEOP @@ -2110,4 +2110,1356 @@ EXTCONST U32 PL_opargs[] = { END_EXTERN_C + +#define OPpARG1_MASK 0x01 +#define OPpCOREARGS_DEREF1 0x01 +#define OPpENTERSUB_INARGS 0x01 +#define OPpSORT_NUMERIC 0x01 +#define OPpTRANS_FROM_UTF 0x01 +#define OPpCONST_NOVER 0x02 +#define OPpCOREARGS_DEREF2 0x02 +#define OPpEVAL_HAS_HH 0x02 +#define OPpFT_ACCESS 0x02 +#define OPpGREP_LEX 0x02 +#define OPpHINT_STRICT_REFS 0x02 +#define OPpSORT_INTEGER 0x02 +#define OPpTRANS_TO_UTF 0x02 +#define OPpARG2_MASK 0x03 +#define OPpCONST_SHORTCIRCUIT 0x04 +#define OPpDONT_INIT_GV 0x04 +#define OPpENTERSUB_HASTARG 0x04 +#define OPpEVAL_UNICODE 0x04 +#define OPpFT_STACKED 0x04 +#define OPpITER_REVERSED 0x04 +#define OPpSLICEWARNING 0x04 +#define OPpSORT_REVERSE 0x04 +#define OPpTRANS_IDENTICAL 0x04 +#define OPpARG3_MASK 0x07 +#define OPpPADRANGE_COUNTSHIFT 0x07 +#define OPpCONST_STRICT 0x08 +#define OPpENTERSUB_AMPER 0x08 +#define OPpEVAL_BYTES 0x08 +#define OPpFT_STACKING 0x08 +#define OPpITER_DEF 0x08 +#define OPpMAYBE_LVSUB 0x08 +#define OPpREVERSE_INPLACE 0x08 +#define OPpSORT_INPLACE 0x08 +#define OPpTRANS_SQUASH 0x08 +#define OPpARG4_MASK 0x0f +#define OPpALLOW_FAKE 0x10 +#define OPpCONST_ENTERED 0x10 +#define OPpENTERSUB_DB 0x10 +#define OPpEVAL_COPHH 0x10 +#define OPpFT_AFTER_t 0x10 +#define OPpLVAL_DEFER 0x10 +#define OPpOPEN_IN_RAW 0x10 +#define OPpOUR_INTRO 0x10 +#define OPpPAD_STATE 0x10 +#define OPpSORT_DESCEND 0x10 +#define OPpSUBSTR_REPL_FIRST 0x10 +#define OPpTARGET_MY 0x10 +#define OPpDEREF_AV 0x20 +#define OPpEARLY_CV 0x20 +#define OPpEVAL_RE_REPARSING 0x20 +#define OPpHUSH_VMSISH 0x20 +#define OPpOPEN_IN_CRLF 0x20 +#define OPpSORT_QSORT 0x20 +#define OPpTRANS_COMPLEMENT 0x20 +#define OPpTRUEBOOL 0x20 +#define OPpASSIGN_BACKWARDS 0x40 +#define OPpASSIGN_COMMON 0x40 +#define OPpCONST_BARE 0x40 +#define OPpCOREARGS_SCALARMOD 0x40 +#define OPpDEREF_HV 0x40 +#define OPpEXISTS_SUB 0x40 +#define OPpFLIP_LINENUM 0x40 +#define OPpHINT_M_VMSISH_STATUS 0x40 +#define OPpLIST_GUESSED 0x40 +#define OPpMAYBE_TRUEBOOL 0x40 +#define OPpMAY_RETURN_CONSTANT 0x40 +#define OPpOPEN_OUT_RAW 0x40 +#define OPpREFCOUNTED 0x40 +#define OPpREPEAT_DOLIST 0x40 +#define OPpRUNTIME 0x40 +#define OPpSLICE 0x40 +#define OPpSORT_STABLE 0x40 +#define OPpTRANS_GROWS 0x40 +#define OPpDEREF 0x60 +#define OPpDEREF_SV 0x60 +#define OPpPADRANGE_COUNTMASK 0x7f +#define OPpASSIGN_CV_TO_GV 0x80 +#define OPpCOREARGS_PUSHMARK 0x80 +#define OPpENTERSUB_NOPAREN 0x80 +#define OPpHINT_M_VMSISH_TIME 0x80 +#define OPpLVALUE 0x80 +#define OPpLVAL_INTRO 0x80 +#define OPpOFFBYONE 0x80 +#define OPpOPEN_OUT_CRLF 0x80 +#define OPpPV_IS_UTF8 0x80 +#define OPpSPLIT_IMPLIM 0x80 +#define OPpTRANS_DELETE 0x80 +START_EXTERN_C + +#ifndef PERL_GLOBAL_STRUCT_INIT + +# ifndef DOINIT + +/* data about the flags in op_private */ + +EXTCONST I16 PL_op_private_bitdef_ix[]; +EXTCONST U16 PL_op_private_bitdefs[]; +EXTCONST char PL_op_private_labels[]; +EXTCONST I16 PL_op_private_bitfields[]; +EXTCONST U8 PL_op_private_valid[]; + +# else + + +/* PL_op_private_labels[]: the short descriptions of private flags. + * All labels are concatenated into a single char array + * (separated by \0's) for compactness. + */ + +EXTCONST char PL_op_private_labels[] = { + '$','M','O','D','\0', + '+','1','\0', + '-','\0', + '<','U','T','F','\0', + '>','U','T','F','\0', + 'A','M','P','E','R','\0', + 'B','A','R','E','\0', + 'B','K','W','A','R','D','\0', + 'B','O','O','L','\0', + 'B','O','O','L','?','\0', + 'B','Y','T','E','S','\0', + 'C','O','M','M','O','N','\0', + 'C','O','M','P','L','\0', + 'C','O','N','S','T','\0', + 'C','O','P','H','H','\0', + 'C','V','2','G','V','\0', + 'D','B','G','\0', + 'D','E','L','\0', + 'D','E','R','E','F','1','\0', + 'D','E','R','E','F','2','\0', + 'D','E','S','C','\0', + 'D','O','L','I','S','T','\0', + 'D','R','E','F','A','V','\0', + 'D','R','E','F','H','V','\0', + 'D','R','E','F','S','V','\0', + 'E','A','R','L','Y','C','V','\0', + 'E','N','T','E','R','E','D','\0', + 'F','A','K','E','\0', + 'F','T','A','C','C','E','S','S','\0', + 'F','T','A','F','T','E','R','t','\0', + 'F','T','S','T','A','C','K','E','D','\0', + 'F','T','S','T','A','C','K','I','N','G','\0', + 'G','R','E','P','L','E','X','\0', + 'G','R','O','W','S','\0', + 'G','U','E','S','S','E','D','\0', + 'H','A','S','_','H','H','\0', + 'H','U','S','H','\0', + 'I','D','E','N','T','\0', + 'I','M','P','L','I','M','\0', + 'I','N','A','R','G','S','\0', + 'I','N','B','I','N','\0', + 'I','N','C','R','\0', + 'I','N','P','L','A','C','E','\0', + 'I','N','T','\0', + 'L','I','N','E','N','U','M','\0', + 'L','V','\0', + 'L','V','D','E','F','E','R','\0', + 'L','V','I','N','T','R','O','\0', + 'L','V','S','U','B','\0', + 'M','A','R','K','\0', + 'N','O','(',')','\0', + 'N','O','I','N','I','T','\0', + 'N','O','V','E','R','\0', + 'N','U','M','\0', + 'O','U','R','I','N','T','R','\0', + 'O','U','T','B','I','N','\0', + 'O','U','T','C','R','\0', + 'Q','S','O','R','T','\0', + 'R','E','F','C','\0', + 'R','E','P','L','1','S','T','\0', + 'R','E','V','\0', + 'R','E','V','E','R','S','E','D','\0', + 'R','T','I','M','E','\0', + 'S','H','O','R','T','\0', + 'S','L','I','C','E','\0', + 'S','L','I','C','E','W','A','R','N','\0', + 'S','Q','U','A','S','H','\0', + 'S','T','A','B','L','E','\0', + 'S','T','A','T','E','\0', + 'S','T','R','I','C','T','\0', + 'S','U','B','\0', + 'T','A','R','G','\0', + 'T','A','R','G','M','Y','\0', + 'U','N','I','\0', + 'U','T','F','\0', + 'V','M','S','I','S','H','_','S','T','A','T','U','S','\0', + 'V','M','S','I','S','H','_','T','I','M','E','\0', + +}; + + + +/* PL_op_private_bitfields[]: details about each bit field type. + * Each defintition consists of the following list of words: + * bitmin + * label (index into PL_op_private_labels[]; -1 if no label) + * repeat for each enum entry (if any): + * enum value + * enum label (index into PL_op_private_labels[]) + * -1 + */ + +EXTCONST I16 PL_op_private_bitfields[] = { + 0, 8, -1, + 0, 8, -1, + 0, 8, -1, + 0, 8, -1, + 0, 8, -1, + 0, 8, -1, + 5, -1, 1, 120, 2, 127, 3, 134, -1, + +}; + + +/* PL_op_private_bitdef_ix[]: map an op number to a starting position + * in PL_op_private_bitdefs. If -1, the op has no bits defined */ + +EXTCONST I16 PL_op_private_bitdef_ix[] = { + -1, /* null */ + -1, /* stub */ + 0, /* scalar */ + 1, /* pushmark */ + 3, /* wantarray */ + 4, /* const */ + 9, /* gvsv */ + 11, /* gv */ + 12, /* gelem */ + 13, /* padsv */ + 16, /* padav */ + 20, /* padhv */ + -1, /* padany */ + 26, /* pushre */ + 27, /* rv2gv */ + 34, /* rv2sv */ + 39, /* av2arylen */ + 41, /* rv2cv */ + -1, /* anoncode */ + 48, /* prototype */ + 49, /* refgen */ + 50, /* srefgen */ + 51, /* ref */ + 52, /* bless */ + 53, /* backtick */ + 58, /* glob */ + 59, /* readline */ + -1, /* rcatline */ + 60, /* regcmaybe */ + 61, /* regcreset */ + 62, /* regcomp */ + 63, /* match */ + 65, /* qr */ + 66, /* subst */ + 68, /* substcont */ + 70, /* trans */ + 78, /* transr */ + 86, /* sassign */ + 89, /* aassign */ + 92, /* chop */ + 93, /* schop */ + 94, /* chomp */ + 96, /* schomp */ + 98, /* defined */ + 99, /* undef */ + 100, /* study */ + 101, /* pos */ + 104, /* preinc */ + 105, /* i_preinc */ + 106, /* predec */ + 107, /* i_predec */ + 108, /* postinc */ + 109, /* i_postinc */ + 111, /* postdec */ + 112, /* i_postdec */ + 114, /* pow */ + 116, /* multiply */ + 118, /* i_multiply */ + 120, /* divide */ + 122, /* i_divide */ + 124, /* modulo */ + 126, /* i_modulo */ + 128, /* repeat */ + 130, /* add */ + 132, /* i_add */ + 134, /* subtract */ + 136, /* i_subtract */ + 138, /* concat */ + 140, /* stringify */ + 142, /* left_shift */ + 144, /* right_shift */ + 146, /* lt */ + 147, /* i_lt */ + 148, /* gt */ + 149, /* i_gt */ + 150, /* le */ + 151, /* i_le */ + 152, /* ge */ + 153, /* i_ge */ + 154, /* eq */ + 155, /* i_eq */ + 156, /* ne */ + 157, /* i_ne */ + 158, /* ncmp */ + 159, /* i_ncmp */ + 160, /* slt */ + 161, /* sgt */ + 162, /* sle */ + 163, /* sge */ + 164, /* seq */ + 165, /* sne */ + 166, /* scmp */ + 167, /* bit_and */ + 168, /* bit_xor */ + 169, /* bit_or */ + 170, /* negate */ + 171, /* i_negate */ + 173, /* not */ + 174, /* complement */ + 175, /* smartmatch */ + 176, /* atan2 */ + 178, /* sin */ + 180, /* cos */ + 182, /* rand */ + 184, /* srand */ + 186, /* exp */ + 188, /* log */ + 190, /* sqrt */ + 192, /* int */ + 194, /* hex */ + 196, /* oct */ + 198, /* abs */ + 200, /* length */ + 202, /* substr */ + 206, /* vec */ + 209, /* index */ + 211, /* rindex */ + 213, /* sprintf */ + 214, /* formline */ + 215, /* ord */ + 217, /* chr */ + 219, /* crypt */ + 221, /* ucfirst */ + 222, /* lcfirst */ + 223, /* uc */ + 224, /* lc */ + 225, /* quotemeta */ + 226, /* rv2av */ + 232, /* aelemfast */ + 233, /* aelemfast_lex */ + 234, /* aelem */ + 239, /* aslice */ + 242, /* kvaslice */ + 243, /* aeach */ + 244, /* akeys */ + 245, /* avalues */ + 246, /* each */ + 247, /* values */ + 248, /* keys */ + 250, /* delete */ + 253, /* exists */ + 255, /* rv2hv */ + 263, /* helem */ + 268, /* hslice */ + 271, /* kvhslice */ + 272, /* unpack */ + 273, /* pack */ + 274, /* split */ + 275, /* join */ + 276, /* list */ + 278, /* lslice */ + 279, /* anonlist */ + 280, /* anonhash */ + 281, /* splice */ + 282, /* push */ + 284, /* pop */ + 285, /* shift */ + 286, /* unshift */ + 288, /* sort */ + 295, /* reverse */ + 297, /* grepstart */ + 298, /* grepwhile */ + 300, /* mapstart */ + 301, /* mapwhile */ + 303, /* range */ + 304, /* flip */ + 306, /* flop */ + 308, /* and */ + 309, /* or */ + 310, /* xor */ + 311, /* dor */ + 312, /* cond_expr */ + 314, /* andassign */ + 315, /* orassign */ + 316, /* dorassign */ + 317, /* method */ + 318, /* entersub */ + 325, /* leavesub */ + 327, /* leavesublv */ + 329, /* caller */ + 331, /* warn */ + 332, /* die */ + 333, /* reset */ + -1, /* lineseq */ + 334, /* nextstate */ + 337, /* dbstate */ + -1, /* unstack */ + -1, /* enter */ + 340, /* leave */ + -1, /* scope */ + 342, /* enteriter */ + 346, /* iter */ + -1, /* enterloop */ + 347, /* leaveloop */ + -1, /* return */ + 349, /* last */ + 351, /* next */ + 353, /* redo */ + 355, /* dump */ + 357, /* goto */ + 359, /* exit */ + -1, /* method_named */ + 360, /* entergiven */ + 361, /* leavegiven */ + 362, /* enterwhen */ + 363, /* leavewhen */ + -1, /* break */ + -1, /* continue */ + 364, /* open */ + 369, /* close */ + 370, /* pipe_op */ + 371, /* fileno */ + 372, /* umask */ + 373, /* binmode */ + 374, /* tie */ + 375, /* untie */ + 376, /* tied */ + 377, /* dbmopen */ + 378, /* dbmclose */ + 379, /* sselect */ + 380, /* select */ + 381, /* getc */ + 382, /* read */ + 383, /* enterwrite */ + 384, /* leavewrite */ + -1, /* prtf */ + -1, /* print */ + -1, /* say */ + 386, /* sysopen */ + 387, /* sysseek */ + 388, /* sysread */ + 389, /* syswrite */ + 390, /* eof */ + 391, /* tell */ + 392, /* seek */ + 393, /* truncate */ + 394, /* fcntl */ + 395, /* ioctl */ + 396, /* flock */ + 398, /* send */ + 399, /* recv */ + 400, /* socket */ + 401, /* sockpair */ + 402, /* bind */ + 403, /* connect */ + 404, /* listen */ + 405, /* accept */ + 406, /* shutdown */ + 407, /* gsockopt */ + 408, /* ssockopt */ + 409, /* getsockname */ + 410, /* getpeername */ + 411, /* lstat */ + 412, /* stat */ + 413, /* ftrread */ + 418, /* ftrwrite */ + 423, /* ftrexec */ + 428, /* fteread */ + 433, /* ftewrite */ + 438, /* fteexec */ + 443, /* ftis */ + 447, /* ftsize */ + 451, /* ftmtime */ + 455, /* ftatime */ + 459, /* ftctime */ + 463, /* ftrowned */ + 467, /* fteowned */ + 471, /* ftzero */ + 475, /* ftsock */ + 479, /* ftchr */ + 483, /* ftblk */ + 487, /* ftfile */ + 491, /* ftdir */ + 495, /* ftpipe */ + 499, /* ftsuid */ + 503, /* ftsgid */ + 507, /* ftsvtx */ + 511, /* ftlink */ + 515, /* fttty */ + 519, /* fttext */ + 523, /* ftbinary */ + 527, /* chdir */ + 529, /* chown */ + 531, /* chroot */ + 533, /* unlink */ + 535, /* chmod */ + 537, /* utime */ + 539, /* rename */ + 541, /* link */ + 543, /* symlink */ + 545, /* readlink */ + 546, /* mkdir */ + 548, /* rmdir */ + 550, /* open_dir */ + 551, /* readdir */ + 552, /* telldir */ + 553, /* seekdir */ + 554, /* rewinddir */ + 555, /* closedir */ + -1, /* fork */ + 556, /* wait */ + 557, /* waitpid */ + 559, /* system */ + 561, /* exec */ + 563, /* kill */ + 565, /* getppid */ + 566, /* getpgrp */ + 568, /* setpgrp */ + 570, /* getpriority */ + 572, /* setpriority */ + 574, /* time */ + -1, /* tms */ + 575, /* localtime */ + 576, /* gmtime */ + 577, /* alarm */ + 578, /* sleep */ + 580, /* shmget */ + 581, /* shmctl */ + 582, /* shmread */ + 583, /* shmwrite */ + 584, /* msgget */ + 585, /* msgctl */ + 586, /* msgsnd */ + 587, /* msgrcv */ + 588, /* semop */ + 589, /* semget */ + 590, /* semctl */ + 591, /* require */ + 592, /* dofile */ + -1, /* hintseval */ + 593, /* entereval */ + 599, /* leaveeval */ + 601, /* entertry */ + -1, /* leavetry */ + 602, /* ghbyname */ + 603, /* ghbyaddr */ + -1, /* ghostent */ + 604, /* gnbyname */ + 605, /* gnbyaddr */ + -1, /* gnetent */ + 606, /* gpbyname */ + 607, /* gpbynumber */ + -1, /* gprotoent */ + 608, /* gsbyname */ + 609, /* gsbyport */ + -1, /* gservent */ + 610, /* shostent */ + 611, /* snetent */ + 612, /* sprotoent */ + 613, /* sservent */ + -1, /* ehostent */ + -1, /* enetent */ + -1, /* eprotoent */ + -1, /* eservent */ + 614, /* gpwnam */ + 615, /* gpwuid */ + -1, /* gpwent */ + -1, /* spwent */ + -1, /* epwent */ + 616, /* ggrnam */ + 617, /* ggrgid */ + -1, /* ggrent */ + -1, /* sgrent */ + -1, /* egrent */ + -1, /* getlogin */ + 618, /* syscall */ + 619, /* lock */ + 620, /* once */ + -1, /* custom */ + 621, /* reach */ + 622, /* rkeys */ + 624, /* rvalues */ + 625, /* coreargs */ + 629, /* runcv */ + 630, /* fc */ + -1, /* padcv */ + -1, /* introcv */ + -1, /* clonecv */ + 631, /* padrange */ + +}; + + + +/* PL_op_private_bitdefs[]: given a starting position in this array (as + * supplied by PL_op_private_bitdef_ix[]), each word (until a stop bit is + * seen) defines the meaning of a particular op_private bit for a + * particular op. Each word consists of: + * bit 0: stop bit: this is the last bit def for the current op + * bit 1: bitfield: if set, this defines a bit field rather than a flag + * bits 2..4: unsigned number in the range 0..7 which is the bit number + * bits 5..15: unsigned number in the range 0..2047 which is an index + * into PL_op_private_labels[] (for a flag), or + * into PL_op_private_bitfields[] (for a bit field) + */ + +EXTCONST U16 PL_op_private_bitdefs[] = { + /* scalar */ 0x0003, + /* pushmark */ 0x253c, 0x3631, + /* wantarray */ 0x00bd, + /* const */ 0x0358, 0x12b0, 0x36ec, 0x31a8, 0x2905, + /* gvsv */ 0x253c, 0x2a51, + /* gv */ 0x11b5, + /* gelem */ 0x0067, + /* padsv */ 0x253c, 0x025a, 0x3631, + /* padav */ 0x253c, 0x3630, 0x262c, 0x3329, + /* padhv */ 0x253c, 0x0578, 0x04d4, 0x3630, 0x262c, 0x3329, + /* pushre */ 0x30f9, + /* rv2gv */ 0x253c, 0x025a, 0x13b0, 0x262c, 0x2828, 0x0104, 0x0003, + /* rv2sv */ 0x253c, 0x025a, 0x2a50, 0x0104, 0x0003, + /* av2arylen */ 0x262c, 0x0003, + /* rv2cv */ 0x279c, 0x0898, 0x0ad0, 0x028c, 0x3848, 0x0104, 0x0003, + /* prototype */ 0x0003, + /* refgen */ 0x0003, + /* srefgen */ 0x0003, + /* ref */ 0x0003, + /* bless */ 0x012f, + /* backtick */ 0x2c3c, 0x2b58, 0x20b4, 0x1ff0, 0x0003, + /* glob */ 0x012f, + /* readline */ 0x0003, + /* regcmaybe */ 0x0003, + /* regcreset */ 0x0003, + /* regcomp */ 0x0003, + /* match */ 0x30f8, 0x38f1, + /* qr */ 0x30f9, + /* subst */ 0x30f8, 0x38f1, + /* substcont */ 0x30f8, 0x0003, + /* trans */ 0x0b5c, 0x1a38, 0x07d4, 0x38f0, 0x346c, 0x1d68, 0x01e4, 0x0141, + /* transr */ 0x0b5c, 0x1a38, 0x07d4, 0x38f0, 0x346c, 0x1d68, 0x01e4, 0x0141, + /* sassign */ 0x0a1c, 0x03f8, 0x0067, + /* aassign */ 0x06f8, 0x262c, 0x0067, + /* chop */ 0x0003, + /* schop */ 0x0003, + /* chomp */ 0x38f0, 0x0003, + /* schomp */ 0x38f0, 0x0003, + /* defined */ 0x0003, + /* undef */ 0x0003, + /* study */ 0x0003, + /* pos */ 0x253c, 0x262c, 0x0003, + /* preinc */ 0x0003, + /* i_preinc */ 0x0003, + /* predec */ 0x0003, + /* i_predec */ 0x0003, + /* postinc */ 0x0003, + /* i_postinc */ 0x38f0, 0x0003, + /* postdec */ 0x0003, + /* i_postdec */ 0x38f0, 0x0003, + /* pow */ 0x38f0, 0x0067, + /* multiply */ 0x38f0, 0x0067, + /* i_multiply */ 0x38f0, 0x0067, + /* divide */ 0x38f0, 0x0067, + /* i_divide */ 0x38f0, 0x0067, + /* modulo */ 0x38f0, 0x0067, + /* i_modulo */ 0x38f0, 0x0067, + /* repeat */ 0x0e38, 0x0067, + /* add */ 0x38f0, 0x0067, + /* i_add */ 0x38f0, 0x0067, + /* subtract */ 0x38f0, 0x0067, + /* i_subtract */ 0x38f0, 0x0067, + /* concat */ 0x38f0, 0x0067, + /* stringify */ 0x38f0, 0x012f, + /* left_shift */ 0x38f0, 0x0067, + /* right_shift */ 0x38f0, 0x0067, + /* lt */ 0x0067, + /* i_lt */ 0x0067, + /* gt */ 0x0067, + /* i_gt */ 0x0067, + /* le */ 0x0067, + /* i_le */ 0x0067, + /* ge */ 0x0067, + /* i_ge */ 0x0067, + /* eq */ 0x0067, + /* i_eq */ 0x0067, + /* ne */ 0x0067, + /* i_ne */ 0x0067, + /* ncmp */ 0x0067, + /* i_ncmp */ 0x0067, + /* slt */ 0x0067, + /* sgt */ 0x0067, + /* sle */ 0x0067, + /* sge */ 0x0067, + /* seq */ 0x0067, + /* sne */ 0x0067, + /* scmp */ 0x0067, + /* bit_and */ 0x0067, + /* bit_xor */ 0x0067, + /* bit_or */ 0x0067, + /* negate */ 0x0003, + /* i_negate */ 0x38f0, 0x0003, + /* not */ 0x0003, + /* complement */ 0x0003, + /* smartmatch */ 0x0067, + /* atan2 */ 0x38f0, 0x012f, + /* sin */ 0x38f0, 0x0003, + /* cos */ 0x38f0, 0x0003, + /* rand */ 0x38f0, 0x012f, + /* srand */ 0x38f0, 0x012f, + /* exp */ 0x38f0, 0x0003, + /* log */ 0x38f0, 0x0003, + /* sqrt */ 0x38f0, 0x0003, + /* int */ 0x38f0, 0x0003, + /* hex */ 0x38f0, 0x0003, + /* oct */ 0x38f0, 0x0003, + /* abs */ 0x38f0, 0x0003, + /* length */ 0x38f0, 0x0003, + /* substr */ 0x253c, 0x2e50, 0x262c, 0x00cb, + /* vec */ 0x253c, 0x262c, 0x0067, + /* index */ 0x38f0, 0x012f, + /* rindex */ 0x38f0, 0x012f, + /* sprintf */ 0x012f, + /* formline */ 0x012f, + /* ord */ 0x38f0, 0x0003, + /* chr */ 0x38f0, 0x0003, + /* crypt */ 0x38f0, 0x012f, + /* ucfirst */ 0x0003, + /* lcfirst */ 0x0003, + /* uc */ 0x0003, + /* lc */ 0x0003, + /* quotemeta */ 0x0003, + /* rv2av */ 0x253c, 0x2a50, 0x262c, 0x3328, 0x0104, 0x0003, + /* aelemfast */ 0x01ff, + /* aelemfast_lex */ 0x01ff, + /* aelem */ 0x253c, 0x025a, 0x2430, 0x262c, 0x0067, + /* aslice */ 0x253c, 0x262c, 0x3329, + /* kvaslice */ 0x262d, + /* aeach */ 0x0003, + /* akeys */ 0x0003, + /* avalues */ 0x0003, + /* each */ 0x0003, + /* values */ 0x0003, + /* keys */ 0x262c, 0x0003, + /* delete */ 0x253c, 0x3278, 0x0003, + /* exists */ 0x37d8, 0x0003, + /* rv2hv */ 0x253c, 0x0578, 0x04d4, 0x2a50, 0x262c, 0x3328, 0x0104, 0x0003, + /* helem */ 0x253c, 0x025a, 0x2430, 0x262c, 0x0067, + /* hslice */ 0x253c, 0x262c, 0x3329, + /* kvhslice */ 0x262d, + /* unpack */ 0x012f, + /* pack */ 0x012f, + /* split */ 0x1e3d, + /* join */ 0x012f, + /* list */ 0x253c, 0x1af9, + /* lslice */ 0x0067, + /* anonlist */ 0x012f, + /* anonhash */ 0x012f, + /* splice */ 0x012f, + /* push */ 0x38f0, 0x012f, + /* pop */ 0x0003, + /* shift */ 0x0003, + /* unshift */ 0x38f0, 0x012f, + /* sort */ 0x3558, 0x2cf4, 0x0d90, 0x214c, 0x2f48, 0x2244, 0x29c1, + /* reverse */ 0x214c, 0x0003, + /* grepstart */ 0x1925, + /* grepwhile */ 0x1924, 0x0003, + /* mapstart */ 0x1925, + /* mapwhile */ 0x1924, 0x0003, + /* range */ 0x0003, + /* flip */ 0x22d8, 0x0003, + /* flop */ 0x22d8, 0x0003, + /* and */ 0x0003, + /* or */ 0x0003, + /* xor */ 0x0067, + /* dor */ 0x0003, + /* cond_expr */ 0x253c, 0x0003, + /* andassign */ 0x0003, + /* orassign */ 0x0003, + /* dorassign */ 0x0003, + /* method */ 0x0003, + /* entersub */ 0x253c, 0x025a, 0x0ad0, 0x028c, 0x3848, 0x0104, 0x1f01, + /* leavesub */ 0x2db8, 0x0003, + /* leavesublv */ 0x2db8, 0x0003, + /* caller */ 0x00bc, 0x012f, + /* warn */ 0x012f, + /* die */ 0x012f, + /* reset */ 0x012f, + /* nextstate */ 0x3c9c, 0x3ad8, 0x1cd5, + /* dbstate */ 0x3c9c, 0x3ad8, 0x1cd5, + /* leave */ 0x23dc, 0x2db9, + /* enteriter */ 0x253c, 0x2a50, 0x010c, 0x2fc9, + /* iter */ 0x2fc9, + /* leaveloop */ 0x23dc, 0x0067, + /* last */ 0x3a5c, 0x0003, + /* next */ 0x3a5c, 0x0003, + /* redo */ 0x3a5c, 0x0003, + /* dump */ 0x3a5c, 0x0003, + /* goto */ 0x3a5c, 0x0003, + /* exit */ 0x012f, + /* entergiven */ 0x0003, + /* leavegiven */ 0x0003, + /* enterwhen */ 0x0003, + /* leavewhen */ 0x0003, + /* open */ 0x2c3c, 0x2b58, 0x20b4, 0x1ff0, 0x012f, + /* close */ 0x012f, + /* pipe_op */ 0x012f, + /* fileno */ 0x012f, + /* umask */ 0x012f, + /* binmode */ 0x012f, + /* tie */ 0x012f, + /* untie */ 0x0003, + /* tied */ 0x0003, + /* dbmopen */ 0x012f, + /* dbmclose */ 0x0003, + /* sselect */ 0x012f, + /* select */ 0x012f, + /* getc */ 0x012f, + /* read */ 0x012f, + /* enterwrite */ 0x012f, + /* leavewrite */ 0x2db8, 0x0003, + /* sysopen */ 0x012f, + /* sysseek */ 0x012f, + /* sysread */ 0x012f, + /* syswrite */ 0x012f, + /* eof */ 0x012f, + /* tell */ 0x012f, + /* seek */ 0x012f, + /* truncate */ 0x012f, + /* fcntl */ 0x012f, + /* ioctl */ 0x012f, + /* flock */ 0x38f0, 0x012f, + /* send */ 0x012f, + /* recv */ 0x012f, + /* socket */ 0x012f, + /* sockpair */ 0x012f, + /* bind */ 0x012f, + /* connect */ 0x012f, + /* listen */ 0x012f, + /* accept */ 0x012f, + /* shutdown */ 0x012f, + /* gsockopt */ 0x012f, + /* ssockopt */ 0x012f, + /* getsockname */ 0x0003, + /* getpeername */ 0x0003, + /* lstat */ 0x0003, + /* stat */ 0x0003, + /* ftrread */ 0x1570, 0x17cc, 0x1688, 0x1444, 0x0003, + /* ftrwrite */ 0x1570, 0x17cc, 0x1688, 0x1444, 0x0003, + /* ftrexec */ 0x1570, 0x17cc, 0x1688, 0x1444, 0x0003, + /* fteread */ 0x1570, 0x17cc, 0x1688, 0x1444, 0x0003, + /* ftewrite */ 0x1570, 0x17cc, 0x1688, 0x1444, 0x0003, + /* fteexec */ 0x1570, 0x17cc, 0x1688, 0x1444, 0x0003, + /* ftis */ 0x1570, 0x17cc, 0x1688, 0x0003, + /* ftsize */ 0x1570, 0x17cc, 0x1688, 0x0003, + /* ftmtime */ 0x1570, 0x17cc, 0x1688, 0x0003, + /* ftatime */ 0x1570, 0x17cc, 0x1688, 0x0003, + /* ftctime */ 0x1570, 0x17cc, 0x1688, 0x0003, + /* ftrowned */ 0x1570, 0x17cc, 0x1688, 0x0003, + /* fteowned */ 0x1570, 0x17cc, 0x1688, 0x0003, + /* ftzero */ 0x1570, 0x17cc, 0x1688, 0x0003, + /* ftsock */ 0x1570, 0x17cc, 0x1688, 0x0003, + /* ftchr */ 0x1570, 0x17cc, 0x1688, 0x0003, + /* ftblk */ 0x1570, 0x17cc, 0x1688, 0x0003, + /* ftfile */ 0x1570, 0x17cc, 0x1688, 0x0003, + /* ftdir */ 0x1570, 0x17cc, 0x1688, 0x0003, + /* ftpipe */ 0x1570, 0x17cc, 0x1688, 0x0003, + /* ftsuid */ 0x1570, 0x17cc, 0x1688, 0x0003, + /* ftsgid */ 0x1570, 0x17cc, 0x1688, 0x0003, + /* ftsvtx */ 0x1570, 0x17cc, 0x1688, 0x0003, + /* ftlink */ 0x1570, 0x17cc, 0x1688, 0x0003, + /* fttty */ 0x1570, 0x17cc, 0x1688, 0x0003, + /* fttext */ 0x1570, 0x17cc, 0x1688, 0x0003, + /* ftbinary */ 0x1570, 0x17cc, 0x1688, 0x0003, + /* chdir */ 0x38f0, 0x012f, + /* chown */ 0x38f0, 0x012f, + /* chroot */ 0x38f0, 0x0003, + /* unlink */ 0x38f0, 0x012f, + /* chmod */ 0x38f0, 0x012f, + /* utime */ 0x38f0, 0x012f, + /* rename */ 0x38f0, 0x012f, + /* link */ 0x38f0, 0x012f, + /* symlink */ 0x38f0, 0x012f, + /* readlink */ 0x0003, + /* mkdir */ 0x38f0, 0x012f, + /* rmdir */ 0x38f0, 0x0003, + /* open_dir */ 0x012f, + /* readdir */ 0x0003, + /* telldir */ 0x0003, + /* seekdir */ 0x012f, + /* rewinddir */ 0x0003, + /* closedir */ 0x0003, + /* wait */ 0x38f1, + /* waitpid */ 0x38f0, 0x012f, + /* system */ 0x38f0, 0x012f, + /* exec */ 0x38f0, 0x012f, + /* kill */ 0x38f0, 0x012f, + /* getppid */ 0x38f1, + /* getpgrp */ 0x38f0, 0x012f, + /* setpgrp */ 0x38f0, 0x012f, + /* getpriority */ 0x38f0, 0x012f, + /* setpriority */ 0x38f0, 0x012f, + /* time */ 0x38f1, + /* localtime */ 0x0003, + /* gmtime */ 0x012f, + /* alarm */ 0x0003, + /* sleep */ 0x38f0, 0x012f, + /* shmget */ 0x012f, + /* shmctl */ 0x012f, + /* shmread */ 0x012f, + /* shmwrite */ 0x012f, + /* msgget */ 0x012f, + /* msgctl */ 0x012f, + /* msgsnd */ 0x012f, + /* msgrcv */ 0x012f, + /* semop */ 0x012f, + /* semget */ 0x012f, + /* semctl */ 0x012f, + /* require */ 0x0003, + /* dofile */ 0x0003, + /* entereval */ 0x0114, 0x0950, 0x062c, 0x39c8, 0x1be4, 0x0003, + /* leaveeval */ 0x2db8, 0x0003, + /* entertry */ 0x0003, + /* ghbyname */ 0x0003, + /* ghbyaddr */ 0x012f, + /* gnbyname */ 0x0003, + /* gnbyaddr */ 0x012f, + /* gpbyname */ 0x0003, + /* gpbynumber */ 0x012f, + /* gsbyname */ 0x012f, + /* gsbyport */ 0x012f, + /* shostent */ 0x0003, + /* snetent */ 0x0003, + /* sprotoent */ 0x0003, + /* sservent */ 0x0003, + /* gpwnam */ 0x0003, + /* gpwuid */ 0x0003, + /* ggrnam */ 0x0003, + /* ggrgid */ 0x0003, + /* syscall */ 0x012f, + /* lock */ 0x0003, + /* once */ 0x0003, + /* reach */ 0x0003, + /* rkeys */ 0x262c, 0x0003, + /* rvalues */ 0x0003, + /* coreargs */ 0x26fc, 0x0018, 0x0ca4, 0x0bc1, + /* runcv */ 0x00bd, + /* fc */ 0x0003, + /* padrange */ 0x253c, 0x019b, + +}; + + +/* PL_op_private_valid: for each op, indexed by op_type, indicate which + * flags bits in op_private are legal */ + +EXTCONST U8 PL_op_private_valid[] = { + /* NULL */ (0xff), + /* STUB */ (0), + /* SCALAR */ (OPpARG1_MASK), + /* PUSHMARK */ (OPpPAD_STATE|OPpLVAL_INTRO), + /* WANTARRAY */ (OPpOFFBYONE), + /* CONST */ (OPpCONST_NOVER|OPpCONST_SHORTCIRCUIT|OPpCONST_STRICT|OPpCONST_ENTERED|OPpCONST_BARE), + /* GVSV */ (OPpOUR_INTRO|OPpLVAL_INTRO), + /* GV */ (OPpEARLY_CV), + /* GELEM */ (OPpARG2_MASK), + /* PADSV */ (OPpPAD_STATE|OPpDEREF|OPpLVAL_INTRO), + /* PADAV */ (OPpSLICEWARNING|OPpMAYBE_LVSUB|OPpPAD_STATE|OPpLVAL_INTRO), + /* PADHV */ (OPpSLICEWARNING|OPpMAYBE_LVSUB|OPpPAD_STATE|OPpTRUEBOOL|OPpMAYBE_TRUEBOOL|OPpLVAL_INTRO), + /* PADANY */ (0), + /* PUSHRE */ (OPpRUNTIME), + /* RV2GV */ (OPpARG1_MASK|OPpHINT_STRICT_REFS|OPpDONT_INIT_GV|OPpMAYBE_LVSUB|OPpALLOW_FAKE|OPpDEREF|OPpLVAL_INTRO), + /* RV2SV */ (OPpARG1_MASK|OPpHINT_STRICT_REFS|OPpOUR_INTRO|OPpDEREF|OPpLVAL_INTRO), + /* AV2ARYLEN */ (OPpARG1_MASK|OPpMAYBE_LVSUB), + /* RV2CV */ (OPpARG1_MASK|OPpHINT_STRICT_REFS|OPpENTERSUB_HASTARG|OPpENTERSUB_AMPER|OPpENTERSUB_DB|OPpMAY_RETURN_CONSTANT|OPpENTERSUB_NOPAREN), + /* ANONCODE */ (0), + /* PROTOTYPE */ (OPpARG1_MASK), + /* REFGEN */ (OPpARG1_MASK), + /* SREFGEN */ (OPpARG1_MASK), + /* REF */ (OPpARG1_MASK), + /* BLESS */ (OPpARG4_MASK), + /* BACKTICK */ (OPpARG1_MASK|OPpOPEN_IN_RAW|OPpOPEN_IN_CRLF|OPpOPEN_OUT_RAW|OPpOPEN_OUT_CRLF), + /* GLOB */ (OPpARG4_MASK), + /* READLINE */ (OPpARG1_MASK), + /* RCATLINE */ (0), + /* REGCMAYBE */ (OPpARG1_MASK), + /* REGCRESET */ (OPpARG1_MASK), + /* REGCOMP */ (OPpARG1_MASK), + /* MATCH */ (OPpTARGET_MY|OPpRUNTIME), + /* QR */ (OPpRUNTIME), + /* SUBST */ (OPpTARGET_MY|OPpRUNTIME), + /* SUBSTCONT */ (OPpARG1_MASK|OPpRUNTIME), + /* TRANS */ (OPpTRANS_FROM_UTF|OPpTRANS_TO_UTF|OPpTRANS_IDENTICAL|OPpTRANS_SQUASH|OPpTARGET_MY|OPpTRANS_COMPLEMENT|OPpTRANS_GROWS|OPpTRANS_DELETE), + /* TRANSR */ (OPpTRANS_FROM_UTF|OPpTRANS_TO_UTF|OPpTRANS_IDENTICAL|OPpTRANS_SQUASH|OPpTARGET_MY|OPpTRANS_COMPLEMENT|OPpTRANS_GROWS|OPpTRANS_DELETE), + /* SASSIGN */ (OPpARG2_MASK|OPpASSIGN_BACKWARDS|OPpASSIGN_CV_TO_GV), + /* AASSIGN */ (OPpARG2_MASK|OPpMAYBE_LVSUB|OPpASSIGN_COMMON), + /* CHOP */ (OPpARG1_MASK), + /* SCHOP */ (OPpARG1_MASK), + /* CHOMP */ (OPpARG1_MASK|OPpTARGET_MY), + /* SCHOMP */ (OPpARG1_MASK|OPpTARGET_MY), + /* DEFINED */ (OPpARG1_MASK), + /* UNDEF */ (OPpARG1_MASK), + /* STUDY */ (OPpARG1_MASK), + /* POS */ (OPpARG1_MASK|OPpMAYBE_LVSUB|OPpLVAL_INTRO), + /* PREINC */ (OPpARG1_MASK), + /* I_PREINC */ (OPpARG1_MASK), + /* PREDEC */ (OPpARG1_MASK), + /* I_PREDEC */ (OPpARG1_MASK), + /* POSTINC */ (OPpARG1_MASK), + /* I_POSTINC */ (OPpARG1_MASK|OPpTARGET_MY), + /* POSTDEC */ (OPpARG1_MASK), + /* I_POSTDEC */ (OPpARG1_MASK|OPpTARGET_MY), + /* POW */ (OPpARG2_MASK|OPpTARGET_MY), + /* MULTIPLY */ (OPpARG2_MASK|OPpTARGET_MY), + /* I_MULTIPLY */ (OPpARG2_MASK|OPpTARGET_MY), + /* DIVIDE */ (OPpARG2_MASK|OPpTARGET_MY), + /* I_DIVIDE */ (OPpARG2_MASK|OPpTARGET_MY), + /* MODULO */ (OPpARG2_MASK|OPpTARGET_MY), + /* I_MODULO */ (OPpARG2_MASK|OPpTARGET_MY), + /* REPEAT */ (OPpARG2_MASK|OPpREPEAT_DOLIST), + /* ADD */ (OPpARG2_MASK|OPpTARGET_MY), + /* I_ADD */ (OPpARG2_MASK|OPpTARGET_MY), + /* SUBTRACT */ (OPpARG2_MASK|OPpTARGET_MY), + /* I_SUBTRACT */ (OPpARG2_MASK|OPpTARGET_MY), + /* CONCAT */ (OPpARG2_MASK|OPpTARGET_MY), + /* STRINGIFY */ (OPpARG4_MASK|OPpTARGET_MY), + /* LEFT_SHIFT */ (OPpARG2_MASK|OPpTARGET_MY), + /* RIGHT_SHIFT */ (OPpARG2_MASK|OPpTARGET_MY), + /* LT */ (OPpARG2_MASK), + /* I_LT */ (OPpARG2_MASK), + /* GT */ (OPpARG2_MASK), + /* I_GT */ (OPpARG2_MASK), + /* LE */ (OPpARG2_MASK), + /* I_LE */ (OPpARG2_MASK), + /* GE */ (OPpARG2_MASK), + /* I_GE */ (OPpARG2_MASK), + /* EQ */ (OPpARG2_MASK), + /* I_EQ */ (OPpARG2_MASK), + /* NE */ (OPpARG2_MASK), + /* I_NE */ (OPpARG2_MASK), + /* NCMP */ (OPpARG2_MASK), + /* I_NCMP */ (OPpARG2_MASK), + /* SLT */ (OPpARG2_MASK), + /* SGT */ (OPpARG2_MASK), + /* SLE */ (OPpARG2_MASK), + /* SGE */ (OPpARG2_MASK), + /* SEQ */ (OPpARG2_MASK), + /* SNE */ (OPpARG2_MASK), + /* SCMP */ (OPpARG2_MASK), + /* BIT_AND */ (OPpARG2_MASK), + /* BIT_XOR */ (OPpARG2_MASK), + /* BIT_OR */ (OPpARG2_MASK), + /* NEGATE */ (OPpARG1_MASK), + /* I_NEGATE */ (OPpARG1_MASK|OPpTARGET_MY), + /* NOT */ (OPpARG1_MASK), + /* COMPLEMENT */ (OPpARG1_MASK), + /* SMARTMATCH */ (OPpARG2_MASK), + /* ATAN2 */ (OPpARG4_MASK|OPpTARGET_MY), + /* SIN */ (OPpARG1_MASK|OPpTARGET_MY), + /* COS */ (OPpARG1_MASK|OPpTARGET_MY), + /* RAND */ (OPpARG4_MASK|OPpTARGET_MY), + /* SRAND */ (OPpARG4_MASK|OPpTARGET_MY), + /* EXP */ (OPpARG1_MASK|OPpTARGET_MY), + /* LOG */ (OPpARG1_MASK|OPpTARGET_MY), + /* SQRT */ (OPpARG1_MASK|OPpTARGET_MY), + /* INT */ (OPpARG1_MASK|OPpTARGET_MY), + /* HEX */ (OPpARG1_MASK|OPpTARGET_MY), + /* OCT */ (OPpARG1_MASK|OPpTARGET_MY), + /* ABS */ (OPpARG1_MASK|OPpTARGET_MY), + /* LENGTH */ (OPpARG1_MASK|OPpTARGET_MY), + /* SUBSTR */ (OPpARG3_MASK|OPpMAYBE_LVSUB|OPpSUBSTR_REPL_FIRST|OPpLVAL_INTRO), + /* VEC */ (OPpARG2_MASK|OPpMAYBE_LVSUB|OPpLVAL_INTRO), + /* INDEX */ (OPpARG4_MASK|OPpTARGET_MY), + /* RINDEX */ (OPpARG4_MASK|OPpTARGET_MY), + /* SPRINTF */ (OPpARG4_MASK), + /* FORMLINE */ (OPpARG4_MASK), + /* ORD */ (OPpARG1_MASK|OPpTARGET_MY), + /* CHR */ (OPpARG1_MASK|OPpTARGET_MY), + /* CRYPT */ (OPpARG4_MASK|OPpTARGET_MY), + /* UCFIRST */ (OPpARG1_MASK), + /* LCFIRST */ (OPpARG1_MASK), + /* UC */ (OPpARG1_MASK), + /* LC */ (OPpARG1_MASK), + /* QUOTEMETA */ (OPpARG1_MASK), + /* RV2AV */ (OPpARG1_MASK|OPpHINT_STRICT_REFS|OPpSLICEWARNING|OPpMAYBE_LVSUB|OPpOUR_INTRO|OPpLVAL_INTRO), + /* AELEMFAST */ (255), + /* AELEMFAST_LEX */ (255), + /* AELEM */ (OPpARG2_MASK|OPpMAYBE_LVSUB|OPpLVAL_DEFER|OPpDEREF|OPpLVAL_INTRO), + /* ASLICE */ (OPpSLICEWARNING|OPpMAYBE_LVSUB|OPpLVAL_INTRO), + /* KVASLICE */ (OPpMAYBE_LVSUB), + /* AEACH */ (OPpARG1_MASK), + /* AKEYS */ (OPpARG1_MASK), + /* AVALUES */ (OPpARG1_MASK), + /* EACH */ (OPpARG1_MASK), + /* VALUES */ (OPpARG1_MASK), + /* KEYS */ (OPpARG1_MASK|OPpMAYBE_LVSUB), + /* DELETE */ (OPpARG1_MASK|OPpSLICE|OPpLVAL_INTRO), + /* EXISTS */ (OPpARG1_MASK|OPpEXISTS_SUB), + /* RV2HV */ (OPpARG1_MASK|OPpHINT_STRICT_REFS|OPpSLICEWARNING|OPpMAYBE_LVSUB|OPpOUR_INTRO|OPpTRUEBOOL|OPpMAYBE_TRUEBOOL|OPpLVAL_INTRO), + /* HELEM */ (OPpARG2_MASK|OPpMAYBE_LVSUB|OPpLVAL_DEFER|OPpDEREF|OPpLVAL_INTRO), + /* HSLICE */ (OPpSLICEWARNING|OPpMAYBE_LVSUB|OPpLVAL_INTRO), + /* KVHSLICE */ (OPpMAYBE_LVSUB), + /* UNPACK */ (OPpARG4_MASK), + /* PACK */ (OPpARG4_MASK), + /* SPLIT */ (OPpSPLIT_IMPLIM), + /* JOIN */ (OPpARG4_MASK), + /* LIST */ (OPpLIST_GUESSED|OPpLVAL_INTRO), + /* LSLICE */ (OPpARG2_MASK), + /* ANONLIST */ (OPpARG4_MASK), + /* ANONHASH */ (OPpARG4_MASK), + /* SPLICE */ (OPpARG4_MASK), + /* PUSH */ (OPpARG4_MASK|OPpTARGET_MY), + /* POP */ (OPpARG1_MASK), + /* SHIFT */ (OPpARG1_MASK), + /* UNSHIFT */ (OPpARG4_MASK|OPpTARGET_MY), + /* SORT */ (OPpSORT_NUMERIC|OPpSORT_INTEGER|OPpSORT_REVERSE|OPpSORT_INPLACE|OPpSORT_DESCEND|OPpSORT_QSORT|OPpSORT_STABLE), + /* REVERSE */ (OPpARG1_MASK|OPpREVERSE_INPLACE), + /* GREPSTART */ (OPpGREP_LEX), + /* GREPWHILE */ (OPpARG1_MASK|OPpGREP_LEX), + /* MAPSTART */ (OPpGREP_LEX), + /* MAPWHILE */ (OPpARG1_MASK|OPpGREP_LEX), + /* RANGE */ (OPpARG1_MASK), + /* FLIP */ (OPpARG1_MASK|OPpFLIP_LINENUM), + /* FLOP */ (OPpARG1_MASK|OPpFLIP_LINENUM), + /* AND */ (OPpARG1_MASK), + /* OR */ (OPpARG1_MASK), + /* XOR */ (OPpARG2_MASK), + /* DOR */ (OPpARG1_MASK), + /* COND_EXPR */ (OPpARG1_MASK|OPpLVAL_INTRO), + /* ANDASSIGN */ (OPpARG1_MASK), + /* ORASSIGN */ (OPpARG1_MASK), + /* DORASSIGN */ (OPpARG1_MASK), + /* METHOD */ (OPpARG1_MASK), + /* ENTERSUB */ (OPpENTERSUB_INARGS|OPpHINT_STRICT_REFS|OPpENTERSUB_HASTARG|OPpENTERSUB_AMPER|OPpENTERSUB_DB|OPpDEREF|OPpLVAL_INTRO), + /* LEAVESUB */ (OPpARG1_MASK|OPpREFCOUNTED), + /* LEAVESUBLV */ (OPpARG1_MASK|OPpREFCOUNTED), + /* CALLER */ (OPpARG4_MASK|OPpOFFBYONE), + /* WARN */ (OPpARG4_MASK), + /* DIE */ (OPpARG4_MASK), + /* RESET */ (OPpARG4_MASK), + /* LINESEQ */ (0), + /* NEXTSTATE */ (OPpHUSH_VMSISH|OPpHINT_M_VMSISH_STATUS|OPpHINT_M_VMSISH_TIME), + /* DBSTATE */ (OPpHUSH_VMSISH|OPpHINT_M_VMSISH_STATUS|OPpHINT_M_VMSISH_TIME), + /* UNSTACK */ (0), + /* ENTER */ (0), + /* LEAVE */ (OPpREFCOUNTED|OPpLVALUE), + /* SCOPE */ (0), + /* ENTERITER */ (OPpITER_REVERSED|OPpITER_DEF|OPpOUR_INTRO|OPpLVAL_INTRO), + /* ITER */ (OPpITER_REVERSED), + /* ENTERLOOP */ (0), + /* LEAVELOOP */ (OPpARG2_MASK|OPpLVALUE), + /* RETURN */ (0), + /* LAST */ (OPpARG1_MASK|OPpPV_IS_UTF8), + /* NEXT */ (OPpARG1_MASK|OPpPV_IS_UTF8), + /* REDO */ (OPpARG1_MASK|OPpPV_IS_UTF8), + /* DUMP */ (OPpARG1_MASK|OPpPV_IS_UTF8), + /* GOTO */ (OPpARG1_MASK|OPpPV_IS_UTF8), + /* EXIT */ (OPpARG4_MASK), + /* METHOD_NAMED */ (0), + /* ENTERGIVEN */ (OPpARG1_MASK), + /* LEAVEGIVEN */ (OPpARG1_MASK), + /* ENTERWHEN */ (OPpARG1_MASK), + /* LEAVEWHEN */ (OPpARG1_MASK), + /* BREAK */ (0), + /* CONTINUE */ (0), + /* OPEN */ (OPpARG4_MASK|OPpOPEN_IN_RAW|OPpOPEN_IN_CRLF|OPpOPEN_OUT_RAW|OPpOPEN_OUT_CRLF), + /* CLOSE */ (OPpARG4_MASK), + /* PIPE_OP */ (OPpARG4_MASK), + /* FILENO */ (OPpARG4_MASK), + /* UMASK */ (OPpARG4_MASK), + /* BINMODE */ (OPpARG4_MASK), + /* TIE */ (OPpARG4_MASK), + /* UNTIE */ (OPpARG1_MASK), + /* TIED */ (OPpARG1_MASK), + /* DBMOPEN */ (OPpARG4_MASK), + /* DBMCLOSE */ (OPpARG1_MASK), + /* SSELECT */ (OPpARG4_MASK), + /* SELECT */ (OPpARG4_MASK), + /* GETC */ (OPpARG4_MASK), + /* READ */ (OPpARG4_MASK), + /* ENTERWRITE */ (OPpARG4_MASK), + /* LEAVEWRITE */ (OPpARG1_MASK|OPpREFCOUNTED), + /* PRTF */ (0), + /* PRINT */ (0), + /* SAY */ (0), + /* SYSOPEN */ (OPpARG4_MASK), + /* SYSSEEK */ (OPpARG4_MASK), + /* SYSREAD */ (OPpARG4_MASK), + /* SYSWRITE */ (OPpARG4_MASK), + /* EOF */ (OPpARG4_MASK), + /* TELL */ (OPpARG4_MASK), + /* SEEK */ (OPpARG4_MASK), + /* TRUNCATE */ (OPpARG4_MASK), + /* FCNTL */ (OPpARG4_MASK), + /* IOCTL */ (OPpARG4_MASK), + /* FLOCK */ (OPpARG4_MASK|OPpTARGET_MY), + /* SEND */ (OPpARG4_MASK), + /* RECV */ (OPpARG4_MASK), + /* SOCKET */ (OPpARG4_MASK), + /* SOCKPAIR */ (OPpARG4_MASK), + /* BIND */ (OPpARG4_MASK), + /* CONNECT */ (OPpARG4_MASK), + /* LISTEN */ (OPpARG4_MASK), + /* ACCEPT */ (OPpARG4_MASK), + /* SHUTDOWN */ (OPpARG4_MASK), + /* GSOCKOPT */ (OPpARG4_MASK), + /* SSOCKOPT */ (OPpARG4_MASK), + /* GETSOCKNAME */ (OPpARG1_MASK), + /* GETPEERNAME */ (OPpARG1_MASK), + /* LSTAT */ (OPpARG1_MASK), + /* STAT */ (OPpARG1_MASK), + /* FTRREAD */ (OPpARG1_MASK|OPpFT_ACCESS|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTRWRITE */ (OPpARG1_MASK|OPpFT_ACCESS|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTREXEC */ (OPpARG1_MASK|OPpFT_ACCESS|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTEREAD */ (OPpARG1_MASK|OPpFT_ACCESS|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTEWRITE */ (OPpARG1_MASK|OPpFT_ACCESS|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTEEXEC */ (OPpARG1_MASK|OPpFT_ACCESS|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTIS */ (OPpARG1_MASK|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTSIZE */ (OPpARG1_MASK|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTMTIME */ (OPpARG1_MASK|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTATIME */ (OPpARG1_MASK|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTCTIME */ (OPpARG1_MASK|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTROWNED */ (OPpARG1_MASK|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTEOWNED */ (OPpARG1_MASK|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTZERO */ (OPpARG1_MASK|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTSOCK */ (OPpARG1_MASK|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTCHR */ (OPpARG1_MASK|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTBLK */ (OPpARG1_MASK|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTFILE */ (OPpARG1_MASK|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTDIR */ (OPpARG1_MASK|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTPIPE */ (OPpARG1_MASK|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTSUID */ (OPpARG1_MASK|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTSGID */ (OPpARG1_MASK|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTSVTX */ (OPpARG1_MASK|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTLINK */ (OPpARG1_MASK|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTTTY */ (OPpARG1_MASK|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTTEXT */ (OPpARG1_MASK|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* FTBINARY */ (OPpARG1_MASK|OPpFT_STACKED|OPpFT_STACKING|OPpFT_AFTER_t), + /* CHDIR */ (OPpARG4_MASK|OPpTARGET_MY), + /* CHOWN */ (OPpARG4_MASK|OPpTARGET_MY), + /* CHROOT */ (OPpARG1_MASK|OPpTARGET_MY), + /* UNLINK */ (OPpARG4_MASK|OPpTARGET_MY), + /* CHMOD */ (OPpARG4_MASK|OPpTARGET_MY), + /* UTIME */ (OPpARG4_MASK|OPpTARGET_MY), + /* RENAME */ (OPpARG4_MASK|OPpTARGET_MY), + /* LINK */ (OPpARG4_MASK|OPpTARGET_MY), + /* SYMLINK */ (OPpARG4_MASK|OPpTARGET_MY), + /* READLINK */ (OPpARG1_MASK), + /* MKDIR */ (OPpARG4_MASK|OPpTARGET_MY), + /* RMDIR */ (OPpARG1_MASK|OPpTARGET_MY), + /* OPEN_DIR */ (OPpARG4_MASK), + /* READDIR */ (OPpARG1_MASK), + /* TELLDIR */ (OPpARG1_MASK), + /* SEEKDIR */ (OPpARG4_MASK), + /* REWINDDIR */ (OPpARG1_MASK), + /* CLOSEDIR */ (OPpARG1_MASK), + /* FORK */ (0), + /* WAIT */ (OPpTARGET_MY), + /* WAITPID */ (OPpARG4_MASK|OPpTARGET_MY), + /* SYSTEM */ (OPpARG4_MASK|OPpTARGET_MY), + /* EXEC */ (OPpARG4_MASK|OPpTARGET_MY), + /* KILL */ (OPpARG4_MASK|OPpTARGET_MY), + /* GETPPID */ (OPpTARGET_MY), + /* GETPGRP */ (OPpARG4_MASK|OPpTARGET_MY), + /* SETPGRP */ (OPpARG4_MASK|OPpTARGET_MY), + /* GETPRIORITY */ (OPpARG4_MASK|OPpTARGET_MY), + /* SETPRIORITY */ (OPpARG4_MASK|OPpTARGET_MY), + /* TIME */ (OPpTARGET_MY), + /* TMS */ (0), + /* LOCALTIME */ (OPpARG1_MASK), + /* GMTIME */ (OPpARG4_MASK), + /* ALARM */ (OPpARG1_MASK), + /* SLEEP */ (OPpARG4_MASK|OPpTARGET_MY), + /* SHMGET */ (OPpARG4_MASK), + /* SHMCTL */ (OPpARG4_MASK), + /* SHMREAD */ (OPpARG4_MASK), + /* SHMWRITE */ (OPpARG4_MASK), + /* MSGGET */ (OPpARG4_MASK), + /* MSGCTL */ (OPpARG4_MASK), + /* MSGSND */ (OPpARG4_MASK), + /* MSGRCV */ (OPpARG4_MASK), + /* SEMOP */ (OPpARG4_MASK), + /* SEMGET */ (OPpARG4_MASK), + /* SEMCTL */ (OPpARG4_MASK), + /* REQUIRE */ (OPpARG1_MASK), + /* DOFILE */ (OPpARG1_MASK), + /* HINTSEVAL */ (0), + /* ENTEREVAL */ (OPpARG1_MASK|OPpEVAL_HAS_HH|OPpEVAL_UNICODE|OPpEVAL_BYTES|OPpEVAL_COPHH|OPpEVAL_RE_REPARSING), + /* LEAVEEVAL */ (OPpARG1_MASK|OPpREFCOUNTED), + /* ENTERTRY */ (OPpARG1_MASK), + /* LEAVETRY */ (0), + /* GHBYNAME */ (OPpARG1_MASK), + /* GHBYADDR */ (OPpARG4_MASK), + /* GHOSTENT */ (0), + /* GNBYNAME */ (OPpARG1_MASK), + /* GNBYADDR */ (OPpARG4_MASK), + /* GNETENT */ (0), + /* GPBYNAME */ (OPpARG1_MASK), + /* GPBYNUMBER */ (OPpARG4_MASK), + /* GPROTOENT */ (0), + /* GSBYNAME */ (OPpARG4_MASK), + /* GSBYPORT */ (OPpARG4_MASK), + /* GSERVENT */ (0), + /* SHOSTENT */ (OPpARG1_MASK), + /* SNETENT */ (OPpARG1_MASK), + /* SPROTOENT */ (OPpARG1_MASK), + /* SSERVENT */ (OPpARG1_MASK), + /* EHOSTENT */ (0), + /* ENETENT */ (0), + /* EPROTOENT */ (0), + /* ESERVENT */ (0), + /* GPWNAM */ (OPpARG1_MASK), + /* GPWUID */ (OPpARG1_MASK), + /* GPWENT */ (0), + /* SPWENT */ (0), + /* EPWENT */ (0), + /* GGRNAM */ (OPpARG1_MASK), + /* GGRGID */ (OPpARG1_MASK), + /* GGRENT */ (0), + /* SGRENT */ (0), + /* EGRENT */ (0), + /* GETLOGIN */ (0), + /* SYSCALL */ (OPpARG4_MASK), + /* LOCK */ (OPpARG1_MASK), + /* ONCE */ (OPpARG1_MASK), + /* CUSTOM */ (0xff), + /* REACH */ (OPpARG1_MASK), + /* RKEYS */ (OPpARG1_MASK|OPpMAYBE_LVSUB), + /* RVALUES */ (OPpARG1_MASK), + /* COREARGS */ (OPpCOREARGS_DEREF1|OPpCOREARGS_DEREF2|OPpCOREARGS_SCALARMOD|OPpCOREARGS_PUSHMARK), + /* RUNCV */ (OPpOFFBYONE), + /* FC */ (OPpARG1_MASK), + /* PADCV */ (0), + /* INTROCV */ (0), + /* CLONECV */ (0), + /* PADRANGE */ (OPpPADRANGE_COUNTMASK|OPpLVAL_INTRO), + +}; + +# endif /* !DOINIT */ +#endif /* !PERL_GLOBAL_STRUCT_INIT */ + +END_EXTERN_C + + + /* ex: set ro: */ @@ -380,7 +380,7 @@ Does not use C<TARG>. See also C<XPUSHu>, C<mPUSHu> and C<PUSHu>. #define ARGTARG PL_op->op_targ /* See OPpTARGET_MY: */ -#define MAXARG (PL_op->op_private & 15) +#define MAXARG (PL_op->op_private & OPpARG4_MASK) #define SWITCHSTACK(f,t) \ STMT_START { \ @@ -2994,7 +2994,7 @@ PP(pp_ftrread) { I32 result; /* Not const, because things tweak this below. Not bool, because there's - no guarantee that OPp_FT_ACCESS is <= CHAR_MAX */ + no guarantee that OPpFT_ACCESS is <= CHAR_MAX */ #if defined(HAS_ACCESS) || defined (PERL_EFF_ACCESS) I32 use_access = PL_op->op_private & OPpFT_ACCESS; /* Giving some sort of initial value silences compilers. */ diff --git a/regen/op_private b/regen/op_private new file mode 100644 index 0000000000..3a1e9dc344 --- /dev/null +++ b/regen/op_private @@ -0,0 +1,668 @@ +#!perl + +=head1 F<regen/op_private> + +This file contains all the definitions of the meanings of the flags in the +op_private field of an OP. + +After editing this file, run C<make regen>. This will generate/update data +in: + + opcode.h + lib/B/Op_private.pm + +C<B::Op_private> holds three global hashes, C<%bits>, C<%defines>, +C<%labels>, which hold roughly the same information as found in this file +(after processing). + +F<opcode.h> gains a series of C<OPp*> defines, and a few static data +structures: + +C<PL_op_private_valid> defines, per-op, which op_private bits are legally, +allowed to be set. This is a first good place to look to see if an op has +any spare private bits. + +C<PL_op_private_bitdef_ix>, C<PL_op_private_bitdefs>, +C<PL_op_private_labels>, C<PL_op_private_bitfields>, +C<PL_op_private_valid> contain (in a compact form) the data needed by +Perl_do_op_dump() to dump the op_private field of an op. + +This file actually contains perl code which is run by F<regen/opcode.pl>. +The basic idea is that you keep calling addbits() to add definitions of +what a particular bit or range of bits in op_private means for a +particular op. This can be specified either as a 1-bit flag or a 1-or-more +bit bit field. Here's a general example: + + addbits('aelem', + 7 => qw(OPpLVAL_INTRO LVINTRO), + '5..6' => { + mask_def => 'OPpDEREF', + enum => [ qw( + 1 OPpDEREF_AV DREFAV + 2 OPpDEREF_HV DREFHV + 3 OPpDEREF_SV DREFSV + )], + }, + 4 => qw(OPpLVAL_DEFER LVDEFER), + ); + +Here for the op C<aelem>, bits 4 and 7 (bits are numbered 0..7) are +defined as single-bit flags. The first string following the bit number is +the define name that gets emitted in F<opcode.h>, and the second string is +the label, which will be displayed by F<Concise.pm> and Perl_do_op_dump() +(as used by C<perl -Dx>). + +If the bit number is actually two numbers connected with '..', then this +defines a bit field, which is 1 or more bits taken to hold a small +unsigned integer. Instead of two string arguments, it just has a single +hash ref argument. A bit field allows you to generate extra defines, such +as a mask, and optionally allows you to define an enumeration, where a +subset of the possible values of the bit field are given their own defines +and labels. The full syntax of this hash is explained further below. + +Note that not all bits for a particular op need to be added in a single +addbits() call; they accumulate. In particular, this file is arranged in +two halves; first, generic flags shared by multiple ops are added, then +in the second half, specific per-op flags are added, e.g. + + addbits($_, 7 => qw(OPpLVAL_INTRO LVINTRO)) for qw(pos substr vec ...); + + .... + + addbits('substr', + 4 => qw(OPpSUBSTR_REPL_FIRST REPL1ST), + 3 => ... + ); + +(although the diving line between these two halves is somewhat subjective, +and is based on whether "OPp" is followed by the op name or something +generic). + +There are some utility functions for generating a list of ops from +F<regen/opcodes> based on various criteria. These are: + + ops_with_check('ck_foo') + ops_with_flag('X') + ops_with_arg(N, 'XYZ') + +which return a list of op names where: + + field 3 of regen/opcodes specifies 'ck_foo' as the check function; + field 4 of of regen/opcodes has flag or type 'X' set; + argument field N of of regen/opcodes matches 'XYZ'; + +For example + + addbits($_, 4 => qw(OPpTARGET_MY TARGMY)) for ops_with_flag('T'); + +If a label is specified as '-', then the flag or bit field is not +displayed symbolically by Concise/-Dx; instead the bits are treated as +unrecognised and included in the final residual integer value after all +recognised bits have been processed (this doesn't apply to individual +enum labels). + +Here is a full example of a bit field hash: + + '5..6' => { + mask_def => 'OPpFOO_MASK', + baseshift_def => 'OPpFOO_SHIFT', + bitcount_def => 'OPpFOO_BITS', + label => 'FOO', + enum => [ qw( + 1 OPpFOO_A A + 2 OPpFOO_B B + 3 OPpFOO_C C + )], + }; + +The optional C<*_def> keys cause defines to be emitted that specify +useful values based on the bit range (5 to 6 in this case): + + mask_def: a mask that will extract the bit field + baseshift_def: how much to shift to make the bit field reach bit 0 + bitcount_def: how many bits make up the bit field + +The example above will generate + + #define OPpFOO_MASK 0x60 + #define OPpFOO_SHIFT 5 + #define OPpFOO_BITS 2 + +The optional enum list specifies a set of defines and labels for (possibly +a subset of) the possible values of the bit field (which in this example +are 0,1,2,3). If a particular value matches an enum, then it will be +displayed symbolically (e.g. 'C'), otherwise as a small integer. The +defines are suitably shifted. The example above will generate + + #define OPpFOO_A 0x20 + #define OPpFOO_B 0x40 + #define OPpFOO_C 0x60 + +So you can write code like + + if ((o->op_private & OPpFOO_MASK) == OPpFOO_C) ... + +The optional 'label' key causes Concise/-Dx output to prefix the value +with C<LABEL=>; so in this case it might display C<FOO=C>. If the field +value is zero, and if no label is present, and if no enum matches, then +the field isn't displayed. + +=cut + + +use warnings; +use strict; + + + + +# ==================================================================== +# +# GENERIC OPpFOO flags +# +# Flags where FOO is a generic term (like LVAL), and the flag is +# shared between multiple (possibly unrelated) ops. + + + + +{ + # The lower few bits of op_private often indicate the number of + # arguments. This is usually set by newUNOP() and newLOGOP (to 1), + # by newBINOP() (to 1 or 2), and by ck_fun() (to 1..15). + # + # These values are sometimes used at runtime: in particular, + # the MAXARG macro extracts out the lower 4 bits. + # + # Some ops encroach upon these bits; for example, entersub is a unop, + # but uses bit 0 for something else. Bit 0 is initially set to 1 in + # newUNOP(), but is later cleared (in ck_rvconst()), when the code + # notices that this op is an entersub. + # + # The important thing below is that any ops which use MAXARG at + # runtime must have all 4 bits allocated; if bit 3 were used for a new + # flag say, then things could break. The information on the other + # types of op is for completeness (so we can account for every bit + # used in every op) + + my (%maxarg, %args0, %args1, %args2, %args3, %args4); + + # these are the functions which currently use MAXARG at runtime + # (i.e. in the pp() functions). Thus they must always have 4 bits + # allocated + $maxarg{$_} = 1 for qw( + binmode bless caller chdir close enterwrite eof exit fileno getc + getpgrp gmtime index mkdir rand reset setpgrp sleep srand sysopen + tell umask + ); + + # find which ops use 0,1,2,3 or 4 bits of op_private for arg count info + + $args0{$_} = 1 for qw(entersub); # UNOPs that usurp bit 0 + + $args1{$_} = 1 for ( + qw(reverse), # ck_fun(), but most bits stolen + grep !$maxarg{$_} && !$args0{$_}, + ops_with_flag('1'), # UNOP + ops_with_flag('%'), # BASEOP/UNOP + ops_with_flag('|'), # LOGOP + ops_with_flag('-'), # FILESTATOP + ops_with_flag('}'), # LOOPEXOP + ); + + $args2{$_} = 1 for ( + qw(vec), + grep !$maxarg{$_} && !$args0{$_} && !$args1{$_}, + ops_with_flag('2'), # BINOP + # this is a binop, but special-cased as a + # baseop in regen/opcodes + 'sassign', + ); + + $args3{$_} = 1 for grep !$maxarg{$_} && !$args0{$_} + && !$args1{$_} && !$args2{$_}, + # substr starts off with 4 bits set in + # ck_fun(), but since it never has more than 7 + # args, bit 3 is later stolen + qw(substr); + + $args4{$_} = 1 for keys %maxarg, + grep !$args0{$_} && !$args1{$_} + && !$args2{$_} && !$args3{$_}, + ops_with_check('ck_fun'), + # these other ck_*() functions call ck_fun() + ops_with_check('ck_exec'), + ops_with_check('ck_glob'), + ops_with_check('ck_index'), + ops_with_check('ck_join'), + ops_with_check('ck_lfun'), + ops_with_check('ck_open'), + ops_with_check('ck_select'), + ops_with_check('ck_tell'), + ops_with_check('ck_trunc'), + ; + + + for (sort keys %args1) { + addbits($_, '0..0' => { + mask_def => 'OPpARG1_MASK', + label => '-', + } + ); + } + + for (sort keys %args2) { + addbits($_, '0..1' => { + mask_def => 'OPpARG2_MASK', + label => '-', + } + ); + } + + for (sort keys %args3) { + addbits($_, '0..2' => { + mask_def => 'OPpARG3_MASK', + label => '-', + } + ); + } + + for (sort keys %args4) { + addbits($_, '0..3' => { + mask_def => 'OPpARG4_MASK', + label => '-', + } + ); + } +} + + + +# if NATIVE_HINTS is defined, op_private on cops holds the top 8 bits +# of PL_hints, although only bits 6 & 7 are officially used for that +# purpose (the rest ought to be masked off). Bit 5 is set separately + +for (qw(nextstate dbstate)) { + addbits($_, + 5 => qw(OPpHUSH_VMSISH HUSH), + # should match HINT_M_VMSISH_STATUS, HINT_M_VMSISH_TIME + 6 => qw(OPpHINT_M_VMSISH_STATUS VMSISH_STATUS), + 7 => qw(OPpHINT_M_VMSISH_TIME VMSISH_TIME), + + ); +} + + + +addbits($_, 7 => qw(OPpLVAL_INTRO LVINTRO)) + for qw(pos substr vec gvsv rv2sv rv2hv rv2gv rv2av aelem helem aslice + hslice delete padsv padav padhv enteriter entersub padrange + pushmark cond_expr), + 'list', # this gets set in my_attrs() for some reason + ; + + + +# TARGLEX +# +# in constructs like my $x; ...; $x = $a + $b, +# the sassign is optimised away and OPpTARGET_MY is set on the add op + +# XXX the old Concise.pm disagreed with regen/opcodes as to which ops have +# this flag: in Concise, but not T: +# bit_and bit_or bit_xor chop complement join negate postdec postinc +# quotemeta schop sprintf +# in T but not Concise: +# srand + +addbits($_, 4 => qw(OPpTARGET_MY TARGMY)) + for ops_with_flag('T'), + # This flag is also used to indicate matches against implicit $_, + # where $_ is lexical; e.g. my $_; ....; /foo/ + qw(match subst trans transr); +; + + + + + +# op_targ carries a refcount +addbits($_, 6 => qw(OPpREFCOUNTED REFC)) + for qw(leave leavesub leavesublv leavewrite leaveeval); + + + +# Do not copy return value +addbits($_, 7 => qw(OPpLVALUE LV)) for qw(leave leaveloop); + + + +# Pattern coming in on the stack +addbits($_, 6 => qw(OPpRUNTIME RTIME)) + for qw(match subst substcont qr pushre); + + + +# autovivify: Want ref to something +for (qw(rv2gv rv2sv padsv aelem helem entersub)) { + addbits($_, '5..6' => { + mask_def => 'OPpDEREF', + enum => [ qw( + 1 OPpDEREF_AV DREFAV + 2 OPpDEREF_HV DREFHV + 3 OPpDEREF_SV DREFSV + )], + } + ); +} + + + +# Defer creation of array/hash elem +addbits($_, 4 => qw(OPpLVAL_DEFER LVDEFER)) for qw(aelem helem); + + + +addbits($_, 2 => qw(OPpSLICEWARNING SLICEWARN)) # warn about @hash{$scalar} + for qw(rv2hv rv2av padav padhv hslice aslice); + + + +# XXX Concise seemed to think that OPpOUR_INTRO is used in rv2gv too, +# but I can't see it - DAPM +addbits($_, 4 => qw(OPpOUR_INTRO OURINTR)) # Variable was in an our() + for qw(gvsv rv2sv rv2av rv2hv enteriter); + + + +# We might be an lvalue to return +addbits($_, 3 => qw(OPpMAYBE_LVSUB LVSUB)) + for qw(aassign rv2av rv2gv rv2hv padav padhv aelem helem aslice hslice + av2arylen keys rkeys kvaslice kvhslice substr pos vec); + + + +for (qw(rv2hv padhv)) { + addbits($_, # e.g. %hash in (%hash || $foo) ... + 5 => qw(OPpTRUEBOOL BOOL), # ... in void cxt + 6 => qw(OPpMAYBE_TRUEBOOL BOOL?), # ... cx not known till run time + ); +} + + + +addbits($_, 1 => qw(OPpHINT_STRICT_REFS -)) for qw(rv2sv rv2av rv2hv rv2gv); + + + +# Treat caller(1) as caller(2) +addbits($_, 7 => qw(OPpOFFBYONE +1)) for qw(caller wantarray runcv); + + + +# label is in UTF8 */ +addbits($_, 7 => qw(OPpPV_IS_UTF8 UTF)) for qw(last redo next goto dump); + + + +# ==================================================================== +# +# OP-SPECIFIC OPpFOO_* flags: +# +# where FOO is typically the name of an op, and the flag is used by a +# single op (or maybe by a few closely related ops). + + + +addbits($_, 4 => qw(OPpPAD_STATE STATE)) for qw(padav padhv padsv pushmark); + + + +addbits('aassign', 6 => qw(OPpASSIGN_COMMON COMMON)); + + + +addbits('sassign', + 6 => qw(OPpASSIGN_BACKWARDS BKWARD), # Left & right switched + 7 => qw(OPpASSIGN_CV_TO_GV CV2GV), # Possible optimisation for constants +); + + + +for (qw(trans transr)) { + addbits($_, + 0 => qw(OPpTRANS_FROM_UTF <UTF), + 1 => qw(OPpTRANS_TO_UTF >UTF), + 2 => qw(OPpTRANS_IDENTICAL IDENT), # right side is same as left + 3 => qw(OPpTRANS_SQUASH SQUASH), + # 4 is used for OPpTARGET_MY + 5 => qw(OPpTRANS_COMPLEMENT COMPL), + 6 => qw(OPpTRANS_GROWS GROWS), + 7 => qw(OPpTRANS_DELETE DEL), + ); +} + + + +addbits('repeat', 6 => qw(OPpREPEAT_DOLIST DOLIST)); # List replication + + + +# OP_ENTERSUB and OP_RV2CV flags +# +# Flags are set on entersub and rv2cv in three phases: +# parser - the parser passes the flag to the op constructor +# check - the check routine called by the op constructor sets the flag +# context - application of scalar/ref/lvalue context applies the flag +# +# In the third stage, an entersub op might turn into an rv2cv op (undef &foo, +# \&foo, lock &foo, exists &foo, defined &foo). The two places where that +# happens (op_lvalue_flags and doref in op.c) need to make sure the flags do +# not conflict, since some flags with different meanings overlap between +# the two ops. Flags applied in the context phase are only set when there +# is no conversion of op type. +# +# bit entersub flag phase rv2cv flag phase +# --- ------------- ----- ---------- ----- +# 0 OPpENTERSUB_INARGS context +# 1 HINT_STRICT_REFS check HINT_STRICT_REFS check +# 2 OPpENTERSUB_HASTARG check +# 3 OPpENTERSUB_AMPER check OPpENTERSUB_AMPER parser +# 4 OPpENTERSUB_DB check +# 5 OPpDEREF_AV context +# 6 OPpDEREF_HV context OPpMAY_RETURN_CONSTANT context +# 7 OPpLVAL_INTRO context OPpENTERSUB_NOPAREN parser + +# NB: OPpHINT_STRICT_REFS must equal HINT_STRICT_REFS + +addbits('entersub', + 0 => qw(OPpENTERSUB_INARGS INARGS), # Lval used as arg to a sub + 1 => qw(OPpHINT_STRICT_REFS - ), # 'use strict' in scope + 2 => qw(OPpENTERSUB_HASTARG TARG ), # Called from OP tree + 3 => qw(OPpENTERSUB_AMPER AMPER), # Used & form to call + 4 => qw(OPpENTERSUB_DB DBG ), # Debug subroutine + # 5..6 => OPpDEREF, already defined above + # 7 => OPpLVAL_INTRO, already defined above +); +addbits('rv2cv', + # If a constant sub, return the constant + 1 => qw(OPpHINT_STRICT_REFS - ), # 'use strict' in scope + + 3 => qw(OPpENTERSUB_AMPER AMPER), # Used & form to call + + 6 => qw(OPpMAY_RETURN_CONSTANT CONST), + 7 => qw(OPpENTERSUB_NOPAREN NO() ), # bare sub call (without parens) +); + +# XXX perhaps ought the clear these flags in Perl_doref when converting +# and entersub into an rv2cv???? Failing that, update the comments above +# and add them as part of the main addbits('rv2cv'. + +addbits('rv2cv', + # If a constant sub, return the constant + 2 => qw(OPpENTERSUB_HASTARG TARG), + 4 => qw(OPpENTERSUB_DB DBG ), # Debug subroutine +); + + + +#foo() called before sub foo was parsed */ +addbits('gv', 5 => qw(OPpEARLY_CV EARLYCV)); + + + +# 1st arg is replacement string */ +addbits('substr', 4 => qw(OPpSUBSTR_REPL_FIRST REPL1ST)); + + + +addbits('padrange', + # bits 0..6 hold target range + '0..6' => { + label => '-', + mask_def => 'OPpPADRANGE_COUNTMASK', + bitcount_def => 'OPpPADRANGE_COUNTSHIFT', + } + # 7 => OPpLVAL_INTRO, already defined above +); + + + +for (qw(aelemfast aelemfast_lex)) { + addbits($_, + '0..7' => { + label => '-', + } + ); +} + + + +addbits('rv2gv', + 2 => qw(OPpDONT_INIT_GV NOINIT), # Call gv_fetchpv with GV_NOINIT + # (Therefore will return whatever is currently in + # the symbol table, not guaranteed to be a PVGV) + 4 => qw(OPpALLOW_FAKE FAKE), # OK to return fake glob +); + + + +addbits('enteriter', + 2 => qw(OPpITER_REVERSED REVERSED),# for (reverse ...) + 3 => qw(OPpITER_DEF -), # 'for $_' or 'for my $_' +); +addbits('iter', 2 => qw(OPpITER_REVERSED REVERSED)); + + + +addbits('const', + 1 => qw(OPpCONST_NOVER NOVER), # no 6; + 2 => qw(OPpCONST_SHORTCIRCUIT SHORT), # e.g. the constant 5 in (5 || foo) + 3 => qw(OPpCONST_STRICT STRICT), # bareword subject to strict 'subs' + 4 => qw(OPpCONST_ENTERED ENTERED), # Has been entered as symbol + 6 => qw(OPpCONST_BARE BARE), # Was a bare word (filehandle?) +); + + + +# Range arg potentially a line num. */ +addbits($_, 6 => qw(OPpFLIP_LINENUM LINENUM)) for qw(flip flop); + + + +# Guessed that pushmark was needed. */ +addbits('list', 6 => qw(OPpLIST_GUESSED GUESSED)); + + + +# Operating on a list of keys +addbits('delete', 6 => qw(OPpSLICE SLICE)); +# also 7 => OPpLVAL_INTRO, already defined above + + + +# Checking for &sub, not {} or []. +addbits('exists', 6 => qw(OPpEXISTS_SUB SUB)); + + + +addbits('sort', + 0 => qw(OPpSORT_NUMERIC NUM ), # Optimized away { $a <=> $b } + 1 => qw(OPpSORT_INTEGER INT ), # Ditto while under "use integer" + 2 => qw(OPpSORT_REVERSE REV ), # Reversed sort + 3 => qw(OPpSORT_INPLACE INPLACE), # sort in-place; eg @a = sort @a + 4 => qw(OPpSORT_DESCEND DESC ), # Descending sort + 5 => qw(OPpSORT_QSORT QSORT ), # Use quicksort (not mergesort) + 6 => qw(OPpSORT_STABLE STABLE ), # Use a stable algorithm +); + + + +# reverse in-place (@a = reverse @a) */ +addbits('reverse', 3 => qw(OPpREVERSE_INPLACE INPLACE)); + + + +for (qw(open backtick)) { + addbits($_, + 4 => qw(OPpOPEN_IN_RAW INBIN ), # binmode(F,":raw") on input fh + 5 => qw(OPpOPEN_IN_CRLF INCR ), # binmode(F,":crlf") on input fh + 6 => qw(OPpOPEN_OUT_RAW OUTBIN), # binmode(F,":raw") on output fh + 7 => qw(OPpOPEN_OUT_CRLF OUTCR ), # binmode(F,":crlf") on output fh + ); +} + + + +# The various OPpFT* filetest ops + +# "use filetest 'access'" is in scope: +# this flag is set only on a subset of the FT* ops +addbits($_, 1 => qw(OPpFT_ACCESS FTACCESS)) for ops_with_arg(0, 'F-+'); + +# all OPpFT* ops except stat and lstat +for (grep { $_ !~ /^l?stat$/ } ops_with_flag('-')) { + addbits($_, + 2 => qw(OPpFT_STACKED FTSTACKED ), # stacked filetest, + # e.g. "-f" in "-f -x $foo" + 3 => qw(OPpFT_STACKING FTSTACKING), # stacking filetest. + # e.g. "-x" in "-f -x $foo" + 4 => qw(OPpFT_AFTER_t FTAFTERt ), # previous op was -t + ); +} + + + +addbits($_, 1 => qw(OPpGREP_LEX GREPLEX)) # iterate over lexical $_ + for qw(mapwhile mapstart grepwhile grepstart); + + + +addbits('entereval', + 1 => qw(OPpEVAL_HAS_HH HAS_HH ), # Does it have a copy of %^H ? + 2 => qw(OPpEVAL_UNICODE UNI ), + 3 => qw(OPpEVAL_BYTES BYTES ), + 4 => qw(OPpEVAL_COPHH COPHH ), # Construct %^H from COP hints + 5 => qw(OPpEVAL_RE_REPARSING - ), # eval_sv(..., G_RE_REPARSING) +); + + + +# These must not conflict with OPpDONT_INIT_GV or OPpALLOW_FAKE. +# See pp.c:S_rv2gv. */ +addbits('coreargs', + 0 => qw(OPpCOREARGS_DEREF1 DEREF1), # Arg 1 is a handle constructor + 1 => qw(OPpCOREARGS_DEREF2 DEREF2), # Arg 2 is a handle constructor + #2 reserved for OPpDONT_INIT_GV in rv2gv + #4 reserved for OPpALLOW_FAKE in rv2gv + 6 => qw(OPpCOREARGS_SCALARMOD $MOD ), # \$ rather than \[$@%*] + 7 => qw(OPpCOREARGS_PUSHMARK MARK ), # Call pp_pushmark +); + + + +addbits('split', 7 => qw(OPpSPLIT_IMPLIM IMPLIM)); # implicit limit + +1; + +# ex: set ts=8 sts=4 sw=4 et: diff --git a/regen/opcode.pl b/regen/opcode.pl index a081c64784..34f9d4bd2a 100755 --- a/regen/opcode.pl +++ b/regen/opcode.pl @@ -5,9 +5,12 @@ # opcode.h # opnames.h # pp_proto.h +# lib/B/Op_private.pm # -# from information stored in regen/opcodes, plus the -# values hardcoded into this script in @raw_alias. +# from: +# * information stored in regen/opcodes; +# * information stored in regen/op_private (which is actually perl code); +# * the values hardcoded into this script in @raw_alias. # # Accepts the standard regen_lib -q and -v args. # @@ -29,7 +32,14 @@ my $on = open_new('opnames.h', '>', { by => 'regen/opcode.pl', from => 'its data', style => '*', file => 'opnames.h', copyright => [1999 .. 2008] }); -# Read data. +my $oprivpm = open_new('lib/B/Op_private.pm', '>', + { by => 'regen/opcode.pl', + from => 'data in regen/op_private', + style => '#', + file => 'lib/B/Op_private.pm', + copyright => [2014 .. 2014] }); + +# Read 'opcodes' data. my %seen; my (@ops, %desc, %check, %ckname, %flags, %args, %opnum); @@ -143,6 +153,725 @@ foreach my $sock_func (qw(socket bind listen accept shutdown $alias{$sock_func} = ["Perl_pp_$sock_func", '#ifdef HAS_SOCKET'], } + + +# ================================================================= +# +# Functions for processing regen/op_private data. +# +# Put them in a separate package so that croak() does the right thing + +package OP_PRIVATE; + +use Carp; + + +# the vars holding the global state built up by all the calls to addbits() + + +# map OPpLVAL_INTRO => LVINTRO +my %LABELS; + + +# the numeric values of flags - what will get output as a #define +my %DEFINES; + +# %BITFIELDS: the various bit field types. The key is the concatenation of +# all the field values that make up a bit field hash; the values are bit +# field hash refs. This allows us to de-dup identical bit field defs +# across different ops, and thus make the output tables more compact (esp +# important for the C version) +my %BITFIELDS; + +# %FLAGS: the main data structure. Indexed by op name, then bit index: +# single bit flag: +# $FLAGS{rv2av}{2} = 'OPpSLICEWARNING'; +# bit field (bits 5 and 6): +# $FLAGS{rv2av}{5} = $FLAGS{rv2av}{6} = { .... }; +my %FLAGS; + + +# do, with checking, $LABELS{$name} = $label + +sub add_label { + my ($name, $label) = @_; + if (exists $LABELS{$name} and $LABELS{$name} ne $label) { + croak "addbits(): label for flag '$name' redefined:\n" + . " was '$LABELS{$name}', now '$label'"; + } + $LABELS{$name} = $label; +} + +# +# do, with checking, $DEFINES{$name} = $val + +sub add_define { + my ($name, $val) = @_; + if (exists $DEFINES{$name} && $DEFINES{$name} != $val) { + croak "addbits(): value for flag '$name' redefined:\n" + . " was $DEFINES{$name}, now $val"; + } + $DEFINES{$name} = $val; +} + + +# intended to be called from regen/op_private; see that file for details + +sub ::addbits { + my @args = @_; + + croak "too few arguments for addbits()" unless @args >= 3; + my $op = shift @args; + croak "invalid op name: '$op'" unless exists $opnum{$op}; + + while (@args) { + my $bits = shift @args; + if ($bits =~ /^[0-7]$/) { + # single bit + croak "addbits(): too few arguments for single bit flag" + unless @args >= 2; + my $flag_name = shift @args; + my $flag_label = shift @args; + add_label($flag_name, $flag_label); + croak "addbits(): bit $bits of $op already specified" + if defined $FLAGS{$op}{$bits}; + $FLAGS{$op}{$bits} = $flag_name; + add_define($flag_name, (1 << $bits)); + } + elsif ($bits =~ /^([0-7])\.\.([0-7])$/) { + # bit range + my ($bitmin, $bitmax) = ($1,$2); + + croak "addbits(): min bit > max bit in bit range '$bits'" + unless $bitmin <= $bitmax; + croak "addbits(): bit field argument missing" + unless @args >= 1; + + my $arg_hash = shift @args; + croak "addbits(): arg to $bits must be a hash ref" + unless defined $arg_hash and ref($arg_hash) =~ /HASH/; + + my %valid_keys; + @valid_keys{qw(baseshift_def bitcount_def mask_def label enum)} = (); + for (keys %$arg_hash) { + croak "addbits(): unrecognised bifield key: '$_'" + unless exists $valid_keys{$_}; + } + + my $bitmask = 0; + $bitmask += (1 << $_) for $bitmin..$bitmax; + + my $enum_id =''; + + if (defined $arg_hash->{enum}) { + my $enum = $arg_hash->{enum}; + croak "addbits(): arg to enum must be an array ref" + unless defined $enum and ref($enum) =~ /ARRAY/; + croak "addbits(): enum list must be in triplets" + unless @$enum % 3 == 0; + + my $max_id = (1 << ($bitmax - $bitmin + 1)) - 1; + + my @e = @$enum; + while (@e) { + my $enum_ix = shift @e; + my $enum_name = shift @e; + my $enum_label = shift @e; + croak "addbits(): enum index must be a number: '$enum_ix'" + unless $enum_ix =~ /^\d+$/; + croak "addbits(): enum index too big: '$enum_ix'" + unless $enum_ix <= $max_id; + add_label($enum_name, $enum_label); + add_define($enum_name, $enum_ix << $bitmin); + $enum_id .= "($enum_ix:$enum_name:$enum_label)"; + } + } + + # id is a fingerprint of all the content of the bit field hash + my $id = join ':', map defined() ? $_ : "-undef-", + $bitmin, $bitmax, + $arg_hash->{label}, + $arg_hash->{mask_def}, + $arg_hash->{baseshift_def}, + $arg_hash->{bitcount_def}, + $enum_id; + + unless (defined $BITFIELDS{$id}) { + + if (defined $arg_hash->{mask_def}) { + add_define($arg_hash->{mask_def}, $bitmask); + } + + if (defined $arg_hash->{baseshift_def}) { + add_define($arg_hash->{baseshift_def}, $bitmin); + } + + if (defined $arg_hash->{bitcount_def}) { + add_define($arg_hash->{bitcount_def}, $bitmax-$bitmin+1); + } + + # create deep copy + + my $copy = {}; + for (qw(baseshift_def bitcount_def mask_def label)) { + $copy->{$_} = $arg_hash->{$_} if defined $arg_hash->{$_}; + } + if (defined $arg_hash->{enum}) { + $copy->{enum} = [ @{$arg_hash->{enum}} ]; + } + + # and add some extra fields + + $copy->{bitmask} = $bitmask; + $copy->{bitmin} = $bitmin; + $copy->{bitmax} = $bitmax; + + $BITFIELDS{$id} = $copy; + } + + for my $bit ($bitmin..$bitmax) { + croak "addbits(): bit $bit of $op already specified" + if defined $FLAGS{$op}{$bit}; + $FLAGS{$op}{$bit} = $BITFIELDS{$id}; + } + } + else { + croak "addbits(): invalid bit specifier '$bits'"; + } + } +} + + +# intended to be called from regen/op_private; see that file for details + +sub ::ops_with_flag { + my $flag = shift; + return grep $flags{$_} =~ /\Q$flag/, sort keys %flags; +} + + +# intended to be called from regen/op_private; see that file for details + +sub ::ops_with_check { + my $c = shift; + return grep $check{$_} eq $c, sort keys %check; +} + + +# intended to be called from regen/op_private; see that file for details + +sub ::ops_with_arg { + my ($i, $arg_type) = @_; + my @ops; + for my $op (sort keys %args) { + my @args = split(' ',$args{$op}); + push @ops, $op if defined $args[$i] and $args[$i] eq $arg_type; + } + @ops; +} + + +# output '#define OPpLVAL_INTRO 0x80' etc + +sub print_defines { + my $fh = shift; + + for (sort { $DEFINES{$a} <=> $DEFINES{$b} || $a cmp $b } keys %DEFINES) { + printf $fh "#define %-23s 0x%02x\n", $_, $DEFINES{$_}; + } +} + + +# Generate the content of B::Op_private + +sub print_B_Op_private { + my $fh = shift; + + my $header = <<'EOF'; +@=head1 NAME +@ +@B::Op_private - OP op_private flag definitions +@ +@=head1 SYNOPSIS +@ +@ use B::Op_private; +@ +@ # flag details for bit 7 of OP_AELEM's op_private: +@ my $name = $B::Op_private::bits{aelem}{7}; # OPpLVAL_INTRO +@ my $value = $B::Op_private::defines{$name}; # 128 +@ my $label = $B::Op_private::labels{$name}; # LVINTRO +@ +@ # the bit field at bits 5..6 of OP_AELEM's op_private: +@ my $bf = $B::Op_private::bits{aelem}{6}; +@ my $mask = $bf->{bitmask}; # etc +@ +@=head1 DESCRIPTION +@ +@This module provides three global hashes: +@ +@ %B::Op_private::bits +@ %B::Op_private::defines +@ %B::Op_private::labels +@ +@which contain information about the per-op meanings of the bits in the +@op_private field. +@ +@=head2 C<%bits> +@ +@This is indexed by op name and then bit number (0..7). For single bit flags, +@it returns the name of the define (if any) for that bit: +@ +@ $B::Op_private::bits{aelem}{7} eq 'OPpLVAL_INTRO'; +@ +@For bit fields, it returns a hash ref containing details about the field. +@The same reference will be returned for all bit positions that make +@up the bit field; so for example these both return the same hash ref: +@ +@ $bitfield = $B::Op_private::bits{aelem}{5}; +@ $bitfield = $B::Op_private::bits{aelem}{6}; +@ +@The general format of this hash ref is +@ +@ { +@ # The bit range and mask; these are always present. +@ bitmin => 5, +@ bitmax => 6, +@ bitmask => 0x60, +@ +@ # (The remaining keys are optional) +@ +@ # The names of any defines that were requested: +@ mask_def => 'OPpFOO_MASK', +@ baseshift_def => 'OPpFOO_SHIFT', +@ bitcount_def => 'OPpFOO_BITS', +@ +@ # If present, Concise etc will display the value with a 'FOO=' +@ # prefix. If it equals '-', then Concise will treat the bit field +@ # as raw bits and not try to interpret it. +@ label => 'FOO', +@ +@ # If present, specifies the names of some defines and the display +@ # labels that are used to assign meaning to particular integer +@ # values within the bit field; e.g. 3 is displayed as 'C'. +@ enum => [ qw( +@ 1 OPpFOO_A A +@ 2 OPpFOO_B B +@ 3 OPpFOO_C C +@ )], +@ +@ }; +@ +@ +@=head2 C<%defines> +@ +@This gives the value of every C<OPp> define, e.g. +@ +@ $B::Op_private::defines{OPpLVAL_INTRO} == 128; +@ +@=head2 C<%labels> +@ +@This gives the short display label for each define, as used by C<B::Concise> +@and C<perl -Dx>, e.g. +@ +@ $B::Op_private::labels{OPpLVAL_INTRO} eq 'LVINTRO'; +@ +@If the label equals '-', then Concise will treat the bit as a raw bit and +@not try to display it symbolically. +@ +@=cut + +package B::Op_private; + +our %bits; + +EOF + # remove podcheck.t-defeating leading char + $header =~ s/^\@//gm; + print $fh $header; + + # for each flag/bit combination, find the ops which use it + my %combos; + for my $op (sort keys %FLAGS) { + my $entry = $FLAGS{$op}; + for my $bit (0..7) { + my $e = $entry->{$bit}; + next unless defined $e; + next if ref $e; # bit field, not flag + push @{$combos{$e}{$bit}}, $op; + } + } + + # dump flags used by multiple ops + for my $flag (sort keys %combos) { + for my $bit (sort keys %{$combos{$flag}}) { + my $ops = $combos{$flag}{$bit}; + next unless @$ops > 1; + my @o = sort @$ops; + print $fh "\$bits{\$_}{$bit} = '$flag' for qw(@o);\n"; + } + } + + # dump bit field definitions + + my %bitfield_ix; + { + my %bitfields; + # stringified-ref to ref mapping + $bitfields{$_} = $_ for values %BITFIELDS; + my $ix = -1; + my $s = "\nmy \@bf = (\n"; + for my $bitfield_key (sort keys %BITFIELDS) { + my $bitfield = $BITFIELDS{$bitfield_key}; + $ix++; + $bitfield_ix{$bitfield} = $ix; + + $s .= " {\n"; + for (qw(label mask_def baseshift_def bitcount_def)) { + next unless defined $bitfield->{$_}; + $s .= sprintf " %-9s => '%s',\n", + $_, $bitfield->{$_}; + } + for (qw(bitmin bitmax bitmask)) { + croak "panic" unless defined $bitfield->{$_}; + $s .= sprintf " %-9s => %d,\n", + $_, $bitfield->{$_}; + } + if (defined $bitfield->{enum}) { + $s .= " enum => [\n"; + my @enum = @{$bitfield->{enum}}; + while (@enum) { + my $i = shift @enum; + my $name = shift @enum; + my $label = shift @enum; + $s .= sprintf " %d, %-10s, %s,\n", + $i, "'$name'", "'$label'"; + } + $s .= " ],\n"; + } + $s .= " },\n"; + + } + $s .= ");\n"; + print $fh "$s\n"; + } + + # dump bitfields and remaining labels + + for my $op (sort keys %FLAGS) { + my @indices; + my @vals; + my $entry = $FLAGS{$op}; + my $bit; + + for ($bit = 7; $bit >= 0; $bit--) { + next unless defined $entry->{$bit}; + my $e = $entry->{$bit}; + if (ref $e) { + my $ix = $bitfield_ix{$e}; + for (reverse $e->{bitmin}..$e->{bitmax}) { + push @indices, $_; + push @vals, "\$bf[$ix]"; + } + $bit = $e->{bitmin}; + } + else { + next if @{$combos{$e}{$bit}} > 1; # already output + push @indices, $bit; + push @vals, "'$e'"; + } + } + if (@indices) { + my $s = ''; + $s = '@{' if @indices > 1; + $s .= "\$bits{$op}"; + $s .= '}' if @indices > 1; + $s .= '{' . join(',', @indices) . '} = '; + $s .= '(' if @indices > 1; + $s .= join ', ', @vals; + $s .= ')' if @indices > 1; + print $fh "$s;\n"; + } + } + + # populate %defines and %labels + + print $fh "\n\nour %defines = (\n"; + printf $fh " %-23s => %3d,\n", $_ , $DEFINES{$_} for sort keys %DEFINES; + print $fh ");\n\nour %labels = (\n"; + printf $fh " %-23s => '%s',\n", $_ , $LABELS{$_} for sort keys %LABELS; + print $fh ");\n"; + +} + + + +# output the contents of the assorted PL_op_private_*[] tables + +sub print_PL_op_private_tables { + my $fh = shift; + + my $PL_op_private_labels = ''; + my $PL_op_private_valid = ''; + my $PL_op_private_bitdef_ix = ''; + my $PL_op_private_bitdefs = ''; + my $PL_op_private_bitfields = ''; + + my %label_ix; + my %bitfield_ix; + + # generate $PL_op_private_labels + + { + my %labs; + $labs{$_} = 1 for values %LABELS; # de-duplicate labels + # add in bit field labels + for (values %BITFIELDS) { + next unless defined $_->{label}; + $labs{$_->{label}} = 1; + } + + my $labels = ''; + for my $lab (sort keys %labs) { + $label_ix{$lab} = length $labels; + $labels .= "$lab\0"; + $PL_op_private_labels .= + " " + . join(',', map("'$_'", split //, $lab)) + . ",'\\0',\n"; + } + } + + + # generate PL_op_private_bitfields + + { + my %bitfields; + # stringified-ref to ref mapping + $bitfields{$_} = $_ for values %BITFIELDS; + + my $ix = 0; + for my $bitfield_key (sort keys %BITFIELDS) { + my $bf = $BITFIELDS{$bitfield_key}; + $bitfield_ix{$bf} = $ix; + + my @b; + push @b, $bf->{bitmin}, + defined $bf->{label} ? $label_ix{$bf->{label}} : -1; + my $enum = $bf->{enum}; + if (defined $enum) { + my @enum = @$enum; + while (@enum) { + my $i = shift @enum; + my $name = shift @enum; + my $label = shift @enum; + push @b, $i, $label_ix{$label}; + } + } + push @b, -1; # terminate enum list + + $PL_op_private_bitfields .= " " . join(', ', @b) .",\n"; + $ix += @b; + } + } + + + # generate PL_op_private_bitdefs, PL_op_private_bitdef_ix + + { + my $bitdef_count = 0; + + my %not_seen = %FLAGS; + + my $opnum = -1; + for my $op (sort { $opnum{$a} <=> $opnum{$b} } keys %opnum) { + $opnum++; + die "panic: opnum misorder: opnum=$opnum opnum{op}=$opnum{$op}" + unless $opnum == $opnum{$op}; + delete $not_seen{$op}; + + my @bitdefs; + my $entry = $FLAGS{$op}; + my $bit; + my $index; + + for ($bit = 7; $bit >= 0; $bit--) { + my $e = $entry->{$bit}; + next unless defined $e; + + my $ix; + if (ref $e) { + $ix = $bitfield_ix{$e}; + die "panic: \$bit =\= $e->{bitmax}" + unless $bit == $e->{bitmax}; + + push @bitdefs, ( ($ix << 5) | ($bit << 2) | 2 ); + $bit = $e->{bitmin}; + } + else { + $ix = $label_ix{$LABELS{$e}}; + die "panic: no label ix for '$e'" unless defined $ix; + push @bitdefs, ( ($ix << 5) | ($bit << 2)); + } + if ($ix > 2047) { + die "Too many labels or bitfields (ix=$ix): " + . "maybe the type of PL_op_private_bitdefs needs " + . "expanding from U16 to U32???"; + } + } + if (@bitdefs) { + $bitdefs[-1] |= 1; # stop bit + $index = $bitdef_count; + $bitdef_count += @bitdefs; + $PL_op_private_bitdefs .= sprintf " /* %-13s */ %s,\n", + $op, + join(', ', map(sprintf("0x%04x", $_), @bitdefs)); + } + else { + $index = -1; + } + $PL_op_private_bitdef_ix .= sprintf " %4d, /* %s */\n", $index, $op; + } + if (%not_seen) { + die "panic: unprocessed ops: ". join(',', keys %not_seen); + } + } + + + # generate PL_op_private_valid + + for my $op (@ops) { + my $last; + my @flags; + for my $bit (0..7) { + next unless exists $FLAGS{$op}; + my $entry = $FLAGS{$op}{$bit}; + next unless defined $entry; + if (ref $entry) { + # skip later entries for the same bit field + next if defined $last and $last == $entry; + $last = $entry; + push @flags, + defined $entry->{mask_def} + ? $entry->{mask_def} + : $entry->{bitmask}; + } + else { + push @flags, $entry; + } + } + + # all bets are off + @flags = '0xff' if $op eq 'null' or $op eq 'custom'; + + $PL_op_private_valid .= sprintf " /* %-10s */ (%s),\n", uc($op), + @flags ? join('|', @flags): '0'; + } + + print $fh <<EOF; +START_EXTERN_C + +#ifndef PERL_GLOBAL_STRUCT_INIT + +# ifndef DOINIT + +/* data about the flags in op_private */ + +EXTCONST I16 PL_op_private_bitdef_ix[]; +EXTCONST U16 PL_op_private_bitdefs[]; +EXTCONST char PL_op_private_labels[]; +EXTCONST I16 PL_op_private_bitfields[]; +EXTCONST U8 PL_op_private_valid[]; + +# else + + +/* PL_op_private_labels[]: the short descriptions of private flags. + * All labels are concatenated into a single char array + * (separated by \\0's) for compactness. + */ + +EXTCONST char PL_op_private_labels[] = { +$PL_op_private_labels +}; + + + +/* PL_op_private_bitfields[]: details about each bit field type. + * Each defintition consists of the following list of words: + * bitmin + * label (index into PL_op_private_labels[]; -1 if no label) + * repeat for each enum entry (if any): + * enum value + * enum label (index into PL_op_private_labels[]) + * -1 + */ + +EXTCONST I16 PL_op_private_bitfields[] = { +$PL_op_private_bitfields +}; + + +/* PL_op_private_bitdef_ix[]: map an op number to a starting position + * in PL_op_private_bitdefs. If -1, the op has no bits defined */ + +EXTCONST I16 PL_op_private_bitdef_ix[] = { +$PL_op_private_bitdef_ix +}; + + + +/* PL_op_private_bitdefs[]: given a starting position in this array (as + * supplied by PL_op_private_bitdef_ix[]), each word (until a stop bit is + * seen) defines the meaning of a particular op_private bit for a + * particular op. Each word consists of: + * bit 0: stop bit: this is the last bit def for the current op + * bit 1: bitfield: if set, this defines a bit field rather than a flag + * bits 2..4: unsigned number in the range 0..7 which is the bit number + * bits 5..15: unsigned number in the range 0..2047 which is an index + * into PL_op_private_labels[] (for a flag), or + * into PL_op_private_bitfields[] (for a bit field) + */ + +EXTCONST U16 PL_op_private_bitdefs[] = { +$PL_op_private_bitdefs +}; + + +/* PL_op_private_valid: for each op, indexed by op_type, indicate which + * flags bits in op_private are legal */ + +EXTCONST U8 PL_op_private_valid[] = { +$PL_op_private_valid +}; + +# endif /* !DOINIT */ +#endif /* !PERL_GLOBAL_STRUCT_INIT */ + +END_EXTERN_C + + +EOF + +} + + +# ================================================================= + + +package main; + +# read regen/op_private data +# +# This file contains Perl code that builds up some data structures +# which define what bits in op_private have what meanings for each op. +# It populates %LABELS, %DEFINES, %FLAGS, %BITFIELDS. + +require 'regen/op_private'; + +#use Data::Dumper; +#print Dumper \%LABELS, \%DEFINES, \%FLAGS, \%BITFIELDS; + + # Emit defines. print $oc "#ifndef PERL_GLOBAL_STRUCT_INIT\n\n"; @@ -469,7 +1198,14 @@ my $pp = open_new('pp_proto.h', '>', } print $pp "PERL_CALLCONV OP *$_(pTHX);\n" foreach sort keys %funcs; } -foreach ($oc, $on, $pp) { + +print $oc "\n\n"; +OP_PRIVATE::print_defines($oc); +OP_PRIVATE::print_PL_op_private_tables($oc); + +OP_PRIVATE::print_B_Op_private($oprivpm); + +foreach ($oc, $on, $pp, $oprivpm) { read_only_bottom_close_and_rename($_); } diff --git a/t/porting/regen.t b/t/porting/regen.t index 3198183f0b..0c378cd190 100644 --- a/t/porting/regen.t +++ b/t/porting/regen.t @@ -20,7 +20,7 @@ if ( $Config{usecrosscompile} ) { skip_all( "Not all files are available during cross-compilation" ); } -my $tests = 25; # I can't see a clean way to calculate this automatically. +my $tests = 26; # I can't see a clean way to calculate this automatically. my %skip = ("regen_perly.pl" => [qw(perly.act perly.h perly.tab)], "regen/keywords.pl" => [qw(keywords.c keywords.h)], |