Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is RMAGICAL?

Tags:

perl

xs

I'm trying to understand some XS code that I inherited. I've been trying to add comments to a section that invokes Perl magic stuff, but I can't find any documentation to help me understand this line:

SvRMAGICAL_off((SV *) myVar);

What is RMAGICAL for? When should one turn in on or off when working with Perl magic variables?

Update

Perlguts Illustrated is very interesting and has a little bit of info on RMAGICAL (the 'R' is for 'random'), but it doesn't say when to mess with it: http://cpansearch.perl.org/src/RURBAN/illguts-0.42/index.html

like image 863
Nate Glenn Avatar asked May 13 '13 17:05

Nate Glenn


People also ask

What do we mean by magic?

(mædʒɪk ) 1. uncountable noun. Magic is the power to use supernatural forces to make impossible things happen, such as making people disappear or controlling events in nature.

What is a magical person?

A magician, also known as an enchanter/enchantress, mage, magic-user, archmage, sorcerer/sorceress, spell-caster, warlock, witch, or wizard, is someone who uses or practices magic derived from supernatural, occult, or arcane sources.

What does magical world mean?

The Magical World is the half of the Earth which is occupied by magical beings, most prominently the fairies and the elves. Originally, the Magical World and the Human World were one and the same, but have since separated.


2 Answers

It's a flag that indicates whether a variable has "clear" magic, magic that should be called when the variable is cleared (e.g. when it's destroyed). It's used by mg_clear which is called when one attempts to do something like

undef %hash;
delete $a[4];
etc

It's derived information calculated by mg_magical that should never be touched. mg_magical will be called to update the flag when magic is added to or removed from a variable. If any of the magic attached to the scalar has a "clear" handler in its Magic Virtual Table, the scalar gets RMAGICAL set. Otherwise, it gets turned off. Effectively, this caches the information to save Perl from repeatedly checking all the magic attached to a scalar for this information.

One example use of clear magic: When a %SIG entry is cleared, the magic removes the signal handler for that signal.


Here's mg_magical:

void
Perl_mg_magical(pTHX_ SV *sv)
{
    const MAGIC* mg;
    PERL_ARGS_ASSERT_MG_MAGICAL;
    PERL_UNUSED_CONTEXT;

    SvMAGICAL_off(sv);
    if ((mg = SvMAGIC(sv))) {
        do {
            const MGVTBL* const vtbl = mg->mg_virtual;
            if (vtbl) {
                if (vtbl->svt_get && !(mg->mg_flags & MGf_GSKIP))
                    SvGMAGICAL_on(sv);
                if (vtbl->svt_set)
                    SvSMAGICAL_on(sv);
                if (vtbl->svt_clear)
                    SvRMAGICAL_on(sv);
            }
        } while ((mg = mg->mg_moremagic));
        if (!(SvFLAGS(sv) & (SVs_GMG|SVs_SMG)))
            SvRMAGICAL_on(sv);
    }
}
like image 162
ikegami Avatar answered Oct 04 '22 00:10

ikegami


The SVs_RMG flag (which is what SvRMAGICAL tests for and SvRMAGICAL_on/SvRMAGICAL_off sets/clears) means that the variable has some magic associated with it other than a magic getter method (which is indicated by the SVs_GMG flag) and magic setter method (indicated by SVs_SMG).

I'm getting out of my depth, here, but examples of variables where RMAGIC is on include most of the values in %ENV (the ones that are set when the program begins, but not ones you define at run-time), the values in %! and %SIG, and stash values for named subroutines (i.e., in the program

 package main;
 sub foo { 42 }

$::{"foo"} is RMAGICAL and $::{"bar"} is not). Using Devel::Peek is a little bit, but not totally enlightening about what this magic might be:

$ /usr/bin/perl -MDevel::Peek -e 'Dump $ENV{HOSTNAME}'
SV = PVMG(0x8003e910) at 0x800715f0
  REFCNT = 1
  FLAGS = (SMG,RMG,POK,pPOK)
  IV = 0
  NV = 0
  PV = 0x80072790 "localhost"\0
  CUR = 10
  LEN = 12
  MAGIC = 0x800727a0
    MG_VIRTUAL = &PL_vtbl_envelem
    MG_TYPE = PERL_MAGIC_envelem(e)
    MG_LEN = 8
    MG_PTR = 0x800727c0 "HOSTNAME"

Here we see that the scalar held in $ENV{HOSTNAME} has an MG_TYPE and MG_VIRTUAL that give you the what, but not the how and why of this variable's magic. On a "regular" magical variable, these are usually (always?) PERL_MAGIC_sv and &PL_vtbl_sv:

$ /usr/bin/perl -MDevel::Peek -e 'Dump $='
SV = PVMG(0x8008e080) at 0x80071de8
  REFCNT = 1
  FLAGS = (GMG,SMG)
  IV = 0
  NV = 0
  PV = 0
  MAGIC = 0x80085aa8
    MG_VIRTUAL = &PL_vtbl_sv
    MG_TYPE = PERL_MAGIC_sv(\0)
    MG_OBJ = 0x80071d58
    MG_LEN = 1
    MG_PTR = 0x80081ad0 "="

There is one place in the perl source where SvRMAGICAL_off is used -- in perlio.c, in the XS(XS_io_MODIFY_SCALAR_ATTRIBUTES).

XS(XS_io_MODIFY_SCALAR_ATTRIBUTES)
{
    dXSARGS;
    SV * const sv = SvRV(ST(1));
    AV * const av = newAV();
    MAGIC *mg;
    int count = 0;
    int i;
    sv_magic(sv, MUTABLE_SV(av), PERL_MAGIC_ext, NULL, 0);

    SvRMAGICAL_off(sv);

    mg = mg_find(sv, PERL_MAGIC_ext);
    mg->mg_virtual = &perlio_vtab;
    mg_magical(sv);
    Perl_warn(aTHX_ "attrib %" SVf, SVfARG(sv));
    for (i = 2; i < items; i++) {
    STRLEN len;
    const char * const name = SvPV_const(ST(i), len);
    SV * const layer = PerlIO_find_layer(aTHX_ name, len, 1);
    if (layer) {
        av_push(av, SvREFCNT_inc_simple_NN(layer));
    }
    else {
        ST(count) = ST(i);
        count++;
    }
    }
    SvREFCNT_dec(av);
    XSRETURN(count);
}

where for some reason (again, I'm out of my depth), they want that magic turned off during the mg_find call.

like image 35
mob Avatar answered Oct 04 '22 00:10

mob