File Coverage

lib/Data/Dump/Streamer.xs
Criterion Covered Total %
statement 124 225 55.1
branch 118 304 38.8
condition n/a
subroutine n/a
pod n/a
total 242 529 45.7


line stmt bran cond sub pod time code
1             /*
2             * Streamer.xs
3             *
4             * Code from Array::RefElem
5             * Copyright (c) 1997-2000 Graham Barr . All rights reserved.
6             * This program is free software; you can redistribute it and/or
7             * modify it under the same terms as Perl itself.
8             *
9             * Code From Scalar::Util
10             * Copyright 2000 Gisle Aas.
11             * This library is free software; you can redistribute it and/or
12             * modify it under the same terms as Perl itself.
13             * A good chunk of the XS is morphed or taken directly from this module.
14             * Thanks Gisle.
15             *
16             * alias_ref is from Lexical::Alias by Jeff Pinyan which
17             * was borrowed/modified from Devel::LexAlias by Richard Clamp
18             *
19             *
20             * Additional Code and Modifications
21             * Copyright 2003 Yves Orton.
22             * This library is free software; you can redistribute it and/or
23             * modify it under the same terms as Perl itself.
24             *
25             */
26              
27             #ifdef __cplusplus
28             extern "C" {
29             #endif
30             #include "EXTERN.h"
31             #include "perl.h"
32             #include "XSUB.h"
33             #include "ppport.h"
34             #ifdef __cplusplus
35             }
36             #endif
37              
38             #ifndef PERL_VERSION
39             # include
40             # if !(defined(PERL_VERSION) || (PERL_SUBVERSION > 0 && defined(PATCHLEVEL)))
41             # include
42             # endif
43             # define PERL_REVISION 5
44             # define PERL_VERSION PATCHLEVEL
45             # define PERL_SUBVERSION PERL_SUBVERSION
46             #endif
47             #if PERL_VERSION < 8
48             # define PERL_MAGIC_qr 'r' /* precompiled qr// regex */
49             # define BFD_Svs_SMG_OR_RMG SVs_RMG
50             #elif ((PERL_VERSION==8) && (PERL_SUBVERSION >= 1) || (PERL_VERSION>8))
51             # define BFD_Svs_SMG_OR_RMG SVs_SMG
52             # define MY_PLACEHOLDER PL_sv_placeholder
53             #else
54             # define BFD_Svs_SMG_OR_RMG SVs_RMG
55             # define MY_PLACEHOLDER PL_sv_undef
56             #endif
57             #if (((PERL_VERSION == 9) && (PERL_SUBVERSION >= 4)) || (PERL_VERSION > 9))
58             # define NEW_REGEX_ENGINE 1
59             #endif
60             #if (((PERL_VERSION == 8) && (PERL_SUBVERSION >= 1)) || (PERL_VERSION > 8))
61             #define MY_CAN_FIND_PLACEHOLDERS
62             #define HAS_SV2OBJ
63             #endif
64              
65             #ifdef SvWEAKREF
66              
67             # ifndef PERL_MAGIC_backref
68             # define PERL_MAGIC_backref '<'
69             # endif
70              
71             #define ADD_WEAK_REFCOUNT do { \
72             MAGIC *mg = NULL; \
73             if( SvMAGICAL(sv) \
74             && (mg = mg_find(sv, PERL_MAGIC_backref) ) \
75             ){ \
76             SV **svp = (SV**)mg->mg_obj; \
77             if (svp && *svp) { \
78             RETVAL += \
79             SvTYPE(*svp) == SVt_PVAV \
80             ? av_len((AV*)*svp)+1 \
81             : 1; \
82             } \
83             } \
84             } while (0)
85             #else
86             #define ADD_WEAK_REFCOUNT
87             #endif
88              
89              
90             #if PERL_VERSION < 7
91             /* Not in 5.6.1. */
92             # define SvUOK(sv) SvIOK_UV(sv)
93             # ifdef cxinc
94             # undef cxinc
95             # endif
96             # define cxinc() my_cxinc(aTHX)
97             static I32
98             my_cxinc(pTHX)
99             {
100             cxstack_max = cxstack_max * 3 / 2;
101             Renew(cxstack, cxstack_max + 1, struct context); /* XXX should fix CXINC macro */
102             return cxstack_ix + 1;
103             }
104             #endif
105              
106             #if PERL_VERSION < 6
107             # define NV double
108             #endif
109              
110             #if PERL_VERSION < 8
111             # define MY_XS_AMAGIC
112             #endif
113             #if ((PERL_VERSION == 8) && (PERL_SUBVERSION <= 8))
114             # define MY_XS_AMAGIC
115             #endif
116              
117             /*
118             the following three subs are outright stolen from Data::Dumper ( Dumper.xs )
119             from the 5.6.1 distribution of Perl. Probably Gurusamy Sarathy's work.
120             As is much of the code in _globname and globname
121             */
122              
123             /* does a string need to be protected? */
124             static I32
125 134           needs_q(register char *s)
126             {
127             TOP:
128 85 100         if (s[0] == ':') {
129 67 50         if (*++s) {
130 67 50         if (*s++ != ':')
131             return 1;
132             }
133             else
134             return 1;
135             }
136 85 50         if (isIDFIRST(*s)) {
137 350 100         while (*++s)
138 283 100         if (!isALNUM(*s)) {
139 103 50         if (*s == ':')
140             goto TOP;
141             else
142             return 1;
143             }
144             }
145             else
146             return 1;
147             return 0;
148             }
149              
150             /* count the number of "'"s and "\"s in string */
151             static I32
152             num_q(register char *s, register STRLEN slen)
153             {
154             register I32 ret = 0;
155              
156             while (slen > 0) {
157             if (*s == '\'' || *s == '\\')
158             ++ret;
159             ++s;
160             --slen;
161             }
162             return ret;
163             }
164              
165              
166             /* returns number of chars added to escape "'"s and "\"s in s */
167             /* slen number of characters in s will be escaped */
168             /* destination must be long enough for additional chars */
169             static I32
170             esc_q(register char *d, register char *s, register STRLEN slen)
171             {
172             register I32 ret = 0;
173              
174 0 0         while (slen > 0) {
    0          
    0          
175 0 0         switch (*s) {
    0          
    0          
176             case '\'':
177             case '\\':
178 0           *d = '\\';
179 0           ++d; ++ret;
180             default:
181 0           *d = *s;
182 0           ++d; ++s; --slen;
183             break;
184             }
185             }
186             return ret;
187             }
188              
189             XS(XS_Data__Dump__Streamer_SvREADONLY);
190 609           XS(XS_Data__Dump__Streamer_SvREADONLY) /* This is dangerous stuff. */
191             {
192 1218           dXSARGS;
193 609           SV *sv = SvRV(ST(0));
194 609 100         if (items == 1) {
195 566 100         if (SvREADONLY(sv))
196 42           XSRETURN_YES;
197             else
198 524           XSRETURN_NO;
199             }
200 43 50         else if (items == 2) {
201 43 50         if (SvTRUE(ST(1))) {
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
202 43           SvREADONLY_on(sv);
203 43           XSRETURN_YES;
204             }
205             else {
206             /* I hope you really know what you are doing. */
207 0           SvREADONLY_off(sv);
208 0           XSRETURN_NO;
209             }
210             }
211 0           XSRETURN_UNDEF; /* Can't happen. */
212             }
213              
214             XS(XS_Data__Dump__Streamer_SvREFCNT);
215 0           XS(XS_Data__Dump__Streamer_SvREFCNT) /* This is dangerous stuff. */
216             {
217 0           dXSARGS;
218 0           SV *sv = SvRV(ST(0));
219 0 0         if (items == 1)
220 0           XSRETURN_IV(SvREFCNT(sv) - 1); /* Minus the ref created for us. */
221 0 0         else if (items == 2) {
222             /* I hope you really know what you are doing. */
223 0 0         SvREFCNT(sv) = SvIV(ST(1));
224 0           XSRETURN_IV(SvREFCNT(sv));
225             }
226 0           XSRETURN_UNDEF; /* Can't happen. */
227             }
228              
229             /* this is from B is perl 5.9.2 */
230             typedef SV *B__SV;
231              
232             MODULE = B PACKAGE = B::SV
233              
234             #ifndef HAS_SV2OBJ
235              
236             #define object_2svref(sv) sv
237             #define SVREF SV *
238              
239             SVREF
240             object_2svref(sv)
241             B::SV sv
242              
243             #endif
244              
245             MODULE = Data::Dump::Streamer PACKAGE = Data::Dump::Streamer
246              
247             void
248             dualvar(num,str)
249             SV * num
250             SV * str
251             PROTOTYPE: $$
252             CODE:
253             {
254             STRLEN len;
255 3 50         char *ptr = SvPV(str,len);
256 3           ST(0) = sv_newmortal();
257 3 50         (void)SvUPGRADE(ST(0),SVt_PVNV);
258 3           sv_setpvn(ST(0),ptr,len);
259 3 50         if(SvNOK(num) || SvPOK(num) || SvMAGICAL(num)) {
260 0 0         SvNVX(ST(0)) = SvNV(num);
261 0           SvNOK_on(ST(0));
262             }
263             #ifdef SVf_IVisUV
264 3 50         else if (SvUOK(num)) {
265 0 0         SvUVX(ST(0)) = SvUV(num);
266 0           SvIOK_on(ST(0));
267 0           SvIsUV_on(ST(0));
268             }
269             #endif
270             else {
271 3 50         SvIVX(ST(0)) = SvIV(num);
272 3           SvIOK_on(ST(0));
273             }
274 3 50         if(PL_tainting && (SvTAINTED(num) || SvTAINTED(str)))
    0          
    0          
    0          
    0          
275 0 0         SvTAINTED_on(ST(0));
276 3           XSRETURN(1);
277             }
278              
279             bool
280             _could_be_dualvar(sv)
281             SV * sv
282             PROTOTYPE: $
283             CODE:
284             {
285 1112 100         RETVAL = ((SvNIOK(sv)) && (SvPOK(sv))) ? 1 : 0;
    100          
286             }
287             OUTPUT:
288             RETVAL
289              
290              
291             int
292             alias_av(avref, key, val)
293             SV* avref
294             I32 key
295             SV* val
296             PROTOTYPE: \@$$
297             PREINIT:
298             AV* av;
299             CODE:
300             {
301 48 50         if (!SvROK(avref) || SvTYPE(SvRV(avref)) != SVt_PVAV)
    50          
302 0           croak("First argument to alias_av() must be an array reference");
303             av = (AV*)SvRV(avref);
304             SvREFCNT_inc(val);
305 48 50         if (!av_store(av, key, val)) {
306             SvREFCNT_dec(val);
307             RETVAL=0;
308             } else {
309             RETVAL=1;
310             }
311             }
312             OUTPUT:
313             RETVAL
314              
315             void
316             push_alias(avref, val)
317             SV* avref
318             SV* val
319             PROTOTYPE: \@$
320             PREINIT:
321             AV* av;
322             CODE:
323 1 50         if (!SvROK(avref) || SvTYPE(SvRV(avref)) != SVt_PVAV)
    50          
324 0           croak("First argument to push_alias() must be an array reference");
325             av = (AV*)SvRV(avref);
326             SvREFCNT_inc(val);
327 1           av_push(av, val);
328              
329             int
330             alias_hv(hvref, key, val)
331             SV* hvref
332             SV* key
333             SV* val
334             PROTOTYPE: \%$$
335             PREINIT:
336             HV* hv;
337             CODE:
338             {
339 19 50         if (!SvROK(hvref) || SvTYPE(SvRV(hvref)) != SVt_PVHV)
    50          
340 0           croak("First argument to alias_hv() must be a hash reference");
341             hv = (HV*)SvRV(hvref);
342             SvREFCNT_inc(val);
343 19 50         if (!hv_store_ent(hv, key, val, 0)) {
344             SvREFCNT_dec(val);
345             RETVAL=0;
346             } else {
347             RETVAL=1;
348             }
349              
350             }
351             OUTPUT:
352             RETVAL
353              
354             char *
355             blessed(sv)
356             SV * sv
357             PROTOTYPE: $
358             CODE:
359             {
360 5127 100         if (SvMAGICAL(sv))
361 21           mg_get(sv);
362 5127 100         if(!sv_isobject(sv)) {
363 4487           XSRETURN_UNDEF;
364             }
365 640           RETVAL = (char *)sv_reftype(SvRV(sv),TRUE);
366             }
367             OUTPUT:
368             RETVAL
369              
370              
371             UV
372             refaddr(sv)
373             SV * sv
374             PROTOTYPE: $
375             CODE:
376             {
377 20763 100         if(!SvROK(sv)) {
378             RETVAL = 0;
379             } else {
380 18735           RETVAL = PTR2UV(SvRV(sv));
381             }
382             }
383             OUTPUT:
384             RETVAL
385              
386              
387             void
388             weaken(sv)
389             SV *sv
390             PROTOTYPE: $
391             CODE:
392             #ifdef SvWEAKREF
393 14           sv_rvweaken(sv);
394 14           XSRETURN_YES;
395             #else
396             croak("weak references are not implemented in this release of perl");
397             #endif
398              
399             void
400             isweak(sv)
401             SV *sv
402             PROTOTYPE: $
403             CODE:
404             #ifdef SvWEAKREF
405 1210 100         ST(0) = boolSV(SvROK(sv) && SvWEAKREF(sv));
406 1210           XSRETURN(1);
407             #else
408             XSRETURN_NO;
409             #endif
410              
411              
412             IV
413             weak_refcount(sv)
414             SV * sv
415             PROTOTYPE: $
416             CODE:
417             {
418             RETVAL=0;
419 1 50         ADD_WEAK_REFCOUNT;
    50          
    50          
    50          
    50          
420             }
421             OUTPUT:
422             RETVAL
423              
424             IV
425             sv_refcount(sv)
426             SV * sv
427             PROTOTYPE: $
428             CODE:
429             {
430 3627           RETVAL = SvREFCNT(sv);
431 3627 100         ADD_WEAK_REFCOUNT;
    100          
    100          
    50          
    50          
432             }
433             OUTPUT:
434             RETVAL
435              
436             IV
437             refcount(sv)
438             SV * sv
439             PROTOTYPE: $
440             CODE:
441             {
442 2336 100         if(!SvROK(sv)) {
443             RETVAL=0;
444             } else {
445 2330           sv = (SV*)SvRV(sv);
446 2330           RETVAL = SvREFCNT(sv);
447 2330 100         ADD_WEAK_REFCOUNT;
    100          
    50          
    50          
    50          
448             }
449             }
450             OUTPUT:
451             RETVAL
452              
453              
454             bool
455             is_numeric(sv)
456             SV * sv
457             PROTOTYPE: $
458             CODE:
459             {
460 7           RETVAL = (SvNIOK(sv)) ? 1 : 0;
461             }
462             OUTPUT:
463             RETVAL
464              
465              
466             int
467             _make_ro(sv)
468             SV *sv
469             PROTOTYPE: $
470             CODE:
471 0           RETVAL = SvREADONLY_on(sv);
472             OUTPUT:
473             RETVAL
474              
475              
476             SV *
477             make_ro(sv)
478             SV *sv
479             PROTOTYPE: $
480             CODE:
481 8           SvREADONLY_on(sv);
482             SvREFCNT_inc(sv);
483             RETVAL=sv;
484             OUTPUT:
485             RETVAL
486              
487              
488              
489              
490             int
491             readonly_set(sv,set)
492             SV *sv
493             SV *set
494             PROTOTYPE: $
495             CODE:
496 0 0         if (SvTRUE(set)) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
497 0           RETVAL = SvREADONLY_on(sv);
498             } else {
499 0           RETVAL = SvREADONLY_off(sv);
500             }
501             OUTPUT:
502             RETVAL
503              
504             int
505             readonly(sv)
506             SV *sv
507             PROTOTYPE: $
508             CODE:
509 4335           RETVAL = SvREADONLY(sv);
510             OUTPUT:
511             RETVAL
512              
513             int
514             looks_like_number(sv)
515             SV *sv
516             PROTOTYPE: $
517             CODE:
518 0           RETVAL = looks_like_number(sv);
519             OUTPUT:
520             RETVAL
521              
522              
523              
524              
525             int
526             alias_ref (dst,src)
527             SV *dst
528             SV *src
529             CODE:
530             {
531 30           AV* padv = PL_comppad;
532             int dt, st;
533             int ok=0;
534             I32 i;
535              
536 30 50         if (!SvROK(src) || !SvROK(dst))
    50          
537 0           croak("destination and source must be references");
538              
539 30           dt = SvTYPE(SvRV(dst));
540 30           st = SvTYPE(SvRV(src));
541              
542 30 50         if (!(dt < SVt_PVAV && st < SVt_PVAV || dt == st && dt <= SVt_PVHV))
    0          
543 0           croak("destination and source must be same type (%d != %d)",dt,st);
544              
545 1555 100         for (i = 0; i <= av_len(padv); ++i) {
546 1525           SV** myvar_ptr = av_fetch(padv, i, 0);
547 1525 100         if (myvar_ptr) {
548 1495 100         if (SvRV(dst) == *myvar_ptr) {
549 30           av_store(padv, i, SvRV(src));
550 30           SvREFCNT_inc(SvRV(src));
551             ok=1;
552             }
553             }
554             }
555 30 50         if (!ok)
556 0           croak("Failed to created alias");
557             RETVAL = ok;
558             }
559             OUTPUT:
560             RETVAL
561              
562             char *
563             reftype(sv)
564             SV * sv
565             PROTOTYPE: $
566             CODE:
567             {
568 6116 100         if (SvMAGICAL(sv))
569 4           mg_get(sv);
570 6116 100         if(!SvROK(sv)) {
571 126           XSRETURN_NO;
572             } else {
573 5990           RETVAL = (char *)sv_reftype(SvRV(sv),FALSE);
574             }
575             }
576             OUTPUT:
577             RETVAL
578              
579             char *
580             _globname(sv)
581             SV * sv
582             PROTOTYPE: $
583             CODE:
584             {
585 0 0         if (SvMAGICAL(sv))
586 0           mg_get(sv);
587 0 0         if(SvROK(sv)) {
588 0           XSRETURN_NO;
589             } else {
590             U32 realtype;
591 0           realtype = SvTYPE(sv);
592 0 0         if (realtype == SVt_PVGV) {
593             STRLEN i;
594 0 0         RETVAL = SvPV(sv, i);
595             } else {
596 0           XSRETURN_NO;
597             }
598             }
599             }
600             OUTPUT:
601             RETVAL
602              
603             SV *
604             reftype_or_glob(sv)
605             SV * sv
606             PROTOTYPE: $
607             CODE:
608             {
609 3695 100         if (SvMAGICAL(sv))
610 18           mg_get(sv);
611 3695 100         if(SvROK(sv)) {
612 2232           RETVAL = newSVpv(sv_reftype(SvRV(sv),FALSE),0);
613             } else {
614             U32 realtype;
615 1463           realtype = SvTYPE(sv);
616 1463 100         if (realtype == SVt_PVGV) {
617             char *c, *r;
618             STRLEN i;
619             /* SV *retval; */
620              
621 28           RETVAL = newSVpvn("", 0);
622              
623              
624             /* RETVAL = SvPV(sv, i); */
625              
626 28 50         c = SvPV(sv, i);
627              
628              
629 28           ++c; --i; /* just get the name */
630 28 50         if (i >= 6 && strncmp(c, "main::", 6) == 0) {
    100          
631 19           c += 4;
632 19           i -= 4;
633             }
634 28 50         if (needs_q(c)) {
635 0           sv_grow(RETVAL, 6+2*i);
636 0           r = SvPVX(RETVAL);
637 0           r[0] = '*'; r[1] = '{'; r[2] = '\'';
638             /* i have a feeling this will cause problems with utf8 glob names */
639 0           i += esc_q(r+3, c, i);
640 0           i += 3;
641 0           r[i++] = '\''; r[i++] = '}';
642 0           r[i] = '\0';
643             }
644             else {
645 28           sv_grow(RETVAL, i+2);
646 28           r = SvPVX(RETVAL);
647 28           r[0] = '*'; strcpy(r+1, c);
648 28           i++;
649             }
650 28           SvCUR_set(RETVAL, i);
651             /*sv_2mortal(RETVAL);*/ /*causes an error*/
652             } else {
653 1435           XSRETURN_NO;
654             }
655             }
656             }
657             OUTPUT:
658             RETVAL
659              
660              
661             SV *
662             refaddr_or_glob(sv)
663             SV * sv
664             PROTOTYPE: $
665             CODE:
666             {
667 0 0         if (SvMAGICAL(sv))
668 0           mg_get(sv);
669 0 0         if(SvROK(sv)) {
670             UV uv;
671 0           uv = PTR2UV(SvRV(sv));
672 0           RETVAL = newSVuv(uv);
673             } else {
674             U32 realtype;
675 0           realtype = SvTYPE(sv);
676 0 0         if (realtype == SVt_PVGV) {
677             char *c, *r;
678             STRLEN i;
679             /* SV *retval; */
680              
681 0           RETVAL = newSVpvn("", 0);
682              
683              
684             /* RETVAL = SvPV(sv, i); */
685              
686 0 0         c = SvPV(sv, i);
687              
688              
689 0           ++c; --i; /* just get the name */
690 0 0         if (i >= 6 && strncmp(c, "main::", 6) == 0) {
    0          
691 0           c += 4;
692 0           i -= 4;
693             }
694 0 0         if (needs_q(c)) {
695 0           sv_grow(RETVAL, 6+2*i);
696 0           r = SvPVX(RETVAL);
697 0           r[0] = '*'; r[1] = '{'; r[2] = '\'';
698 0           i += esc_q(r+3, c, i);
699 0           i += 3;
700 0           r[i++] = '\''; r[i++] = '}';
701 0           r[i] = '\0';
702             }
703             else {
704 0           sv_grow(RETVAL, i+2);
705 0           r = SvPVX(RETVAL);
706 0           r[0] = '*'; strcpy(r+1, c);
707 0           i++;
708             }
709 0           SvCUR_set(RETVAL, i);
710             /*sv_2mortal(RETVAL);*/ /*causes an error*/
711             } else {
712 0           XSRETURN_NO;
713             }
714             }
715             }
716             OUTPUT:
717             RETVAL
718              
719              
720             SV *
721             globname(sv)
722             SV * sv
723             PROTOTYPE: $
724             CODE:
725             {
726 3267 50         if (SvMAGICAL(sv))
727 0           mg_get(sv);
728 3267 100         if(SvROK(sv)) {
729 1998           XSRETURN_NO;
730             } else {
731             U32 realtype;
732 1269           realtype = SvTYPE(sv);
733 1269 100         if (realtype == SVt_PVGV) {
734             char *c, *r;
735             STRLEN i;
736             /* SV *retval; */
737              
738 39           RETVAL = newSVpvn("", 0);
739              
740              
741             /* RETVAL = SvPV(sv, i); */
742              
743 39 50         c = SvPV(sv, i);
744              
745              
746 39           ++c; --i; /* just get the name */
747 39 50         if (i >= 6 && strncmp(c, "main::", 6) == 0) {
    100          
748 30           c += 4;
749 30           i -= 4;
750             }
751 39 50         if (needs_q(c)) {
752 0           sv_grow(RETVAL, 6+2*i);
753 0           r = SvPVX(RETVAL);
754 0           r[0] = '*'; r[1] = '{'; r[2] = '\'';
755 0           i += esc_q(r+3, c, i);
756 0           i += 3;
757 0           r[i++] = '\''; r[i++] = '}';
758 0           r[i] = '\0';
759             }
760             else {
761 39           sv_grow(RETVAL, i+2);
762 39           r = SvPVX(RETVAL);
763 39           r[0] = '*'; strcpy(r+1, c);
764 39           i++;
765             }
766 39           SvCUR_set(RETVAL, i);
767             /*sv_2mortal(RETVAL);*/ /*causes an error*/
768             } else {
769 1230           XSRETURN_NO;
770             }
771             }
772             }
773             OUTPUT:
774             RETVAL
775              
776             #ifdef MY_XS_AMAGIC
777              
778             void
779             SvAMAGIC_off(sv)
780             SV * sv
781             PROTOTYPE: $
782             CODE:
783             SvAMAGIC_off(sv);
784              
785             void
786             SvAMAGIC_on(sv,klass)
787             SV * sv
788             SV * klass
789             PROTOTYPE: $$
790             CODE:
791             SvAMAGIC_off(sv);
792              
793             #endif
794              
795              
796             #ifndef NEW_REGEX_ENGINE
797              
798             void
799             regex(sv)
800             SV * sv
801             PROTOTYPE: $
802             PREINIT:
803             STRLEN patlen;
804             char reflags[6];
805             int left;
806             PPCODE:
807             {
808             /*
809             Checks if a reference is a regex or not. If the parameter is
810             not a ref, or is not the result of a qr// then returns undef.
811             Otherwise in list context it returns the pattern and the
812             modifiers, in scalar context it returns the pattern just as it
813             would if the qr// was blessed into the package Regexp and
814             stringified normally.
815             */
816              
817             if (SvMAGICAL(sv)) { /* is this if needed??? Why?*/
818             mg_get(sv);
819             }
820             if(!SvROK(sv)) { /* bail if we dont have a ref. */
821             XSRETURN_UNDEF;
822             }
823             patlen=0;
824             left=0;
825             if (SvTHINKFIRST(sv))
826             {
827             sv = (SV*)SvRV(sv);
828             if (sv)
829             {
830             MAGIC *mg;
831             if (SvTYPE(sv)==SVt_PVMG)
832             {
833             if ( ((SvFLAGS(sv) &
834             (SVs_OBJECT|SVf_OK|SVs_GMG|SVs_SMG|SVs_RMG))
835             == (SVs_OBJECT|BFD_Svs_SMG_OR_RMG))
836             && (mg = mg_find(sv, PERL_MAGIC_qr)))
837             {
838             /* Housten, we have a regex! */
839             SV *pattern;
840             regexp *re = (regexp *)mg->mg_obj;
841             I32 gimme = GIMME_V;
842              
843             if ( gimme == G_ARRAY ) {
844             /*
845             we are in list/array context so stringify
846             the modifiers that apply. We ignore "negative
847             modifiers" in this scenario. Also we dont cache
848             the modifiers. AFAICT there isnt anywhere for
849             them to go. :-(
850             */
851              
852             char *fptr = "msix";
853             char ch;
854             U16 reganch = (U16)((re->reganch & PMf_COMPILETIME) >> 12);
855              
856             while((ch = *fptr++)) {
857             if(reganch & 1) {
858             reflags[left++] = ch;
859             }
860             reganch >>= 1;
861             }
862              
863             pattern = sv_2mortal(newSVpvn(re->precomp,re->prelen));
864             if (re->reganch & ROPT_UTF8) SvUTF8_on(pattern);
865              
866             /* return the pattern and the modifiers */
867             XPUSHs(pattern);
868             XPUSHs(sv_2mortal(newSVpvn(reflags,left)));
869             XSRETURN(2);
870             } else {
871             /*
872             Non array/list context. So we build up the
873             stringified form just as PL_sv_2pv does,
874             and like it we also cache the result. The
875             entire content of the if() is directly taken
876             from PL_sv_2pv
877             */
878              
879             if (!mg->mg_ptr )
880             {
881             char *fptr = "msix";
882             char ch;
883             int right = 4;
884             char need_newline = 0;
885             U16 reganch = (U16)((re->reganch & PMf_COMPILETIME) >> 12);
886              
887             while((ch = *fptr++)) {
888             if(reganch & 1) {
889             reflags[left++] = ch;
890             }
891             else {
892             reflags[right--] = ch;
893             }
894             reganch >>= 1;
895             }
896             if(left != 4) {
897             reflags[left] = '-';
898             left = 5;
899             }
900             mg->mg_len = re->prelen + 4 + left;
901             /*
902             * If /x was used, we have to worry about a regex
903             * ending with a comment later being embedded
904             * within another regex. If so, we don't want this
905             * regex's "commentization" to leak out to the
906             * right part of the enclosing regex, we must cap
907             * it with a newline.
908             *
909             * So, if /x was used, we scan backwards from the
910             * end of the regex. If we find a '#' before we
911             * find a newline, we need to add a newline
912             * ourself. If we find a '\n' first (or if we
913             * don't find '#' or '\n'), we don't need to add
914             * anything. -jfriedl
915             */
916             if (PMf_EXTENDED & re->reganch)
917             {
918             char *endptr = re->precomp + re->prelen;
919             while (endptr >= re->precomp)
920             {
921             char c = *(endptr--);
922             if (c == '\n')
923             break; /* don't need another */
924             if (c == '#') {
925             /* we end while in a comment, so we
926             need a newline */
927             mg->mg_len++; /* save space for it */
928             need_newline = 1; /* note to add it */
929             break;
930             }
931             }
932             }
933             /**/
934             New(616, mg->mg_ptr, mg->mg_len + 1 + left, char);
935             Copy("(?", mg->mg_ptr, 2, char);
936             Copy(reflags, mg->mg_ptr+2, left, char);
937             Copy(":", mg->mg_ptr+left+2, 1, char);
938             Copy(re->precomp, mg->mg_ptr+3+left, re->prelen, char);
939             if (need_newline)
940             mg->mg_ptr[mg->mg_len - 2] = '\n';
941             mg->mg_ptr[mg->mg_len - 1] = ')';
942             mg->mg_ptr[mg->mg_len] = 0;
943              
944             }
945             /* return the pattern in (?msix:..) format */
946             pattern = sv_2mortal(newSVpvn(mg->mg_ptr,mg->mg_len));
947             if (re->reganch & ROPT_UTF8) SvUTF8_on(pattern);
948             XPUSHs(pattern);
949             XSRETURN(1);
950             }
951             }
952             }
953             }
954             }
955             /* 'twould appear it aint a regex, so return undef/empty list */
956             XSRETURN_UNDEF;
957             }
958              
959             #endif
960              
961             #ifdef MY_CAN_FIND_PLACEHOLDERS
962              
963             void
964             all_keys(hash,keys,placeholder)
965             SV* hash
966             SV* keys
967             SV* placeholder
968             PROTOTYPE: \%\@\@
969             PREINIT:
970             AV* av_k;
971             AV* av_p;
972             HV* hv;
973             SV *key;
974             HE *he;
975             CODE:
976 0 0         if (!SvROK(hash) || SvTYPE(SvRV(hash)) != SVt_PVHV)
    0          
977 0           croak("First argument to all_keys() must be an HASH reference");
978 0 0         if (!SvROK(keys) || SvTYPE(SvRV(keys)) != SVt_PVAV)
    0          
979 0           croak("Second argument to all_keys() must be an ARRAY reference");
980 0 0         if (!SvROK(placeholder) || SvTYPE(SvRV(placeholder)) != SVt_PVAV)
    0          
981 0           croak("Third argument to all_keys() must be an ARRAY reference");
982              
983             hv = (HV*)SvRV(hash);
984             av_k = (AV*)SvRV(keys);
985             av_p = (AV*)SvRV(placeholder);
986              
987 0           av_clear(av_k);
988 0           av_clear(av_p);
989              
990 0           (void)hv_iterinit(hv);
991 0 0         while((he = hv_iternext_flags(hv, HV_ITERNEXT_WANTPLACEHOLDERS))!= NULL) {
992 0           key=hv_iterkeysv(he);
993 0 0         if (HeVAL(he) == &MY_PLACEHOLDER) {
994             SvREFCNT_inc(key);
995 0           av_push(av_p, key);
996             } else {
997             SvREFCNT_inc(key);
998 0           av_push(av_k, key);
999             }
1000             }
1001              
1002              
1003              
1004             void
1005             hidden_keys(hash)
1006             SV* hash
1007             PROTOTYPE: \%
1008             PREINIT:
1009             HV* hv;
1010             SV *key;
1011             HE *he;
1012             PPCODE:
1013 48 50         if (!SvROK(hash) || SvTYPE(SvRV(hash)) != SVt_PVHV)
    50          
1014 0           croak("First argument to hidden_keys() must be an HASH reference");
1015              
1016             hv = (HV*)SvRV(hash);
1017 48           (void)hv_iterinit(hv);
1018 328 100         while((he = hv_iternext_flags(hv, HV_ITERNEXT_WANTPLACEHOLDERS))!= NULL) {
1019 232           key=hv_iterkeysv(he);
1020 232 100         if (HeVAL(he) == &MY_PLACEHOLDER) {
1021 134 50         XPUSHs( key );
1022             }
1023             }
1024              
1025             void
1026             legal_keys(hash)
1027             SV* hash
1028             PROTOTYPE: \%
1029             PREINIT:
1030             HV* hv;
1031             SV *key;
1032             HE *he;
1033             PPCODE:
1034 6 50         if (!SvROK(hash) || SvTYPE(SvRV(hash)) != SVt_PVHV)
    50          
1035 0           croak("First argument to legal_keys() must be an HASH reference");
1036              
1037             hv = (HV*)SvRV(hash);
1038              
1039 6           (void)hv_iterinit(hv);
1040 60 100         while((he = hv_iternext_flags(hv, HV_ITERNEXT_WANTPLACEHOLDERS))!= NULL) {
1041 54           key=hv_iterkeysv(he);
1042 54 50         XPUSHs( key );
1043             }
1044              
1045              
1046             #endif
1047              
1048             BOOT:
1049 24           newXSproto("Data::Dump::Streamer::SvREADONLY_ref", XS_Data__Dump__Streamer_SvREADONLY, file,"$;$");
1050 24           newXSproto("Data::Dump::Streamer::SvREFCNT_ref", XS_Data__Dump__Streamer_SvREFCNT, file,"$;$");