typedef struct {
vartype_t type;
- char *name;
- I32 namelen;
+ SV *name;
} varspec_t;
static U32 name_hash, namespace_hash, type_hash;
}
}
-void _deconstruct_variable_name(SV *varsv, varspec_t *varspec)
+void _deconstruct_variable_name(SV *variable, varspec_t *varspec)
{
- char *variable;
- STRLEN len;
+ char *varpv;
- variable = SvPV(varsv, len);
- if (!variable[0])
+ if (!SvCUR(variable))
croak("You must pass a variable name");
- switch (variable[0]) {
+ varspec->name = sv_2mortal(newSVsv(variable));
+
+ varpv = SvPV_nolen(varspec->name);
+ switch (varpv[0]) {
case '$':
varspec->type = VAR_SCALAR;
- varspec->name = &variable[1];
- varspec->namelen = len - 1;
+ sv_chop(varspec->name, &varpv[1]);
break;
case '@':
varspec->type = VAR_ARRAY;
- varspec->name = &variable[1];
- varspec->namelen = len - 1;
+ sv_chop(varspec->name, &varpv[1]);
break;
case '%':
varspec->type = VAR_HASH;
- varspec->name = &variable[1];
- varspec->namelen = len - 1;
+ sv_chop(varspec->name, &varpv[1]);
break;
case '&':
varspec->type = VAR_CODE;
- varspec->name = &variable[1];
- varspec->namelen = len - 1;
+ sv_chop(varspec->name, &varpv[1]);
break;
default:
varspec->type = VAR_IO;
- varspec->name = variable;
- varspec->namelen = len;
break;
}
}
void _deconstruct_variable_hash(HV *variable, varspec_t *varspec)
{
HE *val;
- char *valpv;
STRLEN len;
val = hv_fetch_ent(variable, name_key, 0, name_hash);
if (!val)
croak("The 'name' key is required in variable specs");
- valpv = HePV(val, len);
- varspec->name = savepvn(valpv, len);
- SAVEFREEPV(varspec->name);
- varspec->namelen = len;
+ varspec->name = sv_2mortal(newSVhe(val));
val = hv_fetch_ent(variable, type_key, 0, type_hash);
if (!val)
croak("The 'type' key is required in variable specs");
- valpv = HePV(val, len);
- varspec->type = string_to_vartype(valpv);
+ varspec->type = string_to_vartype(HePV(val, len));
}
int _valid_for_type(SV *value, vartype_t type)
return ret;
}
-void _expand_glob(SV *self, char *name)
+void _expand_glob(SV *self, SV *varname)
{
- SV *namesv;
+ SV *name;
- namesv = newSVsv(_get_name(self));
- sv_catpvs(namesv, "::");
- sv_catpv(namesv, name);
+ name = newSVsv(_get_name(self));
+ sv_catpvs(name, "::");
+ sv_catsv(name, varname);
/* can't use gv_init here, because it screws up @ISA in a way that I
* can't reproduce, but that CMOP triggers */
- gv_fetchsv(namesv, GV_ADD, SVt_NULL);
- SvREFCNT_dec(namesv);
+ gv_fetchsv(name, GV_ADD, SVt_NULL);
+ SvREFCNT_dec(name);
}
SV *_get_symbol(SV *self, varspec_t *variable, int vivify)
{
HV *namespace;
- SV **entry;
+ HE *entry;
GV *glob;
namespace = _get_namespace(self);
- entry = hv_fetch(namespace, variable->name, variable->namelen, vivify);
+ entry = hv_fetch_ent(namespace, variable->name, vivify, 0);
if (!entry)
return NULL;
- glob = (GV*)(*entry);
+ glob = (GV*)(HeVAL(entry));
if (!isGV(glob))
_expand_glob(self, variable->name);
SV*
new(class, package_name)
- char *class
+ SV *class
SV *package_name
PREINIT:
HV *instance;
croak("Couldn't initialize the 'namespace' key, hv_store failed");
}
- RETVAL = sv_bless(newRV_noinc((SV*)instance), gv_stashpv(class, 0));
+ RETVAL = sv_bless(newRV_noinc((SV*)instance), gv_stashsv(class, 0));
OUTPUT:
RETVAL
name = newSVsv(_get_name(self));
sv_catpvs(name, "::");
- sv_catpv(name, variable.name);
+ sv_catsv(name, variable.name);
if (items > 2 && (PL_perldb & 0x10) && variable.type == VAR_CODE) {
int i;
- char *filename = NULL, *namepv;
+ char *filename = NULL;
I32 first_line_num = -1, last_line_num = -1;
STRLEN namelen;
SV *dbval;
/* http://perldoc.perl.org/perldebguts.html#Debugger-Internals */
dbsub = get_hv("DB::sub", 1);
dbval = newSVpvf("%s:%d-%d", filename, first_line_num, last_line_num);
- namepv = SvPV(name, namelen);
- if (!hv_store(dbsub, namepv, namelen, dbval, 0)) {
- warn("Failed to update $DB::sub for subroutine %s", namepv);
+ if (!hv_store_ent(dbsub, name, dbval, 0)) {
+ warn("Failed to update $DB::sub for subroutine %s",
+ SvPV_nolen(name));
SvREFCNT_dec(dbval);
}
}
SvREFCNT_dec(name);
void
-remove_glob(self, namesv)
+remove_glob(self, name)
SV *self
- SV *namesv
- PREINIT:
- char *name;
- STRLEN len;
+ SV *name
CODE:
- name = SvPV(namesv, len);
- hv_delete(_get_namespace(self), name, len, G_DISCARD);
+ hv_delete_ent(_get_namespace(self), name, G_DISCARD, 0);
int
has_symbol(self, variable)
varspec_t variable
PREINIT:
HV *namespace;
- SV **entry;
+ HE *entry;
+ SV *val;
CODE:
namespace = _get_namespace(self);
- entry = hv_fetch(namespace, variable.name, variable.namelen, 0);
+ entry = hv_fetch_ent(namespace, variable.name, 0, 0);
if (!entry)
XSRETURN_UNDEF;
- if (isGV(*entry)) {
- GV *glob = (GV*)(*entry);
+ val = HeVAL(entry);
+ if (isGV(val)) {
+ GV *glob = (GV*)val;
switch (variable.type) {
case VAR_SCALAR:
RETVAL = GvSVOK(glob) ? 1 : 0;
varspec_t variable
PREINIT:
HV *namespace;
- SV **entry;
+ HE *entry;
+ SV *val;
CODE:
namespace = _get_namespace(self);
- entry = hv_fetch(namespace, variable.name, variable.namelen, 0);
+ entry = hv_fetch_ent(namespace, variable.name, 0, 0);
if (!entry)
XSRETURN_EMPTY;
- if (isGV(*entry)) {
- GV *glob = (GV*)(*entry);
+ val = HeVAL(entry);
+ if (isGV(val)) {
+ GV *glob = (GV*)val;
switch (variable.type) {
case VAR_SCALAR:
GvSetSV(glob, NULL);
}
else {
if (variable.type == VAR_CODE) {
- hv_delete(namespace, variable.name, variable.namelen, G_DISCARD);
+ hv_delete_ent(namespace, variable.name, G_DISCARD, 0);
}
}
while ((val = hv_iternextsv(namespace, &key, &len))) {
GV *gv = (GV*)val;
- if (!isGV(gv))
- _expand_glob(self, key);
+ if (!isGV(gv)) {
+ SV *keysv = newSVpvn(key, len);
+ _expand_glob(self, keysv);
+ SvREFCNT_dec(keysv);
+ }
switch (vartype) {
case VAR_SCALAR: