summaryrefslogtreecommitdiffstats
path: root/Stash.xs
diff options
context:
space:
mode:
Diffstat (limited to 'Stash.xs')
-rw-r--r--Stash.xs73
1 files changed, 48 insertions, 25 deletions
diff --git a/Stash.xs b/Stash.xs
index 42b3ee5..ff8cf70 100644
--- a/Stash.xs
+++ b/Stash.xs
@@ -396,37 +396,30 @@ get_package_symbol(self, variable, ...)
HV *namespace;
SV **entry;
GV *glob;
+ int i, vivify = 0;
+ SV *val;
CODE:
- namespace = _get_namespace(self);
-
- if (!hv_exists(namespace, variable.name, strlen(variable.name))) {
- int i, vivify = 0;
- if ((items - 2) % 2)
- croak("get_package_symbol: Odd number of elements in %%opts");
-
- for (i = 2; i < items; i += 2) {
- char *key;
- key = SvPV_nolen(ST(i));
- if (strEQ(key, "vivify")) {
- vivify = SvTRUE(ST(i + 1));
- }
- }
+ if (items > 2 && (items - 2) % 2)
+ croak("get_package_symbol: Odd number of elements in %%opts");
- if (vivify) {
- /* XXX: vivify */
+ for (i = 2; i < items; i += 2) {
+ char *key;
+ key = SvPV_nolen(ST(i));
+ if (strEQ(key, "vivify")) {
+ vivify = SvTRUE(ST(i + 1));
}
}
- entry = hv_fetch(namespace, variable.name, strlen(variable.name), 0);
+ namespace = _get_namespace(self);
+ entry = hv_fetch(namespace, variable.name, strlen(variable.name), vivify);
if (!entry)
XSRETURN_UNDEF;
glob = (GV*)(*entry);
-
- if (!isGV(*entry)) {
+ if (!isGV(glob)) {
SV *namesv;
char *name;
- int len;
+ STRLEN len;
namesv = newSVsv(_get_name(self));
sv_catpvs(namesv, "::");
@@ -437,23 +430,53 @@ get_package_symbol(self, variable, ...)
gv_init(glob, namespace, name, len, 1);
}
+ if (vivify) {
+ switch (variable.type) {
+ case VAR_SCALAR:
+ if (!GvSV(glob))
+ GvSV(glob) = newSV(0);
+ break;
+ case VAR_ARRAY:
+ if (!GvAV(glob))
+ GvAV(glob) = newAV();
+ break;
+ case VAR_HASH:
+ if (!GvHV(glob))
+ GvHV(glob) = newHV();
+ break;
+ case VAR_CODE:
+ croak("Don't know how to vivify CODE variables");
+ case VAR_IO:
+ if (!GvIO(glob))
+ GvIOp(glob) = newIO();
+ break;
+ default:
+ croak("Unknown type in vivication");
+ }
+ }
+
switch (variable.type) {
case VAR_SCALAR:
- RETVAL = newRV(GvSV(glob));
+ val = GvSV(glob);
break;
case VAR_ARRAY:
- RETVAL = newRV((SV*)GvAV(glob));
+ val = (SV*)GvAV(glob);
break;
case VAR_HASH:
- RETVAL = newRV((SV*)GvHV(glob));
+ val = (SV*)GvHV(glob);
break;
case VAR_CODE:
- RETVAL = newRV((SV*)GvCV(glob));
+ val = (SV*)GvCV(glob);
break;
case VAR_IO:
- RETVAL = newRV((SV*)GvIO(glob));
+ val = (SV*)GvIO(glob);
break;
}
+
+ if (!val)
+ XSRETURN_UNDEF;
+
+ RETVAL = newRV(val);
OUTPUT:
RETVAL