File Coverage

XS.xs
Criterion Covered Total %
statement 308 384 80.2
branch 178 328 54.2
condition n/a
subroutine n/a
pod n/a
total 486 712 68.2


line stmt bran cond sub pod time code
1             #include "EXTERN.h"
2             #include "perl.h"
3             #include "XSUB.h"
4              
5             #include "ppport.h"
6              
7             #ifndef gv_fetchsv
8             #define gv_fetchsv(n,f,t) gv_fetchpv(SvPV_nolen(n), f, t)
9             #endif
10              
11             #ifndef mro_method_changed_in
12             #define mro_method_changed_in(x) PL_sub_generation++
13             #endif
14              
15             #ifndef HvENAME
16             #define HvENAME HvNAME
17             #endif
18              
19             #ifndef hv_name_set
20             #define hv_name_set(stash, name, namelen, flags) \
21             (HvNAME(stash) = savepvn(name, namelen))
22             #endif
23              
24             #ifdef newSVhek
25             #define newSVhe(he) newSVhek(HeKEY_hek(he))
26             #else
27             #define newSVhe(he) newSVpv(HePV(he, PL_na), 0)
28             #endif
29              
30             #ifndef GvCV_set
31             #define GvCV_set(gv, cv) (GvCV(gv) = (CV*)(cv))
32             #endif
33              
34             #ifndef MUTABLE_PTR
35             #define MUTABLE_PTR(p) ((void *) (p))
36             #endif
37              
38             #ifndef MUTABLE_SV
39             #define MUTABLE_SV(p) ((SV *)MUTABLE_PTR(p))
40             #endif
41              
42             #ifndef SVT_SCALAR
43             #define SVT_SCALAR(svt) (svt <= SVt_PVLV)
44             #endif
45              
46             #ifndef SVT_ARRAY
47             #define SVT_ARRAY(svt) (svt == SVt_PVAV)
48             #endif
49              
50             #ifndef SVT_HASH
51             #define SVT_HASH(svt) (svt == SVt_PVHV)
52             #endif
53              
54             #ifndef SVT_CODE
55             #define SVT_CODE(svt) (svt == SVt_PVCV)
56             #endif
57              
58             #ifndef SVT_IO
59             #define SVT_IO(svt) (svt == SVt_PVIO)
60             #endif
61              
62             #ifndef SVT_FORMAT
63             #define SVT_FORMAT(svt) (svt == SVt_PVFM)
64             #endif
65              
66             /* HACK: scalar slots are always populated on perl < 5.10, so treat undef
67             * as nonexistent. this is consistent with the previous behavior of the pure
68             * perl version of this module (since this is the behavior that perl sees
69             * in all versions */
70             #if PERL_VERSION < 10
71             #define GvSVOK(g) (GvSV(g) && SvTYPE(GvSV(g)) != SVt_NULL)
72             #else
73             #define GvSVOK(g) GvSV(g)
74             #endif
75              
76             #define GvAVOK(g) GvAV(g)
77             #define GvHVOK(g) GvHV(g)
78             #define GvCVOK(g) GvCVu(g) /* XXX: should this really be GvCVu? or GvCV? */
79             #define GvIOOK(g) GvIO(g)
80              
81             /* see above - don't let scalar slots become unpopulated, this breaks
82             * assumptions in core */
83             #if PERL_VERSION < 10
84             #define GvSetSV(g,v) do { \
85             SV *_v = (SV*)(v); \
86             SvREFCNT_dec(GvSV(g)); \
87             if ((GvSV(g) = _v ? _v : newSV(0))) \
88             GvIMPORTED_SV_on(g); \
89             } while (0)
90             #else
91             #define GvSetSV(g,v) do { \
92             SvREFCNT_dec(GvSV(g)); \
93             if ((GvSV(g) = (SV*)(v))) \
94             GvIMPORTED_SV_on(g); \
95             } while (0)
96             #endif
97              
98             #define GvSetAV(g,v) do { \
99             SvREFCNT_dec(GvAV(g)); \
100             if ((GvAV(g) = (AV*)(v))) \
101             GvIMPORTED_AV_on(g); \
102             } while (0)
103             #define GvSetHV(g,v) do { \
104             SvREFCNT_dec(GvHV(g)); \
105             if ((GvHV(g) = (HV*)(v))) \
106             GvIMPORTED_HV_on(g); \
107             } while (0)
108             #define GvSetCV(g,v) do { \
109             SvREFCNT_dec(GvCV(g)); \
110             if ((GvCV_set(g, (CV*)(v)))) { \
111             GvIMPORTED_CV_on(g); \
112             GvASSUMECV_on(g); \
113             } \
114             GvCVGEN(g) = 0; \
115             mro_method_changed_in(GvSTASH(g)); \
116             } while (0)
117             #define GvSetIO(g,v) do { \
118             SvREFCNT_dec(GvIO(g)); \
119             GvIOp(g) = (IO*)(v); \
120             } while (0)
121              
122             typedef enum {
123             VAR_NONE = 0,
124             VAR_SCALAR,
125             VAR_ARRAY,
126             VAR_HASH,
127             VAR_CODE,
128             VAR_IO,
129             VAR_GLOB, /* TODO: unimplemented */
130             VAR_FORMAT /* TODO: unimplemented */
131             } vartype_t;
132              
133             typedef struct {
134             vartype_t type;
135             SV *name;
136             } varspec_t;
137              
138             static U32 name_hash, namespace_hash, type_hash;
139             static SV *name_key, *namespace_key, *type_key;
140             static REGEXP *valid_module_regex;
141              
142 5           static const char *vartype_to_string(vartype_t type)
143             {
144 5           switch (type) {
145             case VAR_SCALAR:
146 3           return "SCALAR";
147             case VAR_ARRAY:
148 1           return "ARRAY";
149             case VAR_HASH:
150 0           return "HASH";
151             case VAR_CODE:
152 0           return "CODE";
153             case VAR_IO:
154 1           return "IO";
155             default:
156 0           return "unknown";
157             }
158             }
159              
160 26           static vartype_t string_to_vartype(char *vartype)
161             {
162 26 100         if (strEQ(vartype, "SCALAR")) {
163 2           return VAR_SCALAR;
164             }
165 24 100         else if (strEQ(vartype, "ARRAY")) {
166 1           return VAR_ARRAY;
167             }
168 23 100         else if (strEQ(vartype, "HASH")) {
169 3           return VAR_HASH;
170             }
171 20 50         else if (strEQ(vartype, "CODE")) {
172 20           return VAR_CODE;
173             }
174 0 0         else if (strEQ(vartype, "IO")) {
175 0           return VAR_IO;
176             }
177             else {
178 0           croak("Type must be one of 'SCALAR', 'ARRAY', 'HASH', 'CODE', or 'IO', not '%s'", vartype);
179             }
180             }
181              
182 78           static int _is_valid_module_name(SV *package)
183             {
184             char *buf;
185             STRLEN len;
186             SV *sv;
187              
188 78 50         buf = SvPV(package, len);
189              
190             /* whee cargo cult */
191 78           sv = sv_newmortal();
192 78           sv_upgrade(sv, SVt_PV);
193 78           SvREADONLY_on(sv);
194 78           SvLEN(sv) = 0;
195 78           SvUTF8_on(sv);
196 78           SvPVX(sv) = buf;
197 78           SvCUR_set(sv, len);
198 78           SvPOK_on(sv);
199              
200 78           return pregexec(valid_module_regex, buf, buf + len, buf, 1, sv, 1);
201             }
202              
203 566           static void _deconstruct_variable_name(SV *variable, varspec_t *varspec)
204             {
205             char *varpv;
206              
207 566 50         if (!SvCUR(variable))
208 0           croak("You must pass a variable name");
209              
210 566           varspec->name = sv_2mortal(newSVsv(variable));
211              
212 566 50         varpv = SvPV_nolen(varspec->name);
213 566           switch (varpv[0]) {
214             case '$':
215 48           varspec->type = VAR_SCALAR;
216 48           sv_chop(varspec->name, &varpv[1]);
217 48           break;
218             case '@':
219 39           varspec->type = VAR_ARRAY;
220 39           sv_chop(varspec->name, &varpv[1]);
221 39           break;
222             case '%':
223 35           varspec->type = VAR_HASH;
224 35           sv_chop(varspec->name, &varpv[1]);
225 35           break;
226             case '&':
227 424           varspec->type = VAR_CODE;
228 424           sv_chop(varspec->name, &varpv[1]);
229 424           break;
230             default:
231 20           varspec->type = VAR_IO;
232 20           break;
233             }
234 566           }
235              
236 0           static void _deconstruct_variable_hash(HV *variable, varspec_t *varspec)
237             {
238             HE *val;
239              
240 0           val = hv_fetch_ent(variable, name_key, 0, name_hash);
241 0 0         if (!val)
242 0           croak("The 'name' key is required in variable specs");
243              
244 0           varspec->name = sv_2mortal(newSVsv(HeVAL(val)));
245              
246 0           val = hv_fetch_ent(variable, type_key, 0, type_hash);
247 0 0         if (!val)
248 0           croak("The 'type' key is required in variable specs");
249              
250 0 0         varspec->type = string_to_vartype(SvPV_nolen(HeVAL(val)));
251 0           }
252              
253 566           static void _check_varspec_is_valid(varspec_t *varspec)
254             {
255 566 50         if (strstr(SvPV_nolen(varspec->name), "::")) {
    100          
256 3           croak("Variable names may not contain ::");
257             }
258 563           }
259              
260 227           static int _valid_for_type(SV *value, vartype_t type)
261             {
262 227 100         svtype sv_type = SvROK(value) ? SvTYPE(SvRV(value)) : SVt_NULL;
263              
264 227           switch (type) {
265             case VAR_SCALAR:
266             /* XXX is a glob a scalar? assigning a glob to the scalar slot seems
267             * to work here, but in pure perl i'm pretty sure it goes to the EGV
268             * slot, which seems more correct to me. just disable it for now
269             * i guess */
270 15 100         return SVT_SCALAR(sv_type) && sv_type != SVt_PVGV;
    100          
271             case VAR_ARRAY:
272 4           return SVT_ARRAY(sv_type);
273             case VAR_HASH:
274 6           return SVT_HASH(sv_type);
275             case VAR_CODE:
276 200           return SVT_CODE(sv_type);
277             case VAR_IO:
278 2           return SVT_IO(sv_type);
279             default:
280 0           return 0;
281             }
282             }
283              
284 587           static HV *_get_namespace(SV *self)
285             {
286 587           dSP;
287             SV *ret;
288              
289 587 50         PUSHMARK(SP);
290 587 50         XPUSHs(self);
291 587           PUTBACK;
292              
293 587           call_method("namespace", G_SCALAR);
294              
295 587           SPAGAIN;
296 587           ret = POPs;
297 587           PUTBACK;
298              
299 587           return (HV*)SvRV(ret);
300             }
301              
302 85           static SV *_get_name(SV *self)
303             {
304 85           dSP;
305             SV *ret;
306              
307 85 50         PUSHMARK(SP);
308 85 50         XPUSHs(self);
309 85           PUTBACK;
310              
311 85           call_method("name", G_SCALAR);
312              
313 85           SPAGAIN;
314 85           ret = POPs;
315 85           PUTBACK;
316              
317 85           return ret;
318             }
319              
320 226           static void _real_gv_init(GV *gv, HV *stash, SV *name)
321             {
322             char *name_pv;
323             STRLEN name_len;
324              
325 226 50         name_pv = SvPV(name, name_len);
326 226 100         if (!HvENAME(stash)) {
    50          
    50          
    50          
    50          
    50          
    50          
327 1           hv_name_set(stash, "__ANON__", 8, 0);
328             }
329 226           gv_init(gv, stash, name_pv, name_len, 1);
330              
331             /* XXX: copied and pasted from gv_fetchpvn_flags and such */
332             /* ignoring the stuff for CORE:: and main:: for now, and also
333             * ignoring the GvMULTI_on bits, since we pass 1 to gv_init above */
334 226           switch (name_pv[0]) {
335             case 'I':
336 3 50         if (strEQ(&name_pv[1], "SA")) {
337             AV *av;
338              
339 3 50         av = GvAVn(gv);
340 3           sv_magic(MUTABLE_SV(av), MUTABLE_SV(gv), PERL_MAGIC_isa,
341             NULL, 0);
342             }
343 3           break;
344             case 'O':
345 0 0         if (strEQ(&name_pv[1], "VERLOAD")) {
346             HV *hv;
347              
348 0 0         hv = GvHVn(gv);
349 0           hv_magic(hv, NULL, PERL_MAGIC_overload);
350             }
351 0           break;
352             default:
353 223           break;
354             }
355 226           }
356              
357 10           static void _expand_glob(SV *self, SV *varname, HE *entry, HV *namespace,
358             int lval)
359             {
360             GV *glob;
361              
362 10 50         if (entry) {
363 10           glob = (GV*)HeVAL(entry);
364 10 50         if (isGV(glob)) {
365 0           croak("_expand_glob called on stash slot with expanded glob: %"SVf,
366             varname);
367             }
368             else {
369 10           SvREFCNT_inc(glob);
370 10           _real_gv_init(glob, namespace, varname);
371 10 50         if (HeVAL(entry)) {
372 10           SvREFCNT_dec(HeVAL(entry));
373             }
374 10           HeVAL(entry) = (SV*)glob;
375             }
376             }
377             else {
378 0           croak("_expand_glob called on nonexistent stash slot");
379             }
380 10           }
381              
382 5           static SV *_undef_for_type(vartype_t type)
383             {
384 5           switch (type) {
385             case VAR_SCALAR:
386 2           return newSV(0);
387             break;
388             case VAR_ARRAY:
389 1           return (SV*)newAV();
390             break;
391             case VAR_HASH:
392 1           return (SV*)newHV();
393             break;
394             case VAR_CODE:
395 0           croak("Don't know how to vivify CODE variables");
396             case VAR_IO:
397 1           return (SV*)newIO();
398             break;
399             default:
400 0           croak("Unknown type in vivification");
401             }
402             }
403              
404 227           static void _add_symbol_entry(SV *self, varspec_t variable, SV *initial,
405             HE *entry, HV *namespace)
406             {
407             GV *glob;
408             SV *val;
409              
410 227 50         if (entry && isGV(HeVAL(entry))) {
    100          
411 11           glob = (GV*)HeVAL(entry);
412             }
413 216 50         else if (entry) {
414 216           glob = (GV*)newSV(0);
415 216           _real_gv_init(glob, namespace, variable.name);
416 216 50         if (HeVAL(entry)) {
417 216           SvREFCNT_dec(HeVAL(entry));
418             }
419 216           HeVAL(entry) = (SV*)glob;
420             }
421             else {
422 0           croak("invalid entry passed to _add_symbol_entry");
423             }
424              
425 227 100         if (!initial) {
426 5           val = _undef_for_type(variable.type);
427             }
428 222 100         else if (SvROK(initial)) {
429 218           val = SvRV(initial);
430 218           SvREFCNT_inc_simple_void_NN(val);
431             }
432             else {
433 4           val = newSVsv(initial);
434             }
435              
436 227           switch (variable.type) {
437             case VAR_SCALAR:
438 14 50         GvSetSV(glob, val);
439 14           break;
440             case VAR_ARRAY:
441 4 50         GvSetAV(glob, val);
442 4           break;
443             case VAR_HASH:
444 7 50         GvSetHV(glob, val);
445 7           break;
446             case VAR_CODE:
447 200 50         GvSetCV(glob, val);
448 200           break;
449             case VAR_IO:
450 2 50         GvSetIO(glob, val);
    50          
    0          
    50          
451 2           break;
452             default:
453 0           croak("Unknown variable type in add_symbol");
454             break;
455             }
456 227           }
457              
458 223           static void _add_symbol(SV *self, varspec_t variable, SV *initial)
459             {
460             HV *namespace;
461             HE *entry;
462              
463 223           namespace = _get_namespace(self);
464 223           entry = hv_fetch_ent(namespace, variable.name, 1, 0);
465              
466 223           _add_symbol_entry(self, variable, initial, entry, namespace);
467 223           }
468              
469 16           static int _slot_exists(GV *glob, vartype_t type)
470             {
471 16           switch (type) {
472             case VAR_SCALAR:
473 4           return GvSVOK(glob) ? 1 : 0;
474             break;
475             case VAR_ARRAY:
476 9           return GvAVOK(glob) ? 1 : 0;
477             break;
478             case VAR_HASH:
479 2           return GvHVOK(glob) ? 1 : 0;
480             break;
481             case VAR_CODE:
482 0           croak("Don't know how to vivify CODE variables");
483             case VAR_IO:
484 1 50         return GvIOOK(glob) ? 1 : 0;
    50          
    0          
    50          
    50          
485             break;
486             default:
487 0           croak("Unknown type in vivification");
488             }
489              
490             return 0;
491             }
492              
493 276           static SV *_get_symbol(SV *self, varspec_t *variable, int vivify)
494             {
495             HV *namespace;
496             HE *entry;
497             GV *glob;
498              
499 276           namespace = _get_namespace(self);
500 276 100         entry = hv_fetch_ent(namespace, variable->name,
    100          
501             vivify && !hv_exists_ent(namespace, variable->name, 0),
502             0);
503 276 100         if (!entry)
504 7           return NULL;
505              
506 269           glob = (GV*)(HeVAL(entry));
507 269 100         if (!isGV(glob))
508 10           _expand_glob(self, variable->name, entry, namespace, vivify);
509              
510 269 100         if (vivify && !_slot_exists(glob, variable->type)) {
    100          
511 4           _add_symbol_entry(self, *variable, NULL, entry, namespace);
512             }
513              
514 269           switch (variable->type) {
515             case VAR_SCALAR:
516 16           return GvSV(glob);
517             case VAR_ARRAY:
518 20           return (SV*)GvAV(glob);
519             case VAR_HASH:
520 16           return (SV*)GvHV(glob);
521             case VAR_CODE:
522 206           return (SV*)GvCV(glob);
523             case VAR_IO:
524 11 50         return (SV*)GvIO(glob);
    50          
    0          
    50          
525             default:
526 0           return NULL;
527             }
528             }
529              
530             MODULE = Package::Stash::XS PACKAGE = Package::Stash::XS
531              
532             PROTOTYPES: DISABLE
533              
534             SV*
535             new(class, package)
536             SV *class
537             SV *package
538             PREINIT:
539             HV *instance;
540             CODE:
541 81 100         if (SvPOK(package)) {
542 78 100         if (!_is_valid_module_name(package))
543 5 50         croak("%s is not a module name", SvPV_nolen(package));
544              
545 73           instance = newHV();
546              
547 73 50         if (!hv_store(instance, "name", 4, SvREFCNT_inc_simple_NN(package), 0)) {
548 0           SvREFCNT_dec(package);
549 0           SvREFCNT_dec(instance);
550 0           croak("Couldn't initialize the 'name' key, hv_store failed");
551             }
552             }
553 3 100         else if (SvROK(package) && SvTYPE(SvRV(package)) == SVt_PVHV) {
    100          
554             #if PERL_VERSION < 10
555             croak("The XS implementation of Package::Stash does not support "
556             "anonymous stashes before perl 5.10");
557             #else
558 1           instance = newHV();
559              
560 1 50         if (!hv_store(instance, "namespace", 9, SvREFCNT_inc_simple_NN(package), 0)) {
561 0           SvREFCNT_dec(package);
562 0           SvREFCNT_dec(instance);
563 0           croak("Couldn't initialize the 'namespace' key, hv_store failed");
564             }
565             #endif
566             }
567             else {
568 2           croak("Package::Stash->new must be passed the name of the package to access");
569             }
570              
571 74           RETVAL = sv_bless(newRV_noinc((SV*)instance), gv_stashsv(class, 0));
572             OUTPUT:
573             RETVAL
574              
575             SV*
576             name(self)
577             SV *self
578             PREINIT:
579             HE *slot;
580             CODE:
581 86 100         if (!sv_isobject(self))
582 1           croak("Can't call name as a class method");
583 85 50         if ((slot = hv_fetch_ent((HV*)SvRV(self), name_key, 0, name_hash))) {
584 85           RETVAL = SvREFCNT_inc_simple_NN(HeVAL(slot));
585             }
586             else {
587 0           croak("Can't get the name of an anonymous package");
588             }
589             OUTPUT:
590             RETVAL
591              
592             SV*
593             namespace(self)
594             SV *self
595             PREINIT:
596             HE *slot;
597             SV *package_name;
598             CODE:
599 584 50         if (!sv_isobject(self))
600 0           croak("Can't call namespace as a class method");
601             #if PERL_VERSION < 10
602             package_name = _get_name(self);
603             RETVAL = newRV_inc((SV*)gv_stashpv(SvPV_nolen(package_name), GV_ADD));
604             #else
605 584           slot = hv_fetch_ent((HV*)SvRV(self), namespace_key, 0, namespace_hash);
606 584 100         if (slot) {
607 513           RETVAL = SvREFCNT_inc_simple_NN(HeVAL(slot));
608             }
609             else {
610             HV *namespace;
611             SV *nsref;
612              
613 71           package_name = _get_name(self);
614 71 50         namespace = gv_stashpv(SvPV_nolen(package_name), GV_ADD);
615 71           nsref = newRV_inc((SV*)namespace);
616 71           sv_rvweaken(nsref);
617 71 50         if (!hv_store((HV*)SvRV(self), "namespace", 9, nsref, 0)) {
618 0           SvREFCNT_dec(nsref);
619 0           SvREFCNT_dec(self);
620 0           croak("Couldn't initialize the 'namespace' key, hv_store failed");
621             }
622 71           RETVAL = SvREFCNT_inc_simple_NN(nsref);
623             }
624             #endif
625             OUTPUT:
626             RETVAL
627              
628             void
629             add_symbol(self, variable, initial=NULL, ...)
630             SV *self
631             varspec_t variable
632             SV *initial
633             CODE:
634 228 100         if (initial && !_valid_for_type(initial, variable.type))
    100          
635 5 50         croak("%s is not of type %s",
636 5           SvPV_nolen(initial), vartype_to_string(variable.type));
637              
638 223 100         if (items > 2 && (PL_perldb & 0x10) && variable.type == VAR_CODE) {
    100          
    50          
639             int i;
640 14           char *filename = NULL;
641 14           I32 first_line_num = -1, last_line_num = -1;
642             SV *dbval, *name;
643             HV *dbsub;
644              
645 14 50         if ((items - 3) % 2)
646 0           croak("add_symbol: Odd number of elements in %%opts");
647              
648 17 100         for (i = 3; i < items; i += 2) {
649             char *key;
650 3 50         key = SvPV_nolen(ST(i));
651 3 100         if (strEQ(key, "filename")) {
652 1 50         if (!SvPOK(ST(i + 1)))
653 0           croak("add_symbol: filename must be a string");
654 1 50         filename = SvPV_nolen(ST(i + 1));
655             }
656 2 100         else if (strEQ(key, "first_line_num")) {
657 1 50         if (!SvIOK(ST(i + 1)))
658 0           croak("add_symbol: first_line_num must be an integer");
659 1 50         first_line_num = SvIV(ST(i + 1));
660             }
661 1 50         else if (strEQ(key, "last_line_num")) {
662 1 50         if (!SvIOK(ST(i + 1)))
663 0           croak("add_symbol: last_line_num must be an integer");
664 1 50         last_line_num = SvIV(ST(i + 1));
665             }
666             }
667              
668 14 100         if (!filename || first_line_num == -1) {
    50          
669 13 50         if (!filename)
670 13 50         filename = CopFILE(PL_curcop);
671 13 50         if (first_line_num == -1)
672 13           first_line_num = PL_curcop->cop_line;
673             }
674              
675 14 100         if (last_line_num == -1)
676 13           last_line_num = first_line_num;
677              
678 14           name = newSVsv(_get_name(self));
679 14           sv_catpvs(name, "::");
680 14           sv_catsv(name, variable.name);
681              
682             /* http://perldoc.perl.org/perldebguts.html#Debugger-Internals */
683 14           dbsub = get_hv("DB::sub", 1);
684 14           dbval = newSVpvf("%s:%d-%d", filename, first_line_num, last_line_num);
685 14 50         if (!hv_store_ent(dbsub, name, dbval, 0)) {
686 0 0         warn("Failed to update $DB::sub for subroutine %s",
687 0           SvPV_nolen(name));
688 0           SvREFCNT_dec(dbval);
689             }
690              
691 14           SvREFCNT_dec(name);
692             }
693              
694 223           _add_symbol(self, variable, initial);
695              
696             void
697             remove_glob(self, name)
698             SV *self
699             SV *name
700             CODE:
701 0           hv_delete_ent(_get_namespace(self), name, G_DISCARD, 0);
702              
703             int
704             has_symbol(self, variable)
705             SV *self
706             varspec_t variable
707             PREINIT:
708             HV *namespace;
709             HE *entry;
710             SV *val;
711             CODE:
712 53           namespace = _get_namespace(self);
713 53           entry = hv_fetch_ent(namespace, variable.name, 0, 0);
714 53 100         if (!entry)
715 3           XSRETURN_UNDEF;
716              
717 50           val = HeVAL(entry);
718 50 50         if (isGV(val)) {
719 50           GV *glob = (GV*)val;
720 50           switch (variable.type) {
721             case VAR_SCALAR:
722 14           RETVAL = GvSVOK(glob) ? 1 : 0;
723 14           break;
724             case VAR_ARRAY:
725 10           RETVAL = GvAVOK(glob) ? 1 : 0;
726 10           break;
727             case VAR_HASH:
728 8           RETVAL = GvHVOK(glob) ? 1 : 0;
729 8           break;
730             case VAR_CODE:
731 13 50         RETVAL = GvCVOK(glob) ? 1 : 0;
    100          
732 13           break;
733             case VAR_IO:
734 5 50         RETVAL = GvIOOK(glob) ? 1 : 0;
    50          
    0          
    50          
    100          
735 5           break;
736             default:
737 50           croak("Unknown variable type in has_symbol");
738             }
739             }
740             else {
741 0           RETVAL = (variable.type == VAR_CODE);
742             }
743             OUTPUT:
744             RETVAL
745              
746             SV*
747             get_symbol(self, variable)
748             SV *self
749             varspec_t variable
750             PREINIT:
751             SV *val;
752             CODE:
753 260           val = _get_symbol(self, &variable, 0);
754 260 100         if (!val)
755 7           XSRETURN_UNDEF;
756 253           RETVAL = newRV_inc(val);
757             OUTPUT:
758             RETVAL
759              
760             SV*
761             get_or_add_symbol(self, variable)
762             SV *self
763             varspec_t variable
764             PREINIT:
765             SV *val;
766             CODE:
767 16           val = _get_symbol(self, &variable, 1);
768 16 50         if (!val)
769 0           XSRETURN_UNDEF;
770 16           RETVAL = newRV_inc(val);
771             OUTPUT:
772             RETVAL
773              
774             void
775             remove_symbol(self, variable)
776             SV *self
777             varspec_t variable
778             PREINIT:
779             HV *namespace;
780             HE *entry;
781             SV *val;
782             CODE:
783 6           namespace = _get_namespace(self);
784 6           entry = hv_fetch_ent(namespace, variable.name, 0, 0);
785 6 50         if (!entry)
786 0           XSRETURN_EMPTY;
787              
788 6           val = HeVAL(entry);
789 6 50         if (isGV(val)) {
790 6           GV *glob = (GV*)val;
791 6           switch (variable.type) {
792             case VAR_SCALAR:
793 1 50         GvSetSV(glob, NULL);
794 1           break;
795             case VAR_ARRAY:
796 0 0         GvSetAV(glob, NULL);
797 0           break;
798             case VAR_HASH:
799 1 50         GvSetHV(glob, NULL);
800 1           break;
801             case VAR_CODE:
802 3 50         GvSetCV(glob, NULL);
803 6           break;
804             case VAR_IO:
805 1 50         GvSetIO(glob, NULL);
    50          
    0          
    50          
806 1           break;
807             default:
808 0           croak("Unknown variable type in remove_symbol");
809             break;
810             }
811             }
812             else {
813 0 0         if (variable.type == VAR_CODE) {
814 0           hv_delete_ent(namespace, variable.name, G_DISCARD, 0);
815             }
816             }
817              
818             void
819             list_all_symbols(self, vartype=VAR_NONE)
820             SV *self
821             vartype_t vartype
822             PPCODE:
823 26 100         if (vartype == VAR_NONE) {
824             HV *namespace;
825             HE *entry;
826             int keys;
827              
828 2           namespace = _get_namespace(self);
829 2           keys = hv_iterinit(namespace);
830 2 50         EXTEND(SP, keys);
    50          
831 15 100         while ((entry = hv_iternext(namespace))) {
832             #if PERL_VERSION < 10
833             char *pv;
834             STRLEN len;
835             pv = HePV(entry, len);
836             if (strnEQ(entry, "::ISA::CACHE::", len)) {
837             continue;
838             }
839             #endif
840 13           mPUSHs(newSVhe(entry));
841             }
842             }
843             else {
844             HV *namespace;
845             SV *val;
846             char *key;
847             I32 len;
848              
849 24           namespace = _get_namespace(self);
850 24           hv_iterinit(namespace);
851 356 100         while ((val = hv_iternextsv(namespace, &key, &len))) {
852 332           GV *gv = (GV*)val;
853             #if PERL_VERSION < 10
854             if (vartype == VAR_SCALAR && strnEQ(key, "::ISA::CACHE::", len)) {
855             continue;
856             }
857             #endif
858 332 50         if (isGV(gv)) {
859 332           switch (vartype) {
860             case VAR_SCALAR:
861 10 100         if (GvSVOK(val))
862 1 50         mXPUSHp(key, len);
863 10           break;
864             case VAR_ARRAY:
865 7 100         if (GvAVOK(val))
866 2 50         mXPUSHp(key, len);
867 7           break;
868             case VAR_HASH:
869 15 100         if (GvHVOK(val))
870 3 50         mXPUSHp(key, len);
871 15           break;
872             case VAR_CODE:
873 300 100         if (GvCVOK(val))
    100          
874 207 50         mXPUSHp(key, len);
875 300           break;
876             case VAR_IO:
877 0 0         if (GvIOOK(val))
    0          
    0          
    0          
    0          
878 0 0         mXPUSHp(key, len);
879 0           break;
880             default:
881 332           croak("Unknown variable type in list_all_symbols");
882             }
883             }
884 0 0         else if (vartype == VAR_CODE) {
885 0 0         mXPUSHp(key, len);
886             }
887             }
888             }
889              
890             void
891             get_all_symbols(self, vartype=VAR_NONE)
892             SV *self
893             vartype_t vartype
894             PREINIT:
895             HV *namespace, *ret;
896             HE *entry;
897             PPCODE:
898 3           namespace = _get_namespace(self);
899 3           ret = newHV();
900              
901 3           hv_iterinit(namespace);
902 23 100         while ((entry = hv_iternext(namespace))) {
903 20           GV *gv = (GV*)hv_iterval(namespace, entry);
904             char *key;
905             I32 len;
906              
907 20           key = hv_iterkey(entry, &len);
908             #if PERL_VERSION < 10
909             if ((vartype == VAR_SCALAR || vartype == VAR_NONE)
910             && strnEQ(key, "::ISA::CACHE::", len)) {
911             continue;
912             }
913             #endif
914              
915 20 50         if (!isGV(gv)) {
916 0           SV *keysv = newSVpvn(key, len);
917 0           _expand_glob(self, keysv, entry, namespace, 0);
918 0           SvREFCNT_dec(keysv);
919             }
920              
921 20           switch (vartype) {
922             case VAR_SCALAR:
923 0 0         if (GvSVOK(gv))
924 0           hv_store(ret, key, len, newRV_inc(GvSV(gv)), 0);
925 0           break;
926             case VAR_ARRAY:
927 0 0         if (GvAVOK(gv))
928 0           hv_store(ret, key, len, newRV_inc((SV*)GvAV(gv)), 0);
929 0           break;
930             case VAR_HASH:
931 8 100         if (GvHVOK(gv))
932 2           hv_store(ret, key, len, newRV_inc((SV*)GvHV(gv)), 0);
933 8           break;
934             case VAR_CODE:
935 6 50         if (GvCVOK(gv))
    100          
936 2           hv_store(ret, key, len, newRV_inc((SV*)GvCV(gv)), 0);
937 6           break;
938             case VAR_IO:
939 0 0         if (GvIOOK(gv))
    0          
    0          
    0          
    0          
940 0 0         hv_store(ret, key, len, newRV_inc((SV*)GvIO(gv)), 0);
    0          
    0          
    0          
941 0           break;
942             case VAR_NONE:
943 6           hv_store(ret, key, len, SvREFCNT_inc_simple_NN((SV*)gv), 0);
944 20           break;
945             default:
946 0           croak("Unknown variable type in get_all_symbols");
947             }
948             }
949              
950 3           mPUSHs(newRV_noinc((SV*)ret));
951              
952             BOOT:
953             {
954 17           const char *vmre = "\\A[0-9A-Z_a-z]+(?:::[0-9A-Z_a-z]+)*\\z";
955             #if (PERL_VERSION < 9) || ((PERL_VERSION == 9) && (PERL_SUBVERSION < 5))
956             PMOP fakepmop;
957              
958             fakepmop.op_pmflags = 0;
959             valid_module_regex = pregcomp(vmre, vmre + strlen(vmre), &fakepmop);
960             #else
961             SV *re;
962              
963 17           re = newSVpv(vmre, 0);
964 17           valid_module_regex = pregcomp(re, 0);
965             #endif
966              
967 17           name_key = newSVpvs("name");
968 17           PERL_HASH(name_hash, "name", 4);
969              
970 17           namespace_key = newSVpvs("namespace");
971 17           PERL_HASH(namespace_hash, "namespace", 9);
972              
973 17           type_key = newSVpvs("type");
974 17           PERL_HASH(type_hash, "type", 4);
975             }