1*0Sstevel@tonic-gate /* pad.h 2*0Sstevel@tonic-gate * 3*0Sstevel@tonic-gate * Copyright (C) 2002, by Larry Wall and others 4*0Sstevel@tonic-gate * 5*0Sstevel@tonic-gate * You may distribute under the terms of either the GNU General Public 6*0Sstevel@tonic-gate * License or the Artistic License, as specified in the README file. 7*0Sstevel@tonic-gate * 8*0Sstevel@tonic-gate * This file defines the types and macros associated with the API for 9*0Sstevel@tonic-gate * manipulating scratchpads, which are used by perl to store lexical 10*0Sstevel@tonic-gate * variables, op targets and constants. 11*0Sstevel@tonic-gate */ 12*0Sstevel@tonic-gate 13*0Sstevel@tonic-gate 14*0Sstevel@tonic-gate 15*0Sstevel@tonic-gate 16*0Sstevel@tonic-gate /* a padlist is currently just an AV; but that might change, 17*0Sstevel@tonic-gate * so hide the type. Ditto a pad. */ 18*0Sstevel@tonic-gate 19*0Sstevel@tonic-gate typedef AV PADLIST; 20*0Sstevel@tonic-gate typedef AV PAD; 21*0Sstevel@tonic-gate 22*0Sstevel@tonic-gate 23*0Sstevel@tonic-gate /* offsets within a pad */ 24*0Sstevel@tonic-gate 25*0Sstevel@tonic-gate #if PTRSIZE == 4 26*0Sstevel@tonic-gate typedef U32TYPE PADOFFSET; 27*0Sstevel@tonic-gate #else 28*0Sstevel@tonic-gate # if PTRSIZE == 8 29*0Sstevel@tonic-gate typedef U64TYPE PADOFFSET; 30*0Sstevel@tonic-gate # endif 31*0Sstevel@tonic-gate #endif 32*0Sstevel@tonic-gate #define NOT_IN_PAD ((PADOFFSET) -1) 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate 35*0Sstevel@tonic-gate /* flags for the pad_new() function */ 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate #define padnew_CLONE 1 /* this pad is for a cloned CV */ 38*0Sstevel@tonic-gate #define padnew_SAVE 2 /* save old globals */ 39*0Sstevel@tonic-gate #define padnew_SAVESUB 4 /* also save extra stuff for start of sub */ 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate /* values for the pad_tidy() function */ 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate typedef enum { 44*0Sstevel@tonic-gate padtidy_SUB, /* tidy up a pad for a sub, */ 45*0Sstevel@tonic-gate padtidy_SUBCLONE, /* a cloned sub, */ 46*0Sstevel@tonic-gate padtidy_FORMAT /* or a format */ 47*0Sstevel@tonic-gate } padtidy_type; 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate /* ASSERT_CURPAD_LEGAL and ASSERT_CURPAD_ACTIVE respectively determine 50*0Sstevel@tonic-gate * whether PL_comppad and PL_curpad are consistent and whether they have 51*0Sstevel@tonic-gate * active values */ 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate #ifdef DEBUGGING 54*0Sstevel@tonic-gate # define ASSERT_CURPAD_LEGAL(label) \ 55*0Sstevel@tonic-gate if (PL_comppad ? (AvARRAY(PL_comppad) != PL_curpad) : (PL_curpad != 0)) \ 56*0Sstevel@tonic-gate Perl_croak(aTHX_ "panic: illegal pad in %s: 0x%"UVxf"[0x%"UVxf"]",\ 57*0Sstevel@tonic-gate label, PTR2UV(PL_comppad), PTR2UV(PL_curpad)); 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate # define ASSERT_CURPAD_ACTIVE(label) \ 61*0Sstevel@tonic-gate if (!PL_comppad || (AvARRAY(PL_comppad) != PL_curpad)) \ 62*0Sstevel@tonic-gate Perl_croak(aTHX_ "panic: invalid pad in %s: 0x%"UVxf"[0x%"UVxf"]",\ 63*0Sstevel@tonic-gate label, PTR2UV(PL_comppad), PTR2UV(PL_curpad)); 64*0Sstevel@tonic-gate #else 65*0Sstevel@tonic-gate # define ASSERT_CURPAD_LEGAL(label) 66*0Sstevel@tonic-gate # define ASSERT_CURPAD_ACTIVE(label) 67*0Sstevel@tonic-gate #endif 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate /* Note: the following three macros are actually defined in scope.h, but 72*0Sstevel@tonic-gate * they are documented here for completeness, since they directly or 73*0Sstevel@tonic-gate * indirectly affect pads. 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gate =for apidoc m|void|SAVEPADSV |PADOFFSET po 76*0Sstevel@tonic-gate Save a pad slot (used to restore after an iteration) 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate XXX DAPM it would make more sense to make the arg a PADOFFSET 79*0Sstevel@tonic-gate =for apidoc m|void|SAVECLEARSV |SV **svp 80*0Sstevel@tonic-gate Clear the pointed to pad value on scope exit. (ie the runtime action of 'my') 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate =for apidoc m|void|SAVECOMPPAD 83*0Sstevel@tonic-gate save PL_comppad and PL_curpad 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate =for apidoc m|SV *|PAD_SETSV |PADOFFSET po|SV* sv 90*0Sstevel@tonic-gate Set the slot at offset C<po> in the current pad to C<sv> 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate =for apidoc m|void|PAD_SV |PADOFFSET po 93*0Sstevel@tonic-gate Get the value at offset C<po> in the current pad 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate =for apidoc m|SV *|PAD_SVl |PADOFFSET po 96*0Sstevel@tonic-gate Lightweight and lvalue version of C<PAD_SV>. 97*0Sstevel@tonic-gate Get or set the value at offset C<po> in the current pad. 98*0Sstevel@tonic-gate Unlike C<PAD_SV>, does not print diagnostics with -DX. 99*0Sstevel@tonic-gate For internal use only. 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate =for apidoc m|SV *|PAD_BASE_SV |PADLIST padlist|PADOFFSET po 102*0Sstevel@tonic-gate Get the value from slot C<po> in the base (DEPTH=1) pad of a padlist 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate =for apidoc m|void|PAD_SET_CUR |PADLIST padlist|I32 n 105*0Sstevel@tonic-gate Set the current pad to be pad C<n> in the padlist, saving 106*0Sstevel@tonic-gate the previous current pad. 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate =for apidoc m|void|PAD_SET_CUR_NOSAVE |PADLIST padlist|I32 n 109*0Sstevel@tonic-gate like PAD_SET_CUR, but without the save 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate =for apidoc m|void|PAD_SAVE_SETNULLPAD 112*0Sstevel@tonic-gate Save the current pad then set it to null. 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate =for apidoc m|void|PAD_SAVE_LOCAL|PAD *opad|PAD *npad 115*0Sstevel@tonic-gate Save the current pad to the local variable opad, then make the 116*0Sstevel@tonic-gate current pad equal to npad 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate =for apidoc m|void|PAD_RESTORE_LOCAL|PAD *opad 119*0Sstevel@tonic-gate Restore the old pad saved into the local variable opad by PAD_SAVE_LOCAL() 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate =cut 122*0Sstevel@tonic-gate */ 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate #ifdef DEBUGGING 125*0Sstevel@tonic-gate # define PAD_SV(po) pad_sv(po) 126*0Sstevel@tonic-gate # define PAD_SETSV(po,sv) pad_setsv(po,sv) 127*0Sstevel@tonic-gate #else 128*0Sstevel@tonic-gate # define PAD_SV(po) (PL_curpad[po]) 129*0Sstevel@tonic-gate # define PAD_SETSV(po,sv) PL_curpad[po] = (sv) 130*0Sstevel@tonic-gate #endif 131*0Sstevel@tonic-gate 132*0Sstevel@tonic-gate #define PAD_SVl(po) (PL_curpad[po]) 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate #define PAD_BASE_SV(padlist, po) \ 135*0Sstevel@tonic-gate (AvARRAY(padlist)[1]) \ 136*0Sstevel@tonic-gate ? AvARRAY((AV*)(AvARRAY(padlist)[1]))[po] : Nullsv; 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate #define PAD_SET_CUR_NOSAVE(padlist,n) \ 140*0Sstevel@tonic-gate PL_comppad = (PAD*) (AvARRAY(padlist)[n]); \ 141*0Sstevel@tonic-gate PL_curpad = AvARRAY(PL_comppad); \ 142*0Sstevel@tonic-gate DEBUG_Xv(PerlIO_printf(Perl_debug_log, \ 143*0Sstevel@tonic-gate "Pad 0x%"UVxf"[0x%"UVxf"] set_cur depth=%d\n", \ 144*0Sstevel@tonic-gate PTR2UV(PL_comppad), PTR2UV(PL_curpad), (int)(n))); 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate #define PAD_SET_CUR(padlist,n) \ 148*0Sstevel@tonic-gate SAVECOMPPAD(); \ 149*0Sstevel@tonic-gate PAD_SET_CUR_NOSAVE(padlist,n); 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate #define PAD_SAVE_SETNULLPAD() SAVECOMPPAD(); \ 153*0Sstevel@tonic-gate PL_comppad = Null(PAD*); PL_curpad = Null(SV**); \ 154*0Sstevel@tonic-gate DEBUG_Xv(PerlIO_printf(Perl_debug_log, "Pad set_null\n")); 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate #define PAD_SAVE_LOCAL(opad,npad) \ 157*0Sstevel@tonic-gate opad = PL_comppad; \ 158*0Sstevel@tonic-gate PL_comppad = (npad); \ 159*0Sstevel@tonic-gate PL_curpad = PL_comppad ? AvARRAY(PL_comppad) : Null(SV**); \ 160*0Sstevel@tonic-gate DEBUG_Xv(PerlIO_printf(Perl_debug_log, \ 161*0Sstevel@tonic-gate "Pad 0x%"UVxf"[0x%"UVxf"] save_local\n", \ 162*0Sstevel@tonic-gate PTR2UV(PL_comppad), PTR2UV(PL_curpad))); 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate #define PAD_RESTORE_LOCAL(opad) \ 165*0Sstevel@tonic-gate PL_comppad = opad; \ 166*0Sstevel@tonic-gate PL_curpad = PL_comppad ? AvARRAY(PL_comppad) : Null(SV**); \ 167*0Sstevel@tonic-gate DEBUG_Xv(PerlIO_printf(Perl_debug_log, \ 168*0Sstevel@tonic-gate "Pad 0x%"UVxf"[0x%"UVxf"] restore_local\n", \ 169*0Sstevel@tonic-gate PTR2UV(PL_comppad), PTR2UV(PL_curpad))); 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate /* 173*0Sstevel@tonic-gate =for apidoc m|void|CX_CURPAD_SAVE|struct context 174*0Sstevel@tonic-gate Save the current pad in the given context block structure. 175*0Sstevel@tonic-gate 176*0Sstevel@tonic-gate =for apidoc m|SV *|CX_CURPAD_SV|struct context|PADOFFSET po 177*0Sstevel@tonic-gate Access the SV at offset po in the saved current pad in the given 178*0Sstevel@tonic-gate context block structure (can be used as an lvalue). 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate =cut 181*0Sstevel@tonic-gate */ 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate #define CX_CURPAD_SAVE(block) (block).oldcomppad = PL_comppad 184*0Sstevel@tonic-gate #define CX_CURPAD_SV(block,po) (AvARRAY((AV*)((block).oldcomppad))[po]) 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate /* 188*0Sstevel@tonic-gate =for apidoc m|U32|PAD_COMPNAME_FLAGS|PADOFFSET po 189*0Sstevel@tonic-gate Return the flags for the current compiling pad name 190*0Sstevel@tonic-gate at offset C<po>. Assumes a valid slot entry. 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate =for apidoc m|char *|PAD_COMPNAME_PV|PADOFFSET po 193*0Sstevel@tonic-gate Return the name of the current compiling pad name 194*0Sstevel@tonic-gate at offset C<po>. Assumes a valid slot entry. 195*0Sstevel@tonic-gate 196*0Sstevel@tonic-gate =for apidoc m|HV *|PAD_COMPNAME_TYPE|PADOFFSET po 197*0Sstevel@tonic-gate Return the type (stash) of the current compiling pad name at offset 198*0Sstevel@tonic-gate C<po>. Must be a valid name. Returns null if not typed. 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate =for apidoc m|HV *|PAD_COMPNAME_OURSTASH|PADOFFSET po 201*0Sstevel@tonic-gate Return the stash associated with an C<our> variable. 202*0Sstevel@tonic-gate Assumes the slot entry is a valid C<our> lexical. 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate =for apidoc m|STRLEN|PAD_COMPNAME_GEN|PADOFFSET po 205*0Sstevel@tonic-gate The generation number of the name at offset C<po> in the current 206*0Sstevel@tonic-gate compiling pad (lvalue). Note that C<SvCUR> is hijacked for this purpose. 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate =cut 209*0Sstevel@tonic-gate */ 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate #define PAD_COMPNAME_FLAGS(po) SvFLAGS(*av_fetch(PL_comppad_name, (po), FALSE)) 212*0Sstevel@tonic-gate #define PAD_COMPNAME_PV(po) SvPV_nolen(*av_fetch(PL_comppad_name, (po), FALSE)) 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate /* XXX DAPM yuk - using av_fetch twice. Is there a better way? */ 215*0Sstevel@tonic-gate #define PAD_COMPNAME_TYPE(po) \ 216*0Sstevel@tonic-gate ((SvFLAGS(*av_fetch(PL_comppad_name, (po), FALSE)) & SVpad_TYPED) \ 217*0Sstevel@tonic-gate ? (SvSTASH(*av_fetch(PL_comppad_name, (po), FALSE))) : Nullhv) 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate #define PAD_COMPNAME_OURSTASH(po) \ 220*0Sstevel@tonic-gate (GvSTASH(*av_fetch(PL_comppad_name, (po), FALSE))) 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gate #define PAD_COMPNAME_GEN(po) SvCUR(AvARRAY(PL_comppad_name)[po]) 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate /* 228*0Sstevel@tonic-gate =for apidoc m|void|PAD_DUP|PADLIST dstpad|PADLIST srcpad|CLONE_PARAMS* param 229*0Sstevel@tonic-gate Clone a padlist. 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate =for apidoc m|void|PAD_CLONE_VARS|PerlInterpreter *proto_perl \ 232*0Sstevel@tonic-gate |CLONE_PARAMS* param 233*0Sstevel@tonic-gate Clone the state variables associated with running and compiling pads. 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate =cut 236*0Sstevel@tonic-gate */ 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gate #define PAD_DUP(dstpad, srcpad, param) \ 240*0Sstevel@tonic-gate if ((srcpad) && !AvREAL(srcpad)) { \ 241*0Sstevel@tonic-gate /* XXX padlists are real, but pretend to be not */ \ 242*0Sstevel@tonic-gate AvREAL_on(srcpad); \ 243*0Sstevel@tonic-gate (dstpad) = av_dup_inc((srcpad), param); \ 244*0Sstevel@tonic-gate AvREAL_off(srcpad); \ 245*0Sstevel@tonic-gate AvREAL_off(dstpad); \ 246*0Sstevel@tonic-gate } \ 247*0Sstevel@tonic-gate else \ 248*0Sstevel@tonic-gate (dstpad) = av_dup_inc((srcpad), param); 249*0Sstevel@tonic-gate 250*0Sstevel@tonic-gate /* NB - we set PL_comppad to null unless it points at a value that 251*0Sstevel@tonic-gate * has already been dup'ed, ie it points to part of an active padlist. 252*0Sstevel@tonic-gate * Otherwise PL_comppad ends up being a leaked scalar in code like 253*0Sstevel@tonic-gate * the following: 254*0Sstevel@tonic-gate * threads->create(sub { threads->create(sub {...} ) } ); 255*0Sstevel@tonic-gate * where the second thread dups the outer sub's comppad but not the 256*0Sstevel@tonic-gate * sub's CV or padlist. */ 257*0Sstevel@tonic-gate 258*0Sstevel@tonic-gate #define PAD_CLONE_VARS(proto_perl, param) \ 259*0Sstevel@tonic-gate PL_comppad = ptr_table_fetch(PL_ptr_table, proto_perl->Tcomppad); \ 260*0Sstevel@tonic-gate PL_curpad = PL_comppad ? AvARRAY(PL_comppad) : Null(SV**); \ 261*0Sstevel@tonic-gate PL_comppad_name = av_dup(proto_perl->Icomppad_name, param); \ 262*0Sstevel@tonic-gate PL_comppad_name_fill = proto_perl->Icomppad_name_fill; \ 263*0Sstevel@tonic-gate PL_comppad_name_floor = proto_perl->Icomppad_name_floor; \ 264*0Sstevel@tonic-gate PL_min_intro_pending = proto_perl->Imin_intro_pending; \ 265*0Sstevel@tonic-gate PL_max_intro_pending = proto_perl->Imax_intro_pending; \ 266*0Sstevel@tonic-gate PL_padix = proto_perl->Ipadix; \ 267*0Sstevel@tonic-gate PL_padix_floor = proto_perl->Ipadix_floor; \ 268*0Sstevel@tonic-gate PL_pad_reset_pending = proto_perl->Ipad_reset_pending; \ 269*0Sstevel@tonic-gate PL_cop_seqmax = proto_perl->Icop_seqmax; 270