summaryrefslogtreecommitdiffstats
path: root/Stash.xs
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2010-11-12 12:16:57 -0600
committerJesse Luehrs <doy@tozt.net>2010-11-12 12:16:57 -0600
commit76f7c3068e8bd63fcbac28758631fcda72596674 (patch)
tree8ce7295c60515515fb65ff4bb38e9a5833144e05 /Stash.xs
parent2033654760f55aa6b34262de791a32e98a33a046 (diff)
downloadpackage-stash-xs-76f7c3068e8bd63fcbac28758631fcda72596674.tar.gz
package-stash-xs-76f7c3068e8bd63fcbac28758631fcda72596674.zip
add_package_symbol (except the db bits, for now)
Diffstat (limited to 'Stash.xs')
-rw-r--r--Stash.xs154
1 files changed, 152 insertions, 2 deletions
diff --git a/Stash.xs b/Stash.xs
index 5631b9c..f63ab01 100644
--- a/Stash.xs
+++ b/Stash.xs
@@ -19,6 +19,42 @@ typedef struct {
char *name;
} varspec_t;
+const char *vartype_to_string(vartype_t type)
+{
+ switch (type) {
+ case VAR_SCALAR:
+ return "SCALAR";
+ case VAR_ARRAY:
+ return "ARRAY";
+ case VAR_HASH:
+ return "HASH";
+ case VAR_CODE:
+ return "CODE";
+ case VAR_IO:
+ return "IO";
+ default:
+ return "unknown";
+ }
+}
+
+I32 vartype_to_svtype(vartype_t type)
+{
+ switch (type) {
+ case VAR_SCALAR:
+ return SVt_PV; /* or whatever */
+ case VAR_ARRAY:
+ return SVt_PVAV;
+ case VAR_HASH:
+ return SVt_PVHV;
+ case VAR_CODE:
+ return SVt_PVCV;
+ case VAR_IO:
+ return SVt_PVIO;
+ default:
+ return SVt_NULL;
+ }
+}
+
vartype_t string_to_vartype(char *vartype)
{
if (strEQ(vartype, "SCALAR")) {
@@ -116,7 +152,7 @@ int _valid_for_type(SV *value, vartype_t type)
case VAR_CODE:
return sv_type == SVt_PVCV;
case VAR_IO:
- return sv_type == SVt_PVGV;
+ return sv_type == SVt_PVIO;
default:
return 0;
}
@@ -140,6 +176,24 @@ HV *_get_namespace(SV *self)
return (HV*)SvRV(ret);
}
+SV *_get_name(SV *self)
+{
+ dSP;
+ SV *ret;
+
+ PUSHMARK(SP);
+ XPUSHs(self);
+ PUTBACK;
+
+ call_method("name", G_SCALAR);
+
+ SPAGAIN;
+ ret = POPs;
+ PUTBACK;
+
+ return ret;
+}
+
MODULE = Package::Stash PACKAGE = Package::Stash
PROTOTYPES: DISABLE
@@ -192,6 +246,102 @@ namespace(self)
RETVAL
void
+add_package_symbol(self, variable, initial=NULL, ...)
+ SV *self
+ varspec_t variable
+ SV *initial
+ PREINIT:
+ SV *name;
+ GV *glob;
+ CODE:
+ if (initial && !_valid_for_type(initial, variable.type))
+ croak("%s is not of type %s",
+ SvPV_nolen(initial), vartype_to_string(variable.type));
+
+ name = newSVsv(_get_name(self));
+ sv_catpvs(name, "::");
+ sv_catpv(name, variable.name);
+
+ /* XXX: come back to this when i feel like reimplementing caller() */
+/*
+ my $filename = $opts{filename};
+ my $first_line_num = $opts{first_line_num};
+
+ (undef, $filename, $first_line_num) = caller
+ if not defined $filename;
+
+ my $last_line_num = $opts{last_line_num} || ($first_line_num ||= 0);
+
+ # http://perldoc.perl.org/perldebguts.html#Debugger-Internals
+ $DB::sub{$pkg . '::' . $name} = "$filename:$first_line_num-$last_line_num";
+*/
+/*
+ if (items > 2 && (PL_perldb & 0x10) && variable.type == VAR_CODE) {
+ int i;
+ char *filename = NULL, *name;
+ I32 first_line_num, last_line_num;
+
+ if ((items - 3) % 2)
+ croak("add_package_symbol: Odd number of elements in %%opts");
+
+ for (i = 3; i < items; i += 2) {
+ char *key;
+ key = SvPV_nolen(ST(i));
+ if (strEQ(key, "filename")) {
+ if (!SvPOK(ST(i + 1)))
+ croak("add_package_symbol: filename must be a string");
+ filename = SvPV_nolen(ST(i + 1));
+ }
+ else if (strEQ(key, "first_line_num")) {
+ if (!SvIOK(ST(i + 1)))
+ croak("add_package_symbol: first_line_num must be an integer");
+ first_line_num = SvIV(ST(i + 1));
+ }
+ else if (strEQ(key, "last_line_num")) {
+ if (!SvIOK(ST(i + 1)))
+ croak("add_package_symbol: last_line_num must be an integer");
+ last_line_num = SvIV(ST(i + 1));
+ }
+ }
+
+ if (!filename) {
+ }
+ }
+*/
+
+ glob = gv_fetchsv(name, GV_ADD, vartype_to_svtype(variable.type));
+
+ if (initial) {
+ SV *val;
+
+ if (SvROK(initial)) {
+ val = SvRV(initial);
+ SvREFCNT_inc(val);
+ }
+ else {
+ val = newSVsv(initial);
+ }
+
+ switch (variable.type) {
+ case VAR_SCALAR:
+ GvSV(glob) = val;
+ break;
+ case VAR_ARRAY:
+ GvAV(glob) = (AV*)val;
+ break;
+ case VAR_HASH:
+ GvHV(glob) = (HV*)val;
+ break;
+ case VAR_CODE:
+ GvCV(glob) = (CV*)val;
+ break;
+ case VAR_IO:
+ GvIOp(glob) = (IO*)val;
+ break;
+ }
+ }
+
+void
remove_package_glob(self, name)
SV *self
char *name
@@ -266,7 +416,7 @@ remove_package_symbol(self, variable)
GvCV(glob) = Nullcv;
break;
case VAR_IO:
- GvIOp(glob) = Null(struct io*);
+ GvIOp(glob) = Null(IO*);
break;
}
}