PERLINTERN(1)

๐Ÿ’– PERLINTERN(1) ๐Ÿ’–

Perl Programmers Reference Guide โœจ โ€” yeah bestie, this is PERLINTERN(1), and we are going in.


๐ŸŒธ NAME ๐ŸŒธ

perlintern โ€” autogenerated documentation of purely internal Perl functions ๐Ÿซถ


๐Ÿฆ‹ DESCRIPTION ๐Ÿฆ‹

Okay so listen. This file is the autogenerated documentation of functions in the Perl interpreter that are documented using Perl's internal documentation format but are not marked as part of the Perl API. In other words โ€” and I need you to hear me on this โ€” they are not for use in extensions! ๐Ÿšซ๐Ÿ’…

It has the same sections as perlapi, though some may be empty. Yes, some are literally empty. We still show up for them. That's called loyalty. ๐Ÿ’–


โœจ AV Handling โœจ

๐Ÿ’ซ av_fetch_simple

This is a cut-down version of av_fetch that assumes the array is very straightforward โ€” no magic, not readonly, and AvREAL โ€” and that key is not negative. This function MUST NOT be used in situations where any of those assumptions may not hold. Like, fr fr, do not.

Returns the SV at the specified index in the array. The key is the index. If lval is true, you are guaranteed to get a real SV back (in case it wasn't real before), which you can then modify. Check that the return value is non-null before dereferencing it to a SV*. ๐Ÿซถ

The rough perl equivalent is $myarray[$key].

 SV **       av_fetch_simple(      AV *av, SSize_t key, I32 lval)
 SV **  Perl_av_fetch_simple(pTHX_ AV *av, SSize_t key, I32 lval)

๐Ÿ’ซ av_new_alloc

This implements newAV_alloc_x in perlapi and newAV_alloc_xz in perlapi, which are the public API for this functionality. ๐Ÿ‘‘

Creates a new AV and allocates its SV* array.

This is similar to, but more efficient than doing:

 AV *av = newAV();
 av_extend(av, key);

The size parameter is used to pre-allocate a SV* array large enough to hold at least elements 0..(size-1). size must be at least 1. (Not zero. Not negative. One. minimum. periodt.)

The zeroflag parameter controls whether or not the array is NULL initialized.

 AV *       av_new_alloc(      SSize_t size, bool zeroflag)
 AV *  Perl_av_new_alloc(pTHX_ SSize_t size, bool zeroflag)

๐Ÿ’ซ av_store_simple

This is a cut-down version of av_store that assumes that the array is very straightforward โ€” no magic, not readonly, and AvREAL โ€” and that key is not negative. This function MUST NOT be used in situations where any of those assumptions may not hold. Same energy as its sibling above, same warning. ๐Ÿ™ˆ

Stores an SV in an array. The array index is specified as key. It can be dereferenced to get the SV* that was stored there (= val)).

Note that the caller is responsible for suitably incrementing the reference count of val before the call. That's on you, bestie. ๐Ÿซต

Approximate Perl equivalent: splice(@myarray, $key, 1, $val).

 SV **       av_store_simple(      AV *av, SSize_t key, SV *val)
 SV **  Perl_av_store_simple(pTHX_ AV *av, SSize_t key, SV *val)

๐Ÿ’ซ AvFILLp

If the array av is empty, this returns -1; otherwise it returns the maximum value of the indices of all the array elements which are currently defined in av. It does not handle magic, hence the p private indication in its name. ๐Ÿช„๐Ÿšซ

 SSize_t  AvFILLp(AV* av)

๐ŸŽ€ Callback Functions ๐ŸŽ€

๐ŸŒˆ dowantarray

DEPRECATED! It is planned to remove dowantarray from a future release of Perl. Do not use it for new code; remove it from existing code. ๐Ÿ˜ญ

Implements the deprecated GIMME in perlapi.

 U8       dowantarray()
 U8  Perl_dowantarray(pTHX)

๐ŸŒˆ leave_scope

Implements LEAVE_SCOPE which you should use instead. (The way that LEAVE_SCOPE is right there and this one is just the middleman. ๐Ÿ’€)

 void       leave_scope(      I32 base)
 void  Perl_leave_scope(pTHX_ I32 base)

๐ŸŒˆ magic_freedestruct

This function is called via magic to implement the mortal_destructor_sv() and mortal_destructor_x() functions. It should not be called directly and has no user serviceable parts. Like, hands off the machinery, it's not for you. ๐Ÿ›‘

 int       magic_freedestruct(      SV *sv, MAGIC *mg)
 int  Perl_magic_freedestruct(pTHX_ SV *sv, MAGIC *mg)

๐ŸŒˆ mortal_svfunc_x

This function arranges for a C function reference to be called at the end of the current statement with the arguments provided. It is a wrapper around mortal_destructor_sv() which ensures that the latter function is called appropriately.

Be aware that there is a significant difference in timing between the end of the current statement and the end of the current pseudo block. โฐ If you are looking for a mechanism to trigger a function at the end of the current pseudo block you should look at SAVEDESTRUCTOR_X in perlapi instead of this function. iykyk.

 void       mortal_svfunc_x(      SVFUNC_t f, SV *p)
 void  Perl_mortal_svfunc_x(pTHX_ SVFUNC_t f, SV *p)

๐ŸŒˆ pop_scope

Implements LEAVE in perlapi

 void       pop_scope()
 void  Perl_pop_scope(pTHX)

๐ŸŒˆ push_scope

Implements ENTER in perlapi

 void       push_scope()
 void  Perl_push_scope(pTHX)

๐ŸŒˆ save_adelete

Implements SAVEADELETE.

 void       save_adelete(      AV *av, SSize_t key)
 void  Perl_save_adelete(pTHX_ AV *av, SSize_t key)

๐ŸŒˆ save_freercpv

Implements SAVEFREERCPV.

Saves and frees a refcounted string. Calls rcpv_free() on the argument when the current pseudo block is finished. ๐Ÿงน

 void       save_freercpv(      char *rcpv)
 void  Perl_save_freercpv(pTHX_ char *rcpv)

๐ŸŒˆ save_generic_pvref

Implements SAVEGENERICPV.

Like save_pptr(), but also Safefree()s the new value if it is different from the old one. Can be used to restore a global char* to its prior contents, freeing new value. ๐Ÿซถ

 void       save_generic_pvref(      char **str)
 void  Perl_save_generic_pvref(pTHX_ char **str)

๐ŸŒˆ save_generic_svref

Implements SAVEGENERICSV.

Like save_sptr(), but also SvREFCNT_dec()s the new value. Can be used to restore a global SV to its prior contents, freeing new value. โœจ

 void       save_generic_svref(      SV **sptr)
 void  Perl_save_generic_svref(pTHX_ SV **sptr)

๐ŸŒˆ save_hdelete

Implements SAVEHDELETE.

 void       save_hdelete(      HV *hv, SV *keysv)
 void  Perl_save_hdelete(pTHX_ HV *hv, SV *keysv)

๐ŸŒˆ save_hints

Implements SAVEHINTS.

 void       save_hints()
 void  Perl_save_hints(pTHX)

๐ŸŒˆ save_op

Implements SAVEOP.

 void       save_op()
 void  Perl_save_op(pTHX)

๐ŸŒˆ save_padsv_and_mortalize

Implements SAVEPADSVANDMORTALIZE.

 void       save_padsv_and_mortalize(      PADOFFSET off)
 void  Perl_save_padsv_and_mortalize(pTHX_ PADOFFSET off)

๐ŸŒˆ save_pushptr

The refcnt of object ptr will be decremented at the end of the current pseudo-block. type gives the type of ptr, expressed as one of the constants in scope.h whose name begins with SAVEt_. ๐Ÿ“Œ

This is the underlying implementation of several macros, like SAVEFREESV. The blueprint behind the blueprint, lowkey iconic.

 void       save_pushptr(      void * const ptr, const int type)
 void  Perl_save_pushptr(pTHX_ void * const ptr, const int type)

๐ŸŒˆ save_rcpv

Implements SAVERCPV.

Saves and restores a refcounted string, similar to what save_generic_svref would do for a SV*. Can be used to restore a refcounted string to its previous state. Performs the appropriate refcount counting so that nothing should leak or be prematurely freed. ๐Ÿ’œ

 void       save_rcpv(      char **prcpv)
 void  Perl_save_rcpv(pTHX_ char **prcpv)

๐ŸŒˆ save_scalar_at

A helper function for localizing the SV referenced by *sptr.

If SAVEf_KEEPOLDELEM is set in in flags, the function returns the input scalar untouched.

Otherwise it replaces *sptr with a new undef scalar, and returns that. The new scalar will have the old one's magic (if any) copied to it. If there is such magic, and SAVEf_SETMAGIC is set in in flags, 'set' magic will be processed on the new scalar. If unset, 'set' magic will be skipped. The latter typically means that assignment will soon follow (e.g., local $x = $y), and that will handle the magic. ๐Ÿช„

 SV *  save_scalar_at(SV **sptr, const U32 flags)

๐ŸŒˆ save_set_svflags

Implements SAVESETSVFLAGS.

Set the SvFLAGS specified by mask to the values in val

 void       save_set_svflags(      SV *sv, U32 mask, U32 val)
 void  Perl_save_set_svflags(pTHX_ SV *sv, U32 mask, U32 val)

๐ŸŒˆ save_shared_pvref

Implements SAVESHAREDPV.

Like save_generic_pvref(), but uses PerlMemShared_free() rather than Safefree(). Can be used to restore a shared global char* to its prior contents, freeing new value. ๐ŸŒˆ

 void       save_shared_pvref(      char **str)
 void  Perl_save_shared_pvref(pTHX_ char **str)

๐ŸŒˆ save_vptr

Implements SAVEVPTR.

 void       save_vptr(      void *ptr)
 void  Perl_save_vptr(pTHX_ void *ptr)

๐Ÿ’… Casting ๐Ÿ’…

There are currently no internal API items in Casting. Nothing here bestie, moving on. ๐Ÿฆ‹


๐Ÿ’… Character case changing ๐Ÿ’…

There are currently no internal API items in Character case changing. Empty, but we still love her. ๐Ÿ’–


๐Ÿ’… Character classification ๐Ÿ’…

There are currently no internal API items in Character classification. Nada. โœจ


๐Ÿ’… Compiler and Preprocessor information ๐Ÿ’…

There are currently no internal API items in Compiler and Preprocessor information. Zero. Zilch. ๐ŸŽ€


๐Ÿ’… Compiler directives ๐Ÿ’…

There are currently no internal API items in Compiler directives. Nothing to see, but the section said hi. ๐Ÿ‘‹


๐Ÿ”ฅ Compile-time scope hooks ๐Ÿ”ฅ

โญ BhkENTRY

NOTE: BhkENTRY is experimental and may change or be removed without notice. ๐Ÿ˜ญ

Return an entry from the BHK structure. which is a preprocessor token indicating which entry to return. If the appropriate flag is not set this will return NULL. The type of the return value depends on which entry you ask for. ๐Ÿ‘‘

 void *  BhkENTRY(BHK *hk, token which)

โญ BhkFLAGS

NOTE: BhkFLAGS is experimental and may change or be removed without notice. ๐Ÿ˜ญ

Return the BHK's flags.

 U32  BhkFLAGS(BHK *hk)

โญ CALL_BLOCK_HOOKS

NOTE: CALL_BLOCK_HOOKS is experimental and may change or be removed without notice. ๐Ÿ˜ญ

Call all the registered block hooks for type which. which is a preprocessing token; the type of arg depends on which.

 void  CALL_BLOCK_HOOKS(token which, arg)

โœจ Concurrency โœจ

Okay bestie, concurrency internals, let's get into it ๐Ÿ’…. Here's the whole cast of characters โ€” every single one, no cap:

  • "CVf_SLABBED"
  • "CvROOT"
  • "CvSTART"
  • "CX_CUR"
  • "CX_LEAVE_SCOPE"
  • "CX_POP"
  • "cx_type"
  • "CXINC"
  • "cxstack"
  • "cxstack_ix"
  • "CXt_BLOCK"
  • "CXt_EVAL"
  • "CXt_FORMAT"
  • "CXt_GIVEN"
  • "CXt_LOOP_ARY"
  • "CXt_LOOP_LAZYIV"
  • "CXt_LOOP_LAZYSV"
  • "CXt_LOOP_LIST"
  • "CXt_LOOP_PLAIN"
  • "CXt_NULL"
  • "CXt_SUB"
  • "CXt_SUBST"
  • "CXt_WHEN"
  • "dounwind" โ€” Described in perlguts.

And here are the signatures, all lined up like a lil squad โœจ:

OP *                 CvROOT        (      CV * sv)
OP *                 CvSTART       (      CV * sv)
                     CX_CUR        ()
void                 CX_LEAVE_SCOPE(      PERL_CONTEXT* cx)
void                 CX_POP        (      PERL_CONTEXT* cx)
PERL_CONTEXT *       cxstack
I32                  cxstack_ix
void                 dounwind      (      I32 cxix)
void            Perl_dounwind      (pTHX_ I32 cxix)
  • "my_fork" โ€” so this one is for the use of "PerlProc_fork" as a wrapper for the C library fork(2) on some platforms, to hide some platform quirks. It should not be used except through "PerlProc_fork". ๐Ÿ™ˆ
Pid_t       my_fork()
Pid_t  Perl_my_fork()
  • "PERL_CONTEXT" โ€” Described in perlguts.

๐ŸŒธ COPs and Hint Hashes ๐ŸŒธ

There are currently no internal API items in COPs and Hint Hashes โ€” yeah bestie, it's giving empty. Nothing to see here, move along โœจ.


๐Ÿ”ฅ Custom Operators ๐Ÿ”ฅ

  • "core_prototype" โ€” okay so this function assigns the prototype of the named core function to "sv", or to a new mortal SV if "sv" is "NULL". It returns the modified "sv", or "NULL" if the core function has no prototype. "code" is a code as returned by keyword(). It must not be equal to 0. ๐Ÿ‘‘
SV *       core_prototype(      SV *sv, const char *name,
                                const int code,
                                int * const opnum)
SV *  Perl_core_prototype(pTHX_ SV *sv, const char *name,
                                const int code,
                                int * const opnum)

๐Ÿ’– CV Handling ๐Ÿ’–

  • "CvREFCOUNTED_ANYSV" โ€” if true, this flag indicates that the "CvXSUBANY(cv).any_sv" member contains an SV pointer whose reference count should be decremented when the CV itself is freed. In addition, cv_clone() will increment the reference count, and sv_dup() will duplicate the entire pointed-to SV if this flag is set.

Any CV that wraps an XSUB has an "ANY" union that the XSUB function is free to use for its own purposes. It may be the case that the code wishes to store an SV in the "any_sv" member of this union. By setting this flag, this SV reference will be properly reclaimed or duplicated when the CV itself is. Periodt.

bool  CvREFCOUNTED_ANYSV(CV *cv)
  • "CvREFCOUNTED_ANYSV_off" โ€” helper macro to turn off the "CvREFCOUNTED_ANYSV" flag ๐Ÿ’….
void  CvREFCOUNTED_ANYSV_off(CV *cv)
  • "CvREFCOUNTED_ANYSV_on" โ€” helper macro to turn on the "CvREFCOUNTED_ANYSV" flag โœจ.
void  CvREFCOUNTED_ANYSV_on(CV *cv)
  • "CvWEAKOUTSIDE" โ€” okay bestie, this one is a whole saga, so grab a snack ๐Ÿ“.

Each CV has a pointer, CvOUTSIDE(), to its lexically enclosing CV (if any). Because pointers to anonymous sub prototypes are stored in "&" pad slots, it is a possible to get a circular reference, with the parent pointing to the child and vice-versa. To avoid the ensuing memory leak, we do not increment the reference count of the CV pointed to by "CvOUTSIDE" in the one specific instance that the parent has a "&" pad slot pointing back to us. In this case, we set the "CvWEAKOUTSIDE" flag in the child. This allows us to determine under what circumstances we should decrement the refcount of the parent when freeing the child.

There is a further complication with non-closure anonymous subs (i.e. those that do not refer to any lexicals outside that sub). In this case, the anonymous prototype is shared rather than being cloned. This has the consequence that the parent may be freed while there are still active children, e.g.,

BEGIN { $a = sub { eval '$x' } }

In this case, the BEGIN is freed immediately after execution since there are no active references to it: the anon sub prototype has "CvWEAKOUTSIDE" set since it's not a closure, and $a points to the same CV, so it doesn't contribute to BEGIN's refcount either. When $a is executed, the "eval '$x'" causes the chain of "CvOUTSIDE"s to be followed, and the freed BEGIN is accessed.

To avoid this, whenever a CV and its associated pad is freed, any "&" entries in the pad are explicitly removed from the pad, and if the refcount of the pointed-to anon sub is still positive, then that child's "CvOUTSIDE" is set to point to its grandparent. This will only occur in the single specific case of a non-closure anon prototype having one or more active references (such as $a above).

One other thing to consider is that a CV may be merely undefined rather than freed, eg "undef &foo". In this case, its refcount may not have reached zero, but we still delete its pad and its "CvROOT" etc. Since various children may still have their "CvOUTSIDE" pointing at this undefined CV, we keep its own "CvOUTSIDE" for the time being, so that the chain of lexical scopes is unbroken. For example, the following should print 123:

my $x = 123;
sub tmp { sub { eval '$x' } }
my $a = tmp();
undef &tmp;
print  $a->();
bool  CvWEAKOUTSIDE(CV *cv)
  • "docatch" โ€” okay this one is the main character ๐Ÿ‘‘, let's go.

Interpose, for the current op and RUNOPS loop,

  • a new JMPENV stack catch frame, and
  • an inner RUNOPS loop to run all the remaining ops following the current PL_op.

Then handle any exceptions raised while in that loop. For a caught eval at this level, re-enter the loop with the specified restart op (i.e. the op following the OP_LEAVETRY etc); otherwise re-throw the exception.

docatch() is intended to be used like this:

PP(pp_entertry)
{
    if (CATCH_GET)
        return docatch(Perl_pp_entertry);

    ... rest of function ...
    return PL_op->op_next;
}

If a new catch frame isn't needed, the op behaves normally. Otherwise it calls docatch(), which recursively calls pp_entertry(), this time with CATCH_GET() false, so the rest of the body of the entertry is run. Then docatch() calls CALLRUNOPS() which executes all the ops following the entertry. When the loop finally finishes, control returns to docatch(), which pops the JMPENV and returns to the parent pp_entertry(), which itself immediately returns. Note that all subsequent ops are run within the inner RUNOPS loop, not just the body of the eval. For example, in

sub TIEARRAY { eval {1}; my $x }
tie @a, "main";

at the point the 'my' is executed, the C stack will look something like:

#10 main()
#9  perl_run()              # JMPENV_PUSH level 1 here
#8  S_run_body()
#7  Perl_runops_standard()  # main RUNOPS loop
#6  Perl_pp_tie()
#5  Perl_call_sv()
#4  Perl_runops_standard()  # unguarded RUNOPS loop: no new JMPENV
#3  Perl_pp_entertry()
#2  S_docatch()             # JMPENV_PUSH level 2 here
#1  Perl_runops_standard()  # docatch()'s RUNOPs loop
#0  Perl_pp_padsv()

Basically, any section of the perl core which starts a RUNOPS loop may make a promise that it will catch any exceptions and restart the loop if necessary. If it's not prepared to do that (like call_sv() isn't), then it sets CATCH_GET() to true, so that any later eval-like code knows to set up a new handler and loop (via docatch()).

See "Exception handing" in perlinterp for further details.

OP *  docatch(Perl_ppaddr_t firstpp)

๐Ÿ’– Debugging ๐Ÿ’–

Okay bestie, this section is all about the debug-mode goodies โ€” the macros, functions, and globals that show up when you're poking at Perl with DEBUGGING or the -d / -DP / -Dt switches. No cap, every signature stays exactly as written.


comma_aDEPTH

So some functions, when they're compiled under DEBUGGING, take an extra final argument named depth โ€” it tells you the C stack depth. When you're not under DEBUGGING, that argument just peaces out. This macro expands to either , depth under DEBUGGING, or to absolutely nothing at all when not under DEBUGGING, which means fewer #ifdef's cluttering up the code. ๐Ÿ’…

Important: the program itself is responsible for maintaining the correct value for depth. That's on you, bestie.

comma_pDEPTH

This one is used in the prototype declarations for functions that take a ""comma_aDEPTH"" final parameter. It's giving the same energy as pTHX_ is used in functions that take a thread context initial parameter. ๐Ÿซถ

debop

Implements the -Dt perl command line option on OP o. So if you're tracing OPs, this is your girl.

            I32       debop(      const OP *o)
            I32  Perl_debop(pTHX_ const OP *o)

debprof

Called to indicate that o was executed, for profiling purposes under the -DP command line option. Profiling tea โ˜•

            void  debprof(const OP *o)

debprofdump

Dumps the contents of the data collected by the -DP perl command line option. Basically a data dump, but make it debug.

            void       debprofdump()
            void  Perl_debprofdump(pTHX)

debug_aDEPTH

Same as ""comma_aDEPTH"" but with no leading argument. Intended for functions with no normal arguments, and used by ""comma_aDEPTH"" itself. Meta much? Love that.

debug_pDEPTH

Same as ""comma_pDEPTH"" but with no leading argument. Intended for functions with no normal arguments, and used by ""comma_pDEPTH"" itself. Twinsies.

free_c_backtrace

Deallocates a backtrace received from get_c_backtrace. Cleanup era.

            void  free_c_backtrace(Perl_c_backtrace *bt)

get_c_backtrace

Collects the backtrace (aka "stacktrace") into a single linear malloced buffer, which the caller must Perl_free_c_backtrace(). Don't forget that free, bestie.

Scans the frames back by depth + skip, then drops the skip innermost, returning at most depth frames.

            Perl_c_backtrace *       get_c_backtrace(      int max_depth,
                                                           int skip)
            Perl_c_backtrace *  Perl_get_c_backtrace(pTHX_ int max_depth,
                                                           int skip)

PL_DBsingle

When Perl is run in debugging mode, with the -d switch, this SV is a boolean which indicates whether subs are being single-stepped. Single-stepping is automatically turned on after every step. This is the C variable which corresponds to Perl's $DB::single variable. See "PL_DBsub". On threaded perls, each thread has an independent copy of this variable; each initialized at creation time with the current value of the creating thread's copy. So no sharing, no drama.

            SV *  PL_DBsingle

PL_DBsub

When Perl is run in debugging mode, with the -d switch, this GV contains the SV which holds the name of the sub being debugged. This is the C variable which corresponds to Perl's $DB::sub variable. See "PL_DBsingle". On threaded perls, each thread has an independent copy of this variable; each initialized at creation time with the current value of the creating thread's copy.

            GV *  PL_DBsub

PL_DBtrace

Trace variable used when Perl is run in debugging mode, with the -d switch. This is the C variable which corresponds to Perl's $DB::trace variable. See "PL_DBsingle". On threaded perls, each thread has an independent copy of this variable; each initialized at creation time with the current value of the creating thread's copy.

            SV *  PL_DBtrace

runops_debug / runops_standard

Described in perlguts. Go read that for the full lore.

            int       runops_debug   ()
            int  Perl_runops_debug   (pTHX)
            int       runops_standard()
            int  Perl_runops_standard(pTHX)

๐ŸŒธ Display functions ๐ŸŒธ

sv_peek

Implements SvPEEK. Peek behind the curtain, bestie.

            char *       sv_peek(      SV *sv)
            char *  Perl_sv_peek(pTHX_ SV *sv)

๐Ÿฆ‹ Embedding, Threads, and Interpreter Cloning ๐Ÿฆ‹

cv_dump

okay so this one just dumps out the contents of a CV, bestie. that's it, that's the whole vibe ๐Ÿ’…

void  cv_dump(const CV *cv, const char *title)

cv_forget_slab

so when a CV has a reference count on its slab (CvSLABBED), it is responsible for making sure it gets freed. (hence: no two CVs should ever have a reference count on the same slab, periodt.) the CV only needs to reference that slab while it's compiling. once it's compiled and CvROOT is attached, its job is done, so it can forget the slab ๐Ÿซถ

void       cv_forget_slab(      CV *cv)
void  Perl_cv_forget_slab(pTHX_ CV *cv)

do_dump_pad

dumps the contents of a padlist, no biggie โœจ

void       do_dump_pad(      I32 level, PerlIO *file,
                             PADLIST *padlist, int full)
void  Perl_do_dump_pad(pTHX_ I32 level, PerlIO *file,
                             PADLIST *padlist, int full)

get_context

this implements "PERL_GET_CONTEXT" in perlapi โ€” and bestie, you should use that instead, ok? ๐Ÿ˜Œ

void *       get_context()
void *  Perl_get_context()

noshutdownhook

just a lil stub that provides a shutdown hook. iconic minimalism ๐Ÿ’€

void       noshutdownhook()
void  Perl_noshutdownhook()

pad_alloc_name

allocates a spot in the currently-compiling pad (it does this via "pad_alloc" in perlapi) and then stores a name for that entry. name gets adopted and becomes the name entry โ€” so it must already contain the name string, mmkay? typestash and ourstash and the padadd_STATE flag all get added to name. none of the other processing that "pad_add_name_pvn" in perlapi does is done here. it returns the offset of the allocated pad slot ๐ŸŒธ

PADOFFSET  pad_alloc_name(PADNAME *name, U32 flags,
                          NOCHECK HV *typestash, HV *ourstash)

pad_block_start

updates the pad compilation state variables when you enter a new block. new block, who dis ๐Ÿฆ‹

void       pad_block_start(      int full)
void  Perl_pad_block_start(pTHX_ int full)

pad_check_dup

checks for duplicate declarations and reports any of these:

  • a 'my' in the current scope with the same name;
  • an 'our' (anywhere in the pad) with the same name and the same stash as 'ourstash'

is_our tells you that the name being checked is an "our" declaration ๐Ÿ‘‘

void  pad_check_dup(PADNAME *name, U32 flags, const HV *ourstash)

pad_findlex

finds a named lexical anywhere in a chain of nested pads. and if it finds it in an outer one? it adds fake entries in the inner pads, sneaky lil thing โœจ

returns the offset in the bottom pad of the lex or the fake lex. cv is the CV where the search starts, and seq is the current cop_seq to match against. if warn is true, it prints the appropriate warnings. the out_* vars are return values, so they're pointers to where the returned values should be stored. out_capture, if it's non-null, requests that the innermost instance of the lexical is captured; out_name gets set to the innermost matched pad name or fake pad name; out_flags returns the flags normally associated with the PARENT_FAKELEX_FLAGS field of a fake pad name.

heads up bestie: pad_findlex() is recursive. it recurses up the chain of CVs, then comes back down, adding fake entries as it goes. it has to be this way because fake names in anon prototypes have to store in xpadn_low the index into the parent pad. the way that recursion is doing double duty is honestly so much ๐Ÿ˜ญ
PADOFFSET  pad_findlex(const char *namepv, STRLEN namelen,
                       U32 flags, const CV *cv, U32 seq,
                       int warn, SV **out_capture,
                       PADNAME **out_name, int *out_flags)

pad_fixup_inner_anons

for any anon CVs in the pad, changes CvOUTSIDE of that CV from old_cv to new_cv if necessary. needed when a newly-compiled CV has to be moved to a pre-existing CV struct โ€” relocation era, we love to see it ๐Ÿซถ

void       pad_fixup_inner_anons(      PADLIST *padlist,
                                       CV *old_cv, CV *new_cv)
void  Perl_pad_fixup_inner_anons(pTHX_ PADLIST *padlist,
                                       CV *old_cv, CV *new_cv)

pad_free

frees the SV at offset po in the current pad. bye bb ๐Ÿ‘‹

void       pad_free(      PADOFFSET po)
void  Perl_pad_free(pTHX_ PADOFFSET po)

pad_leavemy

cleanup at end of scope during compilation: it sets the max seq number for lexicals in this scope, and warns about any lexicals that never got introduced. (yes it will call you out, respectfully ๐Ÿ’€)

OP *       pad_leavemy()
OP *  Perl_pad_leavemy(pTHX)

pad_push

pushes a new pad frame onto the padlist โ€” unless there's already a pad at this depth, in which case don't even bother creating a new one. then it gives the new pad an @_ in slot zero ๐ŸŒธ

void       pad_push(      PADLIST *padlist, int depth)
void  Perl_pad_push(pTHX_ PADLIST *padlist, int depth)

pad_reset

marks all the current temporaries for reuse. reduce, reuse, recycle, slay โ™ป๏ธ

void  pad_reset()

pad_setsv

sets the value at offset po in the current (compiling or executing) pad. bestie, use the macro PAD_SETSV() rather than calling this function directly, ok? ๐Ÿ’…

void       pad_setsv(      PADOFFSET po, SV *sv)
void  Perl_pad_setsv(pTHX_ PADOFFSET po, SV *sv)

pad_sv

gets the value at offset po in the current (compiling or executing) pad. use the macro PAD_SV instead of calling this function directly, mmkay? โœจ

SV *       pad_sv(      PADOFFSET po)
SV *  Perl_pad_sv(pTHX_ PADOFFSET po)

pad_swipe

abandons the tmp in the current pad at offset po and replaces it with a brand new one. out with the old ๐Ÿฆ‹

void       pad_swipe(      PADOFFSET po, bool refadjust)
void  Perl_pad_swipe(pTHX_ PADOFFSET po, bool refadjust)

padlist_dup

duplicates a pad. twin where have you been ๐Ÿซถ

PADLIST *       padlist_dup(      PADLIST *srcpad,
                                  CLONE_PARAMS *param)
PADLIST *  Perl_padlist_dup(pTHX_ PADLIST *srcpad,
                                  CLONE_PARAMS *param)

padname_dup

duplicates a pad name ๐Ÿ’–

PADNAME *       padname_dup(      PADNAME *src,
                                  CLONE_PARAMS *param)
PADNAME *  Perl_padname_dup(pTHX_ PADNAME *src,
                                  CLONE_PARAMS *param)

padnamelist_dup

duplicates a pad name list. the whole roster, cloned ๐Ÿ‘‘

PADNAMELIST *       padnamelist_dup(      PADNAMELIST *srcpad,
                                          CLONE_PARAMS *param)
PADNAMELIST *  Perl_padnamelist_dup(pTHX_ PADNAMELIST *srcpad,
                                          CLONE_PARAMS *param)

set_context

this implements "PERL_SET_CONTEXT" in perlapi โ€” and again, use that instead, bestie ๐Ÿ˜Œ

void       set_context(void *t)
void  Perl_set_context(void *t)

si_dup

duplicates a stack info structure, and returns a pointer to the cloned object. clone high but make it stack info ๐Ÿ’…

PERL_SI *       si_dup(      PERL_SI *si, CLONE_PARAMS *param)
PERL_SI *  Perl_si_dup(pTHX_ PERL_SI *si, CLONE_PARAMS *param)

ss_dup

duplicates the save stack and returns a pointer to the cloned object. yes ma'am, a whole stack, duplicated ๐ŸŒˆ

ANY *       ss_dup(      PerlInterpreter *proto_perl,
                         CLONE_PARAMS *param)
ANY *  Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl,
                         CLONE_PARAMS *param)

๐ŸŒธ Errno ๐ŸŒธ

dSAVE_ERRNO

declares the variables you need to save errno and any operating-system-specific error number, and saves them so RESTORE_ERRNO can optionally bring them back later. it's giving backup plan ๐Ÿ’พ

void  dSAVE_ERRNO

dSAVEDERRNO

declares the variables you need to save errno and any operating system specific error number. (declares only โ€” no saving here, bestie) โœจ

void  dSAVEDERRNO

RESTORE_ERRNO

restores errno and any operating system specific error number that was saved by dSAVE_ERRNO or RESTORE_ERRNO. the comeback era ๐Ÿซถ

void  RESTORE_ERRNO

SAVE_ERRNO

saves errno and any operating system specific error number so RESTORE_ERRNO can optionally bring them back later. and it requires dSAVEDERRNO or dSAVE_ERRNO to be in scope โ€” so don't try it without them, fr fr ๐Ÿ˜ค

void  SAVE_ERRNO

SETERRNO

sets errno, and on VMS it also sets vaxc$errno. special delivery for the VMS girlies ๐Ÿ“ฌ

void  SETERRNO(int errcode, int vmserrcode)

๐ŸŽ€ Exception Handling (simple) Macros ๐ŸŽ€

there are currently no internal API items in Exception Handling (simple) Macros. empty section, but make it fashion ๐Ÿ’…


๐Ÿฆ‹ Filesystem configuration values ๐Ÿฆ‹

there are currently no internal API items in Filesystem configuration values. nothing to see here, moving on bestie ๐ŸŒธ


โญ Floating point โญ

there are currently no internal API items in Floating point. zero items, zero notes, pure vibes โœจ


๐ŸŒˆ General Configuration ๐ŸŒˆ

there are currently no internal API items in General Configuration. it's giving minimalist ๐Ÿซถ


๐Ÿ‘‘ Global Variables ๐Ÿ‘‘

there are currently no internal API items in Global Variables. truly the quietest section in the building ๐Ÿ’€

๐Ÿ’– GV Handling and Stashes ๐Ÿ’–

โœจ amagic_applies โœจ

Okay so bestie, this one is a vibe check for overloaded magic. ๐Ÿ’… You hand it an sv and it peeks to see if the overloaded (active magic) operation method applies to it.

If the sv is not SvROK, or it's not an object? It says nope, false, not today. ๐Ÿ™… Otherwise it checks if the object is blessed into a class supporting overloaded operations, and returns true if a call to amagic_call() with this SV and the given method would trigger an amagic operation โ€” including via the overload fallback rules or via nomethod. So a call like this:

amagic_applies(sv, string_amg, AMG_unary)

would return true for an object with overloading set up in any of these ways:

use overload q("") => sub { ... };
use overload q(0+) => sub { ... }, fallback => 1;

and you could use it to tell if a given object would stringify to something other than the normal default ref stringification. ๐Ÿฆ‹

Heads up though โ€” the fact that this function returns TRUE does not mean you can successfully perform the operation with amagic_call(). For instance, any overloaded method might throw a fatal exception. ๐Ÿ˜ญ But if this function returns FALSE, you can be confident that it will NOT perform the given overload operation. That part's solid. โœจ

method is an integer enum, one of the values found in overload.h, for instance string_amg.

flags should be set to AMG_unary for unary operations.

 bool       amagic_applies(      SV *sv, int method, int flags)
 bool  Perl_amagic_applies(pTHX_ SV *sv, int method, int flags)

๐ŸŒธ gp_dup ๐ŸŒธ

Duplicate a typeglob, and it hands you back a pointer to the cloned object. Cloning is giving copy-paste but make it official. ๐Ÿ‘‘

 GP *       gp_dup(      GP * const gp,
                                CLONE_PARAMS * const param)
 GP *  Perl_gp_dup(pTHX_ GP * const gp,
                                CLONE_PARAMS * const param)

๐Ÿ’œ gv_handler ๐Ÿ’œ

Implements StashHANDLER โ€” and ngl, you should just use StashHANDLER instead. ๐Ÿ’€

 CV *       gv_handler(      HV *stash, I32 id)
 CV *  Perl_gv_handler(pTHX_ HV *stash, I32 id)

๐ŸŽ€ gv_stashsvpvn_cached ๐ŸŽ€

Returns a pointer to the stash for a specified package โ€” possibly cached, because who doesn't love a good cache. โœจ It implements both "gv_stashpvn" in perlapi and "gv_stashsv" in perlapi.

Requires one of either namesv or namepv to be non-null. (Pick one, bestie, you can't have neither. ๐Ÿ™ˆ)

If the flag GV_CACHE_ONLY is set, return the stash only if found in the cache; see "gv_stashpvn" in perlapi for details on the other flags.

Note it is strongly preferred for namesv to be non-null, for performance reasons. Performance girlies, take note. ๐Ÿ”ฅ
 HV *       gv_stashsvpvn_cached(      SV *namesv,
                                              const char *name,
                                              U32 namelen, I32 flags)
 HV *  Perl_gv_stashsvpvn_cached(pTHX_ SV *namesv,
                                              const char *name,
                                              U32 namelen, I32 flags)

โญ gv_try_downgrade โญ

NOTE: gv_try_downgrade is experimental and may change or be removed without notice. So don't get too attached. ๐Ÿ˜ญ

If the typeglob gv can be expressed more succinctly โ€” by having something other than a real GV in its place in the stash โ€” replace it with the optimised form. Basic requirements for this are that gv is a real typeglob, is sufficiently ordinary, and is only referenced from its package. This function is meant to be used when a GV has been looked up in part to see what was there, causing upgrading, but based on what was found it turns out that the real GV isn't required after all. It's giving "oops never mind, put it back." ๐Ÿ™ˆ

If gv is a completely empty typeglob, it is deleted from the stash.

If gv is a typeglob containing only a sufficiently-ordinary constant sub, the typeglob is replaced with a scalar-reference placeholder that more compactly represents the same thing. Downsizing era. ๐Ÿ’…

 void       gv_try_downgrade(      GV *gv)
 void  Perl_gv_try_downgrade(pTHX_ GV *gv)

๐Ÿฆ‹ Hook manipulation ๐Ÿฆ‹

There are currently no internal API items in Hook manipulation

that's it that's the whole section, it's giving minimalist queen ๐Ÿ’€โœจ

โœจ HV Handling โœจ

okay bestie, this is the Hash Value (HV) zone โ€” stashes, buckets, refcounted chains, all of it. buckle up ๐Ÿ’–


๐Ÿ’… hv_eiter_p

This one implements HvEITER โ€” and bestie, you should use HvEITER instead. no cap.

HE **  Perl_hv_eiter_p(pTHX_ HV *hv)

๐Ÿ’… hv_eiter_set

Implements HvEITER_set, which โ€” say it with me โ€” you should use instead. ๐Ÿซถ

void  Perl_hv_eiter_set(pTHX_ HV *hv, HE *eiter)

๐Ÿ’… hv_ename_add

Adds a name to a stash's internal list of effective names. see also hv_ename_delete.

This gets called whenever a stash is assigned to a new location in the symbol table. iconic behaviour, honestly.

void       hv_ename_add(      HV *hv, const char *name, U32 len,
                              U32 flags)
void  Perl_hv_ename_add(pTHX_ HV *hv, const char *name, U32 len,
                              U32 flags)

๐Ÿ’… hv_ename_delete

Removes a name from a stash's internal list of effective names. and lowkey the plot twist: if this is the name that HvENAME returns, then another name in the list will take its place (aka HvENAME will use it). the crown gets passed, periodt. ๐Ÿ‘‘

This one is called when a stash is deleted from the symbol table.

void       hv_ename_delete(      HV *hv, const char *name,
                                 U32 len, U32 flags)
void  Perl_hv_ename_delete(pTHX_ HV *hv, const char *name,
                                 U32 len, U32 flags)

๐Ÿ’… hv_fill

Returns the number of hash buckets that happen to be in use.

This function implements the HvFILL macro, which โ€” you guessed it โ€” you should use instead.

โš ๏ธ As of perl 5.25 this function is used only for debugging purposes, and the number of used hash buckets is not in any way cached. so bestie, this function can be costly to execute, because it must iterate over all the buckets in the hash. it's giving O(n) when you least want it. ๐Ÿ’€
STRLEN  Perl_hv_fill(pTHX_ HV * const hv)

๐Ÿ’… hv_placeholders_get

Implements HvPLACEHOLDERS_get, which you should use instead. โœจ

I32  Perl_hv_placeholders_get(pTHX_ const HV *hv)

๐Ÿ’… hv_placeholders_set

Implements HvPLACEHOLDERS_set, which you should use instead. ๐ŸŽ€

void  Perl_hv_placeholders_set(pTHX_ HV *hv, I32 ph)

๐Ÿ’… hv_riter_p

Implements HvRITER, which you should use instead. ๐Ÿฆ‹

I32 *  Perl_hv_riter_p(pTHX_ HV *hv)

๐Ÿ’… hv_riter_set

Implements HvRITER_set, which you should use instead. ๐ŸŒธ

void  Perl_hv_riter_set(pTHX_ HV *hv, I32 riter)

๐Ÿ’… refcounted_he_chain_2hv

Generates and returns a HV * representing the content of a refcounted_he chain. and heads up: flags is currently unused and must be zero. don't be quirky with it. ๐Ÿ™ˆ

HV *       refcounted_he_chain_2hv(const struct refcounted_he *c,
                                   U32 flags)
HV *  Perl_refcounted_he_chain_2hv(pTHX_
                                   const struct refcounted_he *c,
                                   U32 flags)

๐Ÿ’… refcounted_he_fetch_pv

Like refcounted_he_fetch_pvn, but it takes a nul-terminated string instead of a string/length pair. easy.

SV *       refcounted_he_fetch_pv(
                              const struct refcounted_he *chain,
                               const char *key, U32 hash,
                               U32 flags)
SV *  Perl_refcounted_he_fetch_pv(pTHX_
                               const struct refcounted_he *chain,
                               const char *key, U32 hash,
                               U32 flags)

๐Ÿ’… refcounted_he_fetch_pvn

Search along a refcounted_he chain for an entry with the key specified by keypv and keylen. if flags has the REFCOUNTED_HE_KEY_UTF8 bit set, the key octets get interpreted as UTF-8; otherwise they're interpreted as Latin-1. hash is a precomputed hash of the key string, or zero if it hasn't been precomputed.

Returns a mortal scalar representing the value associated with the key, or &PL_sv_placeholder if there is no value associated with the key. ๐Ÿซง

SV *       refcounted_he_fetch_pvn(
                              const struct refcounted_he *chain,
                               const char *keypv, STRLEN keylen,
                               U32 hash, U32 flags)
SV *  Perl_refcounted_he_fetch_pvn(pTHX_
                               const struct refcounted_he *chain,
                               const char *keypv, STRLEN keylen,
                               U32 hash, U32 flags)

๐Ÿ’… refcounted_he_fetch_pvs

Like refcounted_he_fetch_pvn, but it takes a literal string instead of a string/length pair, and no precomputed hash. lazy girl math, love that for us. ๐Ÿ’…

SV *  refcounted_he_fetch_pvs(const struct refcounted_he *chain,
                              "key", U32 flags)

๐Ÿ’… refcounted_he_fetch_sv

Like refcounted_he_fetch_pvn, but it takes a Perl scalar instead of a string/length pair. slay.

SV *       refcounted_he_fetch_sv(
                              const struct refcounted_he *chain,
                               SV *key, U32 hash, U32 flags)
SV *  Perl_refcounted_he_fetch_sv(pTHX_
                               const struct refcounted_he *chain,
                               SV *key, U32 hash, U32 flags)

๐Ÿ’… refcounted_he_free

Decrements the reference count of a refcounted_he by one. if the reference count reaches zero, the structure's memory is freed โ€” which (recursively) causes a reduction of its parent refcounted_he's reference count. it's dominoes bestie, but make it memory management. ๐Ÿข

and good news: it is safe to pass a null pointer to this function โ€” no action occurs in this case. phew. ๐Ÿ˜Œ

void       refcounted_he_free(      struct refcounted_he *he)
void  Perl_refcounted_he_free(pTHX_ struct refcounted_he *he)

๐Ÿ’… refcounted_he_inc

Increment the reference count of a refcounted_he. the pointer to the refcounted_he is also returned. and yes, same energy as above: it is safe to pass a null pointer to this function โ€” no action occurs and a null pointer is returned. ๐Ÿ’–

struct refcounted_he *       refcounted_he_inc(
                                       struct refcounted_he *he)
struct refcounted_he *  Perl_refcounted_he_inc(pTHX_
                                        struct refcounted_he *he)

๐Ÿ’… refcounted_he_new_pv

Like refcounted_he_new_pvn, but it takes a nul-terminated string instead of a string/length pair.

struct refcounted_he *       refcounted_he_new_pv(
                                   struct refcounted_he *parent,
                                    const char *key, U32 hash,
                                    SV *value, U32 flags)
struct refcounted_he *  Perl_refcounted_he_new_pv(pTHX_
                                    struct refcounted_he *parent,
                                    const char *key, U32 hash,
                                    SV *value, U32 flags)

๐Ÿ’… refcounted_he_new_pvn

Creates a new refcounted_he. this is a single key/value pair plus a reference to an existing refcounted_he chain (which may be empty), so together they form a longer chain. when you use the longer chain, the new key/value pair takes precedence over any entry for the same key further along the chain. newest wins, main character energy. ๐Ÿ‘‘

The new key is specified by keypv and keylen. if flags has the REFCOUNTED_HE_KEY_UTF8 bit set, the key octets are interpreted as UTF-8; otherwise they're interpreted as Latin-1. hash is a precomputed hash of the key string, or zero if it hasn't been precomputed.

value is the scalar value to store for this key. 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 refcounted_he. complex types of scalar will not be stored with referential integrity, but will be coerced to strings. value may be either null or &PL_sv_placeholder to indicate that no value is to be associated with the key; this, as with any non-null value, takes precedence over the existence of a value for the key further along the chain.

parent points to the rest of the refcounted_he chain to be attached to the new refcounted_he. this function takes ownership of one reference to parent, and returns one reference to the new refcounted_he. balance maintained, as it should be. โš–๏ธ

struct refcounted_he *       refcounted_he_new_pvn(
                                   struct refcounted_he *parent,
                                    const char *keypv,
                                    STRLEN keylen, U32 hash,
                                    SV *value, U32 flags)
struct refcounted_he *  Perl_refcounted_he_new_pvn(pTHX_
                                    struct refcounted_he *parent,
                                    const char *keypv,
                                    STRLEN keylen, U32 hash,
                                    SV *value, U32 flags)

๐Ÿ’… refcounted_he_new_pvs

Like refcounted_he_new_pvn, but it takes a literal string instead of a string/length pair, and no precomputed hash. ๐ŸŒˆ

struct refcounted_he *  refcounted_he_new_pvs(
                                   struct refcounted_he *parent,
                                    "key", SV *value, U32 flags)

๐Ÿ’… refcounted_he_new_sv

Like refcounted_he_new_pvn, but it takes a Perl scalar instead of a string/length pair. ๐Ÿ’œ

struct refcounted_he *       refcounted_he_new_sv(
                                   struct refcounted_he *parent,
                                    SV *key, U32 hash, SV *value,
                                    U32 flags)
struct refcounted_he *  Perl_refcounted_he_new_sv(pTHX_
                                    struct refcounted_he *parent,
                                    SV *key, U32 hash, SV *value,
                                    U32 flags)

๐Ÿ’… unsharepvn

If no one has access to shared string str with length len, free it. if it's still got friends, it stays. that's community. ๐Ÿซถ

โš ๏ธ len and hash must both be valid for str. no improvising, bestie.
void       unsharepvn(      const char *sv, I32 len, U32 hash)
void  Perl_unsharepvn(pTHX_ const char *sv, I32 len, U32 hash)

โœจ Input/Output โœจ

okay bestie, this is the whole gang of functions that handle file handles, dir handles, and the globby stuff ๐ŸŽ€

  • dirp_dup โ€” clones a directory handle and hands you back a pointer to the shiny new copy. it's giving duplicate-but-make-it-fresh ๐Ÿ’…
DIR *       dirp_dup(      DIR * const dp,
                           CLONE_PARAMS * const param)
DIR *  Perl_dirp_dup(pTHX_ DIR * const dp,
                           CLONE_PARAMS * const param)
  • fp_dup โ€” same energy but for a file handle: dupe it, get a pointer to the clone back ๐Ÿซถ
PerlIO *       fp_dup(      PerlIO * const fp, const char type,
                            CLONE_PARAMS * const param)
PerlIO *  Perl_fp_dup(pTHX_ PerlIO * const fp, const char type,
                            CLONE_PARAMS * const param)
  • my_fflush_all โ€” this is the one that implements PERL_FLUSHALL_FOR_CHILD on some platforms (not all of them, bestie, don't come for me) ๐ŸŒˆ
I32       my_fflush_all()
I32  Perl_my_fflush_all(pTHX)
  • my_mkostemp โ€” literally just the C library's mkostemp(3) when you've got it, or a lil Perl reimplementation when you don't. iconic backup plan energy โœจ
int  Perl_my_mkostemp(char *templte, int flags)
  • my_mkstemp โ€” same deal, but for mkstemp(3): the real thing if it's available, otherwise Perl's own version steps in ๐Ÿ’–
int  Perl_my_mkstemp(char *templte)
  • PL_last_in_gv โ€” the GV that was most recently used for a filehandle input operation. yes, that's the <FH> vibe exactly ๐Ÿ‘‘

On threaded perls, every thread gets its own independent copy of this variable, and each one is initialized at creation time with whatever the creating thread's copy was at that moment.

GV*  PL_last_in_gv
  • PL_ofsgv โ€” the glob holding the output field separator, which in Perl space is *, ๐ŸŒธ

On threaded perls, each thread has its own independent copy, initialized at creation time with the creating thread's current value.

GV*  PL_ofsgv
  • PL_rs โ€” the input record separator, aka $/ in Perl space, and yes it's that important ๐Ÿ’œ

On threaded perls, each thread has its own independent copy, initialized at creation time from the creating thread's copy.

SV*  PL_rs
  • start_glob โ€” calls do_readline to spawn a glob (or, on VMS, to do the glob inside perl itself).
โš ๏ธ NOTE: start_glob is experimental and may change or get removed with absolutely no notice. don't get attached bestie ๐Ÿ˜ญ

This code used to live inline, but now that perl uses File::Glob, this glob starter is only used by miniperl during the build process, or when PERL_EXTERNAL_GLOB is defined. Moving it out there shrinks pp_hot.c, and shrinking pp_hot.c helps speed perl up. slay, smaller file, faster perl ๐Ÿ”ฅ

PerlIO *  Perl_start_glob(pTHX_ SV *tmpglob, IO *io)

๐Ÿ”ข Integer ๐Ÿ”ข

  • ABS_IV_MIN โ€” gives you the absolute value of IV_MIN (that's the perlapi one), ready to be used inside a UV. chef's kiss for overflow reasons ๐Ÿ’…
UV  ABS_IV_MIN
  • NEGATE_2IV โ€” returns the negative value of uv, and uv has to be non-negative, for use in an IV.
โš ๏ธ the results are undefined if that value would end up less than IV_MIN (the perlapi one). this macro exists because naively writing -uv gives undefined behavior the moment uv equals ABS_IV_MIN. so like... don't do the naive thing, fr fr ๐Ÿ˜ญ
IV  NEGATE_2IV(UV uv)
  • NEGATE_2UV โ€” returns the absolute value of iv, and iv must be negative, all while dodging undefined behavior even when iv is IV_MIN (the perlapi one). safety first, always ๐Ÿซถ
UV  NEGATE_2UV(IV iv)

๐ŸŽ€ I/O Formats ๐ŸŽ€

There are currently no internal API items in I/O Formats. yeah bestie, the section's just sitting there empty, serving absolutely nothing today ๐Ÿ’€


๐Ÿ” Lexer interface ๐Ÿ”

  • validate_proto โ€” this one does syntax checking on a prototype, proto.
โš ๏ธ NOTE: validate_proto is experimental and may change or be removed without notice. enjoy it while it lasts ๐Ÿ’…

If warn is true, any illegal characters or mismatched brackets will fire off illegalproto warnings, and those warnings will declare that they were detected in the prototype for name.

The return value is true if this is a valid prototype, and false if it isn't โ€” and that's the answer regardless of whether warn was true or false, so no sneaky differences, bestie โœจ

Also note: NULL is a valid proto and will always return true. iconic, no notes ๐ŸŒธ

bool       validate_proto(      SV *name, SV *proto, bool warn,
                                bool curstash)
bool  Perl_validate_proto(pTHX_ SV *name, SV *proto, bool warn,
                                bool curstash)

๐ŸŒˆ Locales ๐ŸŒˆ

There are currently no internal API items in Locales. nothing to see here, moving on ๐Ÿฆ‹


๐Ÿ’– Magic ๐Ÿ’–

  • magic_clearhint โ€” gets triggered when you delete from %^H, and it records the key to PL_compiling.cop_hints_hash ๐ŸŽ€
int       magic_clearhint(      SV *sv, MAGIC *mg)
int  Perl_magic_clearhint(pTHX_ SV *sv, MAGIC *mg)
  • magic_clearhints โ€” triggered when you clear %^H, and it resets PL_compiling.cop_hints_hash. full reset era ๐Ÿ’œ
int       magic_clearhints(      SV *sv, MAGIC *mg)
int  Perl_magic_clearhints(pTHX_ SV *sv, MAGIC *mg)
  • magic_methcall โ€” invokes a magic method (think FETCH and friends) ๐Ÿ‘‘

sv and mg are the tied thingy and the tie magic, respectively.

meth is the name of the method you're calling.

argc is how many args (on top of $self) get passed to the method.

The flags can be:

  • G_DISCARD โ€” invoke the method with the G_DISCARD flag and don't return a value
  • G_UNDEF_FILL โ€” fill the stack with argc pointers to PL_sv_undef

The arguments themselves are whatever values follow the flags argument.

It returns the SV (if there even is one) that the method returned, or NULL if it failed. no cap ๐Ÿ˜ญ

SV *  Perl_magic_methcall(pTHX_ SV *sv, const MAGIC *mg,
                                SV *meth, U32 flags, U32 argc,
                                ...)
  • magic_sethint โ€” triggered by a store to %^H, and it records the key/value pair into PL_compiling.cop_hints_hash.

It's assumed that hints aren't storing anything that would need a deep copy. and honestly? maybe we should warn if we find a reference. just a thought ๐Ÿ’…

int       magic_sethint(      SV *sv, MAGIC *mg)
int  Perl_magic_sethint(pTHX_ SV *sv, MAGIC *mg)
  • mg_dup โ€” duplicates a whole chain of magic and returns a pointer to the cloned object. chain dupe, slay ๐Ÿ”ฅ
MAGIC *       mg_dup(      MAGIC *mg, CLONE_PARAMS * const param)
MAGIC *  Perl_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS * const param)
  • mg_localize โ€” copies some of the magic from an existing SV over to a new localized version of that SV. container magic (like %ENV, $1, tie) gets copied, but value magic does not (think taint, pos) ๐Ÿ™ˆ

If setmagic is false, then no set magic will be called on the new (empty) SV. usually that means an assignment is about to happen right after (like local $x = $y), and that assignment will handle the magic itself. it's giving teamwork โœจ

void       mg_localize(      SV *sv, SV *nsv, bool setmagic)
void  Perl_mg_localize(pTHX_ SV *sv, SV *nsv, bool setmagic)

๐Ÿงš Memory Management ๐Ÿงš

  • calloc โ€” implements Newxz in perlapi, which, btw, you should be using instead ๐Ÿ’…
Malloc_t  Perl_calloc(MEM_SIZE elements, MEM_SIZE size)
  • malloc โ€” implements Newx in perlapi, which you should use instead ๐ŸŒธ
Malloc_t  Perl_malloc(MEM_SIZE nbytes)
  • mfree โ€” implements Safefree in perlapi, which you should use instead ๐Ÿซถ
Free_t  Perl_mfree(Malloc_t where)
  • realloc โ€” implements Renew in perlapi, which you should use instead ๐Ÿ’œ
Malloc_t  Perl_realloc(Malloc_t where, MEM_SIZE nbytes)

๐Ÿ‘‘ MRO ๐Ÿ‘‘

  • mro_get_linear_isa_dfs โ€” returns the Depth-First Search linearization of @ISA for the given stash.

The return value is a read-only AV* whose elements are string SVs giving class names. level should be 0 (it's used internally inside this function's own recursion, so don't be cute with it).

You are responsible for SvREFCNT_inc() on the return value if you're planning to store it anywhere semi-permanently โ€” otherwise it might get deleted right out from under you the next time the cache gets invalidated. protect your references bestie ๐Ÿ˜ญ

AV *  mro_get_linear_isa_dfs(HV *stash, U32 level)
  • mro_isa_changed_in โ€” takes all the necessary steps (mostly cache invalidations) when the @ISA of the given package has changed.

It's invoked by the setisa magic, so you shouldn't really need to invoke it directly yourself ๐Ÿ’…

void       mro_isa_changed_in(      HV *stash)
void  Perl_mro_isa_changed_in(pTHX_ HV *stash)
  • mro_package_moved โ€” call this one to signal to a stash that it's been assigned to another spot in the stash hierarchy.

stash is the stash that got assigned. oldstash is the stash it replaces, if there is one. gv is the glob that's actually being assigned to.

You can also call this with a null first argument to indicate that oldstash has been deleted.

This function invalidates isa caches on the old stash, on all the subpackages nested inside it, and on the subclasses of all of those โ€” including non-existent packages that have corresponding entries in stash. it goes deep, no cap ๐Ÿ”ฅ

It also sets the effective names (HvENAME) on all the stashes as appropriate.

If the gv is present and is not in the symbol table, then this function simply returns. that check gets skipped if flags & 1.

void       mro_package_moved(      HV * const stash,
                                   HV * const oldstash,
                                   const GV * const gv,
                                   U32 flags)
void  Perl_mro_package_moved(pTHX_ HV * const stash,
                                   HV * const oldstash,
                                   const GV * const gv,
                                   U32 flags)

๐Ÿ“ž Multicall Functions ๐Ÿ“ž

There are currently no internal API items in Multicall Functions. empty section, empty vibes, that's just how it is today ๐Ÿฆ‹

๐Ÿ’– NUMERIC FUNCTIONS ๐Ÿ’–

isinfnansv

okay so bestie, this one checks whether the argument would be either an infinity or NaN when it's used as a number โ€” but the โœจwhole pointโœจ is that it's super careful not to trigger non-numeric or uninitialized warnings. It assumes the caller has already done SvGETMAGIC(sv) themselves, so that part is on you, not on it. ๐Ÿซถ

๐Ÿšจ lowkey important: this thing always accepts trailing garbage (similar to grok_number_flags with PERL_SCAN_TRAILING), so inferior and NAND gates will both return true. Not a bug, just the vibe. ๐Ÿ’€
 bool       isinfnansv(      SV *sv)
 bool  Perl_isinfnansv(pTHX_ SV *sv)

S_perl_hash_siphash_1_3

Implements the variant of Siphash which performs 1 round function per block, and 3 as part of the finalizer. ๐Ÿ“

Takes a 16 byte seed vector, and uses it to hash inlen bytes from the buffer pointed to by in, returns a 32 bit hash.

The following code should return 0x2976B3A1 โ€” like, that's the receipts, no cap:

char seed[] = "Call me Ishmael.";
char in[] = "It is not down on any map; true places never are.";
U32 hash = S_perl_hash_siphash_1_3(
            (const U8*)seed, (const U8*)in, sizeof(in)-1);
 U64  S_perl_hash_siphash_1_3(const unsigned char * const seed,
                              const unsigned char *in,
                              const STRLEN inlen
)

S_perl_hash_siphash_1_3_with_state

Same energy as the one above โ€” the variant of Siphash which performs 1 round function per block, and 3 as part of the finalizer โ€” except this one's got the state-buffer glow-up. โœจ

Takes a 32 byte 'state' vector prepared by S_perl_siphash_seed_state() and uses it to hash inlen bytes from the buffer pointed to by in, returns a 32 bit hash.

The following code should return 0x2976B3A1

U8 state[32];
char seed[] = "Call me Ishmael.";
S_perl_siphash_seed_state((const U8*)seed, state);

char in[] = "It is not down on any map; true places never are.";
U32 hash = S_perl_hash_siphash_1_3_with_state(
            state, (const U8*)in, sizeof(in)-1);
 U32  S_perl_hash_siphash_1_3_with_state(
                               const unsigned char * const state,
                                const unsigned char *in,
                                const STRLEN inlen
)

S_perl_hash_siphash_1_3_with_state_64

The 64-bit glow-up of the state version, bestie. ๐ŸŽ€ Implements the variant of Siphash which performs 1 round function per block, and 3 as part of the finalizer.

Takes a 32 byte 'state' vector prepared by S_perl_siphash_seed_state() and uses it to hash inlen bytes from the buffer pointed to by in, returns a 64 bit hash.

The following code should return 0xB70339FD9E758A5C

U8 state[32];
char seed[] = "Call me Ishmael.";
S_perl_siphash_seed_state((const U8*)seed, state);

char in[] = "It is not down on any map; true places never are.";
U64 hash = S_perl_hash_siphash_1_3_with_state_64(
            state, (const U8*)in, sizeof(in)-1);
 U64  S_perl_hash_siphash_1_3_with_state_64(
                               const unsigned char * const state,
                                const unsigned char *in,
                                const STRLEN inlen
)

S_perl_hash_siphash_1_3_64

And the plain-seed 64-bit one ๐Ÿฆ‹ โ€” implements the variant of Siphash which performs 1 round function per block, and 3 as part of the finalizer.

Takes a 16 byte seed vector, and uses it to hash inlen bytes from the buffer pointed to by in, returns a 64 bit hash.

The following code should return 0xB70339FD9E758A5C

char seed[] = "Call me Ishmael.";
char in[] = "It is not down on any map; true places never are.";
U64 hash = S_perl_hash_siphash_1_3_64(
            (const U8*)seed, (const U8*)in, sizeof(in)-1);
 U64  S_perl_hash_siphash_1_3_64(const unsigned char * const seed,
                                 const unsigned char *in,
                                 const STRLEN inlen
)

S_perl_hash_siphash_2_4

Now we're leveling up the rounds, babe. ๐Ÿ’… Implements the variant of Siphash which performs 2 round functions per block, and 4 as part of the finalizer.

Takes a 16 byte seed vector, and uses it to hash inlen bytes from the buffer pointed to by in, returns a 32 bit hash.

The following code should return 0x6421D9AA

char seed[] = "Call me Ishmael.";
char in[] = "It is not down on any map; true places never are.";
U32 hash = S_perl_hash_siphash_2_4(
            (const U8*)seed, (const U8*)in, sizeof(in)-1);
 U32  S_perl_hash_siphash_2_4(const unsigned char * const seed,
                              const unsigned char *in,
                              const STRLEN inlen
)

S_perl_hash_siphash_2_4_with_state

Implements the variant of Siphash which performs 2 round function per block, and 4 as part of the finalizer. ๐Ÿงš

Takes a 32 byte 'state' vector prepared by S_perl_siphash_seed_state() and uses it to hash inlen bytes from the buffer pointed to by in, returns a 32 bit hash.

The following code should return 0x6421D9AA

U8 state[32];
char seed[] = "Call me Ishmael.";
S_perl_siphash_seed_state((const U8*)seed, state);

char in[] = "It is not down on any map; true places never are.";
U32 hash = S_perl_hash_siphash_2_4_with_state(
            state, (const U8*)in, sizeof(in)-1);
 U32  S_perl_hash_siphash_2_4_with_state(
                               const unsigned char * const state,
                                const unsigned char *in,
                                const STRLEN inlen
)

S_perl_hash_siphash_2_4_with_state_64

Implements the variant of Siphash which performs 2 round functions per block, and 4 as part of the finalizer. ๐ŸŒˆ

Takes a 32 byte 'state' vector prepared by S_perl_siphash_seed_state() and uses it to hash inlen bytes from the buffer pointed to by in, returns a 64 bit hash.

The following code should return 0x1E84CF1D7AA516B7

U8 state[32];
char seed[] = "Call me Ishmael.";
S_perl_siphash_seed_state((const U8*)seed, state);

char in[] = "It is not down on any map; true places never are.";
U64 hash = S_perl_hash_siphash_2_4_with_state_64(
            state, (const U8*)in, sizeof(in)-1);
 U64  S_perl_hash_siphash_2_4_with_state_64(
                               const unsigned char * const state,
                                const unsigned char *in,
                                const STRLEN inlen
)

S_perl_hash_siphash_2_4_64

Implements the variant of Siphash which performs 2 round functions per block, and 4 as part of the finalizer. โญ

Takes a 16 byte seed vector, and uses it to hash inlen bytes from the buffer pointed to by in, returns a 64 bit hash.

The following code should return 0x1E84CF1D7AA516B7

char seed[] = "Call me Ishmael.";
char in[] = "It is not down on any map; true places never are.";
U64 hash = S_perl_hash_siphash_2_4_64(
            (const U8*)seed, (const U8*)in, sizeof(in)-1);
 U64  S_perl_hash_siphash_2_4_64(const unsigned char * const seed,
                                 const unsigned char *in,
                                 const STRLEN inlen
)

S_perl_siphash_seed_state

The โœจseed-to-state converterโœจ, the behind-the-scenes icon of this whole siphash situation. ๐Ÿ‘‘

Takes a 16 byte seed and converts it into a 32 byte state buffer. The contents of state_buf will be overwritten.

If you need to hash a lot of things, then you can use this to process the seed once, and then reuse the state over and over. Efficiency, we love to see it. ๐Ÿซถ

The siphash functions which take a seed argument will call this function implicitly every time they are used. Those which take a state argument require the seed to be converted into a state before they are used.

See the various _with_state siphash functions for a usage example.

 void  S_perl_siphash_seed_state(
                            const unsigned char * const seed_buf,
                             unsigned char * state_buf
)

๐Ÿฆ‹ OPTREES ๐Ÿฆ‹

newATTRSUB_x

Construct a Perl subroutine, also performing some surrounding jobs. Very main character of it, honestly. ๐Ÿ’…

This function is expected to be called in a Perl compilation context, and some aspects of the subroutine are taken from global variables associated with compilation. In particular, PL_compcv represents the subroutine that is currently being compiled. It must be non-null when this function is called, and some aspects of the subroutine being constructed are taken from it. The constructed subroutine may actually be a reuse of the PL_compcv object, but will not necessarily be so. ๐Ÿ‘€

If block is null then the subroutine will have no body, and for the time being it will be an error to call it. This represents a forward subroutine declaration such as sub foo ($$);. If block is non-null then it provides the Perl code of the subroutine body, which will be executed when the subroutine is called. This body includes any argument unwrapping code resulting from a subroutine signature or similar. The pad use of the code must correspond to the pad attached to PL_compcv. The code is not expected to include a leavesub or leavesublv op; this function will add such an op. block is consumed by this function and will become part of the constructed subroutine. ๐Ÿ˜ค

proto specifies the subroutine's prototype, unless one is supplied as an attribute (see below). If proto is null, then the subroutine will not have a prototype. If proto is non-null, it must point to a const op whose value is a string, and the subroutine will have that string as its prototype. If a prototype is supplied as an attribute, the attribute takes precedence over proto, but in that case proto should preferably be null. In any case, proto is consumed by this function. ๐ŸŽ€

๐ŸŒธ newATTRSUB_x

So attrs is where you hand over the attributes you want slapped onto the subroutine. Some of them are built-in and get applied to PL_compcv the literal second they're spotted ๐Ÿ‘€, but the rest get rounded up and attached to the sub through this exact route. attrs can be null if there's no attributes to speak of, or it can point to a const op for one single attribute, or it can point to a list op whose children โ€” everybody except the pushmark โ€” are const ops standing in for one or more attributes. Every one of those const ops has to be a string giving the attribute name, optionally followed by parenthesised arguments, exactly the way attributes show up in Perl source. This function applies them to the sub. And heads up: attrs gets consumed by this function. ๐Ÿ’…

Now the naming lore ๐ŸŽ€. If o_is_gv is false and o is null, congrats, the subroutine is anonymous. If o_is_gv is false and o is non-null, then o must point to a const OP โ€” consumed by this function too โ€” and its string value is the name for the subroutine. That name can be qualified or unqualified, and if it's unqualified then a default stash gets picked out some kind of way. But if o_is_gv is true, then o isn't pointing at an OP at all โ€” it's a cast pointer to a GV, and that's what names the subroutine.

If a subroutine with that name already exists, the new sub is either going to replace the existing one in the glob or merge with it. Either way a warning about redefinition may pop off ๐Ÿ˜ญ.

And if the subroutine has one of a few special names โ€” think BEGIN or END โ€” it gets claimed by the appropriate queue for automatic running of phase-related subroutines. When that happens, the relevant glob gets left not containing any subroutine, even if it did have one before. And in the case of BEGIN, the subroutine gets executed and the reference to it disposed of before this function even returns. gone. ๐Ÿ˜ณ

The function hands back a pointer to the constructed subroutine. Anonymous sub? Ownership of one counted reference to it transfers to the caller. Named sub? Caller does not get ownership of a reference. In most of those cases โ€” where the sub has a non-phase name โ€” the sub is alive at the point it's returned, by virtue of being contained in the glob that names it. A phase-named subroutine will usually be alive thanks to the reference owned by the phase's automatic run queue. But a BEGIN subroutine, having already been executed, will quite likely have been destroyed already by the time this function returns, which makes it erroneous for the caller to make any use of the returned pointer. It's fully the caller's job to know which of these situations they're in, no cap. ๐Ÿซถ

CV *       newATTRSUB_x(      I32 floor, OP *o, OP *proto,
                              OP *attrs, OP *block, bool o_is_gv)
CV *  Perl_newATTRSUB_x(pTHX_ I32 floor, OP *o, OP *proto,
                              OP *attrs, OP *block, bool o_is_gv)

๐Ÿ’œ newMYSUB

Builds a Perl lexical subroutine, does some surrounding jobs while it's at it, and returns a pointer to the constructed subroutine. It's giving "same energy as newATTRSUB_x in perlintern" fr fr. โœจ

CV *       newMYSUB(      I32 floor, OP *o, OP *proto, OP *attrs,
                          OP *block)
CV *  Perl_newMYSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs,
                          OP *block)

๐Ÿฆ‹ newXS_len_flags

Constructs an XS subroutine, and yeah it's also doing some surrounding jobs on the side. Multitasking queen ๐Ÿ‘‘.

The subroutine's entry point is subaddr. Its prototype is the one given by the nul-terminated string proto, or no prototype at all if proto is null. The prototype string gets copied, so the caller is free to mutate the string they passed in afterwards. If filename is non-null it has to be a nul-terminated filename, and the subroutine gets its CvFILE set to match. By default CvFILE points directly at the supplied string, which means that string must be static. If flags has the XS_DYNAMIC_FILENAME bit set, then a copy of the string gets taken instead.

Everything else about the subroutine gets left in its default state. If the sub needs anything else done to it to actually function correctly, that's on the caller to do after this function has constructed it. But โš ๏ธ beware โ€” the subroutine could potentially get destroyed before this function returns, as described below.

If name is null, the subroutine is anonymous and its CvGV refers to an __ANON__ glob. If name is non-null, the subroutine gets named accordingly and referenced by the appropriate glob. name is a string of length len bytes giving a sigilless symbol name โ€” in UTF-8 if flags has the SVf_UTF8 bit set, and in Latin-1 otherwise. The name can be qualified or unqualified, with the stash defaulting in the same manner as for gv_fetchpvn_flags. flags may contain flag bits understood by gv_fetchpvn_flags, with the exact same meaning they have there โ€” like GV_ADDWARN. The symbol is always added to the stash if necessary, with GV_ADDMULTI semantics. periodt. ๐Ÿ’…

If there's already a subroutine of the specified name, the new sub replaces the existing one in the glob. A warning may get generated about the redefinition. And if the old subroutine was CvCONST, then whether a warning happens is influenced by an expectation about whether the new subroutine will become a constant of similar value โ€” and that expectation comes from const_svp. (Quick note bestie: the call to this function does not make the new subroutine CvCONST in any case; that's left entirely to the caller.) If const_svp is null, it means the new subroutine will not become a constant. If const_svp is non-null, it means the new subroutine will become a constant, and it points to an SV* providing the constant value the subroutine will have. ๐Ÿ’–

If the subroutine has one of a few special names โ€” BEGIN, END, that crowd โ€” it gets claimed by the appropriate queue for automatic running of phase-related subroutines. Then the relevant glob gets left not containing any subroutine, even if it did before. In the case of BEGIN, the subroutine gets executed and the reference to it disposed of before this function returns โ€” and also before its prototype is set. So if a BEGIN subroutine wouldn't be sufficiently constructed by this function to be ready for execution, the caller has to stop that from happening by giving the subroutine a different name. no cap.

The function returns a pointer to the constructed subroutine. Anonymous sub โ†’ ownership of one counted reference transfers to the caller. Named sub โ†’ caller doesn't get ownership of a reference. In most such cases, where the sub has a non-phase name, the sub is alive at the point it's returned by virtue of being contained in the glob that names it. A phase-named subroutine is usually alive because of the reference owned by the phase's automatic run queue. But a BEGIN subroutine, having already been executed, will quite likely have been destroyed already by the time this function returns, making it erroneous for the caller to make any use of the returned pointer. It is the caller's responsibility to ensure that it knows which of these situations applies. ๐Ÿซถ

CV *       newXS_len_flags(      const char *name, STRLEN len,
                                 XSUBADDR_t subaddr,
                                 const char * const filename,
                                 const char * const proto,
                                 SV ** const_svp, U32 flags)
CV *  Perl_newXS_len_flags(pTHX_ const char *name, STRLEN len,
                                 XSUBADDR_t subaddr,
                                 const char * const filename,
                                 const char * const proto,
                                 SV ** const_svp, U32 flags)

๐Ÿ”’ op_refcnt_lock

Implements the OP_REFCNT_LOCK macro โ€” which you should be using instead, bestie. ๐Ÿ™ˆ

void       op_refcnt_lock()
void  Perl_op_refcnt_lock(pTHX)

๐Ÿ”“ op_refcnt_unlock

Implements the OP_REFCNT_UNLOCK macro โ€” which, again, you should use instead. ๐Ÿ’…

void       op_refcnt_unlock()
void  Perl_op_refcnt_unlock(pTHX)

๐ŸŒˆ traverse_op_tree

Returns the next op in a depth-first traversal of the op tree, and returns NULL once the traversal is complete. ๐ŸŽ€

The very first call has to supply the root of the tree as both top and o.

For now it's static, but it may get exposed to the API in the future. iykyk โญ

OP *  traverse_op_tree(OP *top, OP *o)

โœจ PACK AND UNPACK โœจ

There are currently no internal API items in Pack and Unpack. It's giving empty room, clean slate, main character blank page ๐Ÿฆ‹๐ŸŒธ

โœจ Pad Data Structures โœจ

okay so pads. the little scratch spaces where your lexicals live. let's GO ๐Ÿ’…

  • CX_CURPAD_SAVE โ€” stashes the current pad away inside the context block you hand it, so it can be brought back later.
void  CX_CURPAD_SAVE(struct context)
  • CX_CURPAD_SV โ€” grabs the SV sitting at offset po in that saved current pad of the given context block. oh and bestie, you can totally use this as an lvalue ๐Ÿ‘‘
SV *  CX_CURPAD_SV(struct context, PADOFFSET po)
  • PAD_BASE_SV โ€” gets you the value from slot po in the base (that's DEPTH=1) pad of a padlist.
SV *  PAD_BASE_SV(PADLIST padlist, PADOFFSET po)
  • PAD_CLONE_VARS โ€” clones all the state variables that hang out with the running and compiling pads. like a glow-up but for interpreter state.
void  PAD_CLONE_VARS(PerlInterpreter *proto_perl,
                     CLONE_PARAMS* param)
  • PAD_COMPNAME_FLAGS โ€” hands back the flags for the current compiling pad name at offset po. it just assumes you gave it a valid slot entry, no vibe check, no nothing.
U32  PAD_COMPNAME_FLAGS(PADOFFSET po)
  • PAD_COMPNAME_GEN โ€” the generation number of the name at offset po in the current compiling pad. and yes it's an lvalue, you can write to it ๐Ÿ’–
STRLEN  PAD_COMPNAME_GEN(PADOFFSET po)
  • PAD_COMPNAME_GEN_set โ€” sets that generation number for the name at offset po in the current compiling pad (lvalue) to gen. yes this is the lvalue-setter sibling of the one above, they're a matching set, it's giving duo energy.
STRLEN  PAD_COMPNAME_GEN_set(PADOFFSET po, int gen)
  • PAD_COMPNAME_OURSTASH โ€” returns the stash tied to an our variable. assumes the slot entry really is a valid our lexical, so don't come at it with anything else fr.
HV *  PAD_COMPNAME_OURSTASH(PADOFFSET po)
  • PAD_COMPNAME_PV โ€” gives you the name of the current compiling pad name at offset po. assumes a valid slot entry, same deal as always.
char *  PAD_COMPNAME_PV(PADOFFSET po)
  • PAD_COMPNAME_TYPE โ€” returns the type (that's the stash) of the current compiling pad name at offset po. it must be a valid name, and if it's not typed you just get null back. no type, no stash, no problem.
HV *  PAD_COMPNAME_TYPE(PADOFFSET po)
  • PAD_RESTORE_LOCAL โ€” puts back the old pad that PAD_SAVE_LOCAL() tucked into the local variable opad. undoing the thing, iconic behavior.
void  PAD_RESTORE_LOCAL(PAD *opad)
  • PAD_SAVE_LOCAL โ€” saves the current pad into the local variable opad, and then makes the current pad equal to npad. swap, but make it safe.
void  PAD_SAVE_LOCAL(PAD *opad, PAD *npad)
  • PAD_SAVE_SETNULLPAD โ€” saves the current pad and then sets it to null. bye bestie ๐Ÿซถ
void  PAD_SAVE_SETNULLPAD()
  • PAD_SET_CUR โ€” sets the current pad to be pad n in the padlist, saving whatever the previous current pad was. BUT โ€” heads up โ€” right now this macro expands to a string that's too long for some compilers, so the move is to replace it with this instead:
SAVECOMPPAD();
PAD_SET_CUR_NOSAVE(padlist,n);

and the signature, for the record:

void  PAD_SET_CUR(PADLIST padlist, I32 n)
  • PAD_SET_CUR_NOSAVE โ€” literally like PAD_SET_CUR, just without the save. same energy, less storing.
void  PAD_SET_CUR_NOSAVE(PADLIST padlist, I32 n)
  • PAD_SETSV โ€” sets the slot at offset po in the current pad to sv.
SV *  PAD_SETSV(PADOFFSET po, SV* sv)
  • PAD_SV โ€” gets you the value at offset po in the current pad.
SV *  PAD_SV(PADOFFSET po)
  • PAD_SVl โ€” the lightweight and lvalue version of PAD_SV. get or set the value at offset po in the current pad. unlike PAD_SV, it does not print diagnostics with -DX. for internal use only, so stay in your lane ๐Ÿ’€
SV *  PAD_SVl(PADOFFSET po)
  • PadnameIsFIELD โ€” whether this is a field variable. PADNAMEs where this comes back true will have extra info available through PadnameFIELDINFO.
bool  PadnameIsFIELD(PADNAME * pn)
  • PadnameIsOUR โ€” whether this is an our variable.
bool  PadnameIsOUR(PADNAME * pn)
  • PadnameIsSTATE โ€” whether this is a state variable.
bool  PadnameIsSTATE(PADNAME * pn)
  • PadnameOURSTASH โ€” the stash in which this our variable was declared.
HV *  PadnameOURSTASH(PADNAME * pn)
  • PadnameOUTER โ€” whether this entry belongs to an outer pad. entries where this is true are often called 'fake'. yes, really, that's the terminology, we don't make the rules.
bool  PadnameOUTER(PADNAME * pn)
  • PadnameTYPE โ€” the stash associated with a typed lexical. so for my Foo $bar this returns the %Foo:: hash. slay.
HV *  PadnameTYPE(PADNAME * pn)
  • SAVECLEARSV โ€” clears the pad value that's being pointed to when scope exits. that's the runtime action of my, bestie, the whole "this variable dies now" moment.
void  SAVECLEARSV(SV **svp)
  • SAVECOMPPAD โ€” saves PL_comppad and PL_curpad.
void  SAVECOMPPAD()
  • SAVEPADSV โ€” saves a pad slot (used to restore after an iteration).
void  SAVEPADSV(PADOFFSET po)

๐ŸŒธ Password and Group access ๐ŸŒธ

there are currently no internal API items in Password and Group access. empty. void. a whole vibe of nothing ๐Ÿ’€

๐ŸŒธ Paths to system commands ๐ŸŒธ

there are currently no internal API items in Paths to system commands either. nada.

๐ŸŒธ Prototype information ๐ŸŒธ

and there are currently no internal API items in Prototype information. moving on bestie ๐Ÿฆ‹

๐ŸŒธ Reference-counted stack manipulation ๐ŸŒธ

there are currently no internal API items in Reference-counted stack manipulation. zero items, but lots of refcounts somewhere, just not here.

๐ŸŒธ REGEXP Functions ๐ŸŒธ

  • regnode โ€” described in perlreguts. that's the whole entry, go read that one, iykyk โœจ

๐ŸŒธ Reports and Formats ๐ŸŒธ

there are currently no internal API items in Reports and Formats.

๐ŸŒธ Signals ๐ŸŒธ

there are currently no internal API items in Signals. (can't signal what isn't there, periodt)

๐ŸŒธ Site configuration ๐ŸŒธ

there are currently no internal API items in Site configuration.

๐ŸŒธ Sockets configuration values ๐ŸŒธ

there are currently no internal API items in Sockets configuration values.

๐ŸŒธ Source Filters ๐ŸŒธ

there are currently no internal API items in Source Filters.


โœจ Stack Manipulation Macros โœจ

  • djSP โ€” declares Just SP. and honestly? this is actually identical to dSP, and it declares a local copy of perl's stack pointer that you can reach through the SP macro. see "SP" in perlapi. it's available purely for backward source code compatibility with the old (Perl 5.005) thread model, so it's a little vintage moment ๐Ÿ‘‘
djSP();
  • LVRET โ€” true if this op will be the return value of an lvalue subroutine.
  • save_alloc โ€” implements "SSNEW" in perlapi and its whole friend group, which should be used instead of this function. so like, don't call this one directly, call the cool ones.
SSize_t       save_alloc(      SSize_t size, I32 pad)
SSize_t  Perl_save_alloc(pTHX_ SSize_t size, I32 pad)

โœจ String Handling โœจ

  • delimcpy_no_escape โ€” copies a source buffer over to a destination buffer, and it stops at (but does not include) the first place in the source where the delimiter byte delim shows up. the source is the bytes between from and from_end - 1, and similarly the dest is to up to to_end.

the number of bytes copied gets written to *retlen.

it returns the position of delim in the from buffer โ€” but if there's no such occurrence before from_end, then from_end is returned, and the entire buffer from .. from_end - 1 gets copied. so basically "found it" or "copied everything", pick your ending ๐ŸŽ€

if there's room in the destination after the copy, an extra terminating safety NUL byte is appended (and that one is not included in the returned length).

the error case is when the destination buffer isn't large enough to hold everything that should be copied. in that situation, a value larger than to_end - to gets written to *retlen, and as much of the source as fits will be written to the destination. not having room for the safety NUL is not considered an error, so don't panic about that one.

char *       delimcpy_no_escape(char *to, const char *to_end,
                                const char *from,
                                const char *from_end,
                                const int delim, I32 *retlen)
char *  Perl_delimcpy_no_escape(char *to, const char *to_end,
                                const char *from,
                                const char *from_end,
                                const int delim, I32 *retlen)
  • quadmath_format_needed โ€” returns true if the format string seems to contain at least one non-Q-prefixed %[efgaEFGA] format specifier, and false otherwise.

okay so the format specifier detection here is not a complete printf-syntax detection, it's just catching most common cases. it's giving "good enough" energy.

if true comes back, those arguments should in theory be processed with quadmath_snprintf() โ€” but if there's more than one such format specifier (peep quadmath_format_valid), and if there's anything else beyond that one (even just a single byte), they cannot be processed, because quadmath_snprintf() is extremely strict: it accepts only one format spec and nothing else. in that case, the code should probably just fail. no cap.

bool       quadmath_format_needed(const char *format)
bool  Perl_quadmath_format_needed(const char *format)
  • quadmath_format_valid โ€” quadmath_snprintf() is very strict about its format string and will fail, returning -1, if the format is invalid. it accepts exactly one format spec. one. not two. one ๐Ÿ’…

quadmath_format_valid() checks that the intended single spec looks sane: it begins with %, has only one %, ends with [efgaEFGA], and has Q before it. this is not a full printf syntax check, just the basics.

returns true if it's valid, false if not.

see also quadmath_format_needed.

bool       quadmath_format_valid(const char *format)
bool  Perl_quadmath_format_valid(const char *format)

โœจ SV Flags โœจ

  • SVt_INVLIST โ€” type flag for scalars. see svtype in perlapi.

and that's the end of this part, but we're not done yet โ€” more is coming, so don't go anywhere ๐Ÿซถ

๐Ÿ’– SV Handling ๐Ÿ’–

  • PL_Sv โ€” a lil scratch-pad SV for whenever you need something temporary. It's mainly used as a fallback by macros on platforms where PERL_USE_GCC_BRACE_GROUPS in perlapi is unavailable, and which would otherwise evaluate their SV parameter more than once.
BUT BEWARE bestie ๐Ÿ˜ญ if this gets used somewhere where something else that's using it is also sitting in the call stack, this variable would get zapped, and you'd be stuck with hard-to-diagnose errors. Not the vibe.

These days using an inline function is generally preferred instead.

  • sv_add_arena โ€” hand it a chunk of memory, and it links that chunk to the head of the list of arenas and splits it into a list of free SVs. โœจ
void  sv_add_arena(char * const ptr, const U32 size,
                   const U32 flags)
  • sv_clean_all โ€” decrements the refcnt of every remaining SV, possibly triggering a cleanup. Heads up: you might have to call this function multiple times to actually free SVs that are tangled up in complex self-referential hierarchies. ๐ŸŒ€
SSize_t       sv_clean_all()
SSize_t  Perl_sv_clean_all(pTHX)
  • sv_clean_objs โ€” tries to destroy all objects that haven't been freed yet. bye bestie ๐Ÿ’…
void       sv_clean_objs()
void  Perl_sv_clean_objs(pTHX)
  • sv_free_arenas โ€” deallocates the memory used by all the arenas. Important note: all the individual SV heads and bodies inside those arenas must already have been freed first.
void       sv_free_arenas()
void  Perl_sv_free_arenas(pTHX)
  • sv_grow โ€” expands the character buffer in the SV. If it needs to, it uses sv_unref and upgrades the SV to SVt_PV. Returns a pointer to the character buffer. Use the SvGROW wrapper instead tho, fr fr.
char *       sv_grow(      SV * const sv, STRLEN newlen)
char *  Perl_sv_grow(pTHX_ SV * const sv, STRLEN newlen)
  • sv_grow_fresh โ€” a cut-down version of sv_grow, intended only for when sv is a freshly-minted SVt_PV, SVt_PVIV, SVt_PVNV, or SVt_PVMG. Like, sv has the default flags, has never been any other type, and doesn't have an existing string. Basically it just assigns a char buffer and hands you a pointer to it. ๐ŸŽ€
char *       sv_grow_fresh(      SV * const sv, STRLEN newlen)
char *  Perl_sv_grow_fresh(pTHX_ SV * const sv, STRLEN newlen)
  • sv_newref โ€” increments an SV's reference count. Use the SvREFCNT_inc() wrapper instead! ๐Ÿ‘‘
SV *       sv_newref(      SV * const sv)
SV *  Perl_sv_newref(pTHX_ SV * const sv)
  • sv_pv โ€” use the SvPV_nolen macro instead. periodt.
char *       sv_pv(      SV *sv)
char *  Perl_sv_pv(pTHX_ SV *sv)
  • sv_pvbyte โ€” use SvPVbyte_nolen instead.
char *       sv_pvbyte(      SV *sv)
char *  Perl_sv_pvbyte(pTHX_ SV *sv)
  • sv_pvbyten_force โ€” the backend for the SvPVbytex_force macro. Always use the macro instead. And if the SV can't be downgraded from UTF-8, this croaks. ๐Ÿ’€
char *       sv_pvbyten_force(      SV * const sv,
                                    STRLEN * const lp)
char *  Perl_sv_pvbyten_force(pTHX_ SV * const sv,
                                    STRLEN * const lp)
  • sv_pvn_force โ€” gets a sensible string out of the SV somehow. It's a private implementation of the SvPV_force macro, for compilers that can't cope with complex macro expressions. Always use the macro instead, okay? ๐Ÿซถ
char *       sv_pvn_force(      SV *sv, STRLEN *lp)
char *  Perl_sv_pvn_force(pTHX_ SV *sv, STRLEN *lp)
  • sv_pvutf8 โ€” use the SvPVutf8_nolen macro instead.
char *       sv_pvutf8(      SV *sv)
char *  Perl_sv_pvutf8(pTHX_ SV *sv)
  • sv_pvutf8n_force โ€” the backend for the SvPVutf8x_force macro. Always use the macro instead.
char *       sv_pvutf8n_force(      SV * const sv,
                                    STRLEN * const lp)
char *  Perl_sv_pvutf8n_force(pTHX_ SV * const sv,
                                    STRLEN * const lp)
  • sv_tainted โ€” tests an SV for taintedness. Use SvTAINTED instead.
bool       sv_tainted(      SV * const sv)
bool  Perl_sv_tainted(pTHX_ SV * const sv)
  • sv_true โ€” returns true if the SV has a true value by Perl's rules. Use the SvTRUE macro instead, which might call sv_true() or might use an in-line version instead. either way, iconic. โญ
I32       sv_true(      SV * const sv)
I32  Perl_sv_true(pTHX_ SV * const sv)
  • sv_untaint โ€” untaints an SV. Use SvTAINTED_off instead.
void       sv_untaint(      SV * const sv)
void  Perl_sv_untaint(pTHX_ SV * const sv)
  • sv_2bool โ€” this macro is only used by sv_true() or its macro equivalent, and only if the latter's argument is neither SvPOK, SvIOK nor SvNOK. It calls sv_2bool_flags with the SV_GMAGIC flag.
bool       sv_2bool(      SV * const sv)
bool  Perl_sv_2bool(pTHX_ SV * const sv)
  • sv_2bool_flags โ€” this function is only used by sv_true() and friends, and only if the latter's argument is neither SvPOK, SvIOK nor SvNOK. If the flags contain SV_GMAGIC, then it does an mg_get() first. ๐ŸŒธ
bool       sv_2bool_flags(      SV *sv, I32 flags)
bool  Perl_sv_2bool_flags(pTHX_ SV *sv, I32 flags)
  • sv_2num โ€” NOTE: sv_2num is experimental and may change or be removed without notice. โš ๏ธ

Returns an SV with the numeric value of the source SV, doing any necessary reference or overload conversion. The caller is expected to have already handled get-magic. (so like, that part's on you bestie ๐Ÿ’…)

SV *       sv_2num(      SV * const sv)
SV *  Perl_sv_2num(pTHX_ SV * const sv)
  • sv_2pv_nolen โ€” like sv_2pv(), but it doesn't return the length too. You should usually use the macro wrapper SvPV_nolen(sv) instead.
char *       sv_2pv_nolen(      SV *sv)
char *  Perl_sv_2pv_nolen(pTHX_ SV *sv)
  • sv_2pvbyte_nolen โ€” returns a pointer to the byte-encoded representation of the SV. May cause the SV to be downgraded from UTF-8 as a side-effect. Usually accessed via the SvPVbyte_nolen macro.
char *       sv_2pvbyte_nolen(      SV *sv)
char *  Perl_sv_2pvbyte_nolen(pTHX_ SV *sv)
  • sv_2pvutf8_nolen โ€” returns a pointer to the UTF-8-encoded representation of the SV. May cause the SV to be upgraded to UTF-8 as a side-effect. Usually accessed via the SvPVutf8_nolen macro. ๐Ÿฆ‹
char *       sv_2pvutf8_nolen(      SV *sv)
char *  Perl_sv_2pvutf8_nolen(pTHX_ SV *sv)
  • SvTHINKFIRST โ€” a quick lil flag check to see whether an sv should be passed to sv_force_normal to be "downgraded" before SvIVX or SvPVX can be modified directly.

For example: if your scalar is a reference and you wanna modify the SvIVX slot, you can't just do SvROK_off, because that will leak the referent. ๐Ÿ˜ญ

This is used internally by various sv-modifying functions, such as sv_setsv, sv_setiv and sv_pvn_force.

One case that this does not handle is a gv without SvFAKE set. After

if (SvTHINKFIRST(gv)) sv_force_normal(gv);

it will still be a gv.

SvTHINKFIRST sometimes produces false positives. In those cases sv_force_normal does nothing.

U32  SvTHINKFIRST(SV *sv)

๐Ÿงผ Tainting ๐Ÿงผ

  • sv_taint โ€” taints an SV. Use SvTAINTED_on instead.
void       sv_taint(      SV *sv)
void  Perl_sv_taint(pTHX_ SV *sv)
  • TAINT โ€” if we aren't in taint checking mode, it does nothing; otherwise it indicates to TAINT_set and TAINT_PROPER that some unspecified element is tainted. โœจ
void  TAINT
  • TAINT_ENV โ€” looks at several components of %ENV for taintedness, and calls taint_proper if any of them are tainted. The components it searches are things like $PATH. ๐Ÿ‘€
void  TAINT_ENV()
  • taint_env โ€” implements the TAINT_ENV macro, which you should generally use instead.
void       taint_env()
void  Perl_taint_env(pTHX)
  • TAINT_get โ€” returns a boolean as to whether some element is tainted or not. ๐ŸŒˆ
bool  TAINT_get
  • TAINT_IF โ€” if c evaluates to true, it calls TAINT to indicate that something is tainted; otherwise it does nothing.
void  TAINT_IF(bool c)
  • TAINT_NOT โ€” removes any taintedness previously set by, like, TAINT for example.
void  TAINT_NOT
  • TAINT_PROPER โ€” if no element is tainted, it does nothing; otherwise it outputs a message (containing s) that indicates there's a tainting violation. And if such violations are fatal, it croaks. ๐Ÿ’€
void  TAINT_PROPER(const char * s)
  • taint_proper โ€” implements the TAINT_PROPER macro, which you should generally use instead.
void       taint_proper(      const char *f,
                              const char * const s)
void  Perl_taint_proper(pTHX_ const char *f,
                              const char * const s)
  • TAINT_set โ€” if s is true, TAINT_get returns true; if s is false, TAINT_get returns false. (it's giving simple, honestly ๐Ÿ’…)
void  TAINT_set(bool s)
  • TAINT_WARN_get โ€” returns false if tainting violations are fatal; returns true if they're just warnings. ๐ŸŽ€
bool  TAINT_WARN_get
  • TAINT_WARN_set โ€” s being true indicates TAINT_WARN_get should return that tainting violations are just warnings. s being false indicates TAINT_WARN_get should return that tainting violations are fatal.
void  TAINT_WARN_set(bool s)
  • TAINTING_get โ€” returns a boolean as to whether taint checking is enabled or not.
bool  TAINTING_get
  • TAINTING_set โ€” turns taint checking mode off/on. ๐Ÿซถ
void  TAINTING_set(bool s)

โฐ Time โฐ

There are currently no internal API items in Time. bestie the section is literally just vibes rn โœจ


๐Ÿท๏ธ Typedef names ๐Ÿท๏ธ

There are currently no internal API items in Typedef names. empty, but make it fashion ๐ŸŽ€

๐Ÿ’– Unicode Support ๐Ÿ’–

is_utf8_non_invariant_string

okay bestie so this one hands you back TRUE when is_utf8_invariant_string in perlapi gives you FALSE for the first len bytes of the string s โ€” except those bytes are still totally legal Perl-extended UTF-8. If that's not the case? FALSE. that's it, that's the vibe.

and what does a TRUE even mean? it means at least one code point in that sequence is either a wide character that can't be squeezed into a single byte, or its representation changes depending on whether the sequence is UTF-8 encoded or not. lowkey important.

See also is_utf8_invariant_string in perlapi.

 bool       is_utf8_non_invariant_string(const U8 * const s,
                                         STRLEN len)
 bool  Perl_is_utf8_non_invariant_string(const U8 * const s,
                                         STRLEN len)

isSCRIPT_RUN

this one returns a bool telling you whether the sequence of bytes from s up to but not including send forms a "script run" โœจ utf8_target is true iff the sequence starting at s is to be treated as UTF-8.

to be precise (and we ARE being precise, no cap): except for the two degenerate cases listed below, this function returns true iff every code point in it comes from any combination of three "scripts" given by the Unicode "Script Extensions" property: Common, Inherited, and possibly one other. plus, all decimal digits have to come from the same consecutive sequence of 10. slay.

for example, if all the characters in the sequence are Greek, or Common, or Inherited, this function returns true โ€” as long as any decimal digits in it are from the same block of digits in Common. (those are the ASCII digits "0".."9", plus a block for full width forms of these, and several others used in mathematical notation.) for scripts (unlike Greek) that have their own digits defined, this will accept either digits from that set or from one of the Common digit sets, but not a combination of the two. some scripts, like Arabic, have more than one set of digits. all digits must come from the same set for this function to return true. it's giving picky, but like, correctly picky.

*ret_script, if ret_script is not NULL, will on return of true contain the script found, using the SCX_enum typedef. its value will be SCX_INVALID if the function returns false.

if the sequence is empty, true is returned, but *ret_script (if asked for) will be SCX_INVALID.

if the sequence contains a single code point which is unassigned to a character in the version of Unicode being used, the function will return true, and the script will be SCX_Unknown. any other combination of unassigned code points in the input sequence will result in the function treating the input as not being a script run. ๐Ÿ’€

the returned script will be SCX_Inherited iff all the code points in it are from the Inherited script.

otherwise, the returned script will be SCX_Common iff all the code points in it are from the Inherited or Common scripts.

 bool       isSCRIPT_RUN(      const U8 *s, const U8 *send,
                               const bool utf8_target)
 bool  Perl_isSCRIPT_RUN(pTHX_ const U8 *s, const U8 *send,
                               const bool utf8_target)

utf8_to_uvuni

DEPRECATED! it is planned to remove utf8_to_uvuni from a future release of Perl. do not use it for new code; remove it from existing code. fr fr, she's on her way out. ๐Ÿ™ˆ

returns the Unicode code point of the first character in the string s, which is assumed to be in UTF-8 encoding; retlen will be set to the length, in bytes, of that character.

some, but not all, UTF-8 malformations are detected โ€” and honestly some malformed input could cause reading beyond the end of the input buffer, which is one reason why this function is deprecated. the other reason is that only in extremely limited circumstances should the Unicode versus native code point be of any interest to you.

if s points to one of the detected malformations, and UTF8 warnings are enabled, zero is returned and *retlen is set (if retlen doesn't point to NULL) to -1. if those warnings are off, the computed value if well-defined (or the Unicode REPLACEMENT CHARACTER, if not) is silently returned, and *retlen is set (if retlen isn't NULL) so that (s + *retlen) is the next possible position in s that could begin a non-malformed character. see utf8n_to_uvchr in perlapi for details on when the REPLACEMENT CHARACTER is returned.

 UV       utf8_to_uvuni(      const U8 *s, STRLEN *retlen)
 UV  Perl_utf8_to_uvuni(pTHX_ const U8 *s, STRLEN *retlen)

utf8n_to_uvuni

DEPRECATED! it is planned to remove utf8n_to_uvuni from a future release of Perl. do not use it for new code; remove it from existing code. ๐Ÿšซ

instead use utf8_to_uv in perlapi, or rarely, utf8_to_uv_flags in perlapi.

this function was useful for code that wanted to handle both EBCDIC and ASCII platforms with Unicode properties, but starting in Perl v5.20, the distinctions between the platforms have mostly been made invisible to most code, so this function is quite unlikely to be what you want. if you do need this precise functionality, use instead "utf8_to_uv" in perlapi or "utf8_to_uv_flags" in perlapi to calculate the native code point, and then convert to Unicode using "NATIVE_TO_UNI" in perlapi. iykyk.

 UV       utf8n_to_uvuni(      const U8 *s, STRLEN curlen,
                               STRLEN *retlen, U32 flags)
 UV  Perl_utf8n_to_uvuni(pTHX_ const U8 *s, STRLEN curlen,
                               STRLEN *retlen, U32 flags)

uvoffuni_to_utf8_flags

THIS FUNCTION SHOULD BE USED IN ONLY VERY SPECIALIZED CIRCUMSTANCES. instead, almost all code should use uv_to_utf8 in perlapi or uv_to_utf8_flags in perlapi. like, genuinely almost all of it. ๐Ÿ’…

this function is like them, but the input is a strict Unicode (as opposed to native) code point. only in very rare circumstances should code not be using the native code point.

for details, see the description for uv_to_utf8_flags in perlapi.

 U8 *       uvoffuni_to_utf8_flags(      U8 *d, UV uv, UV flags)
 U8 *  Perl_uvoffuni_to_utf8_flags(pTHX_ U8 *d, UV uv, UV flags)

valid_utf8_to_uvchr

like "utf8_to_uv" in perlapi, but should only be called when it is known that the next character in the input UTF-8 string s is well-formed (e.g., it passes "isUTF8_CHAR" in perlapi). surrogates, non-character code points, and non-Unicode code points are allowed. so she's chill, but only if you already did your homework. ๐ŸŽ€

 UV       valid_utf8_to_uvchr(const U8 *s, STRLEN *retlen)
 UV  Perl_valid_utf8_to_uvchr(const U8 *s, STRLEN *retlen)

variant_under_utf8_count

this function looks at the sequence of bytes between s and e, which are assumed to be encoded in ASCII/Latin1, and returns how many of them would change should the string be translated into UTF-8. due to the nature of UTF-8, each of these would occupy two bytes instead of the single one in the input string. thus, this function returns the precise number of bytes the string would expand by when translated to UTF-8. so it's basically a glow-up size estimate. โœจ

unlike most of the other functions that have utf8 in their name, the input to this function is NOT a UTF-8-encoded string. the function name is slightly odd to emphasize this. yes it's confusing. yes it's on purpose. ๐Ÿ˜ญ

this function is internal to Perl because khw thinks that any XS code that would want this is probably operating too close to the internals. presenting a valid use case could change that.

see also "is_utf8_invariant_string" in perlapi and "is_utf8_invariant_string_loc" in perlapi,

 Size_t  variant_under_utf8_count(const U8 * const s,
                                  const U8 * const e)

๐Ÿ› ๏ธ Utility Functions ๐Ÿ› ๏ธ

my_popen_list

implementing function on some systems for PerlProc_popen_list(). doing the lord's work on the platforms that need it. ๐Ÿซถ

 PerlIO *       my_popen_list(      const char *mode, int n,
                                    SV **args)
 PerlIO *  Perl_my_popen_list(pTHX_ const char *mode, int n,
                                    SV **args)

my_socketpair

emulates socketpair(2) on systems that don't have it, but which do have enough functionality for the emulation. iconic fallback behaviour honestly. ๐Ÿ’–

 int       my_socketpair(int family, int type, int protocol,
                         int fd[2])
 int  Perl_my_socketpair(int family, int type, int protocol,
                         int fd[2])

๐ŸŽ€ Versioning ๐ŸŽ€

there are currently no internal API items in Versioning. empty. vacant. a whole section with nothing in it, and we respect her for that. ๐Ÿ’€

๐Ÿ’€ Warning and Dieing ๐Ÿ’€

Okay bestie, this section is literally the "we need to talk" corner of perlapi โ€” all the warnings, the deprecations, and the stuff that screams at you when your code does something sus. Let's go. ๐Ÿซถ

deprecate

It's a lil wrapper around Perl_ck_warner_d() that throws a deprecated warning into whatever category you name, with an appropriate message attached. The message arg has to be a C string. And heads up โ€” the string " is deprecated" gets auto-glued onto the end of your message, so don't add it yourself, okay? ๐Ÿ’…

deprecate(U32 category, "message")

deprecate_disappears_in

Same energy as deprecate, also a wrapper around Perl_ck_warner_d(), but this one is here to announce that the thing you're using is gonna get yeeted in a specific release. The when and message args both have to be C strings, and when needs to look like "5.40", with no minor element in the version. The actual warning that pops out is the result of this expression:

message " is deprecated, and will disappear in Perl " when

which is exactly why message and when have to be literal C strings, fr fr.

deprecate_disappears_in(U32 category, "when", "message")

deprecate_fatal_in

Twin of the above, but the plot twist is that your code won't just be deprecated โ€” it's gonna become fatal in a specific release. ๐Ÿ˜ญ Again it's a wrapper around Perl_ck_warner_d(), again when and message are C strings, again when looks like "5.40" with no minor element in the version. The output is the result of:

message " is deprecated, and will become fatal in Perl " when

so yeah, literal C strings only, bestie.

deprecate_fatal_in(U32 category, "when", "message")

find_uninit_var

NOTE: find_uninit_var is experimental and may change or be removed without notice. ๐Ÿ‘€ Don't get attached, she's mysterious.

This one goes full detective mode ๐Ÿ•ต๏ธ โ€” it hunts down the name of the undefined variable (if there even is one) that made an operator spit out a "Use of uninitialized value" warning.

If match is true, it only hands you back a name when that name's value actually matches uninit_sv. So roughly speaking: if a unary operator (like OP_COS) throws the warning, following the direct child of the op may land you on an OP_PADSV or OP_GV that names the undefined variable. But with OP_ADD there are two branches to chase, so it only prints the variable name if it gets an exact match. desc_p points to a string pointer holding the description of the op โ€” it may get updated if needed.

The name comes back as a mortal SV.

It assumes that PL_op is the OP that originally triggered the error, and that PL_comppad/PL_curpad points at the currently executing pad.

 SV *  find_uninit_var(const OP * const obase,
                       const SV * const uninit_sv, bool match,
                       const char **desc_p)

PL_dowarn

The C variable that roughly corresponds to Perl's $^W warning variable. But plot twist: $^W is treated as a straight-up boolean, whereas PL_dowarn is a whole collection of flag bits. ๐ŸŒˆ

On threaded perls, every thread has its own independent copy of this variable, and each one is initialized at creation time with the current value of the creating thread's copy.

 U8  PL_dowarn

report_uninit

Prints the appropriate "Use of uninitialized variable" warning. That's it, that's the job. ๐Ÿ’–

 void       report_uninit(      const SV *uninit_sv)
 void  Perl_report_uninit(pTHX_ const SV *uninit_sv)

โœจ XS โœจ

my_cxt_init

This implements the MY_CXT_INIT macro from perlxs โ€” and bestie, you should be using that macro instead of calling this directly, okay? ๐ŸŽ€

Here's the lore: the first time a module is loaded, the global PL_my_cxt_index gets incremented, and that value is assigned to that module's static my_cxt_index (whose address is passed in as an arg). Then, for each interpreter this function is called for, it makes sure a void* slot is available to hang the static data off of โ€” by allocating or extending the interpreter's PL_my_cxt_list array. The bookkeeping? Immaculate. ๐Ÿ’…

 void *  Perl_my_cxt_init(pTHX_ int *indexp, size_t size)

๐Ÿ•ณ๏ธ Undocumented elements ๐Ÿ•ณ๏ธ

This section is the lost and found of the whole page: it lists the elements that are otherwise undocumented. If you end up using any of them, please consider creating and submitting documentation for it โ€” be the main character, give back to the community. ๐Ÿซถ

Experimental and deprecated undocumented elements are listed separately at the end, so don't go mixing them up, iykyk.

okay bestie the internals list is STILL going ๐Ÿ’€ this is the part where the page is basically like "these exist, we're not elaborating" and honestly? iconic. every single one below is real, spelled exactly like this, and we're keeping all of them ๐Ÿ’–

the opening girlies โ€” no notes, just vibes โœจ

  • abort_execution
  • add_above_Latin1_folds
  • add_cp_to_invlist
  • _add_range_to_invlist
  • allocmy

the amagic_ squad ๐Ÿ’… these all share a prefix and that's all we're legally allowed to say

  • amagic_cmp
  • amagic_cmp_desc
  • amagic_cmp_locale
  • amagic_cmp_locale_desc
  • amagic_i_ncmp
  • amagic_i_ncmp_desc
  • amagic_is_enabled
  • amagic_ncmp
  • amagic_ncmp_desc

then a lil grab bag ๐ŸŽ€

  • any_dup
  • append_utf8_from_native_byte
  • apply
  • atfork_lock
  • atfork_unlock
  • av_arylen_p
  • av_extend_guts
  • av_iter_p
  • av_nonelem
  • av_reify
  • bind_match
  • block_gimme

the boot_core_ girlies and friends ๐Ÿ‘‘

  • boot_core_builtin
  • boot_core_mro
  • boot_core_PerlIO
  • boot_core_UNIVERSAL
  • build_infix_plugin
  • _byte_dump_string
  • call_list
  • cando
  • capture_clear

the cast_ girlies โ€” casting, but make it internal ๐Ÿซถ

  • cast_iv
  • cast_i32
  • cast_ulong
  • cast_uv

a few checkers checking things โœ…

  • check_hash_fields_and_hekify
  • check_regnode_after
  • check_utf8_print

the ck_ girlies ๐Ÿ”ฅ okay this is the moment. the whole ck_ family. every single one, no skipping, periodt

  • ck_anoncode
  • ck_backtick
  • ck_bitop
  • ck_classname
  • ck_cmp
  • ck_concat
  • ck_defined
  • ck_delete
  • ck_each
  • ck_entersub_args_core
  • ck_eof
  • ck_eval
  • ck_exec
  • ck_exists
  • ck_ftst
  • ck_fun
  • ck_glob
  • ck_grep
  • ck_helemexistsor
  • ck_index
  • ck_isa
  • ck_join
  • ck_length
  • ck_lfun
  • ck_listiob
  • ck_match
  • ck_method
  • ck_null
  • ck_open
  • ck_prototype
  • ck_readline
  • ck_refassign
  • ck_repeat
  • ck_require
  • ck_return
  • ck_rfun
  • ck_rvconst
  • ck_sassign
  • ck_scmp
  • ck_select
  • ck_shift
  • ck_smartmatch
  • ck_sort
  • ck_spair
  • ck_split
  • ck_stringify
  • ck_subr
  • ck_substr
  • ck_svconst
  • ck_tell
  • ck_trunc
  • ck_trycatch

the warn girlies ๐Ÿ˜ญ

  • ckwarn
  • ckwarn_d

the class_ girlies ๐ŸŒธ all ten of them, we're not playing

  • class_add_ADJUST
  • class_add_field
  • class_apply_attributes
  • class_apply_field_attributes
  • class_prepare_initfield_parse
  • class_prepare_method_parse
  • class_seal_stash
  • class_set_field_defop
  • class_setup_stash
  • class_wrap_method_body

a lil cluster of misc ๐Ÿงš

  • clear_defarray
  • closest_cop
  • cmp_desc
  • cmp_locale_desc
  • cmpchain_extend
  • cmpchain_finish
  • cmpchain_start
  • cntrl_to_mnemonic
  • construct_ahocorasick_from_trie
  • cop_file_avn
  • coresub_op

the croak_ girlies ๐Ÿ’€ the whole dramatic family

  • croak_caller
  • croak_kw_unless_class
  • croak_memory_wrap
  • croak_no_mem
  • croak_no_mem_ext
  • croak_popstack

signal handler trio, keeping it numbered ๐Ÿ“ž

  • csighandler
  • csighandler1
  • csighandler3

then more cv/cx business ๐Ÿ’œ

  • current_re_engine
  • custom_op_get_field
  • cv_clone_into
  • cv_const_sv_or_av
  • cv_undef_flags
  • cvgv_from_hek
  • cvgv_set
  • cvstash_set
  • cx_dump
  • cx_dup
  • cxinc

debug + despatch girlies ๐Ÿ”

  • deb_stack_all
  • debstackptrs
  • debug_hash_seed
  • debug_peep
  • debug_show_study_flags
  • debug_studydata
  • defelem_target
  • despatch_signals
  • die_unwind

THE do_ GIRLIES ๐Ÿ‘‘ okay this is the big one. huge main-character energy. every last one:

  • do_aexec
  • do_aexec5
  • do_aspawn
  • do_eof
  • do_exec
  • do_exec3
  • do_gv_dump
  • do_gvgv_dump
  • do_hv_dump
  • do_ipcctl
  • do_ipcget
  • do_magic_dump
  • do_msgrcv
  • do_msgsnd
  • do_ncmp
  • do_op_dump
  • do_pmop_dump
  • do_print
  • do_readline
  • do_seek
  • do_semop
  • do_shmio
  • do_spawn
  • do_spawn_nowait
  • do_sv_dump
  • do_sysseek
  • do_tell
  • do_trans
  • do_uniprop_match
  • do_vecget
  • do_vecset
  • do_vop

a lil more, then the dtrace girlies โœจ

  • does_utf8_overflow
  • dofile
  • doing_taint
  • doref
  • drand48_init_r
  • drand48_r
  • dtrace_probe_call
  • dtrace_probe_load
  • dtrace_probe_op
  • dtrace_probe_phase

the dump/dumpuntil girlies ๐ŸŒˆ

  • dump_all_perl
  • dump_indent
  • dump_packsubs_perl
  • dump_sub_perl
  • dump_sv_child
  • dump_vindent
  • dumpuntil
  • dup_warnings

the find_ girlies plus a fold of folds ๐Ÿฆ‹

  • find_first_differing_byte_pos
  • find_lexical_cv
  • find_runcv_where
  • find_script
  • finish_export_lexical
  • foldEQ_latin1
  • foldEQ_latin1_s2_folded
  • foldEQ_utf8_flags
  • force_locale_unlock
  • force_out_malformed_utf8_message_
  • form_alien_digit_msg
  • form_cp_too_large_msg
  • free_tied_hv_pool
  • free_tmps

the get_ girlies ๐Ÿ’– okay she's LONG. nineteen of them. we're listing every single one:

  • get_and_check_backslash_N_name
  • get_ANYOFHbbm_contents
  • get_ANYOFM_contents
  • get_db_sub
  • get_debug_opts
  • get_deprecated_property_msg
  • get_extended_os_errno
  • get_hash_seed
  • get_invlist_iter_addr
  • get_invlist_offset_addr
  • get_invlist_previous_index_addr
  • get_mstats
  • get_prop_definition
  • get_prop_values
  • get_re_gclass_aux_data
  • get_regclass_aux_data
  • get_regex_charset_name
  • get_win32_message_utf8ness
  • getenv_len

gp, grok, gv ๐Ÿ“

  • gp_free
  • gp_ref
  • grok_bin_oct_hex
  • grok_bslash_c
  • grok_bslash_o
  • grok_bslash_x
  • gv_check
  • gv_fetchmeth_internal
  • gv_override
  • gv_setref
  • gv_stashpvn_internal

he / hv girlies ๐Ÿ’…

  • he_dup
  • hek_dup
  • hfree_next_entry
  • hv_auxalloc
  • hv_common
  • hv_common_key_len
  • hv_delayfree_ent
  • hv_free_ent
  • hv_placeholders_p
  • hv_pushkv
  • hv_rand_set
  • hv_undef_flags

import, infix, and the init_ girlies ๐ŸŽ€

  • import_builtin_bundle
  • infix_plugin_standard
  • init_argv_symbols
  • init_constants
  • init_dbargs
  • init_debugger
  • init_i18nl10n
  • init_named_cv
  • init_stacks
  • init_tm
  • init_uniprops

the inversion/fold girlies ๐Ÿ”„

  • _inverse_folds
  • invert

THE invlist_ GIRLIES ๐Ÿ‘‘ okay she's a whole dynasty. and the _-prefixed ones count too, don't be classist:

  • invlist_array
  • _invlist_array_init
  • invlist_clear
  • invlist_clone
  • _invlist_contains_cp
  • invlist_contents
  • _invlist_dump
  • invlist_extend
  • invlist_highest
  • _invlist_intersection_maybe_complement_2nd
  • _invlist_intersection
  • _invlist_invert
  • invlist_is_iterating
  • invlist_iterfinish
  • invlist_iterinit
  • invlist_iternext
  • _invlist_len
  • invlist_max
  • invlist_previous_index
  • _invlist_search
  • invlist_set_len
  • invlist_set_previous_index
  • _invlist_subtract
  • invlist_trim
  • _invlist_union_maybe_complement_2nd
  • _invlist_union
  • _invlistEQ

then a few โœจ

  • invmap_dump
  • invoke_exception_hook
  • io_close

the is_ girlies ๐Ÿ’œ (yes, _is_uni_FOO and _is_utf8_FOO are literally spelled like that, placeholders and all, no we're not editing them)

  • is_grapheme
  • is_in_locale_category_
  • is_invlist
  • is_standard_filehandle_name
  • _is_uni_FOO
  • _is_uni_perl_idcont
  • _is_uni_perl_idstart
  • is_utf8_char_helper_
  • is_utf8_FF_helper_
  • _is_utf8_FOO
  • is_utf8_overlong
  • _is_utf8_perl_idcont
  • _is_utf8_perl_idstart
  • isFF_overlong

j through l ๐Ÿฆ‹

  • jmaybe
  • join_exact
  • keyword
  • keyword_plugin_standard
  • list
  • load_charnames
  • locale_panic
  • localize
  • lossless_NV_to_IV
  • lsbit_pos32
  • lsbit_pos64

THE magic_ GIRLIES ๐Ÿ”ฎ okay this is the mega-cluster. eighty-plus of them. deep breath. we're doing all of them, no cap. splitting by vibe so it's readable but every name stays exactly as-is ๐Ÿ’–

the clear girls:

  • magic_clear_all_env
  • magic_cleararylen_p
  • magic_clearenv
  • magic_clearhook
  • magic_clearhookall
  • magic_clearisa
  • magic_clearpack
  • magic_clearsig

the copy/exists girls:

  • magic_copycallchecker
  • magic_existspack

the free girls:

  • magic_freearylen_p
  • magic_freecollxfrm
  • magic_freemglob
  • magic_freeovrld
  • magic_freeutf8

the get girls:

  • magic_get
  • magic_getarylen
  • magic_getdebugvar
  • magic_getdefelem
  • magic_getnkeys
  • magic_getpack
  • magic_getpos
  • magic_getsig
  • magic_getsubstr
  • magic_gettaint
  • magic_getuvar
  • magic_getvec

the in-betweeners:

  • magic_killbackrefs
  • magic_nextpack
  • magic_regdata_cnt
  • magic_regdatum_get
  • magic_regdatum_set
  • magic_scalarpack

the set girls (she's the biggest, obviously):

  • magic_set
  • magic_set_all_env
  • magic_setarylen
  • magic_setcollxfrm
  • magic_setdbline
  • magic_setdebugvar
  • magic_setdefelem
  • magic_setenv
  • magic_sethook
  • magic_sethookall
  • magic_setisa
  • magic_setlvref
  • magic_setmglob
  • magic_setnkeys
  • magic_setnonelem
  • magic_setpack
  • magic_setpos
  • magic_setregexp
  • magic_setsig
  • magic_setsigall
  • magic_setsubstr
  • magic_settaint
  • magic_setutf8
  • magic_setuvar
  • magic_setvec

and the closers:

  • magic_sizepack
  • magic_wipepack

m through my ๐Ÿงš the whole stretch, in order:

  • make_trie
  • malloc_good_size
  • malloced_size
  • markstack_grow
  • mbtowc_
  • mem_collxfrm_
  • mem_log_alloc
  • mem_log_del_sv
  • mem_log_free
  • mem_log_new_sv
  • mem_log_realloc
  • mg_find_mglob
  • mg_size
  • mode_from_discipline
  • more_bodies
  • more_sv
  • moreswitches
  • mortal_getenv
  • mortalized_pv_copy
  • mro_get_private_data
  • mro_meta_dup
  • mro_meta_init
  • msbit_pos32
  • msbit_pos64
  • multiconcat_stringify
  • multideref_stringify
  • my_atof2
  • my_atof3
  • my_attrs
  • my_clearenv
  • my_lstat
  • my_lstat_flags
  • my_memrchr
  • my_mkostemp_cloexec
  • my_mkstemp_cloexec
  • my_stat
  • my_stat_flags
  • my_strerror
  • my_unexec

the new girlies โœจ (and yes newFORM, newPROG, newSTUB, newSVavdefelem, newMETHOP_internal and newXS_deffile are all cased exactly like that, don't @ me)

  • _new_invlist_C_array
  • _new_invlist
  • new_stackinfo
  • new_stackinfo_flags
  • new_sv
  • newFORM
  • newMETHOP_internal
  • newPROG
  • newSTUB
  • newSVavdefelem
  • newXS_deffile
  • nextargv
  • no_bareword_allowed
  • no_bareword_filehandle
  • noperl_die
  • notify_parser_that_encoding_changed

oops to opslab ๐Ÿ’…

  • oopsAV
  • oopsHV
  • op_clear
  • op_integerize
  • op_lvalue_flags
  • op_prune_chain_head
  • op_relocate_sv
  • op_std_init
  • op_varname
  • opmethod_stash
  • opslab_force_free
  • opslab_free
  • opslab_free_nopad
  • opslab_slot_offset

p girlies ๐ŸŽ€

  • package
  • package_version
  • pad_add_weakref
  • padlist_store
  • padname_free
  • PadnameIN_SCOPE
  • padnamelist_free
  • parse_unicode_opts
  • parser_dup
  • parser_free
  • parser_free_nexttoke_ops
  • path_is_searchable
  • peep
  • perl_alloc_using
  • perl_clone_using
  • PerlEnv_putenv
  • PerlIO_context_layers
  • PerlIO_restore_errno
  • PerlIO_save_errno
  • PerlLIO_dup_cloexec
  • PerlLIO_dup2_cloexec
  • PerlLIO_open_cloexec
  • PerlLIO_open3_cloexec
  • PerlProc_pipe_cloexec
  • PerlSock_accept_cloexec
  • PerlSock_socket_cloexec
  • PerlSock_socketpair_cloexec
  • perly_sighandler
  • pmruntime
  • POPMARK

populate + friends ๐ŸŒˆ

  • populate_anyof_bitmap_from_invlist
  • populate_bitmap_from_invlist
  • populate_invlist_from_bitmap
  • populate_isa
  • pregfree
  • pregfree2
  • prepare_export_lexical
  • ptr_hash

q through reentrant ๐Ÿ’œ (and yes, ReANY is capitalised like that, it's giving main character)

  • qerror
  • re_exec_indentf
  • re_indentf
  • re_intuit_start
  • re_intuit_string
  • re_op_compile
  • re_printf
  • ReANY
  • reentrant_free
  • reentrant_init
  • reentrant_retry
  • reentrant_size
  • ref

THE reg_/reg GIRLIES ๐Ÿ‘‘ okay last big cluster, and she is HUGE. every single one, spelled exactly, regcurly and regnext included (they have no underscore, they're just like that):

  • reg_add_data
  • reg_named_buff
  • reg_named_buff_all
  • reg_named_buff_exists
  • reg_named_buff_fetch
  • reg_named_buff_firstkey
  • reg_named_buff_iter
  • reg_named_buff_nextkey
  • reg_named_buff_scalar
  • reg_numbered_buff_fetch
  • reg_numbered_buff_fetch_flags
  • reg_numbered_buff_length
  • reg_numbered_buff_store
  • reg_qr_package
  • reg_skipcomment
  • reg_temp_copy
  • regcurly
  • regdump
  • regdupe_internal
  • regexec_flags
  • regfree_internal
  • reginitcolors
  • regnext

and that's where this part cuts off bestie ๐Ÿ˜ญ the list literally does not stop and we are NOT skipping any of them ๐Ÿ’… next part picks up right here, keep scrolling ๐Ÿซถ

...and the list just keeps going, bestie. Alphabetical order, no mercy, no vibes check. Here's the rest of the undocumented roster, exactly as the page spits it out:

regnode_after
regprop
release_RExC_state
report_evil_fh
report_redefined_cv
report_wrongway_fh
resume_compcv
rpeep
rsignal_restore
rsignal_save
rvpv_dup
rxres_save
same_dirent
save_bool
save_clearsv
save_delete
save_destructor
save_destructor_x
save_freeop
save_freepv
save_freesv
save_int
save_iv
save_I8
save_I16
save_I32
save_mortalizesv
save_pptr
save_pushi32ptr
save_pushptrptr
save_re_context
save_sptr
save_strlen
savestack_grow
savestack_grow_cnt
sawparens
scalar
scalarvoid
scan_commit
scan_num
seed
set_ANYOF_arg
set_caret_X
set_numeric_standard
set_numeric_underlying
set_padlist
setfd_cloexec
setfd_cloexec_for_nonsysfd
setfd_cloexec_or_inhexec_by_sysfdness
setfd_inhexec
setfd_inhexec_for_sysfd
_setup_canned_invlist
share_hek
should_warn_nl
should_we_output_Debug_r
sighandler
sighandler1
sighandler3
single_1bit_pos32
single_1bit_pos64
size_to_psize
Slab_Alloc
Slab_Free
Slab_to_ro
Slab_to_rw
softref2xv
sortsv_flags_impl
ssc_init
stack_grow
str_to_version
strxfrm
study_chunk
sub_crush_depth
subsignature_append_positional
subsignature_append_slurpy
subsignature_finish
subsignature_start
sv_add_backref
sv_buf_to_ro
sv_can_swipe_pv_buf
sv_del_backref
sv_i_ncmp
sv_i_ncmp_desc
sv_magicext_mglob
sv_mark_arenas
sv_ncmp
sv_ncmp_desc
sv_only_taint_gmagic
sv_or_pv_pos_u2b
sv_pvbyten_force_wrapper
sv_pvutf8n_force_wrapper
sv_resetpvn
sv_sethek
sv_sweep_arenas
sv_unglob
sv_2iv
sv_2uv
SvTRUE_common
switch_locale_context
sys_init
sys_init3
sys_intern_clear
sys_intern_dup
sys_intern_init
sys_term
tied_method
tmps_grow_p
_to_fold_latin1
to_uni_fold
_to_uni_fold_flags
to_uni_lower
to_uni_title
to_uni_upper
_to_upper_title_latin1
_to_utf8_fold_flags
_to_utf8_lower_flags
_to_utf8_title_flags
_to_utf8_upper_flags
TOPMARK
translate_substr_offsets
try_amagic_bin
try_amagic_un
unlnk
unshare_hek
unwind_paren
utf8_to_bytes_
utf8_to_uv_msgs_helper_
utf16_to_utf8
utf16_to_utf8_base
utf16_to_utf8_reversed
utilize
uvoffuni_to_utf8_flags_msgs
variant_byte_number
varname
vivify_defelem
vivify_ref
wait4pid
warn_elem_scalar_context
warn_problematic_locale
was_lvalue_sub
watch
win32_croak_not_implemented
write_to_stderr
xs_boot_epilog
XS_builtin_indexed
xs_handshake
yyerror
yyerror_pv
yyerror_pvn
yylex
yyparse
yyquit
yyunlex

That's the whole rest of the alphabet, undocumented and unbothered ๐Ÿ’…. If you're out here calling yylex in 2026, that's between you and the parser, bestie. No cap.


โœจ Next are the experimental undocumented elements โœจ

Okay so these ones are lowkey experimental on top of being undocumented, which is giving "we're cooking but don't touch the stove" energy ๐Ÿ”ฅ. Same rules apply: not documented, not promised, no take-backs.

alloc_LOGOP            get_vtbl
av_remove_offset       gimme_V
clear_defarray_simple  hv_backreferences_p
create_eval_scope      hv_kill_backrefs
cv_ckproto_len_flags   invlist_highest_range_start
cx_popblock            invlist_lowest
cx_popeval             new_warnings_bitfield
cx_popformat           newGP
cx_popgiven            op_refcnt_dec
cx_poploop             op_refcnt_inc
cx_popsub              op_unscope
cx_popsub_args         pop_stackinfo
cx_popsub_common       pp_wrap
cx_popwhen             push_stackinfo
cx_pushblock           rpp_free_2_
cx_pusheval            rpp_obliterate_stack_to
cx_pushformat          rpp_replace_2_1_COMMON
cx_pushgiven           runops_wrap
cx_pushloop_for        scan_str
cx_pushloop_plain      scan_word
cx_pushsub             skipspace_flags
cx_pushtry             sv_free2
cx_pushwhen            sv_kill_backrefs
cx_topblock            sv_setpv_freshbuf
delete_eval_scope      sv_setsv_cow
do_open_raw            switch_argstack
do_open6               utf8_to_utf16_base
emulate_cop_io         xs_wrap
get_re_arg

The cx_* family is literally doing the most in that list, and cx_topblock and cx_pushblock are just sitting there like ๐Ÿ‘‘. Experimental means experimental, though โ€” vibe check before you ship it.


๐Ÿšซ Finally are the deprecated undocumented elements ๐Ÿšซ

Do not use any for new code; remove all occurrences of all of these from existing code. Not "maybe." Not "if it's convenient." Remove. All. Of. Them. Periodt. ๐Ÿ˜ญ
get_no_modify  get_opargs  get_ppaddr  uvuni_to_utf8

That's four (4) whole functions living in the deprecated-undocumented shadow realm ๐Ÿ’€. If you see them in a codebase you inherited, that's a you-and-your-git-blame situation, and I'm so sorry bestie ๐Ÿซถ.


๐Ÿ’– AUTHORS ๐Ÿ’–

The autodocumentation system was originally added to the Perl core by Benjamin Stuhl. Documentation is by whoever was kind enough to document their functions.

Shoutout to every single one of those people, honestly ๐ŸŒธ. "Whoever was kind enough to document their functions" is such a real and humbling sentence โ€” the entire perlapi experience is held up by random heroes who decided to write it down. Iconic behavior, no notes ๐Ÿ‘‘.


๐ŸŒˆ SEE ALSO ๐ŸŒˆ

  • config.h
  • perlapi
  • perlapio
  • perlcall
  • perlclib
  • perlembed
  • perlfilter
  • perlguts
  • perlhacktips
  • perlinterp
  • perliol
  • perlmroapi
  • perlreapi
  • perlreguts
  • perlxs

That's the reading list, bestie โ€” perlguts is the main character of that group, perlxs is the one you actually need when things get real, and config.h is just there to humble you ๐Ÿฆ‹.


And that's a wrap on PERLINTERN(1) ๐ŸŽ€ โ€” this one ships from perl v5.42.3, dated 2026-08-03. Go forth, internals gremlin, and remember: the undocumented ones are undocumented for a reason, the deprecated ones are deprecated for your safety, and you ate this whole page. Slay ๐Ÿ’…โœจ

๐Ÿ“ฆ where this page comes from