diff --git a/builtin.c b/builtin.c index ac9f5b9bb857..02879ffbf05b 100644 --- a/builtin.c +++ b/builtin.c @@ -692,15 +692,11 @@ static bool S_cv_is_builtin(pTHX_ CV *cv) void Perl_import_builtin_bundle(pTHX_ U16 ver) { - SV *ampname = sv_newmortal(); - for(int i = 0; builtins[i].name; i++) { - sv_setpvf(ampname, "&%s", builtins[i].name); - bool want = (builtins[i].since_ver <= ver); bool got = false; - PADOFFSET off = pad_findmy_sv(ampname, 0); + PADOFFSET off = pad_find_my_symbol_pv (Perl_Symbol_Table_Code, builtins[i].name, 0); CV *cv; if(off != NOT_IN_PAD && SvTYPE((cv = (CV *)PL_curpad[off])) == SVt_PVCV && diff --git a/class.c b/class.c index 6bf703b537cb..1c4f5eee2ca4 100644 --- a/class.c +++ b/class.c @@ -155,7 +155,7 @@ XS(injected_constructor) SV *name = ST(i); SV *val = (i+1 < items) ? ST(i+1) : &PL_sv_undef; - /* TODO: think about sanity-checking name for being + /* TODO: think about sanity-checking name for being * defined * not ref (but overloaded objects?? boo) * not duplicate @@ -399,10 +399,10 @@ Perl_class_setup_stash(pTHX_ HV *stash) /* We don't want to make `$self` visible during the expression but we * still need to give it a name. Make it unusable from pure perl */ - PADOFFSET padix = pad_add_name_pvs("$(self)", 0, NULL, NULL); + PADOFFSET padix = pad_add_symbol_pvs (Perl_Symbol_Table_Scalar, "(self)", 0, NULL, NULL); assert(padix == PADIX_SELF); - padix = pad_add_name_pvs("%(params)", 0, NULL, NULL); + padix = pad_add_symbol_pvs (Perl_Symbol_Table_Hash, "(params)", 0, NULL, NULL); assert(padix == PADIX_PARAMS); PERL_UNUSED_VAR(padix); @@ -699,7 +699,7 @@ Perl_class_seal_stash(pTHX_ HV *stash) for(SSize_t i = 0; fieldnames && i <= PadnamelistMAX(fieldnames); i++) { PADNAME *pn = PadnamelistARRAY(fieldnames)[i]; - char sigil = PadnamePV(pn)[0]; + perl_symbol_table_id sigil = Padname_Symbol_Table (pn); PADOFFSET fieldix = PadnameFIELDINFO(pn)->fieldix; /* Extract the OP_{NEXT,DB}STATE op from the defop so we can @@ -729,7 +729,7 @@ Perl_class_seal_stash(pTHX_ HV *stash) U8 op_priv = 0; switch(sigil) { - case '$': + case Perl_Symbol_Table_Scalar: if(paramname) { if(!valop) { SV *message = @@ -766,11 +766,11 @@ Perl_class_seal_stash(pTHX_ HV *stash) } break; - case '@': + case Perl_Symbol_Table_Array: op_priv = OPpINITFIELD_AV; break; - case '%': + case Perl_Symbol_Table_Hash: op_priv = OPpINITFIELD_HV; break; @@ -843,7 +843,7 @@ Perl_class_prepare_method_parse(pTHX_ CV *cv) PADOFFSET padix; - padix = pad_add_name_pvs("$self", 0, NULL, NULL); + padix = pad_add_symbol_pvs (Perl_Symbol_Table_Scalar, "self", 0, NULL, NULL); assert(padix == PADIX_SELF); PERL_UNUSED_VAR(padix); @@ -945,9 +945,9 @@ apply_field_attribute_param(pTHX_ PADNAME *pn, SV *value) { if(!value) /* Default to name minus the sigil */ - value = newSVpvn_utf8(PadnamePV(pn) + 1, PadnameLEN(pn) - 1, PadnameUTF8(pn)); + value = newSVpvn_utf8(Padname_Symbol_Name (pn), Padname_Symbol_Name_Length (pn), PadnameUTF8(pn)); - if(PadnamePV(pn)[0] != '$') + if(! Padname_Is_Symbol_Table_Scalar (pn)) croak("Only scalar fields can take a :param attribute"); if(PadnameFIELDINFO(pn)->paramname) @@ -977,7 +977,7 @@ apply_field_attribute_reader(pTHX_ PADNAME *pn, SV *value) SvREFCNT_inc(value); else /* Default to name minus the sigil */ - value = newSVpvn_utf8(PadnamePV(pn) + 1, PadnameLEN(pn) - 1, PadnameUTF8(pn)); + value = newSVpvn_utf8(Padname_Symbol_Name (pn), Padname_Symbol_Name_Length (pn), PadnameUTF8(pn)); if(!valid_identifier_sv(value)) croak("%" SVf_QUOTEDPREFIX " is not a valid name for a generated method", value); @@ -991,10 +991,17 @@ apply_field_attribute_reader(pTHX_ PADNAME *pn, SV *value) PADOFFSET padix; - padix = pad_add_name_pvs("$self", 0, NULL, NULL); + padix = pad_add_symbol_pvs (Perl_Symbol_Table_Scalar, "self", 0, NULL, NULL); assert(padix == PADIX_SELF); - padix = pad_add_name_pvn(PadnamePV(pn), PadnameLEN(pn), 0, NULL, NULL); + padix = pad_add_symbol_pvn ( + /* symbol_table = */ Padname_Symbol_Table (pn), + /* namepv = */ Padname_Symbol_Name (pn), + /* namelen = */ Padname_Symbol_Name_Length (pn), + /* flags = */ 0, + /* typestash = */ NULL, + /* ourstash = */ NULL + ); intro_my(); OP *methstartop; @@ -1028,10 +1035,10 @@ apply_field_attribute_reader(pTHX_ PADNAME *pn, SV *value) OP *retop; { OPCODE optype = 0; - switch(PadnamePV(pn)[0]) { - case '$': optype = OP_PADSV; break; - case '@': optype = OP_PADAV; break; - case '%': optype = OP_PADHV; break; + switch(Padname_Symbol_Table (pn)) { + case Perl_Symbol_Table_Scalar: optype = OP_PADSV; break; + case Perl_Symbol_Table_Array: optype = OP_PADAV; break; + case Perl_Symbol_Table_Hash: optype = OP_PADHV; break; default: NOT_REACHED; } @@ -1238,14 +1245,14 @@ Perl_class_set_field_defop(pTHX_ PADNAME *pn, OPCODE defmode, OP *defop) forbid_outofblock_ops(defop, "field initialiser expression"); - char sigil = PadnamePV(pn)[0]; + perl_symbol_table_id sigil = Padname_Symbol_Table (pn); switch(sigil) { - case '$': + case Perl_Symbol_Table_Scalar: defop = op_contextualize(defop, G_SCALAR); break; - case '@': - case '%': + case Perl_Symbol_Table_Array: + case Perl_Symbol_Table_Hash: defop = op_contextualize(op_force_list(defop), G_LIST); break; } diff --git a/dump.c b/dump.c index cdbbb0e2819d..7bdba179cf8c 100644 --- a/dump.c +++ b/dump.c @@ -166,7 +166,7 @@ Unused or not for public use #define PV_BYTE_HEX_LC "x%02" UVxf char * -Perl_pv_escape( pTHX_ SV *dsv, char const * const str, +Perl_pv_escape( pTHX_ SV *dsv, char const * const str, const STRLEN count, STRLEN max, STRLEN * const escaped, U32 flags ) { @@ -226,21 +226,21 @@ Perl_pv_escape( pTHX_ SV *dsv, char const * const str, /* This won't alter the UTF-8 flag */ SvPVCLEAR(dsv); } - + if ((flags & PERL_PV_ESCAPE_UNI_DETECT) && is_utf8_string((U8*)pv, count)) isuni = 1; - + for ( ; pv < end ; pv += readsize ) { const UV u= (isuni) ? utf8_to_uvchr_buf((U8*)pv, (U8*) end, &readsize) : (U8)*pv; const U8 c = (U8)u; const char *source_buf = octbuf; - + if ( ( u > 255 ) || (flags & PERL_PV_ESCAPE_ALL) || (( ! isASCII(u) ) && (flags & (PERL_PV_ESCAPE_NONASCII|PERL_PV_ESCAPE_DWIM)))) { - if (flags & PERL_PV_ESCAPE_FIRSTCHAR) - chsize = my_snprintf( octbuf, PV_ESCAPE_OCTBUFSIZE, + if (flags & PERL_PV_ESCAPE_FIRSTCHAR) + chsize = my_snprintf( octbuf, PV_ESCAPE_OCTBUFSIZE, "%" UVxf, u); else if ((flags & PERL_PV_ESCAPE_NON_WC) && isWORDCHAR_uvchr(u)) { @@ -248,21 +248,21 @@ Perl_pv_escape( pTHX_ SV *dsv, char const * const str, source_buf = pv; } else - chsize = my_snprintf( octbuf, PV_ESCAPE_OCTBUFSIZE, + chsize = my_snprintf( octbuf, PV_ESCAPE_OCTBUFSIZE, ((flags & PERL_PV_ESCAPE_DWIM) && !isuni) ? ( use_uc_hex ? ("%c" PV_BYTE_HEX_UC) : ("%c" PV_BYTE_HEX_LC) ) : "%cx{%02" UVxf "}", esc, u); } else if (flags & PERL_PV_ESCAPE_NOBACKSLASH) { - chsize = 1; - } else { + chsize = 1; + } else { if ( (c == dq) || (c == esc) || !isPRINT(c) ) { chsize = 2; switch (c) { - + case '\\' : /* FALLTHROUGH */ case '%' : if ( c == esc ) { - octbuf[1] = esc; + octbuf[1] = esc; } else { chsize = 1; } @@ -272,10 +272,10 @@ Perl_pv_escape( pTHX_ SV *dsv, char const * const str, case '\r' : octbuf[1] = 'r'; break; case '\n' : octbuf[1] = 'n'; break; case '\f' : octbuf[1] = 'f'; break; - case '"' : - if ( dq == '"' ) + case '"' : + if ( dq == '"' ) octbuf[1] = '"'; - else + else chsize = 1; break; default: @@ -323,7 +323,7 @@ Perl_pv_escape( pTHX_ SV *dsv, char const * const str, Perl_sv_catpvf( aTHX_ dsv, "%c", c); wrote++; } - if ( flags & PERL_PV_ESCAPE_FIRSTCHAR ) + if ( flags & PERL_PV_ESCAPE_FIRSTCHAR ) break; } if (escaped != NULL) @@ -339,7 +339,7 @@ C and supporting quoting and ellipses. If the C flag is set then the result will be double quoted with any double quotes in the string escaped. Otherwise if the C flag is set then the result be wrapped in -angle brackets. +angle brackets. If the C flag is set and not all characters in string were output then an ellipsis C<...> will be appended to the @@ -356,22 +356,22 @@ Returns a pointer to the prettified text as held by C. =for apidoc Amnh||PERL_PV_PRETTY_LTGT =for apidoc Amnh||PERL_PV_PRETTY_ELLIPSES -=cut +=cut */ char * -Perl_pv_pretty( pTHX_ SV *dsv, char const * const str, const STRLEN count, - const STRLEN max, char const * const start_color, char const * const end_color, - const U32 flags ) +Perl_pv_pretty( pTHX_ SV *dsv, char const * const str, const STRLEN count, + const STRLEN max, char const * const start_color, char const * const end_color, + const U32 flags ) { const U8 *quotes = (U8*)((flags & PERL_PV_PRETTY_QUOTE) ? "\"\"" : (flags & PERL_PV_PRETTY_LTGT) ? "<>" : NULL); STRLEN escaped; STRLEN max_adjust= 0; STRLEN orig_cur; - + PERL_ARGS_ASSERT_PV_PRETTY; - + if (!(flags & PERL_PV_PRETTY_NOCLEAR)) { /* This won't alter the UTF-8 flag */ SvPVCLEAR(dsv); @@ -380,8 +380,8 @@ Perl_pv_pretty( pTHX_ SV *dsv, char const * const str, const STRLEN count, if ( quotes ) Perl_sv_catpvf(aTHX_ dsv, "%c", quotes[0]); - - if ( start_color != NULL ) + + if ( start_color != NULL ) sv_catpv(dsv, start_color); if ((flags & PERL_PV_PRETTY_EXACTSIZE)) { @@ -396,12 +396,12 @@ Perl_pv_pretty( pTHX_ SV *dsv, char const * const str, const STRLEN count, pv_escape( dsv, str, count, max - max_adjust, &escaped, flags | PERL_PV_ESCAPE_NOCLEAR ); - if ( end_color != NULL ) + if ( end_color != NULL ) sv_catpv(dsv, end_color); if ( quotes ) Perl_sv_catpvf(aTHX_ dsv, "%c", quotes[1]); - + if ( (flags & PERL_PV_PRETTY_ELLIPSES) && ( escaped < count ) ) sv_catpvs(dsv, "..."); @@ -409,7 +409,7 @@ Perl_pv_pretty( pTHX_ SV *dsv, char const * const str, const STRLEN count, while( SvCUR(dsv) - orig_cur < max ) sv_catpvs(dsv," "); } - + return SvPVX(dsv); } @@ -795,7 +795,7 @@ S_opdump_link(pTHX_ const OP *base, const OP *o, PerlIO *file) =for apidoc_section $debugging =for apidoc dump_all -Dumps the entire optree of the current program starting at C to +Dumps the entire optree of the current program starting at C to C. Also dumps the optrees for all visible subroutines in C. @@ -2047,7 +2047,7 @@ Perl_do_sv_dump(pTHX_ I32 level, PerlIO *file, SV *sv, I32 nest, I32 maxnest, bo if ((flags & SVs_PADTMP)) sv_catpvs(d, "PADTMP,"); append_flags(d, flags, first_sv_flags_names); - if (flags & SVf_ROK) { + if (flags & SVf_ROK) { sv_catpvs(d, "ROK,"); if (SvWEAKREF(sv)) sv_catpvs(d, "WEAKREF,"); } @@ -2350,7 +2350,7 @@ Perl_do_sv_dump(pTHX_ I32 level, PerlIO *file, SV *sv, I32 nest, I32 maxnest, bo if (ents) { HE *const *const last = ents + HvMAX(sv); count = last + 1 - ents; - + do { if (!*ents) --count; @@ -3056,8 +3056,8 @@ S_append_padvar(pTHX_ PADOFFSET off, CV *cv, SV *out, int n, { STRLEN cur = SvCUR(out); Perl_sv_catpvf(aTHX_ out, "[%" UTF8f, - UTF8fARG(1, PadnameLEN(sv) - 1, - PadnamePV(sv) + 1)); + UTF8fARG(1, Padname_Symbol_Name_Length (sv), + Padname_Symbol_Name (sv))); if (is_scalar) SvPVX(out)[cur] = '$'; } @@ -3375,7 +3375,7 @@ Perl_op_class(pTHX_ const OP *o) return OPclass_SVOP; #endif } - + #ifdef USE_ITHREADS if (o->op_type == OP_GV || o->op_type == OP_GVSV || o->op_type == OP_RCATLINE) @@ -3412,7 +3412,7 @@ Perl_op_class(pTHX_ const OP *o) case OA_PVOP_OR_SVOP: /* - * Character translations (tr///) are usually a PVOP, keeping a + * Character translations (tr///) are usually a PVOP, keeping a * pointer to a table of shorts used to look up translations. * Under utf8, however, a simple table isn't practical; instead, * the OP is an SVOP (or, under threads, a PADOP), diff --git a/embed.fnc b/embed.fnc index 7792a28e7a3c..c355966f2c37 100644 --- a/embed.fnc +++ b/embed.fnc @@ -2257,6 +2257,10 @@ ARTdpx |PADNAME *|newPADNAMEouter \ |NN PADNAME *outer ARTdpx |PADNAME *|newPADNAMEpvn|NN const char *s \ |STRLEN len +ARTdpx |PADNAME *|new_padname_symbol_pvn \ + |perl_symbol_table_id symbol_table \ + |NN const char *name \ + |STRLEN name_len ARdip |OP * |newPADxVOP |I32 type \ |I32 flags \ |PADOFFSET padix @@ -2466,6 +2470,25 @@ Adp |PADOFFSET|pad_add_name_sv \ |U32 flags \ |NULLOK HV *typestash \ |NULLOK HV *ourstash +Adp |PADOFFSET|pad_add_symbol_pv \ + |perl_symbol_table_id symbol_table \ + |NN const char *name \ + |const U32 flags \ + |NULLOK HV *typestash \ + |NULLOK HV *ourstash +Adp |PADOFFSET|pad_add_symbol_pvn \ + |perl_symbol_table_id symbol_table \ + |NN const char *namepv \ + |STRLEN namelen \ + |U32 flags \ + |NULLOK HV *typestash \ + |NULLOK HV *ourstash +Adp |PADOFFSET|pad_add_symbol_sv \ + |perl_symbol_table_id symbol_table \ + |NN SV *name \ + |U32 flags \ + |NULLOK HV *typestash \ + |NULLOK HV *ourstash p |void |pad_add_weakref|NN CV *func Adpx |PADOFFSET|pad_alloc |I32 optype \ |U32 tmptype @@ -2478,6 +2501,19 @@ Adp |PADOFFSET|pad_findmy_pvn \ |U32 flags Adp |PADOFFSET|pad_findmy_sv|NN SV *name \ |U32 flags +Adp |PADOFFSET|pad_find_my_symbol_pv \ + |perl_symbol_table_id find_symbol_table \ + |NN const char *name \ + |U32 flags +Adp |PADOFFSET|pad_find_my_symbol_pvn \ + |perl_symbol_table_id find_symbol_table \ + |NN const char *namepv \ + |STRLEN namelen \ + |U32 flags +Adp |PADOFFSET|pad_find_my_symbol_sv \ + |perl_symbol_table_id find_symbol_table \ + |NN SV *name \ + |U32 flags dp |void |pad_fixup_inner_anons \ |NN PADLIST *padlist \ |NN CV *old_cv \ @@ -4939,7 +4975,8 @@ Sd |PADOFFSET|pad_alloc_name \ Sd |void |pad_check_dup |NN PADNAME *name \ |U32 flags \ |NULLOK const HV *ourstash -Sd |PADOFFSET|pad_findlex |NN const char *namepv \ +Sd |PADOFFSET|pad_findlex |perl_symbol_table_id find_symbol_table \ + |NN const char *namepv \ |STRLEN namelen \ |U32 flags \ |NN const CV *cv \ diff --git a/embed.h b/embed.h index dfcc4f4881e6..f2783df55cce 100644 --- a/embed.h +++ b/embed.h @@ -479,6 +479,7 @@ # define newWHILEOP(a,b,c,d,e,f,g) Perl_newWHILEOP(aTHX_ a,b,c,d,e,f,g) # define newXS(a,b,c) Perl_newXS(aTHX_ a,b,c) # define newXS_flags(a,b,c,d,e) Perl_newXS_flags(aTHX_ a,b,c,d,e) +# define new_padname_symbol_pvn Perl_new_padname_symbol_pvn # define new_stackinfo(a,b) Perl_new_stackinfo(aTHX_ a,b) # define new_stackinfo_flags(a,b,c) Perl_new_stackinfo_flags(aTHX_ a,b,c) # define new_version(a) Perl_new_version(aTHX_ a) @@ -507,7 +508,13 @@ # define pad_add_name_pv(a,b,c,d) Perl_pad_add_name_pv(aTHX_ a,b,c,d) # define pad_add_name_pvn(a,b,c,d,e) Perl_pad_add_name_pvn(aTHX_ a,b,c,d,e) # define pad_add_name_sv(a,b,c,d) Perl_pad_add_name_sv(aTHX_ a,b,c,d) +# define pad_add_symbol_pv(a,b,c,d,e) Perl_pad_add_symbol_pv(aTHX_ a,b,c,d,e) +# define pad_add_symbol_pvn(a,b,c,d,e,f) Perl_pad_add_symbol_pvn(aTHX_ a,b,c,d,e,f) +# define pad_add_symbol_sv(a,b,c,d,e) Perl_pad_add_symbol_sv(aTHX_ a,b,c,d,e) # define pad_alloc(a,b) Perl_pad_alloc(aTHX_ a,b) +# define pad_find_my_symbol_pv(a,b,c) Perl_pad_find_my_symbol_pv(aTHX_ a,b,c) +# define pad_find_my_symbol_pvn(a,b,c,d) Perl_pad_find_my_symbol_pvn(aTHX_ a,b,c,d) +# define pad_find_my_symbol_sv(a,b,c) Perl_pad_find_my_symbol_sv(aTHX_ a,b,c) # define pad_findmy_pv(a,b) Perl_pad_findmy_pv(aTHX_ a,b) # define pad_findmy_pvn(a,b,c) Perl_pad_findmy_pvn(aTHX_ a,b,c) # define pad_findmy_sv(a,b) Perl_pad_findmy_sv(aTHX_ a,b) @@ -1574,7 +1581,7 @@ # if defined(PERL_IN_PAD_C) # define pad_alloc_name(a,b,c,d) S_pad_alloc_name(aTHX_ a,b,c,d) # define pad_check_dup(a,b,c) S_pad_check_dup(aTHX_ a,b,c) -# define pad_findlex(a,b,c,d,e,f,g,h,i) S_pad_findlex(aTHX_ a,b,c,d,e,f,g,h,i) +# define pad_findlex(a,b,c,d,e,f,g,h,i,j) S_pad_findlex(aTHX_ a,b,c,d,e,f,g,h,i,j) # define pad_reset() S_pad_reset(aTHX) # if defined(DEBUGGING) # define cv_dump(a,b) S_cv_dump(aTHX_ a,b) diff --git a/ext/XS-APItest/APItest.pm b/ext/XS-APItest/APItest.pm index 3b7201a0daf4..085e6dc2117e 100644 --- a/ext/XS-APItest/APItest.pm +++ b/ext/XS-APItest/APItest.pm @@ -4,7 +4,7 @@ use strict; use warnings; use Carp; -our $VERSION = '1.40'; +our $VERSION = '1.41'; require XSLoader; diff --git a/ext/XS-APItest/APItest.xs b/ext/XS-APItest/APItest.xs index 4196bbb7004c..c6f9fcebba94 100644 --- a/ext/XS-APItest/APItest.xs +++ b/ext/XS-APItest/APItest.xs @@ -786,6 +786,17 @@ THX_ck_entersub_postinc(pTHX_ OP *entersubop, GV *namegv, SV *ckobj) op_lvalue(op_contextualize(argop, G_SCALAR), OP_POSTINC)); } +enum Pad_Find_Method { + PAD_FINDMY_FOO, + PAD_FINDMY_PV, + PAD_FINDMY_PVN, + PAD_FINDMY_SV, + PAD_FIND_MY_SYMBOL_FOO, + PAD_FIND_MY_SYMBOL_PV, + PAD_FIND_MY_SYMBOL_PVN, + PAD_FIND_MY_SYMBOL_SV, +}; + STATIC OP * THX_ck_entersub_pad_scalar(pTHX_ OP *entersubop, GV *namegv, SV *ckobj) { @@ -802,12 +813,12 @@ THX_ck_entersub_pad_scalar(pTHX_ OP *entersubop, GV *namegv, SV *ckobj) a0 = cSVOPx_sv(argop); a1 = cSVOPx_sv(OpSIBLING(argop)); switch(SvIV(a0)) { - case 1: { + case PAD_FINDMY_SV: { SV *namesv = sv_2mortal(newSVpvs("$")); sv_catsv(namesv, a1); padoff = pad_findmy_sv(namesv, 0); } break; - case 2: { + case PAD_FINDMY_PVN: { char *namepv; STRLEN namelen; SV *namesv = sv_2mortal(newSVpvs("$")); @@ -815,16 +826,35 @@ THX_ck_entersub_pad_scalar(pTHX_ OP *entersubop, GV *namegv, SV *ckobj) namepv = SvPV(namesv, namelen); padoff = pad_findmy_pvn(namepv, namelen, SvUTF8(namesv)); } break; - case 3: { + case PAD_FINDMY_PV: { char *namepv; SV *namesv = sv_2mortal(newSVpvs("$")); sv_catsv(namesv, a1); namepv = SvPV_nolen(namesv); padoff = pad_findmy_pv(namepv, SvUTF8(namesv)); } break; - case 4: { + case PAD_FINDMY_FOO: { padoff = pad_findmy_pvs("$foo", 0); } break; + case PAD_FIND_MY_SYMBOL_FOO: { + padoff = pad_find_my_symbol_pvs (Perl_Symbol_Table_Scalar, "foo", 0); + break; + } + case PAD_FIND_MY_SYMBOL_PV: { + char *namepv = SvPV_nolen(a1); + padoff = pad_find_my_symbol_pv (Perl_Symbol_Table_Scalar, namepv, SvUTF8(a1)); + break; + } + case PAD_FIND_MY_SYMBOL_PVN: { + char *namepv; + STRLEN namelen; + namepv = SvPV(a1, namelen); + padoff = pad_find_my_symbol_pvn (Perl_Symbol_Table_Scalar, namepv, namelen, SvUTF8(a1)); + break; + } + case PAD_FIND_MY_SYMBOL_SV: { + padoff = pad_find_my_symbol_sv (Perl_Symbol_Table_Scalar, a1, 0); + } break; default: croak("bad type value for pad_scalar()"); } op_free(entersubop); @@ -1195,9 +1225,15 @@ static OP *THX_parse_keyword_subsignature(pTHX) case OP_ARGELEM: { PADOFFSET padix = kid->op_targ; PADNAMELIST *names = PadlistNAMES(CvPADLIST(find_runcv(0))); - char *namepv = PadnamePV(padnamelist_fetch(names, padix)); + PADNAME *pv = padnamelist_fetch(names, padix); retop = op_append_list(OP_LIST, retop, newSVOP(OP_CONST, 0, - newSVpvf(kid->op_flags & OPf_KIDS ? "argelem:%s:d" : "argelem:%s", namepv))); + newSVpvf( + kid->op_flags & OPf_KIDS + ? "argelem:" Padname_Symbol_Printf_Format ":d" + : "argelem:" Padname_Symbol_Printf_Format + , + Padname_Symbol_Printf_Params (pv) + ))); break; } default: @@ -1253,7 +1289,7 @@ static OP *THX_parse_keyword_with_vars(pTHX) croak("unexpected '%c'; expecting an identifier", (int)c); } - varname = newSVpvs("$"); + varname = newSVpvs(""); if (lex_bufutf8()) { SvUTF8_on(varname); } @@ -1266,7 +1302,7 @@ static OP *THX_parse_keyword_with_vars(pTHX) lex_read_unichar(0); } - padoff = pad_add_name_sv(varname, padadd_NO_DUP_CHECK, NULL, NULL); + padoff = pad_add_symbol_sv (Perl_Symbol_Table_Scalar, varname, padadd_NO_DUP_CHECK, NULL, NULL); { OP *my_var = newOP(OP_PADSV, OPf_MOD | (OPpLVAL_INTRO << 8)); @@ -4342,6 +4378,23 @@ OUTPUT: RETVAL +#define EXPORT_ENUM(Stash, Name) \ + newCONSTSUB(Stash, #Name, newSViv(Name)) + +BOOT: +{ + HV *stash = gv_stashpv("XS::APItest", TRUE); + + EXPORT_ENUM (stash, PAD_FINDMY_FOO); + EXPORT_ENUM (stash, PAD_FINDMY_PV); + EXPORT_ENUM (stash, PAD_FINDMY_PVN); + EXPORT_ENUM (stash, PAD_FINDMY_SV); + EXPORT_ENUM (stash, PAD_FIND_MY_SYMBOL_FOO); + EXPORT_ENUM (stash, PAD_FIND_MY_SYMBOL_PV); + EXPORT_ENUM (stash, PAD_FIND_MY_SYMBOL_PVN); + EXPORT_ENUM (stash, PAD_FIND_MY_SYMBOL_SV); +} + BOOT: { HV* stash; @@ -4354,6 +4407,7 @@ BOOT: croak("lost method 'make_temp_mg_lv'"); cv = GvCV(*meth); CvLVALUE_on(cv); + } BOOT: @@ -4668,7 +4722,7 @@ lexical_import(SV *name, CV *cv) SAVESPTR(PL_comppad_name); PL_comppad_name = PadlistNAMES(pl); SAVESPTR(PL_comppad); PL_comppad = PadlistARRAY(pl)[1]; SAVESPTR(PL_curpad); PL_curpad = PadARRAY(PL_comppad); - off = pad_add_name_sv(sv_2mortal(newSVpvf("&%" SVf,name)), + off = pad_add_symbol_sv (Perl_Symbol_Table_Code, sv_2mortal(newSVpvf("%" SVf,name)), padadd_STATE, 0, 0); SvREFCNT_dec(PL_curpad[off]); PL_curpad[off] = SvREFCNT_inc(cv); diff --git a/ext/XS-APItest/t/fetch_pad_names.t b/ext/XS-APItest/t/fetch_pad_names.t index 7670e9b3afa7..22f163ce4d96 100644 --- a/ext/XS-APItest/t/fetch_pad_names.t +++ b/ext/XS-APItest/t/fetch_pad_names.t @@ -12,7 +12,7 @@ else { plan tests => 77; } -use XS::APItest qw( fetch_pad_names pad_scalar ); +use XS::APItest qw( fetch_pad_names pad_scalar PAD_FINDMY_SV ); local $SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /Wide character in print at/ }; @@ -34,7 +34,11 @@ $cv = sub { my $zest = 'invariant'; my $zèst = 'latin-1'; - return [pad_scalar(1, "zèst"), pad_scalar(1, "z\350st"), pad_scalar(1, "z\303\250st")]; + return [ + pad_scalar (PAD_FINDMY_SV, "zèst"), + pad_scalar (PAD_FINDMY_SV, "z\350st"), + pad_scalar (PAD_FINDMY_SV, "z\303\250st"), + ]; }; my $names_av = fetch_pad_names($cv); @@ -65,7 +69,11 @@ $cv = do { sub { use utf8; my $партнеры = $ascii; - return [$партнеры, pad_scalar(1, "партнеры"), pad_scalar(1, "\320\277\320\260\321\200\321\202\320\275\320\265\321\200\321\213")]; + return [ + $партнеры, + pad_scalar (PAD_FINDMY_SV, "партнеры"), + pad_scalar (PAD_FINDMY_SV, "\320\277\320\260\321\200\321\202\320\275\320\265\321\200\321\213"), + ]; }; }; @@ -109,7 +117,7 @@ $cv = eval <<"END"; use utf8; my \$Leon = 'Invariant'; my $leon1 = 'Latin-1'; - return [ \$Leon, $leon1, $leon2, pad_scalar(1, "L\x{e9}on"), pad_scalar(1, "L\x{c3}\x{a9}on")]; + return [ \$Leon, $leon1, $leon2, pad_scalar(PAD_FINDMY_SV, "L\x{e9}on"), pad_scalar(PAD_FINDMY_SV, "L\x{c3}\x{a9}on")]; }; END @@ -225,10 +233,10 @@ $cv = sub { return [ $tèst, - pad_scalar(1, "tèst"), #"UTF-8" - pad_scalar(1, "t\350st"), #"Latin-1" - pad_scalar(1, "t\x{c3}\x{a8}st"), #"Octal" - pad_scalar(1, test()), #'UTF-8 enc' + pad_scalar (PAD_FINDMY_SV, "tèst"), #"UTF-8" + pad_scalar (PAD_FINDMY_SV, "t\350st"), #"Latin-1" + pad_scalar (PAD_FINDMY_SV, "t\x{c3}\x{a8}st"), #"Octal" + pad_scalar (PAD_FINDMY_SV, test()), #'UTF-8 enc' ]; }; @@ -261,12 +269,12 @@ $cv = do { return [ $ニコニコ, $にこにこ, - pad_scalar(1, "にこにこ"), - pad_scalar(1, "\x{306b}\x{3053}\x{306b}\x{3053}"), - pad_scalar(1, "\343\201\253\343\201\223\343\201\253\343\201\223"), - pad_scalar(1, "ニコニコ"), - pad_scalar(1, "\x{30cb}\x{30b3}\x{30cb}\x{30b3}"), - pad_scalar(1, "\343\203\213\343\202\263\343\203\213\343\202\263"), + pad_scalar (PAD_FINDMY_SV, "にこにこ"), + pad_scalar (PAD_FINDMY_SV, "\x{306b}\x{3053}\x{306b}\x{3053}"), + pad_scalar (PAD_FINDMY_SV, "\343\201\253\343\201\223\343\201\253\343\201\223"), + pad_scalar (PAD_FINDMY_SV, "ニコニコ"), + pad_scalar (PAD_FINDMY_SV, "\x{30cb}\x{30b3}\x{30cb}\x{30b3}"), + pad_scalar (PAD_FINDMY_SV, "\343\203\213\343\202\263\343\203\213\343\202\263"), ]; } }; @@ -302,7 +310,7 @@ general_tests( $cv->(), $names_av, { use constant utf8_e => $utf8_e; } my $e = 'Invariant'; - is pad_scalar(1, "e"), pad_scalar(1, utf8_e), 'Fetches the same thing, even if invariant but with differing utf8ness.'; + is pad_scalar (PAD_FINDMY_SV, "e"), pad_scalar (PAD_FINDMY_SV, utf8_e), 'Fetches the same thing, even if invariant but with differing utf8ness.'; } diff --git a/ext/XS-APItest/t/pad_scalar.t b/ext/XS-APItest/t/pad_scalar.t index 52c8812c6ba3..b7bf21e29006 100644 --- a/ext/XS-APItest/t/pad_scalar.t +++ b/ext/XS-APItest/t/pad_scalar.t @@ -1,59 +1,122 @@ use warnings; use strict; -use Test::More tests => 76; +use Test::More tests => 139; -use XS::APItest qw(pad_scalar); +use XS::APItest qw ( + PAD_FINDMY_FOO + PAD_FINDMY_PV + PAD_FINDMY_PVN + PAD_FINDMY_SV + PAD_FIND_MY_SYMBOL_FOO + PAD_FIND_MY_SYMBOL_PV + PAD_FIND_MY_SYMBOL_PVN + PAD_FIND_MY_SYMBOL_SV + pad_scalar +); -is pad_scalar(1, "foo"), "NOT_IN_PAD"; -is pad_scalar(2, "foo"), "NOT_IN_PAD"; -is pad_scalar(3, "foo"), "NOT_IN_PAD"; -is pad_scalar(4, "foo"), "NOT_IN_PAD"; -is pad_scalar(1, "bar"), "NOT_IN_PAD"; -is pad_scalar(2, "bar"), "NOT_IN_PAD"; -is pad_scalar(3, "bar"), "NOT_IN_PAD"; +is pad_scalar (PAD_FINDMY_SV, "foo"), "NOT_IN_PAD", q (undeclared '$foo'; pad_findmy_sv ()); +is pad_scalar (PAD_FINDMY_PVN, "foo"), "NOT_IN_PAD", q (undeclared '$foo'; pad_findmy_pvn ()); +is pad_scalar (PAD_FINDMY_PV, "foo"), "NOT_IN_PAD", q (undeclared '$foo'; pad_findmy_pv ()); +is pad_scalar (PAD_FINDMY_FOO, "foo"), "NOT_IN_PAD", q (undeclared '$foo'; pad_findmy_pvs ()); +is pad_scalar (PAD_FIND_MY_SYMBOL_FOO, "foo"), "NOT_IN_PAD", q (undeclared '$foo'; pad_find_my_symbol_pvs ()); +is pad_scalar (PAD_FIND_MY_SYMBOL_PV, "foo"), "NOT_IN_PAD", q (undeclared '$foo'; pad_find_my_symbol_pv ()); +is pad_scalar (PAD_FIND_MY_SYMBOL_PVN, "foo"), "NOT_IN_PAD", q (undeclared '$foo'; pad_find_my_symbol_pvn ()); +is pad_scalar (PAD_FIND_MY_SYMBOL_SV, "foo"), "NOT_IN_PAD", q (undeclared '$foo'; pad_find_my_symbol_sv ()); + +is pad_scalar (PAD_FINDMY_SV, "bar"), "NOT_IN_PAD", q (undeclared '$bar'; pad_findmy_sv ()); +is pad_scalar (PAD_FINDMY_PVN, "bar"), "NOT_IN_PAD", q (undeclared '$bar'; pad_findmy_pvn ()); +is pad_scalar (PAD_FINDMY_PV, "bar"), "NOT_IN_PAD", q (undeclared '$bar'; pad_findmy_pv ()); +is pad_scalar (PAD_FIND_MY_SYMBOL_PV, "bar"), "NOT_IN_PAD", q (undeclared '$bar'; pad_find_my_symbol_pv ()); +is pad_scalar (PAD_FIND_MY_SYMBOL_PVN, "bar"), "NOT_IN_PAD", q (undeclared '$bar'; pad_find_my_symbol_pvn ()); +is pad_scalar (PAD_FIND_MY_SYMBOL_SV, "bar"), "NOT_IN_PAD", q (undeclared '$bar'; pad_find_my_symbol_sv ()); our $foo = "wibble"; my $bar = "wobble"; -is pad_scalar(1, "foo"), "NOT_MY"; -is pad_scalar(2, "foo"), "NOT_MY"; -is pad_scalar(3, "foo"), "NOT_MY"; -is pad_scalar(4, "foo"), "NOT_MY"; -is pad_scalar(1, "bar"), "wobble"; -is pad_scalar(2, "bar"), "wobble"; -is pad_scalar(3, "bar"), "wobble"; +is pad_scalar (PAD_FINDMY_SV, "foo"), "NOT_MY", q ('our $foo'; pad_findmy_sv ()); +is pad_scalar (PAD_FINDMY_PVN, "foo"), "NOT_MY", q ('our $foo'; pad_findmy_pvn ()); +is pad_scalar (PAD_FINDMY_PV, "foo"), "NOT_MY", q ('our $foo'; pad_findmy_pv ()); +is pad_scalar (PAD_FINDMY_FOO, "foo"), "NOT_MY", q ('our $foo'; pad_findmy_pvs ()); +is pad_scalar (PAD_FIND_MY_SYMBOL_FOO, "foo"), "NOT_MY", q ('our $foo'; pad_find_my_symbol_pvs ()); +is pad_scalar (PAD_FIND_MY_SYMBOL_PV, "foo"), "NOT_MY", q ('our $foo'; pad_find_my_symbol_pv ()); +is pad_scalar (PAD_FIND_MY_SYMBOL_PVN, "foo"), "NOT_MY", q ('our $foo'; pad_find_my_symbol_pvn ()); +is pad_scalar (PAD_FIND_MY_SYMBOL_SV, "foo"), "NOT_MY", q ('our $foo'; pad_find_my_symbol_sv ()); + +is pad_scalar (PAD_FINDMY_SV, "bar"), "wobble", q ('my $bar'; pad_findmy_sv ()); +is pad_scalar (PAD_FINDMY_PVN, "bar"), "wobble", q ('my $bar'; pad_findmy_pvn ()); +is pad_scalar (PAD_FINDMY_PV, "bar"), "wobble", q ('my $bar'; pad_findmy_pv ()); +is pad_scalar (PAD_FIND_MY_SYMBOL_PV, "bar"), "wobble", q ('my $bar'; pad_find_my_symbol_pv ()); +is pad_scalar (PAD_FIND_MY_SYMBOL_PVN, "bar"), "wobble", q ('my $bar'; pad_find_my_symbol_pvn ()); +is pad_scalar (PAD_FIND_MY_SYMBOL_SV, "bar"), "wobble", q ('my $bar'; pad_find_my_symbol_sv ()); sub aa($); sub aa($) { my $xyz; - ok \pad_scalar(1, "xyz") == \$xyz; - ok \pad_scalar(2, "xyz") == \$xyz; - ok \pad_scalar(3, "xyz") == \$xyz; - aa(0) if $_[0]; - ok \pad_scalar(1, "xyz") == \$xyz; - ok \pad_scalar(2, "xyz") == \$xyz; - ok \pad_scalar(3, "xyz") == \$xyz; - is pad_scalar(1, "bar"), "wobble"; - is pad_scalar(2, "bar"), "wobble"; - is pad_scalar(3, "bar"), "wobble"; + my $prefix = $_[0] + ? '' + : '(recursive call) ' + ; + + ok \pad_scalar (PAD_FINDMY_SV, "xyz") == \$xyz, $prefix . q (private variable; pad_findmy_sv ()); + ok \pad_scalar (PAD_FINDMY_PVN, "xyz") == \$xyz, $prefix . q (private variable; pad_findmy_pvn ()); + ok \pad_scalar (PAD_FINDMY_PV, "xyz") == \$xyz, $prefix . q (private variable; pad_findmy_pv ()); + ok \pad_scalar (PAD_FIND_MY_SYMBOL_PV, "xyz") == \$xyz, $prefix . q (private variable; pad_find_my_symbol_pv ()); + ok \pad_scalar (PAD_FIND_MY_SYMBOL_PVN, "xyz") == \$xyz, $prefix . q (private variable; pad_find_my_symbol_pvn ()); + ok \pad_scalar (PAD_FIND_MY_SYMBOL_SV, "xyz") == \$xyz, $prefix . q (private variable; pad_find_my_symbol_sv ()); + + if ($_[0]) { + aa(0); # recursive call + ok \pad_scalar (PAD_FINDMY_SV, "xyz") == \$xyz, q (private variable (after recursive call); pad_findmy_sv ()); + ok \pad_scalar (PAD_FINDMY_PVN, "xyz") == \$xyz, q (private variable (after recursive call); pad_findmy_pvn ()); + ok \pad_scalar (PAD_FINDMY_PV, "xyz") == \$xyz, q (private variable (after recursive call); pad_findmy_pv ()); + ok \pad_scalar (PAD_FIND_MY_SYMBOL_PV, "xyz") == \$xyz, q (private variable (after recursive call); pad_find_my_symbol_pv ()); + ok \pad_scalar (PAD_FIND_MY_SYMBOL_PVN, "xyz") == \$xyz, q (private variable (after recursive call); pad_find_my_symbol_pvn ()); + ok \pad_scalar (PAD_FIND_MY_SYMBOL_SV, "xyz") == \$xyz, q (private variable (after recursive call); pad_find_my_symbol_sv ()); + } + + is pad_scalar (PAD_FINDMY_SV, "bar"), "wobble", $prefix . q (Global 'my $bar'; pad_findmy_sv ()); + is pad_scalar (PAD_FINDMY_PVN, "bar"), "wobble", $prefix . q (Global 'my $bar'; pad_findmy_pvn ()); + is pad_scalar (PAD_FINDMY_PV, "bar"), "wobble", $prefix . q (Global 'my $bar'; pad_findmy_pv ()); + is pad_scalar (PAD_FIND_MY_SYMBOL_PV, "bar"), "wobble", $prefix . q (Global 'my $bar'; pad_find_my_symbol_pv ()); + is pad_scalar (PAD_FIND_MY_SYMBOL_PVN, "bar"), "wobble", $prefix . q (Global 'my $bar'; pad_find_my_symbol_pvn ()); + is pad_scalar (PAD_FIND_MY_SYMBOL_SV, "bar"), "wobble", $prefix . q (Global 'my $bar'; pad_find_my_symbol_sv ()); } + aa(1); +my $all_increment_called = 0; + sub bb() { my $counter = 0; my $foo = \$counter; return sub { - ok pad_scalar(1, "foo") == \pad_scalar(1, "counter"); - ok pad_scalar(2, "foo") == \pad_scalar(1, "counter"); - ok pad_scalar(3, "foo") == \pad_scalar(1, "counter"); - ok pad_scalar(4, "foo") == \pad_scalar(1, "counter"); - if(pad_scalar(1, "counter") % 3 == 0) { - return pad_scalar(1, "counter")++; - } elsif(pad_scalar(1, "counter") % 3 == 0) { - return pad_scalar(2, "counter")++; - } else { - return pad_scalar(3, "counter")++; - } + ok pad_scalar (PAD_FINDMY_SV, "foo") == \pad_scalar(PAD_FINDMY_SV, "counter"); + ok pad_scalar (PAD_FINDMY_PVN, "foo") == \pad_scalar(PAD_FINDMY_SV, "counter"); + ok pad_scalar (PAD_FINDMY_PV, "foo") == \pad_scalar(PAD_FINDMY_SV, "counter"); + ok pad_scalar (PAD_FINDMY_FOO, "foo") == \pad_scalar(PAD_FINDMY_SV, "counter"); + ok pad_scalar (PAD_FIND_MY_SYMBOL_PV, "foo") == \pad_scalar(PAD_FINDMY_SV, "counter"); + ok pad_scalar (PAD_FIND_MY_SYMBOL_PVN, "foo") == \pad_scalar(PAD_FINDMY_SV, "counter"); + ok pad_scalar (PAD_FIND_MY_SYMBOL_SV, "foo") == \pad_scalar(PAD_FINDMY_SV, "counter"); + + my $modulus = pad_scalar (PAD_FINDMY_SV, "counter") % 6; + + return pad_scalar (PAD_FINDMY_SV, "counter")++ + if $modulus == 0; + + return pad_scalar (PAD_FINDMY_PVN, "counter")++ + if $modulus == 1; + + return pad_scalar (PAD_FINDMY_PV, "counter")++ + if $modulus == 2; + + return pad_scalar (PAD_FIND_MY_SYMBOL_PV, "counter")++ + if $modulus == 3; + + return pad_scalar (PAD_FIND_MY_SYMBOL_PVN, "counter")++ + if $modulus == 4; + + $all_increment_called = 1; + return pad_scalar (PAD_FIND_MY_SYMBOL_SV, "counter")++; }; } my $a = bb(); @@ -66,10 +129,17 @@ is $b->(), 0; is $b->(), 1; is $a->(), 4; is $b->(), 2; +is $a->(), 5; + +ok $all_increment_called, q (all pad scalar methods called for increment); -is pad_scalar(1, "foo"), "NOT_MY"; -is pad_scalar(2, "foo"), "NOT_MY"; -is pad_scalar(3, "foo"), "NOT_MY"; -is pad_scalar(4, "foo"), "NOT_MY"; +is pad_scalar (PAD_FINDMY_SV, "foo"), "NOT_MY", q ('my $foo' still undeclared; pad_findmy_sv ()); +is pad_scalar (PAD_FINDMY_PVN, "foo"), "NOT_MY", q ('my $foo' still undeclared; pad_findmy_pvn ()); +is pad_scalar (PAD_FINDMY_PV, "foo"), "NOT_MY", q ('my $foo' still undeclared; pad_findmy_pv ()); +is pad_scalar (PAD_FINDMY_FOO, "foo"), "NOT_MY", q ('my $foo' still undeclared; pad_findmy_pvs ()); +is pad_scalar (PAD_FIND_MY_SYMBOL_FOO, "foo"), "NOT_MY", q ('my $foo' still undeclared; pad_find_my_symbol_pvs ()); +is pad_scalar (PAD_FIND_MY_SYMBOL_PV, "foo"), "NOT_MY", q ('my $foo' still undeclared; pad_find_my_symbol_pv ()); +is pad_scalar (PAD_FIND_MY_SYMBOL_PVN, "foo"), "NOT_MY", q ('my $foo' still undeclared; pad_find_my_symbol_pvn ()); +is pad_scalar (PAD_FIND_MY_SYMBOL_SV, "foo"), "NOT_MY", q ('my $foo' still undeclared; pad_find_my_symbol_sv ()); 1; diff --git a/handy.h b/handy.h index ebb17f9cb28d..7e7c05264d7c 100644 --- a/handy.h +++ b/handy.h @@ -416,6 +416,44 @@ Perl_xxx(aTHX_ ...) form for any API calls where it's used. Perl_newSVpvn_flags(aTHX_ STR_WITH_LEN(str), flags) #define newSVpvs_share(str) Perl_newSVpvn_share(aTHX_ STR_WITH_LEN(str), 0) +/* +=for apidoc_section $utility + +=for apidoc Amu|Function call|EXPAND_CALL|Macro, Arguments_List + +When calling macro C with arguments containing another macro +which expands as multiple arguments (for example: C) we +need to expand arguments before expanding C macro. + +Usage: + + #define my_macro(Arg1, Arg2) \ + EXPAND_CALL (Macro, (Arg1, STR_WITH_LEN (Arg2)) + +Note: C must include C<()> to enforce single expression + +Example: + + #define pad_add_symbol_pvs(Table, Name, Flags, Type, Our) \ + EXPAND_CALL ( \ + pad_add_symbol_pvn, \ + (Table, STR_WITH_LEN (Name), Flags, Type, Our) \ + ) + +In this case C is macro so calling it directly fails +because C expands as two arguments, but for preprocessor, when used +directly, it is only one. + +Using C introduces additional step where any macro used in arguments +is expanded before expanding C itself. + +=cut + +*/ + +#define EXPAND_CALL(Macro, Args) \ + Macro Args + /* =for apidoc_defn Am|void|sv_catpvs_flags|SV * const dsv|"literal string"|I32 flags =for apidoc_defn Am|void|sv_catpvs_nomg|SV * const dsv|"literal string" diff --git a/op.c b/op.c index 1b5c11c58bc1..00b0c480bc50 100644 --- a/op.c +++ b/op.c @@ -809,7 +809,7 @@ Perl_allocmy(pTHX_ const char *const name, const STRLEN len, const U32 flags) else if(PL_parser->in_my == KEY_field) addflags |= padadd_FIELD; - off = pad_add_name_pvn(name, len, addflags, + off = pad_add_symbol_pvn (*name, name + 1, len - 1, addflags, PL_parser->in_my_stash, (is_our /* $_ is always in main::, even with our */ @@ -6074,7 +6074,7 @@ Perl_newBINOP(pTHX_ I32 type, I32 flags, OP *first, OP *last) ? 2 /* Otherwise, minimum of 2 hex digits */\ : NUM_HEX_CHARS(num))))))) -/* To make evident, Configure with `-DDEBUGGING`, build, run +/* To make evident, Configure with `-DDEBUGGING`, build, run * `./perl -Ilib -Dy t/op/tr.t` */ void @@ -8622,7 +8622,7 @@ S_newONCEOP(pTHX_ OP *initop, OP *padop) /* Store the initializedness of state vars in a separate pad entry. */ condop->op_targ = - pad_add_name_pvn("$",1,padadd_NO_DUP_CHECK|padadd_STATE,0,0); + pad_add_symbol_pvn (Perl_Symbol_Table_Scalar, "", 0, padadd_NO_DUP_CHECK|padadd_STATE,0,0); /* hijacking PADSTALE for uninitialized state variables */ SvPADSTALE_on(PAD_SVl(condop->op_targ)); @@ -9390,10 +9390,10 @@ Perl_newRANGE(pTHX_ I32 flags, OP *left, OP *right) right->op_next = flop; range->op_targ = - pad_add_name_pvn("$", 1, padadd_NO_DUP_CHECK|padadd_STATE, 0, 0); + pad_add_symbol_pvn (Perl_Symbol_Table_Scalar, "", 0, padadd_NO_DUP_CHECK|padadd_STATE, 0, 0); sv_upgrade(PAD_SV(range->op_targ), SVt_PVNV); flip->op_targ = - pad_add_name_pvn("$", 1, padadd_NO_DUP_CHECK|padadd_STATE, 0, 0);; + pad_add_symbol_pvn (Perl_Symbol_Table_Scalar, "", 0, padadd_NO_DUP_CHECK|padadd_STATE, 0, 0); sv_upgrade(PAD_SV(flip->op_targ), SVt_PVNV); SvPADTMP_on(PAD_SV(flip->op_targ)); @@ -9812,9 +9812,9 @@ Perl_newFOROP(pTHX_ I32 flags, OP *sv, OP *expr, OP *block, OP *cont) Perl_croak(aTHX_ "Can't use %s for loop variable", PL_op_desc[sv->op_type]); if (padoff) { PADNAME * const pn = PAD_COMPNAME(padoff); - const char * const name = PadnamePV(pn); + const char * const name = Padname_Symbol_Name (pn); - if (PadnameLEN(pn) == 2 && name[0] == '$' && name[1] == '_') + if (Padname_Symbol_Name_Length (pn) == 1 && Padname_Is_Symbol_Table_Scalar (pn) && name[0] == '_') enteriterpflags |= OPpITER_DEF; } } @@ -10289,7 +10289,7 @@ S_already_defined(pTHX_ CV *const cv, OP * const block, OP * const o, const line_t oldline = CopLINE(PL_curcop); SV *namesv = o ? cSVOPo->op_sv - : newSVpvn_flags( PadnamePV(name)+1,PadnameLEN(name)-1, + : newSVpvn_flags( Padname_Symbol_Name (name), Padname_Symbol_Name_Length (name), (PadnameUTF8(name)) ? SVf_UTF8|SVs_TEMP : SVs_TEMP ); if (PL_parser && PL_parser->copline != NOLINE) @@ -10400,11 +10400,11 @@ Perl_newMYSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) hek = CvNAME_HEK(*spot); else { U32 hash; - PERL_HASH(hash, PadnamePV(name)+1, PadnameLEN(name)-1); + PERL_HASH(hash, Padname_Symbol_Name (name), Padname_Symbol_Name_Length (name)); CvNAME_HEK_set(*spot, hek = share_hek( - PadnamePV(name)+1, - (PadnameLEN(name)-1) * (PadnameUTF8(name) ? -1 : 1), + Padname_Symbol_Name (name), + (Padname_Symbol_Name_Length (name)) * (PadnameUTF8(name) ? -1 : 1), hash ) ); @@ -10559,9 +10559,9 @@ Perl_newMYSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) if (hek) (void)share_hek_hek(hek); else { U32 hash; - PERL_HASH(hash, PadnamePV(name)+1, PadnameLEN(name)-1); - hek = share_hek(PadnamePV(name)+1, - (PadnameLEN(name)-1) * (PadnameUTF8(name) ? -1 : 1), + PERL_HASH(hash, Padname_Symbol_Name (name), Padname_Symbol_Name_Length (name)); + hek = share_hek(Padname_Symbol_Name (name), + (Padname_Symbol_Name_Length (name)) * (PadnameUTF8(name) ? -1 : 1), hash); } CvNAME_HEK_set(cv, hek); @@ -10622,7 +10622,7 @@ Perl_newMYSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) else sv_setpvs(tmpstr, "__ANON__::"); - sv_catpvn_flags(tmpstr, PadnamePV(name)+1, PadnameLEN(name)-1, + sv_catpvn_flags(tmpstr, Padname_Symbol_Name (name), Padname_Symbol_Name_Length (name), PadnameUTF8(name) ? SV_CATUTF8 : SV_CATBYTES); (void)hv_store_ent(GvHV(PL_DBsub), tmpstr, sv, 0); hv = GvHVn(db_postponed); @@ -13068,8 +13068,8 @@ Perl_ck_fun(pTHX_ OP *o) if (kid->op_type == OP_PADSV) { PADNAME * const pn = PAD_COMPNAME_SV(kid->op_targ); - name = PadnamePV (pn); - len = PadnameLEN(pn); + name = Padname_Symbol_Name (pn); + len = Padname_Symbol_Name_Length (pn); name_utf8 = PadnameUTF8(pn); } else if (kid->op_type == OP_RV2SV @@ -13973,14 +13973,10 @@ Perl_ck_sort(pTHX_ OP *o) } else if (kid->op_type == OP_CONST && kid->op_private & OPpCONST_BARE) { - char tmpbuf[256]; STRLEN len; PADOFFSET off; const char * const name = SvPV(kSVOP_sv, len); - *tmpbuf = '&'; - assert (len < 256); - Copy(name, tmpbuf+1, len, char); - off = pad_findmy_pvn(tmpbuf, len+1, 0); + off = pad_find_my_symbol_pvn (Perl_Symbol_Table_Code, name, len, 0); if (off != NOT_IN_PAD) { if (PAD_COMPNAME_FLAGS_isOUR(off)) { SV * const fq = @@ -14068,9 +14064,9 @@ S_simplify_sort(pTHX_ OP *o) do { if (kid->op_type == OP_PADSV) { PADNAME * const name = PAD_COMPNAME(kid->op_targ); - if (PadnameLEN(name) == 2 && *PadnamePV(name) == '$' - && ( PadnamePV(name)[1] == 'a' - || PadnamePV(name)[1] == 'b' )) + if (Padname_Symbol_Name_Length (name) == 1 && Padname_Is_Symbol_Table_Scalar (name) + && ( Padname_Symbol_Name (name)[0] == 'a' + || Padname_Symbol_Name (name)[0] == 'b' )) /* diag_listed_as: "my %s" used in sort comparison */ Perl_warner(aTHX_ packWARN(WARN_SYNTAX), "\"%s %s\" used in sort comparison", diff --git a/pad.c b/pad.c index 9b943b1158e4..dc7103006b3c 100644 --- a/pad.c +++ b/pad.c @@ -114,7 +114,7 @@ write is called (if necessary). The flag C is cleared on lexicals each time the C is executed, and set on scope exit. This allows the C<"Variable $x is not available"> warning -to be generated in evals, such as +to be generated in evals, such as { my $x = 1; sub f { eval '$x'} } f(); @@ -391,7 +391,7 @@ Perl_cv_undef_flags(pTHX_ CV *cv, U32 flags) PTR2UV(cv), PTR2UV(padlist), PTR2UV(PL_comppad)) ); - /* detach any '&' anon children in the pad; if afterwards they + /* detach any 'Perl_Symbol_Table_Code' anon children in the pad; if afterwards they * are still live, fix up their CvOUTSIDEs to point to our outside, * bypassing us. */ @@ -404,7 +404,7 @@ Perl_cv_undef_flags(pTHX_ CV *cv, U32 flags) SV ** const curpad = AvARRAY(comppad); for (ix = PadnamelistMAX(comppad_name); ix > 0; ix--) { PADNAME * const name = namepad[ix]; - if (name && PadnamePV(name) && *PadnamePV(name) == '&') { + if (name && PadnamePV(name) && Padname_Is_Symbol_Table_Code (name)) { CV * const innercv = MUTABLE_CV(curpad[ix]); if (PadnameIsOUR(name) && CvCLONED(&cvbody)) { assert(!innercv); @@ -577,7 +577,7 @@ S_pad_alloc_name(pTHX_ PADNAME *name, U32 flags, HV *typestash, } padnamelist_store(PL_comppad_name, offset, name); - if (PadnameLEN(name) > 1) + if (! Padname_Symbol_Is_Anonymous (name)) PadnamelistMAXNAMED(PL_comppad_name) = offset; return offset; } @@ -586,6 +586,9 @@ S_pad_alloc_name(pTHX_ PADNAME *name, U32 flags, HV *typestash, =for apidoc pad_add_name_pv =for apidoc_item pad_add_name_pvn =for apidoc_item pad_add_name_sv +=for apidoc_item pad_add_symbol_pv +=for apidoc_item pad_add_symbol_pvn +=for apidoc_item pad_add_symbol_sv These each allocate a place in the currently-compiling pad for a named lexical variable. They store the name and other metadata in the name part of the @@ -616,23 +619,41 @@ In C, C gives the length of the input name in bytes, which means it may contain embedded NUL characters. Again, it must be encoded in UTF-8. +C uses separated symbol table and symbol name arguments. + =cut */ PADOFFSET Perl_pad_add_name_pvn(pTHX_ const char *namepv, STRLEN namelen, U32 flags, HV *typestash, HV *ourstash) +{ + PERL_ARGS_ASSERT_PAD_ADD_NAME_PVN; + + return pad_add_symbol_pvn (*namepv, namepv + 1, namelen - 1, flags, typestash, ourstash); +} + +PADOFFSET +Perl_pad_add_symbol_pvn( + pTHX_ + perl_symbol_table_id symbol_table, + const char *namepv, + STRLEN namelen, + U32 flags, + HV *typestash, + HV *ourstash +) { PADOFFSET offset; PADNAME *name; - PERL_ARGS_ASSERT_PAD_ADD_NAME_PVN; + PERL_ARGS_ASSERT_PAD_ADD_SYMBOL_PVN; if (flags & ~(padadd_OUR|padadd_STATE|padadd_NO_DUP_CHECK|padadd_FIELD)) Perl_croak(aTHX_ "panic: pad_add_name_pvn illegal flag bits 0x%" UVxf, (UV)flags); - name = newPADNAMEpvn(namepv, namelen); + name = new_padname_symbol_pvn (symbol_table, namepv, namelen); if ((flags & (padadd_NO_DUP_CHECK)) == 0) { ENTER; @@ -655,16 +676,23 @@ Perl_pad_add_name_pvn(pTHX_ const char *namepv, STRLEN namelen, /* if it's not a simple scalar, replace with an AV or HV */ assert(SvTYPE(PL_curpad[offset]) == SVt_NULL); assert(SvREFCNT(PL_curpad[offset]) == 1); - if (namelen != 0 && *namepv == '@') - sv_upgrade(PL_curpad[offset], SVt_PVAV); - else if (namelen != 0 && *namepv == '%') - sv_upgrade(PL_curpad[offset], SVt_PVHV); - else if (namelen != 0 && *namepv == '&') - sv_upgrade(PL_curpad[offset], SVt_PVCV); + if (namelen != 0) { + switch (symbol_table) { + case Perl_Symbol_Table_Array: + sv_upgrade(PL_curpad[offset], SVt_PVAV); + break; + case Perl_Symbol_Table_Hash: + sv_upgrade(PL_curpad[offset], SVt_PVHV); + break; + case Perl_Symbol_Table_Code: + sv_upgrade(PL_curpad[offset], SVt_PVCV); + break; + } + } assert(SvPADMY(PL_curpad[offset])); DEBUG_Xv(PerlIO_printf(Perl_debug_log, - "Pad addname: %ld \"%s\" new lex=0x%" UVxf "\n", - (long)offset, PadnamePV(name), + "Pad addname: %ld \"" Padname_Symbol_Printf_Format "\" new lex=0x%" UVxf "\n", + (long)offset, Padname_Symbol_Printf_Params (name), PTR2UV(PL_curpad[offset]))); return offset; @@ -675,7 +703,21 @@ Perl_pad_add_name_pv(pTHX_ const char *name, const U32 flags, HV *typestash, HV *ourstash) { PERL_ARGS_ASSERT_PAD_ADD_NAME_PV; - return pad_add_name_pvn(name, strlen(name), flags, typestash, ourstash); + return pad_add_symbol_pvn (*name, name + 1, strlen(name) - 1, flags, typestash, ourstash); +} + +PADOFFSET +Perl_pad_add_symbol_pv( + pTHX_ + perl_symbol_table_id symbol_table, + const char *name, + const U32 flags, + HV *typestash, + HV *ourstash +) +{ + PERL_ARGS_ASSERT_PAD_ADD_SYMBOL_PV; + return pad_add_symbol_pvn (symbol_table, name, strlen(name), flags, typestash, ourstash); } PADOFFSET @@ -685,7 +727,24 @@ Perl_pad_add_name_sv(pTHX_ SV *name, U32 flags, HV *typestash, HV *ourstash) STRLEN namelen; PERL_ARGS_ASSERT_PAD_ADD_NAME_SV; namepv = SvPVutf8(name, namelen); - return pad_add_name_pvn(namepv, namelen, flags, typestash, ourstash); + return pad_add_symbol_pvn (*namepv, namepv + 1, namelen - 1, flags, typestash, ourstash); +} + +PADOFFSET +Perl_pad_add_symbol_sv ( + pTHX_ + perl_symbol_table_id symbol_table, + SV * name, + U32 flags, + HV * typestash, + HV * ourstash +) +{ + char *namepv; + STRLEN namelen; + PERL_ARGS_ASSERT_PAD_ADD_SYMBOL_SV; + namepv = SvPVutf8(name, namelen); + return pad_add_symbol_pvn (symbol_table, namepv, namelen, flags, typestash, ourstash); } /* @@ -754,9 +813,11 @@ Perl_pad_alloc(pTHX_ I32 optype, U32 tmptype) * can be reused; not so for constants. */ PADNAME *pn; - if (++retval <= names_fill && - (pn = names[retval]) && PadnamePV(pn)) - continue; + if (++retval <= names_fill) { + pn = names[retval]; + if (Padname_Is_Symbol (pn)) + continue; + } sv = *av_fetch_simple(PL_comppad, retval, TRUE); if (!(SvFLAGS(sv) & #ifdef USE_PAD_RESET @@ -810,7 +871,7 @@ PADOFFSET Perl_pad_add_anon(pTHX_ CV* func, I32 optype) { PADOFFSET ix; - PADNAME * const name = newPADNAMEpvn("&", 1); + PADNAME * const name = new_padname_symbol_pvn (Perl_Symbol_Table_Code, "", 0); PERL_ARGS_ASSERT_PAD_ADD_ANON; assert (SvTYPE(func) == SVt_PVCV); @@ -837,7 +898,7 @@ void Perl_pad_add_weakref(pTHX_ CV* func) { const PADOFFSET ix = pad_alloc(OP_NULL, SVs_PADMY); - PADNAME * const name = newPADNAMEpvn("&", 1); + PADNAME * const name = new_padname_symbol_pvn (Perl_Symbol_Table_Code, "", 0); SV * const rv = newRV_inc((SV *)func); PERL_ARGS_ASSERT_PAD_ADD_WEAKREF; @@ -907,7 +968,7 @@ S_pad_check_dup(pTHX_ PADNAME *name, U32 flags, const HV *ourstash) PL_parser->in_my == KEY_sigvar ? "my" : PL_parser->in_my == KEY_field ? "field" : "state" ), - *PadnamePV(pn) == '&' ? "subroutine" : "variable", + Padname_Symbol_Table_Title_lc (pn), PNfARG(pn), (COP_SEQ_RANGE_HIGH(pn) == PERL_PADSEQ_INTRO ? "scope" : "statement")); @@ -974,11 +1035,47 @@ C is reserved and must be zero. =for apidoc Amnh||NOT_IN_PAD +=for apidoc pad_find_my_symbol_pv +=for apidoc_item pad_find_my_symbol_pvn +=for apidoc_item pad_find_my_symbol_pvs +=for apidoc_item pad_find_my_symbol_sv + +Similar to C but with explicit symbol table parameter. + +Difference: + + pad_findmy_pv ("$self", 0); + pad_find_my_symbol_pv (Perl_Symbol_Scalar, "self", 0); + + pad_findmy_pvn ("$self", 5, 0); + pad_find_my_symbol_pvn (Perl_Symbol_Scalar, "self", 5, 0); + + pad_findmy_pvs ("$self", 0); + pad_find_my_symbol_pvs (Perl_Symbol_Scalar, "self", 0); + + // sv (string) means SV * with context "string" + pad_findmy_sv (sv ("$self"), 0); + pad_find_my_symbol_pvs (Perl_Symbol_Scalar, sv ("self"), 0); + =cut */ PADOFFSET Perl_pad_findmy_pvn(pTHX_ const char *namepv, STRLEN namelen, U32 flags) +{ + PERL_ARGS_ASSERT_PAD_FINDMY_PVN; + + return pad_find_my_symbol_pvn (*namepv, namepv + 1, namelen - 1, flags); +} + +PADOFFSET +Perl_pad_find_my_symbol_pvn( + pTHX_ + perl_symbol_table_id find_symbol_table, + const char * namepv, + STRLEN namelen, + U32 flags +) { PADNAME *out_pn; int out_flags; @@ -986,24 +1083,24 @@ Perl_pad_findmy_pvn(pTHX_ const char *namepv, STRLEN namelen, U32 flags) const PADNAMELIST *namelist; PADNAME **name_p; - PERL_ARGS_ASSERT_PAD_FINDMY_PVN; + PERL_ARGS_ASSERT_PAD_FIND_MY_SYMBOL_PVN; if (flags) - Perl_croak(aTHX_ "panic: pad_findmy_pvn illegal flag bits 0x%" UVxf, + Perl_croak(aTHX_ "panic: pad_find_my_symbol_pvn illegal flag bits 0x%" UVxf, (UV)flags); /* compilation errors can zero PL_compcv */ if (!PL_compcv) return NOT_IN_PAD; - offset = pad_findlex(namepv, namelen, flags, + offset = pad_findlex (find_symbol_table, namepv, namelen, flags, PL_compcv, PL_cop_seqmax, 1, NULL, &out_pn, &out_flags); if (offset != NOT_IN_PAD) return offset; /* Skip the ‘our’ hack for subroutines, as the warning does not apply. */ - if (*namepv == '&') return NOT_IN_PAD; + if (find_symbol_table == Perl_Symbol_Table_Code) return NOT_IN_PAD; /* look for an our that's being introduced; this allows * our $foo = 0 unless defined $foo; @@ -1013,11 +1110,12 @@ Perl_pad_findmy_pvn(pTHX_ const char *namepv, STRLEN namelen, U32 flags) name_p = PadnamelistARRAY(namelist); for (offset = PadnamelistMAXNAMED(namelist); offset > 0; offset--) { const PADNAME * const name = name_p[offset]; - if (name && PadnameLEN(name) == namelen + if (Padname_Is_Symbol (name) + && Padname_Symbol_Name_Length (name) == namelen && !PadnameOUTER(name) && (PadnameIsOUR(name)) - && ( PadnamePV(name) == namepv - || memEQ(PadnamePV(name), namepv, namelen) ) + && ( Padname_Symbol_Name (name) == namepv + || memEQ(Padname_Symbol_Name (name), namepv, namelen) ) && COP_SEQ_RANGE_LOW(name) == PERL_PADSEQ_INTRO ) return offset; @@ -1029,7 +1127,19 @@ PADOFFSET Perl_pad_findmy_pv(pTHX_ const char *name, U32 flags) { PERL_ARGS_ASSERT_PAD_FINDMY_PV; - return pad_findmy_pvn(name, strlen(name), flags); + return pad_find_my_symbol_pvn (*name, name + 1, strlen(name) - 1, flags); +} + +PADOFFSET +Perl_pad_find_my_symbol_pv( + pTHX_ + perl_symbol_table_id find_symbol_table, + const char * name, + U32 flags +) +{ + PERL_ARGS_ASSERT_PAD_FIND_MY_SYMBOL_PV; + return pad_find_my_symbol_pvn (find_symbol_table, name, strlen (name), flags); } PADOFFSET @@ -1039,7 +1149,22 @@ Perl_pad_findmy_sv(pTHX_ SV *name, U32 flags) STRLEN namelen; PERL_ARGS_ASSERT_PAD_FINDMY_SV; namepv = SvPVutf8(name, namelen); - return pad_findmy_pvn(namepv, namelen, flags); + return pad_find_my_symbol_pvn (*namepv, namepv + 1, namelen - 1, flags); +} + +PADOFFSET +Perl_pad_find_my_symbol_sv( + pTHX_ + perl_symbol_table_id find_symbol_table, + SV * name, + U32 flags +) +{ + char *namepv; + STRLEN namelen; + PERL_ARGS_ASSERT_PAD_FIND_MY_SYMBOL_SV; + namepv = SvPVutf8(name, namelen); + return pad_find_my_symbol_pvn (find_symbol_table, namepv, namelen, flags); } /* @@ -1094,15 +1219,24 @@ S_unavailable(pTHX_ PADNAME *name) /* diag_listed_as: Variable "%s" is not available */ Perl_ck_warner(aTHX_ packWARN(WARN_CLOSURE), "%s \"%" PNf "\" is not available", - *PadnamePV(name) == '&' - ? "Subroutine" - : "Variable", + Padname_Symbol_Table_Title_ucfirst (name), PNfARG(name)); } STATIC PADOFFSET -S_pad_findlex(pTHX_ const char *namepv, STRLEN namelen, U32 flags, const CV* cv, U32 seq, - int warn, SV** out_capture, PADNAME** out_name, int *out_flags) +S_pad_findlex( + pTHX_ + perl_symbol_table_id find_symbol_table, + const char * namepv, + STRLEN namelen, + U32 flags, + const CV * cv, + U32 seq, + int warn, + SV ** out_capture, + PADNAME ** out_name, + int * out_flags +) { PADOFFSET offset, new_offset; SV *new_capture; @@ -1121,8 +1255,8 @@ S_pad_findlex(pTHX_ const char *namepv, STRLEN namelen, U32 flags, const CV* cv, *out_flags = 0; DEBUG_Xv(PerlIO_printf(Perl_debug_log, - "Pad findlex cv=0x%" UVxf " searching \"%.*s\" seq=%d%s\n", - PTR2UV(cv), (int)namelen, namepv, (int)seq, + "Pad findlex cv=0x%" UVxf " searching \"%c%.*s\" seq=%d%s\n", + PTR2UV(cv), find_symbol_table, (int)namelen, namepv, (int)seq, out_capture ? " capturing" : "" )); /* first, search this pad */ @@ -1134,9 +1268,13 @@ S_pad_findlex(pTHX_ const char *namepv, STRLEN namelen, U32 flags, const CV* cv, for (offset = PadnamelistMAXNAMED(names); offset > 0; offset--) { const PADNAME * const name = name_p[offset]; - if (name && PadnameLEN(name) == namelen - && ( PadnamePV(name) == namepv - || memEQ(PadnamePV(name), namepv, namelen) )) + if (Padname_Is_Symbol (name) + && Padname_Symbol_Table (name) == find_symbol_table + && Padname_Symbol_Name_Length (name) == namelen + && ( + Padname_Symbol_Name (name) == namepv + || memEQ(Padname_Symbol_Name (name), namepv, namelen) + )) { if (PadnameOUTER(name)) { fake_offset = offset; /* in case we don't find a real one */ @@ -1181,7 +1319,7 @@ S_pad_findlex(pTHX_ const char *namepv, STRLEN namelen, U32 flags, const CV* cv, DEBUG_Xv(PerlIO_printf(Perl_debug_log, "Pad findlex cv=0x%" UVxf " matched: offset=%ld flags=0x%lx index=%lu\n", PTR2UV(cv), (long)offset, (unsigned long)*out_flags, - (unsigned long) PARENT_PAD_INDEX(*out_name) + (unsigned long) PARENT_PAD_INDEX(*out_name) )); } @@ -1217,8 +1355,9 @@ S_pad_findlex(pTHX_ const char *namepv, STRLEN namelen, U32 flags, const CV* cv, /* diag_listed_as: Variable "%s" will not stay shared */ Perl_warner(aTHX_ packWARN(WARN_CLOSURE), - "%s \"%" UTF8f "\" will not stay shared", - *namepv == '&' ? "Subroutine" : "Variable", + "%s \"%c%" UTF8f "\" will not stay shared", + Perl_Symbol_Table_Title_ucfirst (find_symbol_table), + Perl_Symbol_Table_To_Sigil (find_symbol_table), UTF8fARG(1, namelen, namepv)); } @@ -1231,7 +1370,7 @@ S_pad_findlex(pTHX_ const char *namepv, STRLEN namelen, U32 flags, const CV* cv, "Pad findlex cv=0x%" UVxf " chasing lex in outer pad\n", PTR2UV(cv))); n = *out_name; - (void) pad_findlex(namepv, namelen, flags, CvOUTSIDE(cv), + (void) pad_findlex (find_symbol_table, namepv, namelen, flags, CvOUTSIDE(cv), CvOUTSIDE_SEQ(cv), newwarn, out_capture, out_name, out_flags); *out_name = n; @@ -1254,14 +1393,21 @@ S_pad_findlex(pTHX_ const char *namepv, STRLEN namelen, U32 flags, const CV* cv, } } if (!*out_capture) { - if (namelen != 0 && *namepv == '@') - *out_capture = newSV_type_mortal(SVt_PVAV); - else if (namelen != 0 && *namepv == '%') - *out_capture = newSV_type_mortal(SVt_PVHV); - else if (namelen != 0 && *namepv == '&') - *out_capture = newSV_type_mortal(SVt_PVCV); - else - *out_capture = newSV_type_mortal(SVt_NULL); + if (namelen != 0) { + switch (find_symbol_table) { + case Perl_Symbol_Table_Array: + *out_capture = newSV_type_mortal(SVt_PVAV); + break; + case Perl_Symbol_Table_Hash: + *out_capture = newSV_type_mortal(SVt_PVHV); + break; + case Perl_Symbol_Table_Code: + *out_capture = newSV_type_mortal(SVt_PVCV); + break; + default: + *out_capture = newSV_type_mortal(SVt_NULL); + } + } } } @@ -1285,7 +1431,7 @@ S_pad_findlex(pTHX_ const char *namepv, STRLEN namelen, U32 flags, const CV* cv, if(CvIsMETHOD(cv)) recurse_flags |= padfind_FIELD_OK; - offset = pad_findlex(namepv, namelen, recurse_flags, + offset = pad_findlex (find_symbol_table, namepv, namelen, recurse_flags, CvOUTSIDE(cv), CvOUTSIDE_SEQ(cv), 1, new_capturep, out_name, out_flags); if (offset == NOT_IN_PAD) @@ -1323,10 +1469,9 @@ S_pad_findlex(pTHX_ const char *namepv, STRLEN namelen, U32 flags, const CV* cv, ); DEBUG_Xv(PerlIO_printf(Perl_debug_log, - "Pad addname: %ld \"%.*s\" FAKE\n", + "Pad addname: %ld \"" Padname_Symbol_Printf_Format "\" FAKE\n", (long)new_offset, - (int) PadnameLEN(new_name), - PadnamePV(new_name))); + Padname_Symbol_Printf_Params (new_name))); PARENT_FAKELEX_FLAGS_set(new_name, *out_flags); PARENT_PAD_INDEX_set(new_name, 0); @@ -1477,8 +1622,8 @@ Perl_intro_my(pTHX) COP_SEQ_RANGE_HIGH_set(sv, PERL_PADSEQ_INTRO); /* Don't know scope end yet. */ COP_SEQ_RANGE_LOW_set(sv, PL_cop_seqmax); DEBUG_Xv(PerlIO_printf(Perl_debug_log, - "Pad intromy: %ld \"%s\", (%lu,%lu)\n", - (long)i, PadnamePV(sv), + "Pad intromy: %ld \"" Padname_Symbol_Printf_Format "\", (%lu,%lu)\n", + (long)i, Padname_Symbol_Printf_Params(sv), (unsigned long)COP_SEQ_RANGE_LOW(sv), (unsigned long)COP_SEQ_RANGE_HIGH(sv)) ); @@ -1530,13 +1675,13 @@ Perl_pad_leavemy(pTHX) { COP_SEQ_RANGE_HIGH_set(sv, PL_cop_seqmax); DEBUG_Xv(PerlIO_printf(Perl_debug_log, - "Pad leavemy: %ld \"%s\", (%lu,%lu)\n", - (long)off, PadnamePV(sv), + "Pad leavemy: %ld \"" Padname_Symbol_Printf_Format "\", (%lu,%lu)\n", + (long)off, Padname_Symbol_Printf_Params (sv), (unsigned long)COP_SEQ_RANGE_LOW(sv), (unsigned long)COP_SEQ_RANGE_HIGH(sv)) ); if (!PadnameIsSTATE(sv) && !PadnameIsOUR(sv) - && *PadnamePV(sv) == '&' && PadnameLEN(sv) > 1) { + && Padname_Is_Symbol_Table_Code (sv) && ! Padname_Symbol_Is_Anonymous (sv)) { OP *kid = newOP(OP_INTROCV, 0); kid->op_targ = off; o = op_prepend_elem(OP_LINESEQ, kid, o); @@ -1708,7 +1853,7 @@ Perl_pad_tidy(pTHX_ padtidy_type type) continue; namesv = namep[ix]; if (!(PadnamePV(namesv) && - (!PadnameLEN(namesv) || *PadnamePV(namesv) == '&'))) + (!PadnameLEN(namesv) || Padname_Is_Symbol_Table_Code (namesv)))) { SvREFCNT_dec(PL_curpad[ix]); PL_curpad[ix] = NULL; @@ -1831,24 +1976,24 @@ Perl_do_dump_pad(pTHX_ I32 level, PerlIO *file, PADLIST *padlist, int full) if (namesv) { if (PadnameOUTER(namesv)) Perl_dump_indent(aTHX_ level+1, file, - "%2d. 0x%" UVxf "<%lu> FAKE \"%s\" flags=0x%lx index=%lu\n", + "%2d. 0x%" UVxf "<%lu> FAKE \"" Padname_Symbol_Printf_Format "\" flags=0x%lx index=%lu\n", (int) ix, PTR2UV(ppad[ix]), (unsigned long) (ppad[ix] ? SvREFCNT(ppad[ix]) : 0), - PadnamePV(namesv), + Padname_Symbol_Printf_Params (namesv), (unsigned long)PARENT_FAKELEX_FLAGS(namesv), (unsigned long)PARENT_PAD_INDEX(namesv) ); else Perl_dump_indent(aTHX_ level+1, file, - "%2d. 0x%" UVxf "<%lu> (%lu,%lu) \"%s\"\n", + "%2d. 0x%" UVxf "<%lu> (%lu,%lu) \"" Padname_Symbol_Printf_Format "\"\n", (int) ix, PTR2UV(ppad[ix]), (unsigned long) (ppad[ix] ? SvREFCNT(ppad[ix]) : 0), (unsigned long)COP_SEQ_RANGE_LOW(namesv), (unsigned long)COP_SEQ_RANGE_HIGH(namesv), - PadnamePV(namesv) + Padname_Symbol_Printf_Params (namesv) ); } else if (full) { @@ -2008,12 +2153,12 @@ S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside, HV *cloned, S_unavailable(aTHX_ namesv); sv = NULL; } - else + else SvREFCNT_inc_simple_void_NN(sv); } if (!sv) { - const char sigil = PadnamePV(namesv)[0]; - if (sigil == '&') + const perl_symbol_table_id sigil = Padname_Symbol_Table (namesv); + if (sigil == Perl_Symbol_Table_Code) /* If there are state subs, we need to clone them, too. But they may need to close over variables we have not cloned yet. So we will have to do a second @@ -2029,37 +2174,37 @@ S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside, HV *cloned, sv = newSV_type(SVt_PVCV); CvLEXICAL_on(sv); } - else if (PadnameLEN(namesv)>1 && !PadnameIsOUR(namesv)) + else if (! Padname_Symbol_Is_Anonymous (namesv) && ! PadnameIsOUR(namesv)) { /* my sub */ /* Just provide a stub, but name it. It will be upgraded to the real thing on scope entry. */ U32 hash; - PERL_HASH(hash, PadnamePV(namesv)+1, - PadnameLEN(namesv) - 1); + PERL_HASH(hash, Padname_Symbol_Name (namesv), + Padname_Symbol_Name_Length (namesv)); sv = newSV_type(SVt_PVCV); CvNAME_HEK_set( sv, - share_hek(PadnamePV(namesv)+1, - 1 - PadnameLEN(namesv), + share_hek(Padname_Symbol_Name (namesv), + - Padname_Symbol_Name_Length (namesv), hash) ); CvLEXICAL_on(sv); } else sv = SvREFCNT_inc(ppad[ix]); - else if (sigil == '@') + else if (sigil == Perl_Symbol_Table_Array) sv = MUTABLE_SV(newAV()); - else if (sigil == '%') + else if (sigil == Perl_Symbol_Table_Hash) sv = MUTABLE_SV(newHV()); else sv = newSV_type(SVt_NULL); /* reset the 'assign only once' flag on each state var */ - if (sigil != '&' && PadnameIsSTATE(namesv)) + if (sigil != Perl_Symbol_Table_Code && PadnameIsSTATE(namesv)) SvPADSTALE_on(sv); } } } - else if (namesv && PadnamePV(namesv)) { + else if (Padname_Is_Symbol (namesv)) { sv = SvREFCNT_inc_NN(ppad[ix]); } else { @@ -2092,7 +2237,7 @@ S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside, HV *cloned, PADNAME * const name = (ix <= fname) ? pname[ix] : NULL; if (name && name != &PL_padname_undef - && !PadnameOUTER(name) && PadnamePV(name)[0] == '&' + && !PadnameOUTER(name) && Padname_Is_Symbol_Table_Code (name) && PadnameIsSTATE(name) && !CvCLONED(PL_curpad[ix])) { CV * const protokey = CvOUTSIDE(ppad[ix]); @@ -2119,7 +2264,7 @@ S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside, HV *cloned, PADNAME * const name = (ix <= fname) ? pname[ix] : NULL; if (name && name != &PL_padname_undef - && !PadnameOUTER(name) && PadnamePV(name)[0] == '&' + && !PadnameOUTER(name) && Padname_Is_Symbol_Table_Code (name) && PadnameIsSTATE(name) && !CvCLONED(PL_curpad[ix])) S_cv_clone(aTHX_ (CV *)ppad[ix], (CV *)PL_curpad[ix], @@ -2129,7 +2274,7 @@ S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside, HV *cloned, else for (ix = fpad; ix > 0; ix--) { PADNAME * const name = (ix <= fname) ? pname[ix] : NULL; if (name && name != &PL_padname_undef && !PadnameOUTER(name) - && PadnamePV(name)[0] == '&' && PadnameIsSTATE(name)) + && Padname_Is_Symbol_Table_Code (name) && PadnameIsSTATE(name)) S_cv_clone(aTHX_ (CV *)ppad[ix], (CV *)PL_curpad[ix], cv, NULL); } @@ -2367,7 +2512,7 @@ Perl_pad_fixup_inner_anons(pTHX_ PADLIST *padlist, CV *old_cv, CV *new_cv) for (ix = PadnamelistMAX(comppad_name); ix > 0; ix--) { const PADNAME *name = namepad[ix]; if (name && name != &PL_padname_undef && !PadnameIsOUR(name) - && *PadnamePV(name) == '&') + && Padname_Is_Symbol_Table_Code (name)) { CV *innercv = MUTABLE_CV(curpad[ix]); if (UNLIKELY(PadnameOUTER(name))) { @@ -2445,13 +2590,13 @@ Perl_pad_push(pTHX_ PADLIST *padlist, int depth) for ( ;ix > 0; ix--) { SV *sv; if (names_fill >= ix && PadnameLEN(names[ix])) { - const char sigil = PadnamePV(names[ix])[0]; + const perl_symbol_table_id sigil = Padname_Symbol_Table (names[ix]); if (PadnameOUTER(names[ix]) || PadnameIsSTATE(names[ix]) - || sigil == '&') + || sigil == Perl_Symbol_Table_Code) { SV *tmp = oldpad[ix]; - if (sigil == '&' && SvTYPE(tmp) == SVt_PVCV + if (sigil == Perl_Symbol_Table_Code && SvTYPE(tmp) == SVt_PVCV && !PadnameOUTER(names[ix]) && CvLEXICAL(tmp) && CvCLONED(tmp) && !PadnameIsOUR(names[ix]) @@ -2465,9 +2610,9 @@ Perl_pad_push(pTHX_ PADLIST *padlist, int depth) } } else { /* our own lexical */ - if (sigil == '@') + if (sigil == Perl_Symbol_Table_Array) sv = MUTABLE_SV(newAV()); - else if (sigil == '%') + else if (sigil == Perl_Symbol_Table_Hash) sv = MUTABLE_SV(newHV()); else sv = newSV_type(SVt_NULL); @@ -2554,10 +2699,10 @@ Perl_padlist_dup(pTHX_ PADLIST *srcpad, CLONE_PARAMS *param) pad1a[ix] = NULL; } else if (names_fill >= ix && names[ix] && PadnameLEN(names[ix])) { - const char sigil = PadnamePV(names[ix])[0]; + const perl_symbol_table_id sigil = Padname_Symbol_Table (names[ix]); if (PadnameOUTER(names[ix]) || PadnameIsSTATE(names[ix]) - || sigil == '&') + || sigil == Perl_Symbol_Table_Code) { /* outer lexical or anon code */ pad1a[ix] = sv_dup_inc(oldpad[ix], param); @@ -2569,11 +2714,11 @@ Perl_padlist_dup(pTHX_ PADLIST *srcpad, CLONE_PARAMS *param) interacts with lexicals. */ pad1a[ix] = sv_dup_inc(oldpad[ix], param); } else { - SV *sv; - - if (sigil == '@') + SV *sv; + + if (sigil == Perl_Symbol_Table_Array) sv = MUTABLE_SV(newAV()); - else if (sigil == '%') + else if (sigil == Perl_Symbol_Table_Hash) sv = MUTABLE_SV(newHV()); else sv = newSV_type(SVt_NULL); @@ -2581,8 +2726,8 @@ Perl_padlist_dup(pTHX_ PADLIST *srcpad, CLONE_PARAMS *param) } } } - else if (( names_fill >= ix && names[ix] - && PadnamePV(names[ix]) )) { + else if (( names_fill >= ix + && Padname_Is_Symbol (names[ix]) )) { pad1a[ix] = sv_dup_inc(oldpad[ix], param); } else { @@ -2783,19 +2928,43 @@ Perl_newPADNAMEpvn(const char *s, STRLEN len) char *alloc2; /* for Newxz */ PADNAME *pn; PERL_ARGS_ASSERT_NEWPADNAMEPVN; + + if (len > 0) + return new_padname_symbol_pvn (*s, s + 1, len - 1); + + /* when called from padname_dup 'len' can be zero (-Dusethreads) */ + Newxz(alloc2, - STRUCT_OFFSET(struct padname_with_str, xpadn_str[0]) + len + 1, + STRUCT_OFFSET(struct padname_with_str, xpadn_str[0]) + 1, char); alloc = (struct padname_with_str *)alloc2; pn = (PADNAME *)alloc; PadnameREFCNT(pn) = 1; PadnamePV(pn) = alloc->xpadn_str; - Copy(s, PadnamePV(pn), len, char); - *(PadnamePV(pn) + len) = '\0'; + *(PadnamePV(pn)) = '\0'; PadnameLEN(pn) = len; return pn; } +/* +=for apidoc new_padname_symbol_pvn + + // allocate padname for "$foo" + PADNAME *name = new_padname_symbol (Perl_Symbol_Table_Scalar, "foo", 3); + +Constructs a new pad name. C must be a UTF-8 string. Do not +use this for pad names that point to outer lexicals. See +C>. + +=cut +*/ + +PADNAME * +Perl_new_padname_symbol_pvn( + perl_symbol_table_id symbol_table, + const char * name, + STRLEN name_len +) /* =for apidoc newPADNAMEouter @@ -2809,6 +2978,27 @@ C flag already set. =cut */ +{ + struct padname_with_str *alloc; + char *alloc2; /* for Newxz */ + PADNAME *pn; + STRLEN len = name_len + sizeof (symbol_table); + PERL_ARGS_ASSERT_NEW_PADNAME_SYMBOL_PVN; + + Newxz(alloc2, + STRUCT_OFFSET(struct padname_with_str, xpadn_str[0]) + len + 1, + char); + alloc = (struct padname_with_str *)alloc2; + pn = (PADNAME *)alloc; + PadnameREFCNT(pn) = 1; + PadnamePV(pn) = alloc->xpadn_str; + Padname_Symbol_Table (pn) = symbol_table; + Copy(name, Padname_Symbol_Name (pn), name_len, char); + *(PadnamePV(pn) + len) = '\0'; + PadnameLEN(pn) = len; + return pn; +} + PADNAME * Perl_newPADNAMEouter(PADNAME *outer) { @@ -2887,6 +3077,7 @@ Perl_padname_dup(pTHX_ PADNAME *src, CLONE_PARAMS *param) dst = PadnameOUTER(src) ? newPADNAMEouter(padname_dup(PADNAME_FROM_PV(PadnamePV(src)), param)) + /* TODO: PadnameLEN(src) sometimes evaluates to 0 */ : newPADNAMEpvn(PadnamePV(src), PadnameLEN(src)); ptr_table_store(PL_ptr_table, src, dst); PadnameLEN(dst) = PadnameLEN(src); diff --git a/pad.h b/pad.h index 0877aa6c3124..fdc1e5e14515 100644 --- a/pad.h +++ b/pad.h @@ -141,7 +141,7 @@ typedef enum { padtidy_FORMAT /* or a format */ } padtidy_type; -/* flags for pad_add_name_pvn. */ +/* flags for pad_add_name_pvn / pad_add_symbol_pvn. */ #define padadd_OUR 0x01 /* our declaration. */ #define padadd_STATE 0x02 /* state declaration. */ @@ -313,9 +313,181 @@ current pad equal to C =for apidoc m|void|PAD_RESTORE_LOCAL|PAD *opad Restore the old pad saved into the local variable C by C + +=for apidoc Am|bool|Padname_Is_Symbol|PADNAME * pn +Checks whether C represents valid symbol (aka: has name, empty string ok) +Every other C or C macro expects valid symbol. + + +=for apidoc Am|bool|Padname_Is_Symbol_Table|PADNAME * pn|Perl_Symbol_Table symbol_table +=for apidoc_item m|bool|Padname_Is_Symbol_Table_Array|PADNAME * pn +=for apidoc_item m|bool|Padname_Is_Symbol_Table_Code|PADNAME * pn +=for apidoc_item m|bool|Padname_Is_Symbol_Table_Hash|PADNAME * pn +=for apidoc_item m|bool|Padname_Is_Symbol_Table_Scalar|PADNAME * pn + +Whether PADNAME represents symbol for given symbol table. + + if (! Padname_Is_Symbol_Table_Code (pn)) { + ... + } + + +=for apidoc Am|bool|Padname_Symbol_Is_Anonymous|PADNAME * pn +Whether valid PADNAME represents anonymous symbol (has zero length name). + + +=for apidoc Am|char *|Padname_Symbol_Name|PADNAME * pn +Extract symbol name from valid symbol (see L). +For backward compatibility its index C<-1> is valid index for read. + + # pseudocode + Padname_Symbol_Name ("$self") == "self" + + +=for apidoc Am|STRLEN|Padname_Symbol_Name_Length|PADNAME * pn +Length of name of valid symbol (see L). + + # pseudocode + Padname_Symbol_Name_Length ("$self") == 4 + + +=for apidoc Am|char|Padname_Symbol_Table|PADNAME * pn +Extract symbol table identifier from valid symbol (see L). + + # pseudocode + Padname_Symbol_Table ("$self") == Perl_Symbol_Table_Scalar + + +=for apidoc Am|const char *|Padname_Symbol_Printf_Format +C format (as literal string) to output symbol name with its sigil + + +=for apidoc Amu|args|Padname_Symbol_Printf_Params|PADNAME * pn +C arguments required by L + + +=for apidoc Am|const char const *|Padname_Symbol_Table_Title_lc|PADNAME * pn +=for apidoc_item m|const char const *|Padname_Symbol_Table_Title_ucfirst|PADNAME * pn + +Similar to L / L +but computes symbol table from valid symbol (see L). + + +=for apidoc Am|char|Perl_Sigil_To_Symbol_Table|char +Converts sigil to symbol table + + Perl_Sigil_To_Symbol_Table ('$') == Perl_Symbol_Table_Scalar + + +=for apidoc Ay||Perl_Symbol_Table +=for apidoc_item Perl_Symbol_Table_Array +=for apidoc_item Perl_Symbol_Table_Code +=for apidoc_item Perl_Symbol_Table_Hash +=for apidoc_item Perl_Symbol_Table_Scalar + +Symbol table identifies how symbol value is represented internally. + +For example, C<'&'> can be: + +=over + +=item Internal identification of symbol + + &foo + +=item External identification of expression + + goto &foo; + +=item Predefined variable name + + $& + +=item Prototype + + sub foo :prototype(&); + +=back + + +=for apidoc Am|const char const *|Perl_Symbol_Table_Title_lc|Perl_Symbol_Table symbol_table +=for apidoc_item m|const char const *|Perl_Symbol_Table_Title_ucfirst|Perl_Symbol_Table symbol_table + +Expand as a title of symbol table, for example C or C. + + +=for apidoc Ay | | perl_symbol_table_id + +Typedef how symbol table id is represented + =cut */ +typedef char perl_symbol_table_id; + +enum Perl_Symbol_Table { + Perl_Symbol_Table_Array = '@', + Perl_Symbol_Table_Code = '&', + Perl_Symbol_Table_Hash = '%', + Perl_Symbol_Table_Scalar = '$', +}; + +#define Padname_Is_Symbol(Pn) \ + ((Pn) && PadnamePV (Pn)) + +#define Padname_Is_Symbol_Table(Pn, Table) \ + (PadnamePV (Pn)[0] == (Table)) + +#define Padname_Is_Symbol_Table_Array(Pn) \ + Padname_Is_Symbol_Table (Pn, Perl_Symbol_Table_Array) + +#define Padname_Is_Symbol_Table_Code(Pn) \ + Padname_Is_Symbol_Table (Pn, Perl_Symbol_Table_Code) + +#define Padname_Is_Symbol_Table_Hash(Pn) \ + Padname_Is_Symbol_Table (Pn, Perl_Symbol_Table_Hash) + +#define Padname_Is_Symbol_Table_Scalar(Pn) \ + Padname_Is_Symbol_Table (Pn, Perl_Symbol_Table_Scalar) + +#define Padname_Symbol_Is_Anonymous(Pn) \ + (Padname_Symbol_Name_Length (Pn) == 0) + +#define Padname_Symbol_Name(Pn) \ + (PadnamePV (Pn) + 1) + +#define Padname_Symbol_Name_Length(Pn) \ + ((STRLEN) ((PadnamePV (Pn)) ? (PadnameLEN (Pn) - 1) : 0)) + +#define Padname_Symbol_Printf_Format \ + "%c%.*s" + +#define Padname_Symbol_Printf_Params(Pn) \ + Perl_Symbol_Table_To_Sigil (Padname_Symbol_Table (Pn)), \ + (int) Padname_Symbol_Name_Length (Pn), \ + Padname_Symbol_Name (Pn) + +#define Padname_Symbol_Table(Pn) \ + (PadnamePV (Pn)[0]) + +#define Perl_Sigil_To_Symbol_Table(Sigil) \ + (Sigil) + +#define Perl_Symbol_Table_To_Sigil(Symbol_Table) \ + (Symbol_Table) + +#define Perl_Symbol_Table_Title_lc(Table) \ + (((Table) == Perl_Symbol_Table_Code) ? "subroutine" : "variable") + +#define Perl_Symbol_Table_Title_ucfirst(Table) \ + (((Table) == Perl_Symbol_Table_Code) ? "Subroutine" : "Variable") + +#define Padname_Symbol_Table_Title_lc(Pn) \ + Perl_Symbol_Table_Title_lc (Padname_Symbol_Table (Pn)) + +#define Padname_Symbol_Table_Title_ucfirst(Pn) \ + Perl_Symbol_Table_Title_ucfirst (Padname_Symbol_Table (Pn)) + #define PadlistARRAY(pl) (pl)->xpadl_arr.xpadlarr_alloc #define PadlistMAX(pl) (pl)->xpadl_max #define PadlistNAMES(pl) *((PADNAMELIST **)PadlistARRAY(pl)) @@ -539,7 +711,21 @@ instead of a string/length pair. */ #define pad_add_name_pvs(name,flags,typestash,ourstash) \ - Perl_pad_add_name_pvn(aTHX_ STR_WITH_LEN(name), flags, typestash, ourstash) + EXPAND_CALL (pad_add_name_pvn, (STR_WITH_LEN(name), flags, typestash, ourstash)) + +/* +=for apidoc Am|PADOFFSET|pad_add_symbol_pvs|symbol_table|"name"|U32 flags|HV *typestash|HV *ourstash + +Similar to L, but takes a literal string instead of a string/length pair. + + # Example: create pad entry for "$self" + pad_add_symbol_pvs (Perl_Symbol_Scalar, "self", 0, NULL, NULL); + +=cut +*/ + +#define pad_add_symbol_pvs(Symbol_Table, Name, Flags, Typestash, Ourstash) \ + EXPAND_CALL (pad_add_symbol_pvn, (Symbol_Table, STR_WITH_LEN (Name), Flags, Typestash, Ourstash)) /* =for apidoc_defn Am|PADOFFSET|pad_findmy_pvs|"name"|U32 flags @@ -548,7 +734,16 @@ instead of a string/length pair. */ #define pad_findmy_pvs(name,flags) \ - Perl_pad_findmy_pvn(aTHX_ STR_WITH_LEN(name), flags) + EXPAND_CALL (pad_findmy_pvn, (STR_WITH_LEN(name), flags)) + +/* +=for apidoc_defn Am|PADOFFSET|pad_find_my_symbol_pvs|"symbol_table"|"name"|U32 flags + +=cut +*/ + +#define pad_find_my_symbol_pvs(Symbol_Table, Name, Flags) \ + EXPAND_CALL (pad_find_my_symbol_pvn, (Symbol_Table, STR_WITH_LEN(Name), Flags)) struct suspended_compcv { diff --git a/proto.h b/proto.h index 32e8d48f4fa7..ca1724801733 100644 --- a/proto.h +++ b/proto.h @@ -3193,6 +3193,12 @@ Perl_newXS_len_flags(pTHX_ const char *name, STRLEN len, XSUBADDR_t subaddr, con #define PERL_ARGS_ASSERT_NEWXS_LEN_FLAGS \ assert(subaddr) +PERL_CALLCONV PADNAME * +Perl_new_padname_symbol_pvn(perl_symbol_table_id symbol_table, const char *name, STRLEN name_len) + __attribute__warn_unused_result__; +#define PERL_ARGS_ASSERT_NEW_PADNAME_SYMBOL_PVN \ + assert(name) + PERL_CALLCONV PERL_SI * Perl_new_stackinfo(pTHX_ I32 stitems, I32 cxitems) __attribute__warn_unused_result__; @@ -3407,6 +3413,24 @@ Perl_pad_add_name_sv(pTHX_ SV *name, U32 flags, HV *typestash, HV *ourstash); assert(name); assert(!typestash || SvTYPE(typestash) == SVt_PVHV); \ assert(!ourstash || SvTYPE(ourstash) == SVt_PVHV) +PERL_CALLCONV PADOFFSET +Perl_pad_add_symbol_pv(pTHX_ perl_symbol_table_id symbol_table, const char *name, const U32 flags, HV *typestash, HV *ourstash); +#define PERL_ARGS_ASSERT_PAD_ADD_SYMBOL_PV \ + assert(name); assert(!typestash || SvTYPE(typestash) == SVt_PVHV); \ + assert(!ourstash || SvTYPE(ourstash) == SVt_PVHV) + +PERL_CALLCONV PADOFFSET +Perl_pad_add_symbol_pvn(pTHX_ perl_symbol_table_id symbol_table, const char *namepv, STRLEN namelen, U32 flags, HV *typestash, HV *ourstash); +#define PERL_ARGS_ASSERT_PAD_ADD_SYMBOL_PVN \ + assert(namepv); assert(!typestash || SvTYPE(typestash) == SVt_PVHV); \ + assert(!ourstash || SvTYPE(ourstash) == SVt_PVHV) + +PERL_CALLCONV PADOFFSET +Perl_pad_add_symbol_sv(pTHX_ perl_symbol_table_id symbol_table, SV *name, U32 flags, HV *typestash, HV *ourstash); +#define PERL_ARGS_ASSERT_PAD_ADD_SYMBOL_SV \ + assert(name); assert(!typestash || SvTYPE(typestash) == SVt_PVHV); \ + assert(!ourstash || SvTYPE(ourstash) == SVt_PVHV) + PERL_CALLCONV void Perl_pad_add_weakref(pTHX_ CV *func) __attribute__visibility__("hidden"); @@ -3423,6 +3447,21 @@ Perl_pad_block_start(pTHX_ int full) __attribute__visibility__("hidden"); #define PERL_ARGS_ASSERT_PAD_BLOCK_START +PERL_CALLCONV PADOFFSET +Perl_pad_find_my_symbol_pv(pTHX_ perl_symbol_table_id find_symbol_table, const char *name, U32 flags); +#define PERL_ARGS_ASSERT_PAD_FIND_MY_SYMBOL_PV \ + assert(name) + +PERL_CALLCONV PADOFFSET +Perl_pad_find_my_symbol_pvn(pTHX_ perl_symbol_table_id find_symbol_table, const char *namepv, STRLEN namelen, U32 flags); +#define PERL_ARGS_ASSERT_PAD_FIND_MY_SYMBOL_PVN \ + assert(namepv) + +PERL_CALLCONV PADOFFSET +Perl_pad_find_my_symbol_sv(pTHX_ perl_symbol_table_id find_symbol_table, SV *name, U32 flags); +#define PERL_ARGS_ASSERT_PAD_FIND_MY_SYMBOL_SV \ + assert(name) + PERL_CALLCONV PADOFFSET Perl_pad_findmy_pv(pTHX_ const char *name, U32 flags); #define PERL_ARGS_ASSERT_PAD_FINDMY_PV \ @@ -7531,7 +7570,7 @@ S_pad_check_dup(pTHX_ PADNAME *name, U32 flags, const HV *ourstash); assert(name) STATIC PADOFFSET -S_pad_findlex(pTHX_ const char *namepv, STRLEN namelen, U32 flags, const CV *cv, U32 seq, int warn, SV **out_capture, PADNAME **out_name, int *out_flags); +S_pad_findlex(pTHX_ perl_symbol_table_id find_symbol_table, const char *namepv, STRLEN namelen, U32 flags, const CV *cv, U32 seq, int warn, SV **out_capture, PADNAME **out_name, int *out_flags); # define PERL_ARGS_ASSERT_PAD_FINDLEX \ assert(namepv); assert(cv); assert(out_name); assert(out_flags) diff --git a/toke.c b/toke.c index ae6c7819c444..59a7d544094c 100644 --- a/toke.c +++ b/toke.c @@ -5558,8 +5558,8 @@ yyl_sub(pTHX_ char *s, const int key) format_name = S_newSV_maybe_utf8(aTHX_ s, d - s); *PL_tokenbuf = '&'; if (memchr(tmpbuf, ':', len) || key != KEY_sub - || pad_findmy_pvn( - PL_tokenbuf, len + 1, 0 + || pad_find_my_symbol_pvn ( + Perl_Symbol_Table_Code, PL_tokenbuf + 1, len, 0 ) != NOT_IN_PAD) sv_setpvn(PL_subname, tmpbuf, len); else { @@ -9001,10 +9001,7 @@ yyl_keylookup(pTHX_ char *s, GV *gv) /* Check for lexical sub */ if (PL_expect != XOPERATOR) { - char tmpbuf[sizeof PL_tokenbuf + 1]; - *tmpbuf = '&'; - Copy(PL_tokenbuf, tmpbuf+1, len, char); - c.off = pad_findmy_pvn(tmpbuf, len+1, 0); + c.off = pad_find_my_symbol_pvn (Perl_Symbol_Table_Code, PL_tokenbuf, len, 0); if (c.off != NOT_IN_PAD) { assert(c.off); /* we assume this is boolean-true below */ if (PAD_COMPNAME_FLAGS_isOUR(c.off)) { @@ -9933,7 +9930,7 @@ S_pending_ident(pTHX) in "our" */ yyerror_pv(Perl_form(aTHX_ "No package name allowed for " "%s %s in \"our\"", - *PL_tokenbuf=='&' ? "subroutine" : "variable", + Perl_Symbol_Table_Title_lc (Perl_Sigil_To_Symbol_Table (*PL_tokenbuf)), PL_tokenbuf), UTF ? SVf_UTF8 : 0); tmp = allocmy(PL_tokenbuf, tokenbuf_len, UTF ? SVf_UTF8 : 0); } @@ -9946,7 +9943,7 @@ S_pending_ident(pTHX) yyerror_pv(Perl_form(aTHX_ PL_no_myglob, PL_in_my == KEY_my ? "my" : PL_in_my == KEY_field ? "field" : "state", - *PL_tokenbuf == '&' ? "subroutine" : "variable", + Perl_Symbol_Table_Title_lc (Perl_Sigil_To_Symbol_Table (*PL_tokenbuf)), PL_tokenbuf), UTF ? SVf_UTF8 : 0); GCC_DIAG_RESTORE_STMT; @@ -9985,8 +9982,7 @@ S_pending_ident(pTHX) if (!has_colon) { if (!PL_in_my) - tmp = pad_findmy_pvn(PL_tokenbuf, tokenbuf_len, - 0); + tmp = pad_find_my_symbol_pvn (*PL_tokenbuf, PL_tokenbuf + 1, tokenbuf_len - 1, 0); if (tmp != NOT_IN_PAD) { /* might be an "our" variable" */ if (PAD_COMPNAME_FLAGS_isOUR(tmp)) { @@ -10102,10 +10098,7 @@ S_checkcomma(pTHX_ const char *s, const char *name, const char *what) return; if (s - w <= 254) { PADOFFSET off; - char tmpbuf[256]; - Copy(w, tmpbuf+1, s - w, char); - *tmpbuf = '&'; - off = pad_findmy_pvn(tmpbuf, s-w+1, 0); + off = pad_find_my_symbol_pvn (Perl_Symbol_Table_Code, w, s-w, 0); if (off != NOT_IN_PAD) return; } Perl_croak(aTHX_ "No comma allowed after %s", what); @@ -11443,7 +11436,7 @@ S_scan_inputsymbol(pTHX_ char *start) /* try to find it in the pad for this block, otherwise find add symbol table ops */ - const PADOFFSET tmp = pad_findmy_pvn(d, len, 0); + const PADOFFSET tmp = pad_find_my_symbol_pvn (Perl_Symbol_Table_Scalar, d + 1, len - 1, 0); if (tmp != NOT_IN_PAD) { if (PAD_COMPNAME_FLAGS_isOUR(tmp)) { HV * const stash = PAD_COMPNAME_OURSTASH(tmp);