diff options
author | Norbert Preining <norbert@preining.info> | 2024-03-15 03:06:35 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2024-03-15 03:06:35 +0000 |
commit | 12679ab7d3c2a210f4123163671b532b8b55d5f9 (patch) | |
tree | 0060d13467186ad977f4e73488ee20dd6c0017ab /systems/texlive/tlnet/tlpkg/tlperl/lib/CORE/cop.h | |
parent | 62170822e034fdd3f81de7274835d0d3b0467100 (diff) |
CTAN sync 202403150306
Diffstat (limited to 'systems/texlive/tlnet/tlpkg/tlperl/lib/CORE/cop.h')
-rw-r--r-- | systems/texlive/tlnet/tlpkg/tlperl/lib/CORE/cop.h | 1045 |
1 files changed, 570 insertions, 475 deletions
diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/CORE/cop.h b/systems/texlive/tlnet/tlpkg/tlperl/lib/CORE/cop.h index b5f30bd041..1b2b7947e1 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/CORE/cop.h +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/CORE/cop.h @@ -33,7 +33,7 @@ struct jmpenv { struct jmpenv * je_prev; Sigjmp_buf je_buf; /* uninit if je_prev is NULL */ int je_ret; /* last exception thrown */ - bool je_mustcatch; /* need to call longjmp()? */ + bool je_mustcatch; /* longjmp()s must be caught locally */ U16 je_old_delaymagic; /* saved PL_delaymagic */ SSize_t je_old_stack_hwm; }; @@ -65,12 +65,12 @@ typedef struct jmpenv JMPENV; #define JMPENV_BOOTSTRAP \ STMT_START { \ - PERL_POISON_EXPR(PoisonNew(&PL_start_env, 1, JMPENV));\ - PL_top_env = &PL_start_env; \ - PL_start_env.je_prev = NULL; \ - PL_start_env.je_ret = -1; \ - PL_start_env.je_mustcatch = TRUE; \ - PL_start_env.je_old_delaymagic = 0; \ + PERL_POISON_EXPR(PoisonNew(&PL_start_env, 1, JMPENV));\ + PL_top_env = &PL_start_env; \ + PL_start_env.je_prev = NULL; \ + PL_start_env.je_ret = -1; \ + PL_start_env.je_mustcatch = TRUE; \ + PL_start_env.je_old_delaymagic = 0; \ JE_OLD_STACK_HWM_zero; \ } STMT_END @@ -110,59 +110,78 @@ typedef struct jmpenv JMPENV; #define dJMPENV JMPENV cur_env -#define JMPENV_PUSH(v) \ +#define JMPENV_PUSH(v) \ STMT_START { \ - DEBUG_l({ \ - int i = 0; JMPENV *p = PL_top_env; \ - while (p) { i++; p = p->je_prev; } \ - Perl_deb(aTHX_ "JUMPENV_PUSH level=%d at %s:%d\n", \ - i, __FILE__, __LINE__);}) \ - cur_env.je_prev = PL_top_env; \ + DEBUG_l({ \ + int i = 0; \ + JMPENV *p = PL_top_env; \ + while (p) { i++; p = p->je_prev; } \ + Perl_deb(aTHX_ "JMPENV_PUSH pre level=%d in %s at %s:%d\n", \ + i, SAFE_FUNCTION__, __FILE__, __LINE__); \ + }); \ + cur_env.je_prev = PL_top_env; \ JE_OLD_STACK_HWM_save(cur_env); \ - cur_env.je_ret = PerlProc_setjmp(cur_env.je_buf, SCOPE_SAVES_SIGNAL_MASK); \ + /* setjmp() is callable in limited contexts which does not */ \ + /* include assignment, so switch() instead */ \ + switch (PerlProc_setjmp(cur_env.je_buf, SCOPE_SAVES_SIGNAL_MASK)) { \ + case 0: cur_env.je_ret = 0; break; \ + case 1: cur_env.je_ret = 1; break; \ + case 2: cur_env.je_ret = 2; break; \ + case 3: cur_env.je_ret = 3; break; \ + default: Perl_croak(aTHX_ "panic: unexpected setjmp() result\n"); \ + } \ JE_OLD_STACK_HWM_restore(cur_env); \ - PL_top_env = &cur_env; \ - cur_env.je_mustcatch = FALSE; \ - cur_env.je_old_delaymagic = PL_delaymagic; \ - (v) = cur_env.je_ret; \ + PL_top_env = &cur_env; \ + cur_env.je_mustcatch = FALSE; \ + cur_env.je_old_delaymagic = PL_delaymagic; \ + DEBUG_l({ \ + int i = 0; \ + JMPENV *p = PL_top_env; \ + while (p) { i++; p = p->je_prev; } \ + Perl_deb(aTHX_ "JMPENV_PUSH level=%d ret=%d in %s at %s:%d\n", \ + i, cur_env.je_ret, SAFE_FUNCTION__, __FILE__, __LINE__); \ + }); \ + (v) = cur_env.je_ret; \ } STMT_END #define JMPENV_POP \ STMT_START { \ - DEBUG_l({ \ - int i = -1; JMPENV *p = PL_top_env; \ - while (p) { i++; p = p->je_prev; } \ - Perl_deb(aTHX_ "JUMPENV_POP level=%d at %s:%d\n", \ - i, __FILE__, __LINE__);}) \ - assert(PL_top_env == &cur_env); \ - PL_delaymagic = cur_env.je_old_delaymagic; \ - PL_top_env = cur_env.je_prev; \ + DEBUG_l({ \ + int i = -1; JMPENV *p = PL_top_env; \ + while (p) { i++; p = p->je_prev; } \ + Perl_deb(aTHX_ "JMPENV_POP level=%d in %s at %s:%d\n", \ + i, SAFE_FUNCTION__, __FILE__, __LINE__);}) \ + assert(PL_top_env == &cur_env); \ + PL_delaymagic = cur_env.je_old_delaymagic; \ + PL_top_env = cur_env.je_prev; \ } STMT_END #define JMPENV_JUMP(v) \ STMT_START { \ - DEBUG_l({ \ - int i = -1; JMPENV *p = PL_top_env; \ - while (p) { i++; p = p->je_prev; } \ - Perl_deb(aTHX_ "JUMPENV_JUMP(%d) level=%d at %s:%d\n", \ - (int)v, i, __FILE__, __LINE__);}) \ - if (PL_top_env->je_prev) \ - PerlProc_longjmp(PL_top_env->je_buf, (v)); \ - if ((v) == 2) \ - PerlProc_exit(STATUS_EXIT); \ - PerlIO_printf(PerlIO_stderr(), "panic: top_env, v=%d\n", (int)v); \ - PerlProc_exit(1); \ + DEBUG_l({ \ + int i = -1; JMPENV *p = PL_top_env; \ + while (p) { i++; p = p->je_prev; } \ + Perl_deb(aTHX_ "JMPENV_JUMP(%d) level=%d in %s at %s:%d\n", \ + (int)(v), i, SAFE_FUNCTION__, __FILE__, __LINE__);}) \ + if (PL_top_env->je_prev) { \ + assert((v) >= 0 && (v) <= 3); \ + PerlProc_longjmp(PL_top_env->je_buf, (v)); \ + } \ + if ((v) == 2) \ + PerlProc_exit(STATUS_EXIT); \ + PerlIO_printf(PerlIO_stderr(), "panic: top_env, v=%d\n", (int)(v)); \ + PerlProc_exit(1); \ } STMT_END #define CATCH_GET (PL_top_env->je_mustcatch) #define CATCH_SET(v) \ STMT_START { \ - DEBUG_l( \ - Perl_deb(aTHX_ \ - "JUMPLEVEL set catch %d => %d (for %p) at %s:%d\n", \ - PL_top_env->je_mustcatch, v, (void*)PL_top_env, \ - __FILE__, __LINE__);) \ - PL_top_env->je_mustcatch = (v); \ + DEBUG_l( \ + Perl_deb(aTHX_ \ + "JUMPLEVEL set catch %d => %d (for %p) in %s at %s:%d\n", \ + PL_top_env->je_mustcatch, (v), (void*)PL_top_env, \ + SAFE_FUNCTION__, __FILE__, __LINE__);) \ + PL_top_env->je_mustcatch = (v); \ } STMT_END /* @@ -175,109 +194,93 @@ typedef struct refcounted_he COPHH; #define COPHH_EXISTS REFCOUNTED_HE_EXISTS /* -=for apidoc Amx|SV *|cophh_fetch_pvn|const COPHH *cophh|const char *keypv|STRLEN keylen|U32 hash|U32 flags - -Look up the entry in the cop hints hash C<cophh> with the key specified by -C<keypv> and C<keylen>. If C<flags> has the C<COPHH_KEY_UTF8> bit set, -the key octets are interpreted as UTF-8, otherwise they are interpreted -as Latin-1. C<hash> is a precomputed hash of the key string, or zero if -it has not been precomputed. Returns a mortal scalar copy of the value -associated with the key, or C<&PL_sv_placeholder> if there is no value -associated with the key. +=for apidoc Amx|SV *|cophh_fetch_pv |const COPHH *cophh|const char *key |U32 hash|U32 flags +=for apidoc_item|SV *|cophh_fetch_pvn|const COPHH *cophh|const char *key|STRLEN keylen|U32 hash|U32 flags +=for apidoc_item|SV *|cophh_fetch_pvs|const COPHH *cophh| "key" |U32 flags +=for apidoc_item|SV *|cophh_fetch_sv |const COPHH *cophh| SV *key |U32 hash|U32 flags + +These look up the entry in the cop hints hash C<cophh> with the key specified by +C<key> (and C<keylen> in the C<pvn> form), returning that value as a mortal +scalar copy, or C<&PL_sv_placeholder> if there is no value associated with the +key. + +The forms differ in how the key is specified. +In the plain C<pv> form, the key is a C language NUL-terminated string. +In the C<pvs> form, the key is a C language string literal. +In the C<pvn> form, an additional parameter, C<keylen>, specifies the length of +the string, which hence, may contain embedded-NUL characters. +In the C<sv> form, C<*key> is an SV, and the key is the PV extracted from that. +using C<L</SvPV_const>>. + +C<hash> is a precomputed hash of the key string, or zero if it has not been +precomputed. This parameter is omitted from the C<pvs> form, as it is computed +automatically at compile time. + +The only flag currently used from the C<flags> parameter is C<COPHH_KEY_UTF8>. +It is illegal to set this in the C<sv> form. In the C<pv*> forms, it specifies +whether the key octets are interpreted as UTF-8 (if set) or as Latin-1 (if +cleared). The C<sv> form uses the underlying SV to determine the UTF-8ness of +the octets. =for apidoc Amnh||COPHH_KEY_UTF8 =cut -*/ - -#define cophh_fetch_pvn(cophh, keypv, keylen, hash, flags) \ - Perl_refcounted_he_fetch_pvn(aTHX_ cophh, keypv, keylen, hash, flags) - -/* -=for apidoc Amx|SV *|cophh_fetch_pvs|const COPHH *cophh|"key"|U32 flags -Like L</cophh_fetch_pvn>, but takes a literal string instead -of a string/length pair, and no precomputed hash. - -=cut */ -#define cophh_fetch_pvs(cophh, key, flags) \ - Perl_refcounted_he_fetch_pvn(aTHX_ cophh, STR_WITH_LEN(key), 0, flags) +#define cophh_fetch_pvn(cophh, key, keylen, hash, flags) \ + Perl_refcounted_he_fetch_pvn(aTHX_ cophh, key, keylen, hash, \ + (flags & COPHH_KEY_UTF8)) -/* -=for apidoc Amx|SV *|cophh_fetch_pv|const COPHH *cophh|const char *key|U32 hash|U32 flags +#define cophh_fetch_pvs(cophh, key, flags) \ + Perl_refcounted_he_fetch_pvn(aTHX_ cophh, STR_WITH_LEN(key), 0, \ + (flags & COPHH_KEY_UTF8)) -Like L</cophh_fetch_pvn>, but takes a nul-terminated string instead of -a string/length pair. +#define cophh_fetch_pv(cophh, key, hash, flags) \ + Perl_refcounted_he_fetch_pv(aTHX_ cophh, key, hash, \ + (flags & COPHH_KEY_UTF8)) -=cut -*/ - -#define cophh_fetch_pv(cophh, key, hash, flags) \ - Perl_refcounted_he_fetch_pv(aTHX_ cophh, key, hash, flags) +#define cophh_fetch_sv(cophh, key, hash, flags) \ + Perl_refcounted_he_fetch_sv(aTHX_ cophh, key, hash, \ + (flags & COPHH_KEY_UTF8)) /* -=for apidoc Amx|SV *|cophh_fetch_sv|const COPHH *cophh|SV *key|U32 hash|U32 flags - -Like L</cophh_fetch_pvn>, but takes a Perl scalar instead of a -string/length pair. - -=cut -*/ - -#define cophh_fetch_sv(cophh, key, hash, flags) \ - Perl_refcounted_he_fetch_sv(aTHX_ cophh, key, hash, flags) - -/* -=for apidoc Amx|bool|cophh_exists_pvn|const COPHH *cophh|const char *keypv|STRLEN keylen|U32 hash|U32 flags - -Look up the entry in the cop hints hash C<cophh> with the key specified by -C<keypv> and C<keylen>. If C<flags> has the C<COPHH_KEY_UTF8> bit set, -the key octets are interpreted as UTF-8, otherwise they are interpreted -as Latin-1. C<hash> is a precomputed hash of the key string, or zero if -it has not been precomputed. Returns true if a value exists, and false -otherwise. +=for apidoc Amx|bool|cophh_exists_pvn|const COPHH *cophh|const char *key|STRLEN keylen|U32 hash|U32 flags + +These look up the hint entry in the cop C<cop> with the key specified by +C<key> (and C<keylen> in the C<pvn> form), returning true if a value exists, +and false otherwise. + +The forms differ in how the key is specified. +In the plain C<pv> form, the key is a C language NUL-terminated string. +In the C<pvs> form, the key is a C language string literal. +In the C<pvn> form, an additional parameter, C<keylen>, specifies the length of +the string, which hence, may contain embedded-NUL characters. +In the C<sv> form, C<*key> is an SV, and the key is the PV extracted from that. +using C<L</SvPV_const>>. + +C<hash> is a precomputed hash of the key string, or zero if it has not been +precomputed. This parameter is omitted from the C<pvs> form, as it is computed +automatically at compile time. + +The only flag currently used from the C<flags> parameter is C<COPHH_KEY_UTF8>. +It is illegal to set this in the C<sv> form. In the C<pv*> forms, it specifies +whether the key octets are interpreted as UTF-8 (if set) or as Latin-1 (if +cleared). The C<sv> form uses the underlying SV to determine the UTF-8ness of +the octets. =cut */ -#define cophh_exists_pvn(cophh, keypv, keylen, hash, flags) \ - cBOOL(Perl_refcounted_he_fetch_pvn(aTHX_ cophh, keypv, keylen, hash, flags | COPHH_EXISTS)) - -/* -=for apidoc Amx|bool|cophh_exists_pvs|const COPHH *cophh|"key"|U32 flags - -Like L</cophh_exists_pvn>, but takes a literal string instead -of a string/length pair, and no precomputed hash. - -=cut -*/ +#define cophh_exists_pvn(cophh, key, keylen, hash, flags) \ + cBOOL(Perl_refcounted_he_fetch_pvn(aTHX_ cophh, key, keylen, hash, flags | COPHH_EXISTS)) #define cophh_exists_pvs(cophh, key, flags) \ cBOOL(Perl_refcounted_he_fetch_pvn(aTHX_ cophh, STR_WITH_LEN(key), 0, flags | COPHH_EXISTS)) -/* -=for apidoc Amx|bool|cophh_exists_pv|const COPHH *cophh|const char *key|U32 hash|U32 flags - -Like L</cophh_exists_pvn>, but takes a nul-terminated string instead of -a string/length pair. - -=cut -*/ - #define cophh_exists_pv(cophh, key, hash, flags) \ cBOOL(Perl_refcounted_he_fetch_pv(aTHX_ cophh, key, hash, flags | COPHH_EXISTS)) -/* -=for apidoc Amx|bool|cophh_exists_sv|const COPHH *cophh|SV *key|U32 hash|U32 flags - -Like L</cophh_exists_pvn>, but takes a Perl scalar instead of a -string/length pair. - -=cut -*/ - #define cophh_exists_sv(cophh, key, hash, flags) \ cBOOL(Perl_refcounted_he_fetch_sv(aTHX_ cophh, key, hash, flags | COPHH_EXISTS)) @@ -326,122 +329,102 @@ Generate and return a fresh cop hints hash containing no entries. #define cophh_new_empty() ((COPHH *)NULL) /* -=for apidoc Amx|COPHH *|cophh_store_pvn|COPHH *cophh|const char *keypv|STRLEN keylen|U32 hash|SV *value|U32 flags +=for apidoc Amx|COPHH *|cophh_store_pv |COPHH *cophh|const char *key |U32 hash|SV *value|U32 flags +=for apidoc_item|COPHH *|cophh_store_pvn|COPHH *cophh|const char *key|STRLEN keylen|U32 hash|SV *value|U32 flags +=for apidoc_item|COPHH *|cophh_store_pvs|COPHH *cophh| "key" |SV *value|U32 flags +=for apidoc_item|COPHH *|cophh_store_sv |COPHH *cophh| SV *key |U32 hash|SV *value|U32 flags -Stores a value, associated with a key, in the cop hints hash C<cophh>, -and returns the modified hash. The returned hash pointer is in general +These store a value, associated with a key, in the cop hints hash C<cophh>, +and return the modified hash. The returned hash pointer is in general not the same as the hash pointer that was passed in. The input hash is consumed by the function, and the pointer to it must not be subsequently used. Use L</cophh_copy> if you need both hashes. -The key is specified by C<keypv> and C<keylen>. If C<flags> has the -C<COPHH_KEY_UTF8> bit set, the key octets are interpreted as UTF-8, -otherwise they are interpreted as Latin-1. C<hash> is a precomputed -hash of the key string, or zero if it has not been precomputed. - C<value> is the scalar value to store for this key. C<value> is copied -by this function, which thus does not take ownership of any reference -to it, and later changes to the scalar will not be reflected in the -value visible in the cop hints hash. Complex types of scalar will not -be stored with referential integrity, but will be coerced to strings. +by these functions, which thus do not take ownership of any reference +to it, and hence later changes to the scalar will not be reflected in the value +visible in the cop hints hash. Complex types of scalar will not be stored with +referential integrity, but will be coerced to strings. + +The forms differ in how the key is specified. In all forms, the key is pointed +to by C<key>. +In the plain C<pv> form, the key is a C language NUL-terminated string. +In the C<pvs> form, the key is a C language string literal. +In the C<pvn> form, an additional parameter, C<keylen>, specifies the length of +the string, which hence, may contain embedded-NUL characters. +In the C<sv> form, C<*key> is an SV, and the key is the PV extracted from that. +using C<L</SvPV_const>>. + +C<hash> is a precomputed hash of the key string, or zero if it has not been +precomputed. This parameter is omitted from the C<pvs> form, as it is computed +automatically at compile time. + +The only flag currently used from the C<flags> parameter is C<COPHH_KEY_UTF8>. +It is illegal to set this in the C<sv> form. In the C<pv*> forms, it specifies +whether the key octets are interpreted as UTF-8 (if set) or as Latin-1 (if +cleared). The C<sv> form uses the underlying SV to determine the UTF-8ness of +the octets. =cut */ -#define cophh_store_pvn(cophh, keypv, keylen, hash, value, flags) \ - Perl_refcounted_he_new_pvn(aTHX_ cophh, keypv, keylen, hash, value, flags) - -/* -=for apidoc Amx|COPHH *|cophh_store_pvs|COPHH *cophh|"key"|SV *value|U32 flags - -Like L</cophh_store_pvn>, but takes a literal string instead -of a string/length pair, and no precomputed hash. - -=cut -*/ +#define cophh_store_pvn(cophh, key, keylen, hash, value, flags) \ + Perl_refcounted_he_new_pvn(aTHX_ cophh, key, keylen, hash, value, flags) #define cophh_store_pvs(cophh, key, value, flags) \ Perl_refcounted_he_new_pvn(aTHX_ cophh, STR_WITH_LEN(key), 0, value, flags) -/* -=for apidoc Amx|COPHH *|cophh_store_pv|COPHH *cophh|const char *key|U32 hash|SV *value|U32 flags - -Like L</cophh_store_pvn>, but takes a nul-terminated string instead of -a string/length pair. - -=cut -*/ - #define cophh_store_pv(cophh, key, hash, value, flags) \ Perl_refcounted_he_new_pv(aTHX_ cophh, key, hash, value, flags) -/* -=for apidoc Amx|COPHH *|cophh_store_sv|COPHH *cophh|SV *key|U32 hash|SV *value|U32 flags - -Like L</cophh_store_pvn>, but takes a Perl scalar instead of a -string/length pair. - -=cut -*/ - #define cophh_store_sv(cophh, key, hash, value, flags) \ Perl_refcounted_he_new_sv(aTHX_ cophh, key, hash, value, flags) /* -=for apidoc Amx|COPHH *|cophh_delete_pvn|COPHH *cophh|const char *keypv|STRLEN keylen|U32 hash|U32 flags +=for apidoc Amx|COPHH *|cophh_delete_pv |COPHH *cophh|const char *key |U32 hash|U32 flags +=for apidoc_item|COPHH *|cophh_delete_pvn|COPHH *cophh|const char *key|STRLEN keylen|U32 hash|U32 flags +=for apidoc_item|COPHH *|cophh_delete_pvs|COPHH *cophh| "key" |U32 flags +=for apidoc_item|COPHH *|cophh_delete_sv |COPHH *cophh| SV *key |U32 hash|U32 flags -Delete a key and its associated value from the cop hints hash C<cophh>, -and returns the modified hash. The returned hash pointer is in general +These delete a key and its associated value from the cop hints hash C<cophh>, +and return the modified hash. The returned hash pointer is in general not the same as the hash pointer that was passed in. The input hash is consumed by the function, and the pointer to it must not be subsequently used. Use L</cophh_copy> if you need both hashes. -The key is specified by C<keypv> and C<keylen>. If C<flags> has the -C<COPHH_KEY_UTF8> bit set, the key octets are interpreted as UTF-8, -otherwise they are interpreted as Latin-1. C<hash> is a precomputed -hash of the key string, or zero if it has not been precomputed. +The forms differ in how the key is specified. In all forms, the key is pointed +to by C<key>. +In the plain C<pv> form, the key is a C language NUL-terminated string. +In the C<pvs> form, the key is a C language string literal. +In the C<pvn> form, an additional parameter, C<keylen>, specifies the length of +the string, which hence, may contain embedded-NUL characters. +In the C<sv> form, C<*key> is an SV, and the key is the PV extracted from that. +using C<L</SvPV_const>>. + +C<hash> is a precomputed hash of the key string, or zero if it has not been +precomputed. This parameter is omitted from the C<pvs> form, as it is computed +automatically at compile time. + +The only flag currently used from the C<flags> parameter is C<COPHH_KEY_UTF8>. +It is illegal to set this in the C<sv> form. In the C<pv*> forms, it specifies +whether the key octets are interpreted as UTF-8 (if set) or as Latin-1 (if +cleared). The C<sv> form uses the underlying SV to determine the UTF-8ness of +the octets. =cut */ -#define cophh_delete_pvn(cophh, keypv, keylen, hash, flags) \ - Perl_refcounted_he_new_pvn(aTHX_ cophh, keypv, keylen, hash, \ - (SV *)NULL, flags) - -/* -=for apidoc Amx|COPHH *|cophh_delete_pvs|COPHH *cophh|"key"|U32 flags - -Like L</cophh_delete_pvn>, but takes a literal string instead -of a string/length pair, and no precomputed hash. - -=cut -*/ +#define cophh_delete_pvn(cophh, key, keylen, hash, flags) \ + Perl_refcounted_he_new_pvn(aTHX_ cophh, key, keylen, hash, \ + (SV *)NULL, flags) #define cophh_delete_pvs(cophh, key, flags) \ Perl_refcounted_he_new_pvn(aTHX_ cophh, STR_WITH_LEN(key), 0, \ - (SV *)NULL, flags) - -/* -=for apidoc Amx|COPHH *|cophh_delete_pv|COPHH *cophh|char *key|U32 hash|U32 flags - -Like L</cophh_delete_pvn>, but takes a nul-terminated string instead of -a string/length pair. - -=cut -*/ + (SV *)NULL, flags) #define cophh_delete_pv(cophh, key, hash, flags) \ Perl_refcounted_he_new_pv(aTHX_ cophh, key, hash, (SV *)NULL, flags) -/* -=for apidoc Amx|COPHH *|cophh_delete_sv|COPHH *cophh|SV *key|U32 hash|U32 flags - -Like L</cophh_delete_pvn>, but takes a Perl scalar instead of a -string/length pair. - -=cut -*/ - #define cophh_delete_sv(cophh, key, hash, flags) \ Perl_refcounted_he_new_sv(aTHX_ cophh, key, hash, (SV *)NULL, flags) @@ -455,16 +438,21 @@ struct cop { /* label for this construct is now stored in cop_hints_hash */ #ifdef USE_ITHREADS PADOFFSET cop_stashoff; /* offset into PL_stashpad, for the - package the line was compiled in */ - char * cop_file; /* name of file this command is from */ + package the line was compiled in */ + char * cop_file; /* rcpv containing name of file this command is from */ #else HV * cop_stash; /* package line was compiled in */ GV * cop_filegv; /* name of GV file this command is from */ #endif U32 cop_hints; /* hints bits from pragmata */ U32 cop_seq; /* parse sequence number */ - /* Beware. mg.c and warnings.pl assume the type of this is STRLEN *: */ - STRLEN * cop_warnings; /* lexical warnings bitmask */ + char * cop_warnings; /* Lexical warnings bitmask vector. + Refcounted shared copy of ${^WARNING_BITS}. + This pointer either points at one of the + magic values for warnings, or it points + at a buffer constructed with rcpv_new(). + Use the RCPV_LEN() macro to get its length. + */ /* compile time state of %^H. See the comment in op.c for how this is used to recreate a hash to return from caller. */ COPHH * cop_hints_hash; @@ -480,11 +468,18 @@ struct cop { =for apidoc Am|const char *|CopFILE|const COP * c Returns the name of the file associated with the C<COP> C<c> -=for apidoc Am|STRLEN|CopLINE|const COP * c +=for apidoc Am|const char *|CopFILE_LEN|const COP * c +Returns the length of the file associated with the C<COP> C<c> + +=for apidoc Am|line_t|CopLINE|const COP * c Returns the line number in the source code associated with the C<COP> C<c> =for apidoc Am|AV *|CopFILEAV|const COP * c -Returns the AV associated with the C<COP> C<c> +Returns the AV associated with the C<COP> C<c>, creating it if necessary. + +=for apidoc Am|AV *|CopFILEAVn|const COP * c +Returns the AV associated with the C<COP> C<c>, returning NULL if it +doesn't already exist. =for apidoc Am|SV *|CopFILESV|const COP * c Returns the SV associated with the C<COP> C<c> @@ -492,6 +487,17 @@ Returns the SV associated with the C<COP> C<c> =for apidoc Am|void|CopFILE_set|COP * c|const char * pv Makes C<pv> the name of the file associated with the C<COP> C<c> +=for apidoc Am|void|CopFILE_setn|COP * c|const char * pv|STRLEN len +Makes C<pv> the name of the file associated with the C<COP> C<c> + +=for apidoc Am|void|CopFILE_copy|COP * dst|COP * src +Efficiently copies the cop file name from one COP to another. Wraps +the required logic to do a refcounted copy under threads or not. + +=for apidoc Am|void|CopFILE_free|COP * c +Frees the file data in a cop. Under the hood this is a refcounting +operation. + =for apidoc Am|GV *|CopFILEGV|const COP * c Returns the GV associated with the C<COP> C<c> @@ -519,39 +525,132 @@ string C<p>, creating the package if necessary. =cut */ +/* +=for apidoc Am|RCPV *|RCPVx|char *pv +Returns the RCPV structure (struct rcpv) for a refcounted +string pv created with C<rcpv_new()>. +No checks are performed to ensure that C<pv> was actually allocated +with C<rcpv_new()>, it is the callers responsibility to ensure that +this is the case. + +=for apidoc Am|RCPV *|RCPV_REFCOUNT|char *pv +Returns the refcount for a pv created with C<rcpv_new()>. +No checks are performed to ensure that C<pv> was actually allocated +with C<rcpv_new()>, it is the callers responsibility to ensure that +this is the case. + +=for apidoc Am|RCPV *|RCPV_REFCNT_inc|char *pv +Increments the refcount for a C<char *> pointer which was created +with a call to C<rcpv_new()>. Same as calling rcpv_copy(). +No checks are performed to ensure that C<pv> was actually allocated +with C<rcpv_new()>, it is the callers responsibility to ensure that +this is the case. + +=for apidoc Am|RCPV *|RCPV_REFCNT_dec|char *pv +Decrements the refcount for a C<char *> pointer which was created +with a call to C<rcpv_new()>. Same as calling rcpv_free(). +No checks are performed to ensure that C<pv> was actually allocated +with C<rcpv_new()>, it is the callers responsibility to ensure that +this is the case. + +=for apidoc Am|RCPV *|RCPV_LEN|char *pv +Returns the length of a pv created with C<rcpv_new()>. +Note that this reflects the length of the string from the callers +point of view, it does not include the mandatory null which is +always injected at the end of the string by rcpv_new(). +No checks are performed to ensure that C<pv> was actually allocated +with C<rcpv_new()>, it is the callers responsibility to ensure that +this is the case. + +=cut +*/ + +struct rcpv { + STRLEN refcount; /* UV would mean a 64 refcnt on + 32 bit builds with -Duse64bitint */ + STRLEN len; /* length of string including mandatory + null byte at end */ + char pv[1]; +}; +typedef struct rcpv RCPV; + +#define RCPVf_USE_STRLEN (1 << 0) +#define RCPVf_NO_COPY (1 << 1) +#define RCPVf_ALLOW_EMPTY (1 << 2) + +#define RCPVx(pv_arg) ((RCPV *)((pv_arg) - STRUCT_OFFSET(struct rcpv, pv))) +#define RCPV_REFCOUNT(pv) (RCPVx(pv)->refcount) +#define RCPV_LEN(pv) (RCPVx(pv)->len-1) /* len always includes space for a null */ +#define RCPV_REFCNT_inc(pv) rcpv_copy(pv) +#define RCPV_REFCNT_dec(pv) rcpv_free(pv) + #ifdef USE_ITHREADS -# define CopFILE(c) ((c)->cop_file) + +# define CopFILE(c) ((c)->cop_file) +# define CopFILE_LEN(c) (CopFILE(c) ? RCPV_LEN(CopFILE(c)) : 0) # define CopFILEGV(c) (CopFILE(c) \ - ? gv_fetchfile(CopFILE(c)) : NULL) + ? gv_fetchfile(CopFILE(c)) : NULL) + +# define CopFILE_set_x(c,pv) ((c)->cop_file = rcpv_new((pv),0,RCPVf_USE_STRLEN)) +# define CopFILE_setn_x(c,pv,l) ((c)->cop_file = rcpv_new((pv),(l),0)) +# define CopFILE_free_x(c) ((c)->cop_file = rcpv_free((c)->cop_file)) +# define CopFILE_copy_x(dst,src) ((dst)->cop_file = rcpv_copy((src)->cop_file)) + +/* change condition to 1 && to enable this debugging */ +# define CopFILE_debug(c,t,rk) \ + if (0 && (c)->cop_file) \ + PerlIO_printf(Perl_debug_log, \ + "%-14s THX:%p OP:%p PV:%p rc: " \ + "%6zu fn: '%.*s' at %s line %d\n", \ + (t), aTHX, (c), (c)->cop_file, \ + RCPV_REFCOUNT((c)->cop_file)-rk, \ + (int)RCPV_LEN((c)->cop_file), \ + (c)->cop_file,__FILE__,__LINE__) \ + + +# define CopFILE_set(c,pv) \ + STMT_START { \ + CopFILE_set_x(c,pv); \ + CopFILE_debug(c,"CopFILE_set", 0); \ + } STMT_END + +# define CopFILE_setn(c,pv,l) \ + STMT_START { \ + CopFILE_setn_x(c,pv,l); \ + CopFILE_debug(c,"CopFILE_setn", 0); \ + } STMT_END + +# define CopFILE_copy(dst,src) \ + STMT_START { \ + CopFILE_copy_x((dst),(src)); \ + CopFILE_debug((dst),"CopFILE_copy", 0); \ + } STMT_END + +# define CopFILE_free(c) \ + STMT_START { \ + CopFILE_debug((c),"CopFILE_free", 1); \ + CopFILE_free_x(c); \ + } STMT_END -# ifdef NETWARE -# define CopFILE_set(c,pv) ((c)->cop_file = savepv(pv)) -# define CopFILE_setn(c,pv,l) ((c)->cop_file = savepvn((pv),(l))) -# else -# define CopFILE_set(c,pv) ((c)->cop_file = savesharedpv(pv)) -# define CopFILE_setn(c,pv,l) ((c)->cop_file = savesharedpvn((pv),(l))) -# endif # define CopFILESV(c) (CopFILE(c) \ - ? GvSV(gv_fetchfile(CopFILE(c))) : NULL) + ? GvSV(gv_fetchfile(CopFILE(c))) : NULL) # define CopFILEAV(c) (CopFILE(c) \ - ? GvAV(gv_fetchfile(CopFILE(c))) : NULL) + ? GvAV(gv_fetchfile(CopFILE(c))) : NULL) # define CopFILEAVx(c) (assert_(CopFILE(c)) \ - GvAV(gv_fetchfile(CopFILE(c)))) - + GvAV(gv_fetchfile(CopFILE(c)))) +# define CopFILEAVn(c) (cop_file_avn(c)) # define CopSTASH(c) PL_stashpad[(c)->cop_stashoff] # define CopSTASH_set(c,hv) ((c)->cop_stashoff = (hv) \ - ? alloccopstash(hv) \ - : 0) -# ifdef NETWARE -# define CopFILE_free(c) SAVECOPFILE_FREE(c) -# else -# define CopFILE_free(c) (PerlMemShared_free(CopFILE(c)),(CopFILE(c) = NULL)) -# endif -#else /* Above: no threads; Below yes threads */ + ? alloccopstash(hv) \ + : 0) + +#else /* Above: yes threads; Below no threads */ + # define CopFILEGV(c) ((c)->cop_filegv) # define CopFILEGV_set(c,gv) ((c)->cop_filegv = (GV*)SvREFCNT_inc(gv)) # define CopFILE_set(c,pv) CopFILEGV_set((c), gv_fetchfile(pv)) +# define CopFILE_copy(dst,src) CopFILEGV_set((dst),CopFILEGV(src)) # define CopFILE_setn(c,pv,l) CopFILEGV_set((c), gv_fetchfile_flags((pv),(l),0)) # define CopFILESV(c) (CopFILEGV(c) ? GvSV(CopFILEGV(c)) : NULL) # define CopFILEAV(c) (CopFILEGV(c) ? GvAV(CopFILEGV(c)) : NULL) @@ -560,8 +659,11 @@ string C<p>, creating the package if necessary. # else # define CopFILEAVx(c) (GvAV(CopFILEGV(c))) # endif +# define CopFILEAVn(c) (CopFILEGV(c) ? GvAVn(CopFILEGV(c)) : NULL) # define CopFILE(c) (CopFILEGV(c) /* +2 for '_<' */ \ - ? GvNAME(CopFILEGV(c))+2 : NULL) + ? GvNAME(CopFILEGV(c))+2 : NULL) +# define CopFILE_LEN(c) (CopFILEGV(c) /* -2 for '_<' */ \ + ? GvNAMELEN(CopFILEGV(c))-2 : 0) # define CopSTASH(c) ((c)->cop_stash) # define CopSTASH_set(c,hv) ((c)->cop_stash = (hv)) # define CopFILE_free(c) (SvREFCNT_dec(CopFILEGV(c)),(CopFILEGV(c) = NULL)) @@ -576,108 +678,93 @@ string C<p>, creating the package if necessary. #define CopHINTHASH_get(c) ((COPHH*)((c)->cop_hints_hash)) #define CopHINTHASH_set(c,h) ((c)->cop_hints_hash = (h)) -/* -=for apidoc Am|SV *|cop_hints_fetch_pvn|const COP *cop|const char *keypv|STRLEN keylen|U32 hash|U32 flags - -Look up the hint entry in the cop C<cop> with the key specified by -C<keypv> and C<keylen>. If C<flags> has the C<COPHH_KEY_UTF8> bit set, -the key octets are interpreted as UTF-8, otherwise they are interpreted -as Latin-1. C<hash> is a precomputed hash of the key string, or zero if -it has not been precomputed. Returns a mortal scalar copy of the value -associated with the key, or C<&PL_sv_placeholder> if there is no value -associated with the key. - -=cut -*/ - -#define cop_hints_fetch_pvn(cop, keypv, keylen, hash, flags) \ - cophh_fetch_pvn(CopHINTHASH_get(cop), keypv, keylen, hash, flags) +#define CopFEATURES_setfrom(dst, src) ((dst)->cop_features = (src)->cop_features) /* -=for apidoc Am|SV *|cop_hints_fetch_pvs|const COP *cop|"key"|U32 flags - -Like L</cop_hints_fetch_pvn>, but takes a literal string -instead of a string/length pair, and no precomputed hash. +=for apidoc Am|SV *|cop_hints_fetch_pv |const COP *cop|const char *key |U32 hash|U32 flags +=for apidoc_item|SV *|cop_hints_fetch_pvn|const COP *cop|const char *key|STRLEN keylen|U32 hash|U32 flags +=for apidoc_item|SV *|cop_hints_fetch_pvs|const COP *cop| "key" |U32 flags +=for apidoc_item|SV *|cop_hints_fetch_sv |const COP *cop| SV *key |U32 hash|U32 flags + +These look up the hint entry in the cop C<cop> with the key specified by +C<key> (and C<keylen> in the C<pvn> form), returning that value as a mortal +scalar copy, or C<&PL_sv_placeholder> if there is no value associated with the +key. + +The forms differ in how the key is specified. +In the plain C<pv> form, the key is a C language NUL-terminated string. +In the C<pvs> form, the key is a C language string literal. +In the C<pvn> form, an additional parameter, C<keylen>, specifies the length of +the string, which hence, may contain embedded-NUL characters. +In the C<sv> form, C<*key> is an SV, and the key is the PV extracted from that. +using C<L</SvPV_const>>. + +C<hash> is a precomputed hash of the key string, or zero if it has not been +precomputed. This parameter is omitted from the C<pvs> form, as it is computed +automatically at compile time. + +The only flag currently used from the C<flags> parameter is C<COPHH_KEY_UTF8>. +It is illegal to set this in the C<sv> form. In the C<pv*> forms, it specifies +whether the key octets are interpreted as UTF-8 (if set) or as Latin-1 (if +cleared). The C<sv> form uses the underlying SV to determine the UTF-8ness of +the octets. =cut */ +#define cop_hints_fetch_pvn(cop, key, keylen, hash, flags) \ + cophh_fetch_pvn(CopHINTHASH_get(cop), key, keylen, hash, flags) + #define cop_hints_fetch_pvs(cop, key, flags) \ cophh_fetch_pvs(CopHINTHASH_get(cop), key, flags) -/* -=for apidoc Am|SV *|cop_hints_fetch_pv|const COP *cop|const char *key|U32 hash|U32 flags - -Like L</cop_hints_fetch_pvn>, but takes a nul-terminated string instead -of a string/length pair. - -=cut -*/ - #define cop_hints_fetch_pv(cop, key, hash, flags) \ cophh_fetch_pv(CopHINTHASH_get(cop), key, hash, flags) -/* -=for apidoc Am|SV *|cop_hints_fetch_sv|const COP *cop|SV *key|U32 hash|U32 flags - -Like L</cop_hints_fetch_pvn>, but takes a Perl scalar instead of a -string/length pair. - -=cut -*/ - #define cop_hints_fetch_sv(cop, key, hash, flags) \ cophh_fetch_sv(CopHINTHASH_get(cop), key, hash, flags) /* -=for apidoc Am|bool|cop_hints_exists_pvn|const COP *cop|const char *keypv|STRLEN keylen|U32 hash|U32 flags - -Look up the hint entry in the cop C<cop> with the key specified by -C<keypv> and C<keylen>. If C<flags> has the C<COPHH_KEY_UTF8> bit set, -the key octets are interpreted as UTF-8, otherwise they are interpreted -as Latin-1. C<hash> is a precomputed hash of the key string, or zero if -it has not been precomputed. Returns true if a value exists, and false -otherwise. +=for apidoc Am|bool|cop_hints_exists_pv |const COP *cop|const char *key|U32 hash |U32 flags +=for apidoc_item|bool|cop_hints_exists_pvn|const COP *cop|const char *key|STRLEN keylen|U32 hash|U32 flags +=for apidoc_item|bool|cop_hints_exists_pvs|const COP *cop| "key" |U32 flags +=for apidoc_item|bool|cop_hints_exists_sv |const COP *cop| SV *key |U32 hash|U32 flags + +These look up the hint entry in the cop C<cop> with the key specified by +C<key> (and C<keylen> in the C<pvn> form), returning true if a value exists, +and false otherwise. + +The forms differ in how the key is specified. In all forms, the key is pointed +to by C<key>. +In the plain C<pv> form, the key is a C language NUL-terminated string. +In the C<pvs> form, the key is a C language string literal. +In the C<pvn> form, an additional parameter, C<keylen>, specifies the length of +the string, which hence, may contain embedded-NUL characters. +In the C<sv> form, C<*key> is an SV, and the key is the PV extracted from that. +using C<L</SvPV_const>>. + +C<hash> is a precomputed hash of the key string, or zero if it has not been +precomputed. This parameter is omitted from the C<pvs> form, as it is computed +automatically at compile time. + +The only flag currently used from the C<flags> parameter is C<COPHH_KEY_UTF8>. +It is illegal to set this in the C<sv> form. In the C<pv*> forms, it specifies +whether the key octets are interpreted as UTF-8 (if set) or as Latin-1 (if +cleared). The C<sv> form uses the underlying SV to determine the UTF-8ness of +the octets. =cut */ -#define cop_hints_exists_pvn(cop, keypv, keylen, hash, flags) \ - cophh_exists_pvn(CopHINTHASH_get(cop), keypv, keylen, hash, flags) - -/* -=for apidoc Am|bool|cop_hints_exists_pvs|const COP *cop|"key"|U32 flags - -Like L</cop_hints_exists_pvn>, but takes a literal string -instead of a string/length pair, and no precomputed hash. - -=cut -*/ +#define cop_hints_exists_pvn(cop, key, keylen, hash, flags) \ + cophh_exists_pvn(CopHINTHASH_get(cop), key, keylen, hash, flags) #define cop_hints_exists_pvs(cop, key, flags) \ cophh_exists_pvs(CopHINTHASH_get(cop), key, flags) -/* -=for apidoc Am|bool|cop_hints_exists_pv|const COP *cop|const char *key|U32 hash|U32 flags - -Like L</cop_hints_exists_pvn>, but takes a nul-terminated string instead -of a string/length pair. - -=cut -*/ - #define cop_hints_exists_pv(cop, key, hash, flags) \ cophh_exists_pv(CopHINTHASH_get(cop), key, hash, flags) -/* -=for apidoc Am|bool|cop_hints_exists_sv|const COP *cop|SV *key|U32 hash|U32 flags - -Like L</cop_hints_exists_pvn>, but takes a Perl scalar instead of a -string/length pair. - -=cut -*/ - #define cop_hints_exists_sv(cop, key, hash, flags) \ cophh_exists_sv(CopHINTHASH_get(cop), key, hash, flags) @@ -695,19 +782,17 @@ be zero. cophh_2hv(CopHINTHASH_get(cop), flags) /* -=for apidoc Am|const char *|CopLABEL|COP *const cop - -Returns the label attached to a cop. +=for apidoc Am|const char *|CopLABEL |COP *const cop +=for apidoc_item|const char *|CopLABEL_len |COP *const cop|STRLEN *len +=for apidoc_item|const char *|CopLABEL_len_flags|COP *const cop|STRLEN *len|U32 *flags -=for apidoc Am|const char *|CopLABEL_len|COP *const cop|STRLEN *len +These return the label attached to a cop. -Returns the label attached to a cop, and stores its length in bytes into -C<*len>. +C<CopLABEL_len> and C<CopLABEL_len_flags> additionally store the number of +bytes comprising the returned label into C<*len>. -=for apidoc Am|const char *|CopLABEL_len_flags|COP *const cop|STRLEN *len|U32 *flags - -Returns the label attached to a cop, and stores its length in bytes into -C<*len>. Upon return, C<*flags> will be set to either C<SVf_UTF8> or 0. +C<CopLABEL_len_flags> additionally returns the UTF-8ness of the returned label, +by setting C<*flags> to 0 or C<SVf_UTF8>. =cut */ @@ -728,8 +813,8 @@ C<*len>. Upon return, C<*flags> will be set to either C<SVf_UTF8> or 0. #define CopHINTS_get(c) ((c)->cop_hints + 0) #define CopHINTS_set(c, h) STMT_START { \ - (c)->cop_hints = (h); \ - } STMT_END + (c)->cop_hints = (h); \ + } STMT_END /* * Here we have some enormously heavy (or at least ponderous) wizardry. @@ -781,20 +866,20 @@ struct block_format { #endif #define CX_PUSHSUB_GET_LVALUE_MASK(func) \ - /* If the context is indeterminate, then only the lvalue */ \ - /* flags that the caller also has are applicable. */ \ - ( \ - (PL_op->op_flags & OPf_WANT) \ - ? OPpENTERSUB_LVAL_MASK \ - : !(PL_op->op_private & OPpENTERSUB_LVAL_MASK) \ - ? 0 : (U8)func(aTHX) \ - ) + /* If the context is indeterminate, then only the lvalue */ \ + /* flags that the caller also has are applicable. */ \ + ( \ + (PL_op->op_flags & OPf_WANT) \ + ? OPpENTERSUB_LVAL_MASK \ + : !(PL_op->op_private & OPpENTERSUB_LVAL_MASK) \ + ? 0 : (U8)func(aTHX) \ + ) /* Restore old @_ */ #define CX_POP_SAVEARRAY(cx) \ STMT_START { \ AV *cx_pop_savearray_av = GvAV(PL_defgv); \ - GvAV(PL_defgv) = cx->blk_sub.savearray; \ + GvAV(PL_defgv) = cx->blk_sub.savearray; \ cx->blk_sub.savearray = NULL; \ SvREFCNT_dec(cx_pop_savearray_av); \ } STMT_END @@ -803,9 +888,9 @@ struct block_format { * leave any (a fast av_clear(ary), basically) */ #define CLEAR_ARGARRAY(ary) \ STMT_START { \ - AvMAX(ary) += AvARRAY(ary) - AvALLOC(ary); \ - AvARRAY(ary) = AvALLOC(ary); \ - AvFILLp(ary) = -1; \ + AvMAX(ary) += AvARRAY(ary) - AvALLOC(ary); \ + AvARRAY(ary) = AvALLOC(ary); \ + AvFILLp(ary) = -1; \ } STMT_END @@ -827,7 +912,7 @@ struct block_eval { /* blk_u16 bit usage for eval contexts: */ -#define CxOLD_IN_EVAL(cx) (((cx)->blk_u16) & 0x3F) /* saved PL in_eval */ +#define CxOLD_IN_EVAL(cx) (((cx)->blk_u16) & 0x3F) /* saved PL_in_eval */ #define CxEVAL_TXT_REFCNTED(cx) (((cx)->blk_u16) & 0x40) /* cur_text rc++ */ #define CxOLD_OP_TYPE(cx) (((cx)->blk_u16) >> 7) /* type of eval op */ @@ -835,27 +920,27 @@ struct block_eval { struct block_loop { LOOP * my_op; /* My op, that contains redo, next and last ops. */ union { /* different ways of locating the iteration variable */ - SV **svp; /* for lexicals: address of pad slot */ - GV *gv; /* for package vars */ + SV **svp; /* for lexicals: address of pad slot */ + GV *gv; /* for package vars */ } itervar_u; SV *itersave; /* the original iteration var */ union { - struct { /* CXt_LOOP_ARY, C<for (@ary)> */ - AV *ary; /* array being iterated over */ - IV ix; /* index relative to base of array */ - } ary; - struct { /* CXt_LOOP_LIST, C<for (list)> */ - I32 basesp; /* first element of list on stack */ - IV ix; /* index relative to basesp */ - } stack; - struct { /* CXt_LOOP_LAZYIV, C<for (1..9)> */ - IV cur; - IV end; - } lazyiv; - struct { /* CXt_LOOP_LAZYSV C<for ('a'..'z')> */ - SV * cur; - SV * end; /* maxiumum value (or minimum in reverse) */ - } lazysv; + struct { /* CXt_LOOP_ARY, C<for (@ary)> */ + AV *ary; /* array being iterated over */ + IV ix; /* index relative to base of array */ + } ary; + struct { /* CXt_LOOP_LIST, C<for (list)> */ + I32 basesp; /* first element of list on stack */ + IV ix; /* index relative to basesp */ + } stack; + struct { /* CXt_LOOP_LAZYIV, C<for (1..9)> */ + IV cur; + IV end; + } lazyiv; + struct { /* CXt_LOOP_LAZYSV C<for ('a'..'z')> */ + SV * cur; + SV * end; /* maximum value (or minimum in reverse) */ + } lazysv; } state_u; #ifdef USE_ITHREADS PAD *oldcomppad; /* needed to map itervar_u.svp during thread clone */ @@ -869,9 +954,9 @@ struct block_loop { ? &GvSV((c)->blk_loop.itervar_u.gv) \ : (SV **)&(c)->blk_loop.itervar_u.gv) -#define CxLABEL(c) (0 + CopLABEL((c)->blk_oldcop)) -#define CxLABEL_len(c,len) (0 + CopLABEL_len((c)->blk_oldcop, len)) -#define CxLABEL_len_flags(c,len,flags) (0 + CopLABEL_len_flags((c)->blk_oldcop, len, flags)) +#define CxLABEL(c) (CopLABEL((c)->blk_oldcop)) +#define CxLABEL_len(c,len) (CopLABEL_len((c)->blk_oldcop, len)) +#define CxLABEL_len_flags(c,len,flags) ((const char *)CopLABEL_len_flags((c)->blk_oldcop, len, flags)) #define CxHASARGS(c) (((c)->cx_type & CXp_HASARGS) == CXp_HASARGS) /* CxLVAL(): the lval flags of the call site: the relevant flag bits from @@ -885,13 +970,13 @@ struct block_loop { * Note the contrast with CvLVALUE(), which is a property of the sub * rather than the call site. */ -#define CxLVAL(c) (0 + ((c)->blk_u16 & 0xff)) +#define CxLVAL(c) (0 + ((U8)((c)->blk_u16))) /* given/when context */ struct block_givwhen { - OP *leave_op; + OP *leave_op; SV *defsv_save; /* the original $_ */ }; @@ -912,11 +997,11 @@ struct block { I32 blku_oldscopesp; /* scope stack index */ union { - struct block_sub blku_sub; - struct block_format blku_format; - struct block_eval blku_eval; - struct block_loop blku_loop; - struct block_givwhen blku_givwhen; + struct block_sub blku_sub; + struct block_format blku_format; + struct block_eval blku_eval; + struct block_loop blku_loop; + struct block_givwhen blku_givwhen; } blk_u; }; #define blk_oldsp cx_u.cx_blk.blku_oldsp @@ -936,15 +1021,15 @@ struct block { #define CX_DEBUG(cx, action) \ DEBUG_l( \ - Perl_deb(aTHX_ "CX %ld %s %s (scope %ld,%ld) (save %ld,%ld) at %s:%d\n",\ - (long)cxstack_ix, \ - action, \ - PL_block_type[CxTYPE(cx)], \ - (long)PL_scopestack_ix, \ - (long)(cx->blk_oldscopesp), \ - (long)PL_savestack_ix, \ - (long)(cx->blk_oldsaveix), \ - __FILE__, __LINE__)); + Perl_deb(aTHX_ "CX %ld %s %s (scope %ld,%ld) (save %ld,%ld) in %s at %s:%d\n",\ + (long)cxstack_ix, \ + action, \ + PL_block_type[CxTYPE(cx)], \ + (long)PL_scopestack_ix, \ + (long)(cx->blk_oldscopesp), \ + (long)PL_savestack_ix, \ + (long)(cx->blk_oldsaveix), \ + SAFE_FUNCTION__, __FILE__, __LINE__)); @@ -983,32 +1068,32 @@ struct subst { #define sb_rx cx_u.cx_subst.sbu_rx # define CX_PUSHSUBST(cx) CXINC, cx = CX_CUR(), \ - cx->blk_oldsaveix = oldsave, \ - cx->sb_iters = iters, \ - cx->sb_maxiters = maxiters, \ - cx->sb_rflags = r_flags, \ - cx->sb_rxtainted = rxtainted, \ - cx->sb_orig = orig, \ - cx->sb_dstr = dstr, \ - cx->sb_targ = targ, \ - cx->sb_s = s, \ - cx->sb_m = m, \ - cx->sb_strend = strend, \ - cx->sb_rxres = NULL, \ - cx->sb_rx = rx, \ - cx->cx_type = CXt_SUBST | (once ? CXp_ONCE : 0); \ - rxres_save(&cx->sb_rxres, rx); \ - (void)ReREFCNT_inc(rx); \ + cx->blk_oldsaveix = oldsave, \ + cx->sb_iters = iters, \ + cx->sb_maxiters = maxiters, \ + cx->sb_rflags = r_flags, \ + cx->sb_rxtainted = rxtainted, \ + cx->sb_orig = orig, \ + cx->sb_dstr = dstr, \ + cx->sb_targ = targ, \ + cx->sb_s = s, \ + cx->sb_m = m, \ + cx->sb_strend = strend, \ + cx->sb_rxres = NULL, \ + cx->sb_rx = rx, \ + cx->cx_type = CXt_SUBST | (once ? CXp_ONCE : 0); \ + rxres_save(&cx->sb_rxres, rx); \ + (void)ReREFCNT_inc(rx); \ SvREFCNT_inc_void_NN(targ) # define CX_POPSUBST(cx) \ STMT_START { \ REGEXP *re; \ assert(CxTYPE(cx) == CXt_SUBST); \ - rxres_free(&cx->sb_rxres); \ - re = cx->sb_rx; \ - cx->sb_rx = NULL; \ - ReREFCNT_dec(re); \ + rxres_free(&cx->sb_rxres); \ + re = cx->sb_rx; \ + cx->sb_rx = NULL; \ + ReREFCNT_dec(re); \ SvREFCNT_dec_NN(cx->sb_targ); \ } STMT_END #endif @@ -1017,8 +1102,8 @@ struct subst { struct context { union { - struct block cx_blk; - struct subst cx_subst; + struct block cx_blk; + struct subst cx_subst; } cx_u; }; #define cx_type cx_u.cx_subst.sbu_type @@ -1047,6 +1132,7 @@ struct context { #define CXt_FORMAT 10 #define CXt_EVAL 11 /* eval'', eval{}, try{} */ #define CXt_SUBST 12 +#define CXt_DEFER 13 /* SUBST doesn't feature in all switch statements. */ /* private flags for CXt_SUB and CXt_FORMAT */ @@ -1080,41 +1166,50 @@ struct context { && CxTYPE(cx) <= CXt_LOOP_PLAIN) #define CxMULTICALL(c) ((c)->cx_type & CXp_MULTICALL) #define CxREALEVAL(c) (((c)->cx_type & (CXTYPEMASK|CXp_REAL)) \ - == (CXt_EVAL|CXp_REAL)) + == (CXt_EVAL|CXp_REAL)) #define CxEVALBLOCK(c) (((c)->cx_type & (CXTYPEMASK|CXp_EVALBLOCK)) \ - == (CXt_EVAL|CXp_EVALBLOCK)) + == (CXt_EVAL|CXp_EVALBLOCK)) #define CxTRY(c) (((c)->cx_type & (CXTYPEMASK|CXp_TRY)) \ == (CXt_EVAL|CXp_TRY)) #define CxFOREACH(c) ( CxTYPE(cx) >= CXt_LOOP_ARY \ && CxTYPE(cx) <= CXt_LOOP_LIST) +/* private flags for CXt_DEFER */ +#define CXp_FINALLY 0x20 /* `finally` block; semantically identical + * but matters for diagnostic messages */ + /* deprecated old name before real try/catch was added */ #define CXp_TRYBLOCK CXp_EVALBLOCK #define CxTRYBLOCK(c) CxEVALBLOCK(c) #define CXINC (cxstack_ix < cxstack_max ? ++cxstack_ix : (cxstack_ix = cxinc())) -#define G_SCALAR 2 -#define G_ARRAY 3 -#define G_VOID 1 -#define G_WANT 3 +#define G_SCALAR 2 +#define G_LIST 3 +#define G_VOID 1 +#define G_WANT 3 + +#ifndef PERL_CORE + /* name prior to 5.31.1 */ +# define G_ARRAY G_LIST +#endif /* extra flags for Perl_call_* routines */ #define G_DISCARD 0x4 /* Call FREETMPS. - Don't change this without consulting the - hash actions codes defined in hv.h */ + Don't change this without consulting the + hash actions codes defined in hv.h */ #define G_EVAL 0x8 /* Assume eval {} around subroutine call. */ #define G_NOARGS 0x10 /* Don't construct a @_ array. */ #define G_KEEPERR 0x20 /* Warn for errors, don't overwrite $@ */ #define G_NODEBUG 0x40 /* Disable debugging at toplevel. */ #define G_METHOD 0x80 /* Calling method. */ #define G_FAKINGEVAL 0x100 /* Faking an eval context for call_sv or - fold_constants. */ + fold_constants. */ #define G_UNDEF_FILL 0x200 /* Fill the stack with &PL_sv_undef - A special case for UNSHIFT in - Perl_magic_methcall(). */ + A special case for UNSHIFT in + Perl_magic_methcall(). */ #define G_WRITING_TO_STDERR 0x400 /* Perl_write_to_stderr() is calling - Perl_magic_methcall(). */ + Perl_magic_methcall(). */ #define G_RE_REPARSING 0x800 /* compiling a run-time /(?{..})/ */ #define G_METHOD_NAMED 0x1000 /* calling named method, eg without :: or ' */ #define G_RETHROW 0x2000 /* eval_sv(): re-throw any error */ @@ -1158,8 +1253,8 @@ struct stackinfo { I32 si_cxsubix; /* topmost sub/eval/format */ I32 si_type; /* type of runlevel */ I32 si_markoff; /* offset where markstack begins for us. - * currently used only with DEBUGGING, - * but not #ifdef-ed for bincompat */ + * currently used only with DEBUGGING, + * but not #ifdef-ed for bincompat */ #if defined DEBUGGING && !defined DEBUGGING_RE_ONLY /* high water mark: for checking if the stack was correctly extended / * tested for extension by each pp function */ @@ -1181,10 +1276,10 @@ typedef struct stackinfo PERL_SI; #define cxstack_max (PL_curstackinfo->si_cxmax) #ifdef DEBUGGING -# define SET_MARK_OFFSET \ +# define SET_MARK_OFFSET \ PL_curstackinfo->si_markoff = PL_markstack_ptr - PL_markstack #else -# define SET_MARK_OFFSET NOOP +# define SET_MARK_OFFSET NOOP #endif #if defined DEBUGGING && !defined DEBUGGING_RE_ONLY @@ -1195,25 +1290,25 @@ typedef struct stackinfo PERL_SI; #define PUSHSTACKi(type) \ STMT_START { \ - PERL_SI *next = PL_curstackinfo->si_next; \ - DEBUG_l({ \ - int i = 0; PERL_SI *p = PL_curstackinfo; \ - while (p) { i++; p = p->si_prev; } \ - Perl_deb(aTHX_ "push STACKINFO %d at %s:%d\n", \ - i, __FILE__, __LINE__);}) \ - if (!next) { \ - next = new_stackinfo(32, 2048/sizeof(PERL_CONTEXT) - 1); \ - next->si_prev = PL_curstackinfo; \ - PL_curstackinfo->si_next = next; \ - } \ - next->si_type = type; \ - next->si_cxix = -1; \ - next->si_cxsubix = -1; \ + PERL_SI *next = PL_curstackinfo->si_next; \ + DEBUG_l({ \ + int i = 0; PERL_SI *p = PL_curstackinfo; \ + while (p) { i++; p = p->si_prev; } \ + Perl_deb(aTHX_ "push STACKINFO %d in %s at %s:%d\n", \ + i, SAFE_FUNCTION__, __FILE__, __LINE__);}) \ + if (!next) { \ + next = new_stackinfo(32, 2048/sizeof(PERL_CONTEXT) - 1); \ + next->si_prev = PL_curstackinfo; \ + PL_curstackinfo->si_next = next; \ + } \ + next->si_type = type; \ + next->si_cxix = -1; \ + next->si_cxsubix = -1; \ PUSHSTACK_INIT_HWM(next); \ - AvFILLp(next->si_stack) = 0; \ - SWITCHSTACK(PL_curstack,next->si_stack); \ - PL_curstackinfo = next; \ - SET_MARK_OFFSET; \ + AvFILLp(next->si_stack) = 0; \ + SWITCHSTACK(PL_curstack,next->si_stack); \ + PL_curstackinfo = next; \ + SET_MARK_OFFSET; \ } STMT_END #define PUSHSTACK PUSHSTACKi(PERLSI_UNKNOWN) @@ -1222,27 +1317,27 @@ typedef struct stackinfo PERL_SI; * PUTBACK/SPAGAIN to flush/refresh any local SP that may be active */ #define POPSTACK \ STMT_START { \ - dSP; \ - PERL_SI * const prev = PL_curstackinfo->si_prev; \ - DEBUG_l({ \ - int i = -1; PERL_SI *p = PL_curstackinfo; \ - while (p) { i++; p = p->si_prev; } \ - Perl_deb(aTHX_ "pop STACKINFO %d at %s:%d\n", \ - i, __FILE__, __LINE__);}) \ - if (!prev) { \ - Perl_croak_popstack(); \ - } \ - SWITCHSTACK(PL_curstack,prev->si_stack); \ - /* don't free prev here, free them all at the END{} */ \ - PL_curstackinfo = prev; \ + dSP; \ + PERL_SI * const prev = PL_curstackinfo->si_prev; \ + DEBUG_l({ \ + int i = -1; PERL_SI *p = PL_curstackinfo; \ + while (p) { i++; p = p->si_prev; } \ + Perl_deb(aTHX_ "pop STACKINFO %d in %s at %s:%d\n", \ + i, SAFE_FUNCTION__, __FILE__, __LINE__);}) \ + if (!prev) { \ + Perl_croak_popstack(); \ + } \ + SWITCHSTACK(PL_curstack,prev->si_stack); \ + /* don't free prev here, free them all at the END{} */ \ + PL_curstackinfo = prev; \ } STMT_END #define POPSTACK_TO(s) \ STMT_START { \ - while (PL_curstack != s) { \ - dounwind(-1); \ - POPSTACK; \ - } \ + while (PL_curstack != s) { \ + dounwind(-1); \ + POPSTACK; \ + } \ } STMT_END /* @@ -1263,17 +1358,17 @@ program; otherwise 0; /* =for apidoc_section $multicall -=for apidoc Amns||dMULTICALL +=for apidoc Amn;||dMULTICALL Declare local variables for a multicall. See L<perlcall/LIGHTWEIGHT CALLBACKS>. -=for apidoc Ams||PUSH_MULTICALL|CV* the_cv +=for apidoc Am;||PUSH_MULTICALL|CV* the_cv Opening bracket for a lightweight callback. See L<perlcall/LIGHTWEIGHT CALLBACKS>. -=for apidoc Amns||MULTICALL +=for apidoc Amn;||MULTICALL Make a lightweight callback. See L<perlcall/LIGHTWEIGHT CALLBACKS>. -=for apidoc Amns||POP_MULTICALL +=for apidoc Amn;||POP_MULTICALL Closing bracket for a lightweight callback. See L<perlcall/LIGHTWEIGHT CALLBACKS>. @@ -1293,43 +1388,43 @@ See L<perlcall/LIGHTWEIGHT CALLBACKS>. #define PUSH_MULTICALL_FLAGS(the_cv, flags) \ STMT_START { \ PERL_CONTEXT *cx; \ - CV * const _nOnclAshIngNamE_ = the_cv; \ - CV * const cv = _nOnclAshIngNamE_; \ - PADLIST * const padlist = CvPADLIST(cv); \ - multicall_oldcatch = CATCH_GET; \ - CATCH_SET(TRUE); \ - PUSHSTACKi(PERLSI_MULTICALL); \ - cx = cx_pushblock((CXt_SUB|CXp_MULTICALL|flags), (U8)gimme, \ + CV * const _nOnclAshIngNamE_ = the_cv; \ + CV * const cv = _nOnclAshIngNamE_; \ + PADLIST * const padlist = CvPADLIST(cv); \ + multicall_oldcatch = CATCH_GET; \ + CATCH_SET(TRUE); \ + PUSHSTACKi(PERLSI_MULTICALL); \ + cx = cx_pushblock((CXt_SUB|CXp_MULTICALL|flags), (U8)gimme, \ PL_stack_sp, PL_savestack_ix); \ cx_pushsub(cx, cv, NULL, 0); \ - SAVEOP(); \ + SAVEOP(); \ if (!(flags & CXp_SUB_RE_FAKE)) \ CvDEPTH(cv)++; \ - if (CvDEPTH(cv) >= 2) \ - Perl_pad_push(aTHX_ padlist, CvDEPTH(cv)); \ - PAD_SET_CUR_NOSAVE(padlist, CvDEPTH(cv)); \ - multicall_cop = CvSTART(cv); \ + if (CvDEPTH(cv) >= 2) \ + Perl_pad_push(aTHX_ padlist, CvDEPTH(cv)); \ + PAD_SET_CUR_NOSAVE(padlist, CvDEPTH(cv)); \ + multicall_cop = CvSTART(cv); \ } STMT_END #define MULTICALL \ STMT_START { \ - PL_op = multicall_cop; \ - CALLRUNOPS(aTHX); \ + PL_op = multicall_cop; \ + CALLRUNOPS(aTHX); \ } STMT_END #define POP_MULTICALL \ STMT_START { \ PERL_CONTEXT *cx; \ - cx = CX_CUR(); \ - CX_LEAVE_SCOPE(cx); \ + cx = CX_CUR(); \ + CX_LEAVE_SCOPE(cx); \ cx_popsub_common(cx); \ gimme = cx->blk_gimme; \ PERL_UNUSED_VAR(gimme); /* for API */ \ - cx_popblock(cx); \ - CX_POP(cx); \ - POPSTACK; \ - CATCH_SET(multicall_oldcatch); \ - SPAGAIN; \ + cx_popblock(cx); \ + CX_POP(cx); \ + POPSTACK; \ + CATCH_SET(multicall_oldcatch); \ + SPAGAIN; \ } STMT_END /* Change the CV of an already-pushed MULTICALL CxSUB block. @@ -1337,20 +1432,20 @@ See L<perlcall/LIGHTWEIGHT CALLBACKS>. #define CHANGE_MULTICALL_FLAGS(the_cv, flags) \ STMT_START { \ - CV * const _nOnclAshIngNamE_ = the_cv; \ - CV * const cv = _nOnclAshIngNamE_; \ - PADLIST * const padlist = CvPADLIST(cv); \ + CV * const _nOnclAshIngNamE_ = the_cv; \ + CV * const cv = _nOnclAshIngNamE_; \ + PADLIST * const padlist = CvPADLIST(cv); \ PERL_CONTEXT *cx = CX_CUR(); \ - assert(CxMULTICALL(cx)); \ + assert(CxMULTICALL(cx)); \ cx_popsub_common(cx); \ - cx->cx_type = (CXt_SUB|CXp_MULTICALL|flags); \ + cx->cx_type = (CXt_SUB|CXp_MULTICALL|flags); \ cx_pushsub(cx, cv, NULL, 0); \ if (!(flags & CXp_SUB_RE_FAKE)) \ CvDEPTH(cv)++; \ - if (CvDEPTH(cv) >= 2) \ - Perl_pad_push(aTHX_ padlist, CvDEPTH(cv)); \ - PAD_SET_CUR_NOSAVE(padlist, CvDEPTH(cv)); \ - multicall_cop = CvSTART(cv); \ + if (CvDEPTH(cv) >= 2) \ + Perl_pad_push(aTHX_ padlist, CvDEPTH(cv)); \ + PAD_SET_CUR_NOSAVE(padlist, CvDEPTH(cv)); \ + multicall_cop = CvSTART(cv); \ } STMT_END /* * ex: set ts=8 sts=4 sw=4 et: |