File Coverage

Dumper.xs
Criterion Covered Total %
statement 850 879 96.7
branch 746 1156 64.5
condition n/a
subroutine n/a
pod n/a
total 1596 2035 78.4


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT
2             #include "EXTERN.h"
3             #include "perl.h"
4             #include "XSUB.h"
5             #ifdef USE_PPPORT_H
6             # define NEED_my_snprintf
7             # define NEED_my_sprintf
8             # define NEED_sv_2pv_flags
9             # define NEED_utf8_to_uvchr_buf
10             # include "ppport.h"
11             #endif
12              
13             #ifndef strlcpy
14             # ifdef my_strlcpy
15             # define strlcpy(d,s,l) my_strlcpy(d,s,l)
16             # else
17             # define strlcpy(d,s,l) strcpy(d,s)
18             # endif
19             #endif
20              
21             /* These definitions are ASCII only. But the pure-perl .pm avoids
22             * calling this .xs file for releases where they aren't defined */
23              
24             #ifndef ESC_NATIVE /* \e */
25             # define ESC_NATIVE LATIN1_TO_NATIVE(27)
26             #endif
27              
28             /* SvPVCLEAR only from perl 5.25.6 */
29             #ifndef SvPVCLEAR
30             # define SvPVCLEAR(sv) sv_setpvs((sv), "")
31             #endif
32              
33             #ifndef memBEGINs
34             # define memBEGINs(s1, l, s2) \
35             ( (l) >= sizeof(s2) - 1 \
36             && memEQ(s1, "" s2 "", sizeof(s2)-1))
37             #endif
38              
39             /* This struct contains almost all the user's desired configuration, and it
40             * is treated as mostly constant (except for maxrecursed) by the recursive
41             * function. This arrangement has the advantage of needing less memory
42             * than passing all of them on the stack all the time (as was the case in
43             * an earlier implementation). */
44             typedef struct {
45             SV *pad;
46             SV *xpad;
47             SV *sep;
48             SV *pair;
49             SV *sortkeys;
50             SV *freezer;
51             SV *toaster;
52             SV *bless;
53             IV maxrecurse;
54             bool maxrecursed; /* at some point we exceeded the maximum recursion level */
55             I32 indent;
56             I32 purity;
57             I32 deepcopy;
58             I32 quotekeys;
59             I32 maxdepth;
60             I32 useqq;
61             int use_sparse_seen_hash;
62             int trailingcomma;
63             int deparse;
64             } Style;
65              
66             static STRLEN num_q (const char *s, STRLEN slen);
67             static STRLEN esc_q (char *dest, const char *src, STRLEN slen);
68             static STRLEN esc_q_utf8 (pTHX_ SV *sv, const char *src, STRLEN slen, I32 do_utf8, I32 useqq);
69             static bool globname_needs_quote(const char *s, STRLEN len);
70             #ifndef GvNAMEUTF8
71             static bool globname_supra_ascii(const char *s, STRLEN len);
72             #endif
73             static bool key_needs_quote(const char *s, STRLEN len);
74             static bool safe_decimal_number(const char *p, STRLEN len);
75             static SV *sv_x (pTHX_ SV *sv, const char *str, STRLEN len, I32 n);
76             static I32 DD_dump (pTHX_ SV *val, const char *name, STRLEN namelen, SV *retval,
77             HV *seenhv, AV *postav, const I32 level, SV *apad,
78             Style *style);
79              
80             #define DD_is_integer(sv) SvIOK(sv)
81              
82             /* does a glob name need to be protected? */
83             static bool
84 75           globname_needs_quote(const char *ss, STRLEN len)
85             {
86 75           const U8 *s = (const U8 *) ss;
87 75           const U8 *send = s+len;
88             TOP:
89 97 100         if (s[0] == ':') {
90 75 100         if (++s
91 74 50         if (*s++ != ':')
92 0           return TRUE;
93             }
94             else
95 1           return TRUE;
96             }
97 96 100         if (isIDFIRST(*s)) {
98 198 100         while (++s
99 167 100         if (!isWORDCHAR(*s)) {
100 55 100         if (*s == ':')
101 22           goto TOP;
102             else
103 33           return TRUE;
104             }
105             }
106             else
107 10           return TRUE;
108              
109 31           return FALSE;
110             }
111              
112             #ifndef GvNAMEUTF8
113             /* does a glob name contain supra-ASCII characters? */
114             static bool
115             globname_supra_ascii(const char *ss, STRLEN len)
116             {
117             const U8 *s = (const U8 *) ss;
118             const U8 *send = s+len;
119             while (s < send) {
120             if (!isASCII(*s))
121             return TRUE;
122             s++;
123             }
124             return FALSE;
125             }
126             #endif
127              
128             /* does a hash key need to be quoted (to the left of => ).
129             Previously this used (globname_)needs_quote() which accepted strings
130             like '::foo', but these aren't safe as unquoted keys under strict.
131             */
132             static bool
133 206           key_needs_quote(const char *s, STRLEN len) {
134 206           const char *send = s+len;
135              
136 206 100         if (safe_decimal_number(s, len)) {
137 42           return FALSE;
138             }
139 164 100         else if (isIDFIRST(*s)) {
140 406 100         while (++s
141 256 100         if (!isWORDCHAR(*s))
142 2           return TRUE;
143             }
144             else
145 12           return TRUE;
146              
147 150           return FALSE;
148             }
149              
150             /* Check that the SV can be represented as a simple decimal integer.
151             *
152             * The perl code does this by matching against /^(?:0|-?[1-9]\d{0,8})\z/
153             */
154             static bool
155 252           safe_decimal_number(const char *p, STRLEN len) {
156 252 100         if (len == 1 && *p == '0')
    100          
157 2           return TRUE;
158              
159 250 50         if (len && *p == '-') {
    50          
160 0           ++p;
161 0           --len;
162             }
163              
164 250 50         if (len == 0 || *p < '1' || *p > '9')
    100          
    100          
165 202           return FALSE;
166              
167 48           ++p;
168 48           --len;
169              
170 48 100         if (len > 8)
171 4           return FALSE;
172              
173 98 100         while (len > 0) {
174             /* the perl code checks /\d/ but we don't want unicode digits here */
175 56 100         if (*p < '0' || *p > '9')
    50          
176 2           return FALSE;
177 54           ++p;
178 54           --len;
179             }
180 42           return TRUE;
181             }
182              
183             /* count the number of "'"s and "\"s in string */
184             static STRLEN
185 512           num_q(const char *s, STRLEN slen)
186             {
187 512           STRLEN ret = 0;
188              
189 2790 100         while (slen > 0) {
190 2278 100         if (*s == '\'' || *s == '\\')
    100          
191 2           ++ret;
192 2278           ++s;
193 2278           --slen;
194             }
195 512           return ret;
196             }
197              
198              
199             /* returns number of chars added to escape "'"s and "\"s in s */
200             /* slen number of characters in s will be escaped */
201             /* destination must be long enough for additional chars */
202             static STRLEN
203 973           esc_q(char *d, const char *s, STRLEN slen)
204             {
205 973           STRLEN ret = 0;
206              
207 10657 100         while (slen > 0) {
208 9684 100         switch (*s) {
209             case '\'':
210             case '\\':
211 5           *d = '\\';
212 5           ++d; ++ret;
213             /* FALLTHROUGH */
214             default:
215 9684           *d = *s;
216 9684           ++d; ++s; --slen;
217 9684           break;
218             }
219             }
220 973           return ret;
221             }
222              
223             /* this function is also misused for implementing $Useqq */
224             static STRLEN
225 144           esc_q_utf8(pTHX_ SV* sv, const char *src, STRLEN slen, I32 do_utf8, I32 useqq)
226             {
227             char *r, *rstart;
228 144           const char *s = src;
229 144           const char * const send = src + slen;
230 144           STRLEN j, cur = SvCUR(sv);
231             /* Could count 128-255 and 256+ in two variables, if we want to
232             be like &qquote and make a distinction. */
233 144           STRLEN grow = 0; /* bytes needed to represent chars 128+ */
234             /* STRLEN topbit_grow = 0; bytes needed to represent chars 128-255 */
235 144           STRLEN backslashes = 0;
236 144           STRLEN single_quotes = 0;
237 144           STRLEN qq_escapables = 0; /* " $ @ will need a \ in "" strings. */
238 144           STRLEN normal = 0;
239             int increment;
240              
241 1937 100         for (s = src; s < send; s += increment) { /* Sizing pass */
242 1793           UV k = *(U8*)s;
243              
244 1793           increment = 1; /* Will override if necessary for utf-8 */
245              
246 1793 50         if (isPRINT(k)) {
    100          
247 2002 100         if (k == '\\') {
248 6           backslashes++;
249 995 100         } else if (k == '\'') {
250 58           single_quotes++;
251 937 100         } else if (k == '"' || k == '$' || k == '@') {
    100          
    100          
252 22           qq_escapables++;
253             } else {
254 915           normal++;
255             }
256             }
257 792 100         else if (! UTF8_IS_INVARIANT(k)) {
258             /* We treat as low ordinal any code point whose representation is
259             * the same under UTF-8 as not. Thus, this is a high ordinal code
260             * point.
261             *
262             * If UTF-8, output as hex, regardless of useqq. This means there
263             * is an overhead of 4 chars '\x{}'. Then count the number of hex
264             * digits. */
265 636 100         if (do_utf8) {
266 372           k = utf8_to_uvchr_buf((U8*)s, (U8*) send, NULL);
267              
268             /* treat invalid utf8 byte by byte. This loop iteration gets the
269             * first byte */
270 372 100         increment = (k == 0 && *s != '\0') ? 1 : UTF8SKIP(s);
    50          
271              
272 372           grow += 6; /* Smallest we do is "\x{FF}" */
273 372           k >>= 4;
274 480 100         while ((k >>= 4) != 0) { /* Add space for each nibble */
275 108           grow++;
276             }
277             }
278 264 50         else if (useqq) { /* Not utf8, must be <= 0xFF, hence 2 hex
279             * digits. */
280 264           grow += 4 + 2;
281             }
282             else { /* Non-qq generates 3 octal digits plus backslash */
283 636           grow += 4;
284             }
285             } /* End of high-ordinal non-printable */
286 156 100         else if (! useqq) { /* Low ordinal, non-printable, non-qq just
287             * outputs the raw char */
288 2           normal++;
289             }
290             else { /* Is qq, low ordinal, non-printable. Output escape
291             * sequences */
292 154 100         if ( k == '\a' || k == '\b' || k == '\t' || k == '\n' || k == '\r'
    100          
    100          
    100          
    100          
293 132 100         || k == '\f' || k == ESC_NATIVE)
    100          
294             {
295 32           grow += 2; /* 1 char plus backslash */
296             }
297             else /* The other low ordinals are output as an octal escape
298             * sequence */
299 122 100         if (s + 1 >= send || isDIGIT(*(s+1))) {
    100          
300             /* When the following character is a digit, use 3 octal digits
301             * plus backslash, as using fewer digits would concatenate the
302             * following char into this one */
303 6           grow += 4;
304             }
305 116 100         else if (k <= 7) {
306 40           grow += 2; /* 1 octal digit, plus backslash */
307             }
308 76 100         else if (k <= 077) {
309 72           grow += 3; /* 2 octal digits plus backslash */
310             }
311             else {
312 4           grow += 4; /* 3 octal digits plus backslash */
313             }
314             }
315             } /* End of size-calculating loop */
316              
317 144 100         if (grow || useqq) {
    100          
318             /* We have something needing hex. 3 is ""\0 */
319 132           sv_grow(sv, cur + 3 + grow + 2*backslashes + single_quotes
320             + 2*qq_escapables + normal);
321 132           rstart = r = SvPVX(sv) + cur;
322              
323 132           *r++ = '"';
324              
325 1860 100         for (s = src; s < send; s += increment) {
326 1728           U8 c0 = *(U8 *)s;
327             UV k;
328              
329 1728 100         if (do_utf8 && ! UTF8_IS_INVARIANT(c0)) {
    100          
330              
331             /* In UTF-8, we output as \x{} all chars that require more than
332             * a single byte in UTF-8 to represent. */
333 372           k = utf8_to_uvchr_buf((U8*)s, (U8*) send, NULL);
334              
335             /* treat invalid utf8 byte by byte. This loop iteration gets the
336             * first byte */
337 372 100         increment = (k == 0 && *s != '\0') ? 1 : UTF8SKIP(s);
    50          
338              
339 372           r = r + my_sprintf(r, "\\x{%" UVxf "}", k);
340 372           continue;
341             }
342              
343             /* Here 1) isn't UTF-8; or
344             * 2) the current character is ASCII; or
345             * 3) it is an EBCDIC platform and is a low ordinal
346             * non-ASCII control.
347             * In each case the character occupies just one byte */
348 1356           k = *(U8*)s;
349 1356           increment = 1;
350              
351 1356 50         if (isPRINT(k)) {
    100          
352             /* These need a backslash escape */
353 937 100         if (k == '"' || k == '\\' || k == '$' || k == '@') {
    100          
    100          
    100          
354 24           *r++ = '\\';
355             }
356              
357 937           *r++ = (char)k;
358             }
359 419 100         else if (! useqq) { /* non-qq, non-printable, low-ordinal is
360             * output raw */
361 1           *r++ = (char)k;
362             }
363             else { /* Is qq means use escape sequences */
364             bool next_is_digit;
365              
366 418           *r++ = '\\';
367 418           switch (k) {
368 4           case '\a': *r++ = 'a'; break;
369 4           case '\b': *r++ = 'b'; break;
370 4           case '\t': *r++ = 't'; break;
371 6           case '\n': *r++ = 'n'; break;
372 4           case '\f': *r++ = 'f'; break;
373 4           case '\r': *r++ = 'r'; break;
374 6           case ESC_NATIVE: *r++ = 'e'; break;
375             default:
376              
377             /* only ASCII digits matter here, which are invariant,
378             * since we only encode characters \377 and under, or
379             * \x177 and under for a unicode string
380             */
381 386 100         next_is_digit = (s + 1 < send && isDIGIT(*(s+1)));
    100          
382              
383             /* faster than
384             * r = r + my_sprintf(r, "%o", k);
385             */
386 386 100         if (k <= 7 && !next_is_digit) {
    100          
387 42           *r++ = (char)k + '0';
388 344 100         } else if (k <= 63 && !next_is_digit) {
    100          
389 72           *r++ = (char)(k>>3) + '0';
390 72           *r++ = (char)(k&7) + '0';
391             } else {
392 272           *r++ = (char)(k>>6) + '0';
393 272           *r++ = (char)((k&63)>>3) + '0';
394 272           *r++ = (char)(k&7) + '0';
395             }
396             }
397             }
398             }
399 132           *r++ = '"';
400             } else {
401             /* Single quotes. */
402 12           sv_grow(sv, cur + 3 + 2*backslashes + 2*single_quotes
403             + qq_escapables + normal);
404 12           rstart = r = SvPVX(sv) + cur;
405 12           *r++ = '\'';
406 77 100         for (s = src; s < send; s ++) {
407 65           const char k = *s;
408 65 100         if (k == '\'' || k == '\\')
    50          
409 2           *r++ = '\\';
410 65           *r++ = k;
411             }
412 12           *r++ = '\'';
413             }
414 144           *r = '\0';
415 144           j = r - rstart;
416 144           SvCUR_set(sv, cur + j);
417              
418 144           return j;
419             }
420              
421             /* append a repeated string to an SV */
422             static SV *
423 1452           sv_x(pTHX_ SV *sv, const char *str, STRLEN len, I32 n)
424             {
425 1452 100         if (!sv)
426 1431           sv = newSVpvs("");
427             #ifdef DEBUGGING
428             else
429             assert(SvTYPE(sv) >= SVt_PV);
430             #endif
431              
432 1452 100         if (n > 0) {
433 1172 50         SvGROW(sv, len*n + SvCUR(sv) + 1);
    100          
434 1172 100         if (len == 1) {
435 267           char * const start = SvPVX(sv) + SvCUR(sv);
436 267           SvCUR_set(sv, SvCUR(sv) + n);
437 267           start[n] = '\0';
438 2115 100         while (n > 0)
439 1848           start[--n] = str[0];
440             }
441             else
442 2567 100         while (n > 0) {
443 1662           sv_catpvn(sv, str, len);
444 1662           --n;
445             }
446             }
447 1452           return sv;
448             }
449              
450             static SV *
451 5           deparsed_output(pTHX_ SV *val)
452             {
453             SV *text;
454             int n;
455 5           dSP;
456              
457             /* This is passed to load_module(), which decrements its ref count and
458             * modifies it (so we also can't reuse it below) */
459 5           SV *pkg = newSVpvs("B::Deparse");
460              
461             /* Commit ebdc88085efa6fca8a1b0afaa388f0491bdccd5a (first released as part
462             * of 5.19.7) changed core S_process_special_blocks() to use a new stack
463             * for anything using a BEGIN block, on the grounds that doing so "avoids
464             * the stack moving underneath anything that directly or indirectly calls
465             * Perl_load_module()". If we're in an older Perl, we can't rely on that
466             * stack, and must create a fresh sacrificial stack of our own. */
467             #if PERL_VERSION_LT(5,20,0)
468             PUSHSTACKi(PERLSI_REQUIRE);
469             #endif
470              
471 5           load_module(PERL_LOADMOD_NOIMPORT, pkg, 0);
472              
473             #if PERL_VERSION_LT(5,20,0)
474             POPSTACK;
475             SPAGAIN;
476             #endif
477              
478 5           SAVETMPS;
479              
480 5 50         PUSHMARK(SP);
481 5 50         mXPUSHs(newSVpvs("B::Deparse"));
482 5           PUTBACK;
483              
484 5           n = call_method("new", G_SCALAR);
485 5           SPAGAIN;
486              
487 5 50         if (n != 1) {
488 0           croak("B::Deparse->new returned %d items, but expected exactly 1", n);
489             }
490              
491 5 50         PUSHMARK(SP - n);
492 5 50         XPUSHs(val);
493 5           PUTBACK;
494              
495 5           n = call_method("coderef2text", G_SCALAR);
496 5           SPAGAIN;
497              
498 5 50         if (n != 1) {
499 0           croak("$b_deparse->coderef2text returned %d items, but expected exactly 1", n);
500             }
501              
502 5           text = POPs;
503 5           SvREFCNT_inc(text); /* the caller will mortalise this */
504              
505 5 50         FREETMPS;
506              
507 5           PUTBACK;
508              
509 5           return text;
510             }
511              
512             static void
513 54           dump_regexp(pTHX_ SV *retval, SV *val)
514             {
515             STRLEN rlen;
516 54           SV *sv_pattern = NULL;
517 54           SV *sv_flags = NULL;
518             const char *rval;
519             const U8 *rend;
520             U8 *p;
521 54           CV *re_pattern_cv = get_cv("re::regexp_pattern", 0);
522             int do_utf8;
523              
524 54 50         if (!re_pattern_cv) {
525 0           sv_pattern = val;
526             }
527             else {
528 54           dSP;
529             I32 count;
530 54           ENTER;
531 54           SAVETMPS;
532 54 50         PUSHMARK(SP);
533 54 50         XPUSHs(val);
534 54           PUTBACK;
535 54           count = call_sv((SV*)re_pattern_cv, G_ARRAY);
536 54           SPAGAIN;
537 54 50         if (count >= 2) {
538 54           sv_flags = POPs;
539 54           sv_pattern = POPs;
540 54           SvREFCNT_inc(sv_flags);
541 54           SvREFCNT_inc(sv_pattern);
542             }
543 54           PUTBACK;
544 54 50         FREETMPS;
545 54           LEAVE;
546 54 50         if (sv_pattern) {
547 54           sv_2mortal(sv_pattern);
548 54           sv_2mortal(sv_flags);
549             }
550             }
551              
552             assert(sv_pattern);
553              
554 54           sv_catpvs(retval, "qr/");
555              
556             /* The strategy here is from commit 7894fbab1e479c2c (in June 1999) with a
557             * bug fix in Feb 2012 (commit de5ef703c7d8db65).
558             * We need to ensure that / is escaped as \/
559             * To be efficient, we want to avoid copying byte-for-byte, so we scan the
560             * string looking for "things we need to escape", and each time we find
561             * something, we copy over the verbatim section, before writing out the
562             * escaped part. At the end, if there's some verbatim section left, we copy
563             * that over to finish.
564             * The complication (perl #58608) is that we must not convert \/ to \\/
565             * (as that would be a syntax error), so we need to walk the string looking
566             * for either
567             * \ and the character immediately after (together)
568             * a character
569             * and only for the latter, do we need to escape /
570             *
571             * Of course, to add to the fun, we also need to escape Unicode characters
572             * to \x{...} notation (whether they are "escaped" by \ or stand alone).
573             *
574             * which means we need to output qr// notation
575             * even if the input was expressed as q'' (eg q'$foo')
576             *
577             * We can do all this in one pass if we are careful...
578             */
579              
580 54 50         rval = SvPV(sv_pattern, rlen);
581 54           p = (U8 *)rval;
582 54           rend = p + rlen;
583 54 100         do_utf8 = DO_UTF8(sv_pattern);
    50          
584              
585 265 100         while (p < rend) {
586 211           UV k = *p;
587 211           int saw_backslash = k == '\\';
588              
589 211 100         if (saw_backslash) {
590 37 50         if (++p == rend) {
591             /* Oh my, \ at the end. Is this possible? */
592 0           break;
593             }
594             /* Otherwise we look at the next octet */
595 37           k = *p;
596             }
597              
598 211 100         if (/* / that was not backslashed */
599 23 100         (k == '/' && !saw_backslash)
600             /* $ that was not backslashed, unless it is at the end of the regex
601             or it is followed by | or it is followed by ) */
602 189 100         || (k == '$' && !saw_backslash
    100          
603 16 100         && (p + 1 != rend && p[1] != '|' && p[1] != ')'))
    100          
    100          
604             /* or need to use \x{} notation. */
605 181 100         || (do_utf8 && ! UTF8_IS_INVARIANT(k)))
    100          
606 54           {
607 54           STRLEN to_copy = p - (U8 *) rval;
608 54 100         if (to_copy) {
609             /* If saw_backslash is true, this will copy the \ for us too. */
610 38           sv_catpvn(retval, rval, to_copy);
611             }
612 54 100         if (k == '/') {
613 22           sv_catpvs(retval, "\\/");
614 22           ++p;
615             }
616 32 100         else if (k == '$') {
617             /* this approach suggested by Eirik Berg Hanssen: */
618 8           sv_catpvs(retval, "${\\q($)}");
619 8           ++p;
620             }
621             else {
622             /* If there was a \, we have copied it already, so all that is
623             * left to do here is the \x{...} escaping.
624             *
625             * Since this is a pattern, presumably created by perl, we can
626             * assume it is well-formed */
627 24           k = utf8_to_uvchr_buf(p, rend, NULL);
628 24           sv_catpvf(retval, "\\x{%" UVxf "}", k);
629 24           p += UTF8SKIP(p);
630             }
631 54           rval = (const char *) p;
632             }
633             else {
634 157           ++p;
635             }
636             }
637              
638 54           rlen = rend - (U8 *) rval;
639 54 100         if (rlen) {
640 47           sv_catpvn(retval, rval, rlen);
641             }
642 54           sv_catpvs(retval, "/");
643              
644 54 50         if (sv_flags)
645 54           sv_catsv(retval, sv_flags);
646 54           }
647              
648             /*
649             * This ought to be split into smaller functions. (it is one long function since
650             * it exactly parallels the perl version, which was one long thing for
651             * efficiency raisins.) Ugggh!
652             */
653             static I32
654 2611           DD_dump(pTHX_ SV *val, const char *name, STRLEN namelen, SV *retval, HV *seenhv,
655             AV *postav, const I32 level, SV *apad, Style *style)
656             {
657             char tmpbuf[128];
658             Size_t i;
659             char *c, *r, *realpack;
660             UV id_buffer;
661 2611           char *const id = (char *)&id_buffer;
662             SV **svp;
663             SV *sv, *ipad, *ival;
664 2611           SV *blesspad = Nullsv;
665 2611           AV *seenentry = NULL;
666             char *iname;
667 2611           STRLEN inamelen, idlen = 0;
668             U32 realtype;
669 2611           bool no_bless = 0; /* when a qr// is blessed into Regexp we dont want to bless it.
670             in later perls we should actually check the classname of the
671             engine. this gets tricky as it involves lexical issues that arent so
672             easy to resolve */
673 2611           bool is_regex = 0; /* we are dumping a regex, we need to know this before we bless */
674              
675 2611 50         if (!val)
676 0           return 0;
677              
678 2611 100         if (style->maxrecursed)
679 1           return 0;
680              
681             /* If the output buffer has less than some arbitrary amount of space
682             remaining, then enlarge it. For the test case (25M of output),
683             *1.1 was slower, *2.0 was the same, so the first guess of 1.5 is
684             deemed to be good enough. */
685 2610 50         if (SvTYPE(retval) >= SVt_PV && (SvLEN(retval) - SvCUR(retval)) < 42) {
    100          
686 2143           sv_grow(retval, SvCUR(retval) * 3 / 2);
687             }
688              
689 2610           realtype = SvTYPE(val);
690              
691 2610 50         if (SvGMAGICAL(val))
692 0           mg_get(val);
693 2610 100         if (SvROK(val)) {
694              
695             /* If a freeze method is provided and the object has it, call
696             it. Warn on errors. */
697 1084 100         if (SvOBJECT(SvRV(val)) && style->freezer &&
    50          
    100          
698 75           SvPOK(style->freezer) && SvCUR(style->freezer) &&
699 7           gv_fetchmeth(SvSTASH(SvRV(val)), SvPVX_const(style->freezer),
700             SvCUR(style->freezer), -1) != NULL)
701             {
702 6 50         dSP; ENTER; SAVETMPS; PUSHMARK(sp);
703 6 50         XPUSHs(val); PUTBACK;
704 6           i = perl_call_method(SvPVX_const(style->freezer), G_EVAL|G_VOID|G_DISCARD);
705 6           SPAGAIN;
706 6 50         if (SvTRUE(ERRSV))
    50          
    50          
    50          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    100          
707 1 50         warn("WARNING(Freezer method call failed): %" SVf, ERRSV);
708 6 50         PUTBACK; FREETMPS; LEAVE;
709             }
710            
711 1084           ival = SvRV(val);
712 1084           realtype = SvTYPE(ival);
713 1084           id_buffer = PTR2UV(ival);
714 1084           idlen = sizeof(id_buffer);
715 1084 100         if (SvOBJECT(ival))
716 70 50         realpack = HvNAME_get(SvSTASH(ival));
    50          
    50          
    0          
    50          
    50          
717             else
718 1014           realpack = NULL;
719              
720             /* if it has a name, we need to either look it up, or keep a tab
721             * on it so we know when we hit it later
722             */
723 1084 50         if (namelen) {
724 1084 100         if ((svp = hv_fetch(seenhv, id, idlen, FALSE))
725 323 50         && (sv = *svp) && SvROK(sv) && (seenentry = (AV*)SvRV(sv)))
    50          
    50          
726             {
727             SV *othername;
728 323 50         if ((svp = av_fetch(seenentry, 0, FALSE))
729 323 50         && (othername = *svp))
730             {
731 411 100         if (style->purity && level > 0) {
    100          
732             SV *postentry;
733            
734 88 100         if (realtype == SVt_PVHV)
735 28           sv_catpvs(retval, "{}");
736 60 100         else if (realtype == SVt_PVAV)
737 38           sv_catpvs(retval, "[]");
738             else
739 22           sv_catpvs(retval, "do{my $o}");
740 88           postentry = newSVpvn(name, namelen);
741 88           sv_catpvs(postentry, " = ");
742 88           sv_catsv(postentry, othername);
743 88           av_push(postav, postentry);
744             }
745             else {
746 235 100         if (name[0] == '@' || name[0] == '%') {
    100          
747 60 100         if ((SvPVX_const(othername))[0] == '\\' &&
    50          
748 10           (SvPVX_const(othername))[1] == name[0]) {
749 10           sv_catpvn(retval, SvPVX_const(othername)+1,
750             SvCUR(othername)-1);
751             }
752             else {
753 20           sv_catpvn(retval, name, 1);
754 20           sv_catpvs(retval, "{");
755 20           sv_catsv(retval, othername);
756 20           sv_catpvs(retval, "}");
757             }
758             }
759             else
760 205           sv_catsv(retval, othername);
761             }
762 323           return 1;
763             }
764             else {
765 0           warn("ref name not found for 0x%" UVxf, PTR2UV(ival));
766 0           return 0;
767             }
768             }
769             else { /* store our name and continue */
770             SV *namesv;
771 761 100         if (name[0] == '@' || name[0] == '%') {
    100          
772 35           namesv = newSVpvs("\\");
773 35           sv_catpvn(namesv, name, namelen);
774             }
775 726 100         else if (realtype == SVt_PVCV && name[0] == '*') {
    100          
776 2           namesv = newSVpvs("\\");
777 2           sv_catpvn(namesv, name, namelen);
778 2           (SvPVX(namesv))[1] = '&';
779             }
780             else
781 724           namesv = newSVpvn(name, namelen);
782 761           seenentry = newAV();
783 761           av_push(seenentry, namesv);
784 761           (void)SvREFCNT_inc(val);
785 761           av_push(seenentry, val);
786 761           (void)hv_store(seenhv, id, idlen,
787             newRV_inc((SV*)seenentry), 0);
788 761           SvREFCNT_dec(seenentry);
789             }
790             }
791             /* regexps dont have to be blessed into package "Regexp"
792             * they can be blessed into any package.
793             */
794             #if PERL_VERSION_LT(5,11,0)
795             if (realpack && realtype == SVt_PVMG && mg_find(ival, PERL_MAGIC_qr))
796             #else
797 761 100         if (realpack && realtype == SVt_REGEXP)
    100          
798             #endif
799             {
800 54           is_regex = 1;
801 54 100         if (strEQ(realpack, "Regexp"))
802 53           no_bless = 1;
803             else
804 1           no_bless = 0;
805             }
806              
807             /* If purity is not set and maxdepth is set, then check depth:
808             * if we have reached maximum depth, return the string
809             * representation of the thing we are currently examining
810             * at this depth (i.e., 'Foo=ARRAY(0xdeadbeef)').
811             */
812 761 100         if (!style->purity && style->maxdepth > 0 && level >= style->maxdepth) {
    100          
    100          
813             STRLEN vallen;
814 6 50         const char * const valstr = SvPV(val,vallen);
815 6           sv_catpvs(retval, "'");
816 6           sv_catpvn(retval, valstr, vallen);
817 6           sv_catpvs(retval, "'");
818 6           return 1;
819             }
820              
821 755 100         if (style->maxrecurse > 0 && level >= style->maxrecurse) {
    100          
822 4           style->maxrecursed = TRUE;
823             }
824              
825 755 100         if (realpack && !no_bless) { /* we have a blessed ref */
    100          
826             STRLEN blesslen;
827 17 50         const char * const blessstr = SvPV(style->bless, blesslen);
828 17           sv_catpvn(retval, blessstr, blesslen);
829 17           sv_catpvs(retval, "( ");
830 17 100         if (style->indent >= 2) {
831 15           blesspad = apad;
832 15           apad = sv_2mortal(newSVsv(apad));
833 17           sv_x(aTHX_ apad, " ", 1, blesslen+2);
834             }
835             }
836              
837 755           ipad = sv_x(aTHX_ Nullsv, SvPVX_const(style->xpad), SvCUR(style->xpad), level+1);
838 755           sv_2mortal(ipad);
839              
840 755 100         if (is_regex) {
841 54           dump_regexp(aTHX_ retval, val);
842             }
843 701 100         else if (
844             #if PERL_VERSION_LT(5,9,0)
845             realtype <= SVt_PVBM
846             #else
847             realtype <= SVt_PVMG
848             #endif
849             ) { /* scalar ref */
850 79           SV * const namesv = sv_2mortal(newSVpvs("${"));
851 79           sv_catpvn(namesv, name, namelen);
852 79           sv_catpvs(namesv, "}");
853 79 50         if (realpack) { /* blessed */
854 0           sv_catpvs(retval, "do{\\(my $o = ");
855 0           DD_dump(aTHX_ ival, SvPVX_const(namesv), SvCUR(namesv), retval, seenhv,
856             postav, level+1, apad, style);
857 0           sv_catpvs(retval, ")}");
858             } /* plain */
859             else {
860 79           sv_catpvs(retval, "\\");
861 79           DD_dump(aTHX_ ival, SvPVX_const(namesv), SvCUR(namesv), retval, seenhv,
862             postav, level+1, apad, style);
863             }
864             }
865 622 100         else if (realtype == SVt_PVGV) { /* glob ref */
866 54           SV * const namesv = newSVpvs("*{");
867 54           sv_catpvn(namesv, name, namelen);
868 54           sv_catpvs(namesv, "}");
869 54           sv_catpvs(retval, "\\");
870 54           DD_dump(aTHX_ ival, SvPVX_const(namesv), SvCUR(namesv), retval, seenhv,
871             postav, level+1, apad, style);
872 54           SvREFCNT_dec(namesv);
873             }
874 568 100         else if (realtype == SVt_PVAV) {
875             SV *totpad;
876 324           SSize_t ix = 0;
877 324           const SSize_t ixmax = av_len((AV *)ival);
878            
879 324           SV * const ixsv = sv_2mortal(newSViv(0));
880             /* allowing for a 24 char wide array index */
881 324           New(0, iname, namelen+28, char);
882 324           SAVEFREEPV(iname);
883 324           (void) strlcpy(iname, name, namelen+28);
884 324           inamelen = namelen;
885 324 100         if (name[0] == '@') {
886 24           sv_catpvs(retval, "(");
887 24           iname[0] = '$';
888             }
889             else {
890 300           sv_catpvs(retval, "[");
891             /* omit "->" in $foo{bar}->[0], but not in ${$foo}->[0] */
892             /*if (namelen > 0
893             && name[namelen-1] != ']' && name[namelen-1] != '}'
894             && (namelen < 4 || (name[1] != '{' && name[2] != '{')))*/
895 300 50         if ((namelen > 0
896 300 100         && name[namelen-1] != ']' && name[namelen-1] != '}')
    100          
897 182 50         || (namelen > 4
898 182 100         && (name[1] == '{'
899 178 50         || (name[0] == '\\' && name[2] == '{'))))
    0          
900             {
901 122           iname[inamelen++] = '-'; iname[inamelen++] = '>';
902 122           iname[inamelen] = '\0';
903             }
904             }
905 324 100         if (iname[0] == '*' && iname[inamelen-1] == '}' && inamelen >= 8 &&
    50          
    50          
    50          
906 4 50         (instr(iname+inamelen-8, "{SCALAR}") ||
907 0 0         instr(iname+inamelen-7, "{ARRAY}") ||
908 0           instr(iname+inamelen-6, "{HASH}"))) {
909 4           iname[inamelen++] = '-'; iname[inamelen++] = '>';
910             }
911 324           iname[inamelen++] = '['; iname[inamelen] = '\0';
912 324           totpad = sv_2mortal(newSVsv(style->sep));
913 324           sv_catsv(totpad, style->pad);
914 324           sv_catsv(totpad, apad);
915              
916 904 100         for (ix = 0; ix <= ixmax; ++ix) {
917             STRLEN ilen;
918             SV *elem;
919 580           svp = av_fetch((AV*)ival, ix, FALSE);
920 580 50         if (svp)
921 580           elem = *svp;
922             else
923 0           elem = &PL_sv_undef;
924            
925 580           ilen = inamelen;
926 580           sv_setiv(ixsv, ix);
927 580           ilen = ilen + my_sprintf(iname+ilen, "%" IVdf, (IV)ix);
928 580           iname[ilen++] = ']'; iname[ilen] = '\0';
929 580 100         if (style->indent >= 3) {
930 16           sv_catsv(retval, totpad);
931 16           sv_catsv(retval, ipad);
932 16           sv_catpvs(retval, "#");
933 16           sv_catsv(retval, ixsv);
934             }
935 580           sv_catsv(retval, totpad);
936 580           sv_catsv(retval, ipad);
937 580           ENTER;
938 580           SAVETMPS;
939 580           DD_dump(aTHX_ elem, iname, ilen, retval, seenhv, postav,
940             level+1, apad, style);
941 580 100         FREETMPS;
942 580           LEAVE;
943 580 100         if (ix < ixmax || (style->trailingcomma && style->indent >= 1))
    100          
    100          
944 375           sv_catpvs(retval, ",");
945             }
946 324 100         if (ixmax >= 0) {
947 209           SV * const opad = sv_x(aTHX_ Nullsv, SvPVX_const(style->xpad), SvCUR(style->xpad), level);
948 209           sv_catsv(retval, totpad);
949 209           sv_catsv(retval, opad);
950 209           SvREFCNT_dec(opad);
951             }
952 324 100         if (name[0] == '@')
953 24           sv_catpvs(retval, ")");
954             else
955 324           sv_catpvs(retval, "]");
956             }
957 244 100         else if (realtype == SVt_PVHV) {
958             SV *totpad, *newapad;
959             SV *sname;
960 233           HE *entry = NULL;
961             char *key;
962             SV *hval;
963 233           AV *keys = NULL;
964            
965 233           SV * const iname = newSVpvn_flags(name, namelen, SVs_TEMP);
966 233 100         if (name[0] == '%') {
967 11           sv_catpvs(retval, "(");
968 11           (SvPVX(iname))[0] = '$';
969             }
970             else {
971 222           sv_catpvs(retval, "{");
972             /* omit "->" in $foo[0]->{bar}, but not in ${$foo}->{bar} */
973 222 50         if ((namelen > 0
974 222 100         && name[namelen-1] != ']' && name[namelen-1] != '}')
    100          
975 104 50         || (namelen > 4
976 104 100         && (name[1] == '{'
977 88 50         || (name[0] == '\\' && name[2] == '{'))))
    0          
978             {
979 134           sv_catpvs(iname, "->");
980             }
981             }
982 233 100         if (name[0] == '*' && name[namelen-1] == '}' && namelen >= 8 &&
    100          
    50          
    50          
983 20 50         (instr(name+namelen-8, "{SCALAR}") ||
984 20 50         instr(name+namelen-7, "{ARRAY}") ||
985 20           instr(name+namelen-6, "{HASH}"))) {
986 20           sv_catpvs(iname, "->");
987             }
988 233           sv_catpvs(iname, "{");
989 233           totpad = sv_2mortal(newSVsv(style->sep));
990 233           sv_catsv(totpad, style->pad);
991 233           sv_catsv(totpad, apad);
992            
993             /* If requested, get a sorted/filtered array of hash keys */
994 233 100         if (style->sortkeys) {
995 118 100         if (style->sortkeys == &PL_sv_yes) {
996 103           keys = newAV();
997 103           (void)hv_iterinit((HV*)ival);
998 390 100         while ((entry = hv_iternext((HV*)ival))) {
999 287           sv = hv_iterkeysv(entry);
1000 287           (void)SvREFCNT_inc(sv);
1001 287           av_push(keys, sv);
1002             }
1003             #ifdef USE_LOCALE_COLLATE
1004             # ifdef IN_LC /* Use this if available */
1005 103 50         if (IN_LC(LC_COLLATE))
    50          
    0          
    50          
    50          
    50          
    50          
    0          
1006             # else
1007             if (IN_LOCALE)
1008             # endif
1009             {
1010 0           sortsv(AvARRAY(keys),
1011             av_len(keys)+1,
1012             Perl_sv_cmp_locale);
1013             }
1014             else
1015             #endif
1016             {
1017 103           sortsv(AvARRAY(keys),
1018             av_len(keys)+1,
1019             Perl_sv_cmp);
1020             }
1021             }
1022             else
1023             {
1024 15 50         dSP; ENTER; SAVETMPS; PUSHMARK(sp);
1025 15 50         XPUSHs(sv_2mortal(newRV_inc(ival))); PUTBACK;
1026 15           i = perl_call_sv(style->sortkeys, G_SCALAR | G_EVAL);
1027 15           SPAGAIN;
1028 15 50         if (i) {
1029 15           sv = POPs;
1030 15 50         if (SvROK(sv) && (SvTYPE(SvRV(sv)) == SVt_PVAV))
    100          
1031 14           keys = (AV*)SvREFCNT_inc(SvRV(sv));
1032             }
1033 15 100         if (! keys)
1034 1           warn("Sortkeys subroutine did not return ARRAYREF\n");
1035 15 50         PUTBACK; FREETMPS; LEAVE;
1036             }
1037 118 100         if (keys)
1038 118           sv_2mortal((SV*)keys);
1039             }
1040             else
1041 115           (void)hv_iterinit((HV*)ival);
1042              
1043             /* foreach (keys %hash) */
1044 233           for (i = 0; 1; i++) {
1045             char *nkey;
1046 955           char *nkey_buffer = NULL;
1047 955           STRLEN nticks = 0;
1048             SV* keysv;
1049             STRLEN klen;
1050             STRLEN keylen;
1051             STRLEN nlen;
1052 955           bool do_utf8 = FALSE;
1053              
1054 955 100         if (style->sortkeys) {
1055 584 100         if (!(keys && (SSize_t)i <= av_len(keys))) break;
    100          
1056             } else {
1057 371 100         if (!(entry = hv_iternext((HV *)ival))) break;
1058             }
1059              
1060 722 100         if (i)
1061 501           sv_catpvs(retval, ",");
1062              
1063 722 100         if (style->sortkeys) {
1064             char *key;
1065 466           svp = av_fetch(keys, i, FALSE);
1066 466 50         keysv = svp ? *svp : sv_newmortal();
1067 466 50         key = SvPV(keysv, keylen);
1068 466 100         svp = hv_fetch((HV*)ival, key,
1069             SvUTF8(keysv) ? -(I32)keylen : (I32)keylen, 0);
1070 466 50         hval = svp ? *svp : sv_newmortal();
1071             }
1072             else {
1073 256           keysv = hv_iterkeysv(entry);
1074 256           hval = hv_iterval((HV*)ival, entry);
1075             }
1076              
1077 722 50         key = SvPV(keysv, keylen);
1078 722 100         do_utf8 = DO_UTF8(keysv);
    50          
1079 722           klen = keylen;
1080              
1081 722           sv_catsv(retval, totpad);
1082 722           sv_catsv(retval, ipad);
1083              
1084 722           ENTER;
1085 722           SAVETMPS;
1086              
1087             /* The (very)
1088             old logic was first to check utf8 flag, and if utf8 always
1089             call esc_q_utf8. This caused test to break under -Mutf8,
1090             because there even strings like 'c' have utf8 flag on.
1091             Hence with quotekeys == 0 the XS code would still '' quote
1092             them based on flags, whereas the perl code would not,
1093             based on regexps.
1094              
1095             The old logic checked that the string was a valid
1096             perl glob name (foo::bar), which isn't safe under
1097             strict, and differs from the perl code which only
1098             accepts simple identifiers.
1099              
1100             With the fix for [perl #120384] I chose to make
1101             their handling of key quoting compatible between XS
1102             and perl.
1103             */
1104 722 100         if (style->quotekeys || key_needs_quote(key,keylen)) {
    100          
1105 1060 100         if (do_utf8 || style->useqq) {
    100          
1106 35           STRLEN ocur = SvCUR(retval);
1107 35           klen = nlen = esc_q_utf8(aTHX_ retval, key, klen, do_utf8, style->useqq);
1108 35           nkey = SvPVX(retval) + ocur;
1109             }
1110             else {
1111 495           nticks = num_q(key, klen);
1112 495           New(0, nkey_buffer, klen+nticks+3, char);
1113 495           SAVEFREEPV(nkey_buffer);
1114 495           nkey = nkey_buffer;
1115 495           nkey[0] = '\'';
1116 495 50         if (nticks)
1117 0           klen += esc_q(nkey+1, key, klen);
1118             else
1119 495           (void)Copy(key, nkey+1, klen, char);
1120 495           nkey[++klen] = '\'';
1121 495           nkey[++klen] = '\0';
1122 495           nlen = klen;
1123 495           sv_catpvn(retval, nkey, klen);
1124             }
1125             }
1126             else {
1127 192           nkey = key;
1128 192           nlen = klen;
1129 192           sv_catpvn(retval, nkey, klen);
1130             }
1131              
1132 722           sname = sv_2mortal(newSVsv(iname));
1133 722           sv_catpvn(sname, nkey, nlen);
1134 722           sv_catpvs(sname, "}");
1135              
1136 722           sv_catsv(retval, style->pair);
1137 722 100         if (style->indent >= 2) {
1138             char *extra;
1139 349           STRLEN elen = 0;
1140 349           newapad = sv_2mortal(newSVsv(apad));
1141 349           New(0, extra, klen+4+1, char);
1142 3824 100         while (elen < (klen+4))
1143 3475           extra[elen++] = ' ';
1144 349           extra[elen] = '\0';
1145 349           sv_catpvn(newapad, extra, elen);
1146 349           Safefree(extra);
1147             }
1148             else
1149 373           newapad = apad;
1150              
1151 722           DD_dump(aTHX_ hval, SvPVX_const(sname), SvCUR(sname), retval, seenhv,
1152             postav, level+1, newapad, style);
1153              
1154 722 50         FREETMPS;
1155 722           LEAVE;
1156 722           }
1157 233 100         if (i) {
1158 221           SV *opad = sv_x(aTHX_ Nullsv, SvPVX_const(style->xpad),
1159 221           SvCUR(style->xpad), level);
1160 221 100         if (style->trailingcomma && style->indent >= 1)
    100          
1161 4           sv_catpvs(retval, ",");
1162 221           sv_catsv(retval, totpad);
1163 221           sv_catsv(retval, opad);
1164 221           SvREFCNT_dec(opad);
1165             }
1166 233 100         if (name[0] == '%')
1167 11           sv_catpvs(retval, ")");
1168             else
1169 233           sv_catpvs(retval, "}");
1170             }
1171 11 50         else if (realtype == SVt_PVCV) {
1172 11 100         if (style->deparse) {
1173 5           SV *deparsed = sv_2mortal(deparsed_output(aTHX_ val));
1174 5           SV *fullpad = sv_2mortal(newSVsv(style->sep));
1175             const char *p;
1176             STRLEN plen;
1177             I32 i;
1178              
1179 5           sv_catsv(fullpad, style->pad);
1180 5           sv_catsv(fullpad, apad);
1181 9 100         for (i = 0; i < level; i++) {
1182 4           sv_catsv(fullpad, style->xpad);
1183             }
1184              
1185 5           sv_catpvs(retval, "sub ");
1186 5 50         p = SvPV(deparsed, plen);
1187 28 50         while (plen > 0) {
1188 23           const char *nl = (const char *) memchr(p, '\n', plen);
1189 23 100         if (!nl) {
1190 5           sv_catpvn(retval, p, plen);
1191 5           break;
1192             }
1193             else {
1194 18           size_t n = nl - p;
1195 18           sv_catpvn(retval, p, n);
1196 18           sv_catsv(retval, fullpad);
1197 18           p += n + 1;
1198 18           plen -= n + 1;
1199             }
1200             }
1201             }
1202             else {
1203 6           sv_catpvs(retval, "sub { \"DUMMY\" }");
1204 6 50         if (style->purity)
1205 11           warn("Encountered CODE ref, using dummy placeholder");
1206             }
1207             }
1208             else {
1209 0           warn("cannot handle ref type %d", (int)realtype);
1210             }
1211              
1212 755 100         if (realpack && !no_bless) { /* free blessed allocs */
    100          
1213             STRLEN plen, pticks;
1214              
1215 17 100         if (style->indent >= 2) {
1216 15           apad = blesspad;
1217             }
1218 17           sv_catpvs(retval, ", '");
1219              
1220 17           plen = strlen(realpack);
1221 17           pticks = num_q(realpack, plen);
1222 17 100         if (pticks) { /* needs escaping */
1223             char *npack;
1224 2           char *npack_buffer = NULL;
1225              
1226 2           New(0, npack_buffer, plen+pticks+1, char);
1227 2           npack = npack_buffer;
1228 2           plen += esc_q(npack, realpack, plen);
1229 2           npack[plen] = '\0';
1230              
1231 2           sv_catpvn(retval, npack, plen);
1232 2           Safefree(npack_buffer);
1233             }
1234             else {
1235 15           sv_catpvn(retval, realpack, strlen(realpack));
1236             }
1237 17           sv_catpvs(retval, "' )");
1238 17 50         if (style->toaster && SvPOK(style->toaster) && SvCUR(style->toaster)) {
    50          
    50          
1239 0           sv_catpvs(retval, "->");
1240 0           sv_catsv(retval, style->toaster);
1241 755           sv_catpvs(retval, "()");
1242             }
1243             }
1244             }
1245             else {
1246             STRLEN i;
1247             const MAGIC *mg;
1248            
1249 1526 50         if (namelen) {
1250 1526           id_buffer = PTR2UV(val);
1251 1526           idlen = sizeof(id_buffer);
1252 1526 100         if ((svp = hv_fetch(seenhv, id, idlen, FALSE)) &&
    50          
1253 110 50         (sv = *svp) && SvROK(sv) &&
    50          
1254 110           (seenentry = (AV*)SvRV(sv)))
1255 102           {
1256             SV *othername;
1257 110 50         if ((svp = av_fetch(seenentry, 0, FALSE)) && (othername = *svp)
    50          
1258 110 100         && (svp = av_fetch(seenentry, 2, FALSE)) && *svp && SvIV(*svp) > 0)
    50          
    50          
    50          
1259             {
1260 8           sv_catpvs(retval, "${");
1261 8           sv_catsv(retval, othername);
1262 8           sv_catpvs(retval, "}");
1263 8           return 1;
1264             }
1265             }
1266             /* If we're allowed to keep only a sparse "seen" hash
1267             * (IOW, the user does not expect it to contain everything
1268             * after the dump, then only store in seen hash if the SV
1269             * ref count is larger than 1. If it's 1, then we know that
1270             * there is no other reference, duh. This is an optimization.
1271             * Note that we'd have to check for weak-refs, too, but this is
1272             * already the branch for non-refs only. */
1273 1416 50         else if (val != &PL_sv_undef && (!style->use_sparse_seen_hash || SvREFCNT(val) > 1)) {
    100          
    50          
1274 1400           SV * const namesv = newSVpvs("\\");
1275 1400           sv_catpvn(namesv, name, namelen);
1276 1400           seenentry = newAV();
1277 1400           av_push(seenentry, namesv);
1278 1400           av_push(seenentry, newRV_inc(val));
1279 1400           (void)hv_store(seenhv, id, idlen, newRV_inc((SV*)seenentry), 0);
1280 1400           SvREFCNT_dec(seenentry);
1281             }
1282             }
1283              
1284 1518 100         if (DD_is_integer(val)) {
1285             STRLEN len;
1286 419 50         if (SvIsUV(val))
1287 0 0         len = my_snprintf(tmpbuf, sizeof(tmpbuf), "%" UVuf, SvUV(val));
    0          
1288             else
1289 419 50         len = my_snprintf(tmpbuf, sizeof(tmpbuf), "%" IVdf, SvIV(val));
    50          
1290 419 100         if (SvPOK(val)) {
1291             /* Need to check to see if this is a string such as " 0".
1292             I'm assuming from sprintf isn't going to clash with utf8. */
1293             STRLEN pvlen;
1294 120 50         const char * const pv = SvPV(val, pvlen);
1295 120 100         if (pvlen != len || memNE(pv, tmpbuf, len))
    50          
1296             goto integer_came_from_string;
1297             }
1298 387 100         if (len > 10) {
1299             /* Looks like we're on a 64 bit system. Make it a string so that
1300             if a 32 bit system reads the number it will cope better. */
1301 12           sv_catpvf(retval, "'%s'", tmpbuf);
1302             } else
1303 387           sv_catpvn(retval, tmpbuf, len);
1304             }
1305 1099 100         else if (realtype == SVt_PVGV) {/* GLOBs can end up with scribbly names */
1306 75 50         c = SvPV(val, i);
1307 75 50         if(i) ++c, --i; /* just get the name */
1308 75 50         if (memBEGINs(c, i, "main::")) {
    100          
1309 53           c += 4;
1310 53 100         if (i == 6)
1311 53           i = 0; else i -= 4;
1312             }
1313 75 100         if (globname_needs_quote(c,i)) {
1314 44           sv_grow(retval, SvCUR(retval)+3);
1315 44           r = SvPVX(retval)+SvCUR(retval);
1316 44           r[0] = '*'; r[1] = '{'; r[2] = 0;
1317 44           SvCUR_set(retval, SvCUR(retval)+2);
1318 44           i = 3 + esc_q_utf8(aTHX_ retval, c, i,
1319             #ifdef GvNAMEUTF8
1320 44           !!GvNAMEUTF8(val), style->useqq
1321             #else
1322             0, style->useqq || globname_supra_ascii(c, i)
1323             #endif
1324             );
1325 44           sv_grow(retval, SvCUR(retval)+2);
1326 44           r = SvPVX(retval)+SvCUR(retval);
1327 44           r[0] = '}'; r[1] = '\0';
1328 44           SvCUR_set(retval, SvCUR(retval)+1);
1329 44           r = r+1 - i;
1330             }
1331             else {
1332 31           sv_grow(retval, SvCUR(retval)+i+2);
1333 31           r = SvPVX(retval)+SvCUR(retval);
1334 31           r[0] = '*'; strlcpy(r+1, c, SvLEN(retval));
1335 31           i++;
1336 31           SvCUR_set(retval, SvCUR(retval)+i);
1337             }
1338              
1339 75 100         if (style->purity) {
1340             static const char* const entries[] = { "{SCALAR}", "{ARRAY}", "{HASH}" };
1341             static const STRLEN sizes[] = { 8, 7, 6 };
1342             SV *e;
1343 24           SV * const nname = newSVpvs("");
1344 24           SV * const newapad = newSVpvs("");
1345 24           GV * const gv = (GV*)val;
1346             I32 j;
1347            
1348 96 100         for (j=0; j<3; j++) {
1349 72 100         e = ((j == 0) ? GvSV(gv) : (j == 1) ? (SV*)GvAV(gv) : (SV*)GvHV(gv));
    100          
1350 72 100         if (!e)
1351 16           continue;
1352 56 100         if (j == 0 && !SvOK(e))
    100          
    50          
    50          
1353 12           continue;
1354              
1355             {
1356 44           SV *postentry = newSVpvn(r,i);
1357            
1358 44           sv_setsv(nname, postentry);
1359 44           sv_catpvn(nname, entries[j], sizes[j]);
1360 44           sv_catpvs(postentry, " = ");
1361 44           av_push(postav, postentry);
1362 44           e = newRV_inc(e);
1363            
1364 44           SvCUR_set(newapad, 0);
1365 44 100         if (style->indent >= 2)
1366 6           (void)sv_x(aTHX_ newapad, " ", 1, SvCUR(postentry));
1367            
1368 44           DD_dump(aTHX_ e, SvPVX_const(nname), SvCUR(nname), postentry,
1369             seenhv, postav, 0, newapad, style);
1370 44           SvREFCNT_dec(e);
1371             }
1372             }
1373            
1374 24           SvREFCNT_dec(newapad);
1375 75           SvREFCNT_dec(nname);
1376             }
1377             }
1378 1024 50         else if (val == &PL_sv_undef || !SvOK(val)) {
    100          
    50          
    50          
1379 12           sv_catpvs(retval, "undef");
1380             }
1381             #ifdef SvVOK
1382 1012 100         else if (SvMAGICAL(val) && (mg = mg_find(val, 'V'))) {
    100          
1383             # if !defined(PL_vtbl_vstring) && PERL_VERSION_LT(5,17,0)
1384             SV * const vecsv = sv_newmortal();
1385             # if PERL_VERSION_LT(5,10,0)
1386             scan_vstring(mg->mg_ptr, vecsv);
1387             # else
1388             scan_vstring(mg->mg_ptr, mg->mg_ptr + mg->mg_len, vecsv);
1389             # endif
1390             if (!sv_eq(vecsv, val)) goto integer_came_from_string;
1391             # endif
1392 6           sv_catpvn(retval, (const char *)mg->mg_ptr, mg->mg_len);
1393             }
1394             #endif
1395              
1396             else {
1397             integer_came_from_string:
1398 1038 100         c = SvPV(val, i);
1399             /* the pure perl and XS non-qq outputs have historically been
1400             * different in this case, but for useqq, let's try to match
1401             * the pure perl code.
1402             * see [perl #74798]
1403             */
1404 1038 100         if (style->useqq && safe_decimal_number(c, i)) {
    100          
1405 2           sv_catsv(retval, val);
1406             }
1407 1036 100         else if (DO_UTF8(val) || style->useqq)
    50          
    100          
1408 65 100         i += esc_q_utf8(aTHX_ retval, c, i, DO_UTF8(val), style->useqq);
    50          
1409             else {
1410 971           sv_grow(retval, SvCUR(retval)+3+2*i); /* 3: ""\0 */
1411 971           r = SvPVX(retval) + SvCUR(retval);
1412 971           r[0] = '\'';
1413 971           i += esc_q(r+1, c, i);
1414 971           ++i;
1415 971           r[i++] = '\'';
1416 971           r[i] = '\0';
1417 1518           SvCUR_set(retval, SvCUR(retval)+i);
1418             }
1419             }
1420             }
1421              
1422 2273 50         if (idlen) {
1423 2273 100         if (style->deepcopy)
1424 90           (void)hv_delete(seenhv, id, idlen, G_DISCARD);
1425 2183 50         else if (namelen && seenentry) {
    100          
1426 2167           SV *mark = *av_fetch(seenentry, 2, TRUE);
1427 2167           sv_setiv(mark,1);
1428             }
1429             }
1430 2611           return 1;
1431             }
1432              
1433              
1434             MODULE = Data::Dumper PACKAGE = Data::Dumper PREFIX = Data_Dumper_
1435              
1436             #
1437             # This is the exact equivalent of Dump. Well, almost. The things that are
1438             # different as of now (due to Laziness):
1439             # * doesn't do deparse yet.'
1440             #
1441              
1442             void
1443             Data_Dumper_Dumpxs(href, ...)
1444             SV *href;
1445             PROTOTYPE: $;$$
1446             PPCODE:
1447             {
1448             HV *hv;
1449             SV *retval, *valstr;
1450 373           HV *seenhv = NULL;
1451             AV *postav, *todumpav, *namesav;
1452 373           I32 terse = 0;
1453             SSize_t i, imax, postlen;
1454             SV **svp;
1455 373           SV *apad = &PL_sv_undef;
1456             Style style;
1457              
1458 373           SV *name_sv, *val = &PL_sv_undef, *varname = &PL_sv_undef;
1459 373 100         I32 gimme = GIMME_V;
1460              
1461 373 100         if (!SvROK(href)) { /* call new to get an object first */
1462 153 50         if (items < 2)
1463 0           croak("Usage: Data::Dumper::Dumpxs(PACKAGE, VAL_ARY_REF, [NAME_ARY_REF])");
1464            
1465 153           ENTER;
1466 153           SAVETMPS;
1467            
1468 153 50         PUSHMARK(sp);
1469 153 50         EXTEND(SP, 3); /* 3 == max of all branches below */
1470 153           PUSHs(href);
1471 153           PUSHs(sv_2mortal(newSVsv(ST(1))));
1472 153 100         if (items >= 3)
1473 56           PUSHs(sv_2mortal(newSVsv(ST(2))));
1474 153           PUTBACK;
1475 153           i = perl_call_method("new", G_SCALAR);
1476 153           SPAGAIN;
1477 153 50         if (i)
1478 153           href = newSVsv(POPs);
1479              
1480 153           PUTBACK;
1481 153 50         FREETMPS;
1482 153           LEAVE;
1483 153 50         if (i)
1484 153           (void)sv_2mortal(href);
1485             }
1486              
1487 373           todumpav = namesav = NULL;
1488 373           style.indent = 2;
1489 373           style.quotekeys = 1;
1490 373           style.maxrecurse = 1000;
1491 373           style.maxrecursed = FALSE;
1492 373           style.purity = style.deepcopy = style.useqq = style.maxdepth
1493 373           = style.use_sparse_seen_hash = style.trailingcomma = 0;
1494 373           style.pad = style.xpad = style.sep = style.pair = style.sortkeys
1495 373           = style.freezer = style.toaster = style.bless = &PL_sv_undef;
1496 373           seenhv = NULL;
1497 373           name_sv = sv_newmortal();
1498            
1499 373           retval = newSVpvs_flags("", SVs_TEMP);
1500 373 50         if (SvROK(href)
1501 373 50         && (hv = (HV*)SvRV((SV*)href))
1502 373 50         && SvTYPE(hv) == SVt_PVHV) {
1503              
1504 373 50         if ((svp = hv_fetchs(hv, "seen", FALSE)) && SvROK(*svp))
    50          
1505 373           seenhv = (HV*)SvRV(*svp);
1506             else
1507 0           style.use_sparse_seen_hash = 1;
1508 373 50         if ((svp = hv_fetchs(hv, "noseen", FALSE)))
1509 373 100         style.use_sparse_seen_hash = (SvOK(*svp) && SvIV(*svp) != 0);
    50          
    50          
    50          
    100          
    0          
1510 373 50         if ((svp = hv_fetchs(hv, "todump", FALSE)) && SvROK(*svp))
    50          
1511 373           todumpav = (AV*)SvRV(*svp);
1512 373 50         if ((svp = hv_fetchs(hv, "names", FALSE)) && SvROK(*svp))
    50          
1513 373           namesav = (AV*)SvRV(*svp);
1514 373 50         if ((svp = hv_fetchs(hv, "indent", FALSE)))
1515 373 50         style.indent = SvIV(*svp);
1516 373 50         if ((svp = hv_fetchs(hv, "purity", FALSE)))
1517 373 50         style.purity = SvIV(*svp);
1518 373 50         if ((svp = hv_fetchs(hv, "terse", FALSE)))
1519 373 50         terse = SvTRUE(*svp);
    50          
    0          
    100          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
1520 373 50         if ((svp = hv_fetchs(hv, "useqq", FALSE)))
1521 373 50         style.useqq = SvTRUE(*svp);
    50          
    0          
    100          
    50          
    50          
    100          
    50          
    50          
    50          
    0          
    50          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
1522 373 50         if ((svp = hv_fetchs(hv, "pad", FALSE)))
1523 373           style.pad = *svp;
1524 373 50         if ((svp = hv_fetchs(hv, "xpad", FALSE)))
1525 373           style.xpad = *svp;
1526 373 50         if ((svp = hv_fetchs(hv, "apad", FALSE)))
1527 373           apad = *svp;
1528 373 50         if ((svp = hv_fetchs(hv, "sep", FALSE)))
1529 373           style.sep = *svp;
1530 373 50         if ((svp = hv_fetchs(hv, "pair", FALSE)))
1531 373           style.pair = *svp;
1532 373 50         if ((svp = hv_fetchs(hv, "varname", FALSE)))
1533 373           varname = *svp;
1534 373 50         if ((svp = hv_fetchs(hv, "freezer", FALSE)))
1535 373           style.freezer = *svp;
1536 373 50         if ((svp = hv_fetchs(hv, "toaster", FALSE)))
1537 373           style.toaster = *svp;
1538 373 50         if ((svp = hv_fetchs(hv, "deepcopy", FALSE)))
1539 373 50         style.deepcopy = SvTRUE(*svp);
    50          
    0          
    100          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
1540 373 50         if ((svp = hv_fetchs(hv, "quotekeys", FALSE)))
1541 373 50         style.quotekeys = SvTRUE(*svp);
    50          
    0          
    100          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
1542 373 50         if ((svp = hv_fetchs(hv, "trailingcomma", FALSE)))
1543 373 50         style.trailingcomma = SvTRUE(*svp);
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
1544 373 50         if ((svp = hv_fetchs(hv, "deparse", FALSE)))
1545 373 50         style.deparse = SvTRUE(*svp);
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
1546 373 50         if ((svp = hv_fetchs(hv, "bless", FALSE)))
1547 373           style.bless = *svp;
1548 373 50         if ((svp = hv_fetchs(hv, "maxdepth", FALSE)))
1549 373 50         style.maxdepth = SvIV(*svp);
1550 373 50         if ((svp = hv_fetchs(hv, "maxrecurse", FALSE)))
1551 373 50         style.maxrecurse = SvIV(*svp);
1552 373 50         if ((svp = hv_fetchs(hv, "sortkeys", FALSE))) {
1553 373           SV *sv = *svp;
1554 373 50         if (! SvTRUE(sv))
    50          
    0          
    100          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    100          
    50          
    100          
    50          
    0          
    100          
    50          
1555 177           style.sortkeys = NULL;
1556 196 100         else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVCV)
    50          
1557 10           style.sortkeys = sv;
1558             else
1559             /* flag to use sortsv() for sorting hash keys */
1560 186           style.sortkeys = &PL_sv_yes;
1561             }
1562 373           postav = newAV();
1563 373           sv_2mortal((SV*)postav);
1564              
1565 373 50         if (todumpav)
1566 373           imax = av_len(todumpav);
1567             else
1568 0           imax = -1;
1569 373           valstr = newSVpvs_flags("", SVs_TEMP);
1570 1505 100         for (i = 0; i <= imax; ++i) {
1571             SV *newapad;
1572             char *name;
1573             STRLEN name_len;
1574            
1575 1132           av_clear(postav);
1576 1132 50         if ((svp = av_fetch(todumpav, i, FALSE)))
1577 1132           val = *svp;
1578             else
1579 0           val = &PL_sv_undef;
1580 1132 50         if ((svp = av_fetch(namesav, i, TRUE))) {
1581 1132 100         if (SvOK(*svp)) {
    50          
    50          
1582 270           sv_setsv(name_sv, *svp);
1583 270 100         name = SvPV(name_sv, name_len);
1584             }
1585             else {
1586 1132           name = NULL;
1587             }
1588             }
1589             else {
1590 0           name = NULL;
1591             }
1592            
1593 1132 100         if (name) {
1594 270 100         if (*name == '*') {
1595 81 100         if (SvROK(val)) {
1596 79           switch (SvTYPE(SvRV(val))) {
1597             case SVt_PVAV:
1598 28           *name = '@';
1599 28           break;
1600             case SVt_PVHV:
1601 37           *name = '%';
1602 37           break;
1603             case SVt_PVCV:
1604 4           *name = '*';
1605 4           break;
1606             default:
1607 10           *name = '$';
1608 79           break;
1609             }
1610             }
1611             else
1612 81           *name = '$';
1613             }
1614 189 100         else if (*name != '$') {
1615 187           sv_insert(name_sv, 0, 0, "$", 1);
1616 270 50         name = SvPV(name_sv, name_len);
1617             }
1618             }
1619             else {
1620 862           sv_setpvf(name_sv, "$%" SVf "%" IVdf, SVfARG(varname), (IV)(i+1));
1621 862 50         name = SvPV(name_sv, name_len);
1622             }
1623            
1624 1378 100         if (style.indent >= 2 && !terse) {
    100          
1625 246           SV * const tmpsv = sv_x(aTHX_ NULL, " ", 1, name_len + 3);
1626 246           newapad = sv_2mortal(newSVsv(apad));
1627 246           sv_catsv(newapad, tmpsv);
1628 246           SvREFCNT_dec(tmpsv);
1629             }
1630             else
1631 886           newapad = apad;
1632            
1633 1132           ENTER;
1634 1132           SAVETMPS;
1635 1132           PUTBACK;
1636 1132           DD_dump(aTHX_ val, name, name_len, valstr, seenhv,
1637             postav, 0, newapad, &style);
1638 1132           SPAGAIN;
1639 1132 100         FREETMPS;
1640 1132           LEAVE;
1641              
1642 1132           postlen = av_len(postav);
1643 1132 100         if (postlen >= 0 || !terse) {
    100          
1644 1123           sv_insert(valstr, 0, 0, " = ", 3);
1645 1123           sv_insert(valstr, 0, 0, name, name_len);
1646 1123           sv_catpvs(valstr, ";");
1647             }
1648 1132           sv_catsv(retval, style.pad);
1649 1132           sv_catsv(retval, valstr);
1650 1132           sv_catsv(retval, style.sep);
1651 1132 100         if (postlen >= 0) {
1652             SSize_t i;
1653 36           sv_catsv(retval, style.pad);
1654 168 100         for (i = 0; i <= postlen; ++i) {
1655             SV *elem;
1656 132           svp = av_fetch(postav, i, FALSE);
1657 132 50         if (svp && (elem = *svp)) {
    50          
1658 132           sv_catsv(retval, elem);
1659 132 100         if (i < postlen) {
1660 96           sv_catpvs(retval, ";");
1661 96           sv_catsv(retval, style.sep);
1662 96           sv_catsv(retval, style.pad);
1663             }
1664             }
1665             }
1666 36           sv_catpvs(retval, ";");
1667 36           sv_catsv(retval, style.sep);
1668             }
1669 1132           SvPVCLEAR(valstr);
1670 1132 100         if (gimme == G_ARRAY) {
1671 241 50         XPUSHs(retval);
1672 241 100         if (i < imax) /* not the last time thro ? */
1673 79           retval = newSVpvs_flags("", SVs_TEMP);
1674             }
1675             }
1676              
1677             /* we defer croaking until here so that temporary SVs and
1678             * buffers won't be leaked */
1679 373 100         if (style.maxrecursed)
1680 4           croak("Recursion limit of %" IVdf " exceeded",
1681             style.maxrecurse);
1682            
1683             }
1684             else
1685 0           croak("Call to new() method failed to return HASH ref");
1686 369 100         if (gimme != G_ARRAY)
1687 207 50         XPUSHs(retval);
1688             }
1689              
1690             SV *
1691             Data_Dumper__vstring(sv)
1692             SV *sv;
1693             PROTOTYPE: $
1694             CODE:
1695             {
1696             #ifdef SvVOK
1697             const MAGIC *mg;
1698 1711           RETVAL =
1699 6 50         SvMAGICAL(sv) && (mg = mg_find(sv, 'V'))
1700 6           ? newSVpvn((const char *)mg->mg_ptr, mg->mg_len)
1701 1717 100         : &PL_sv_undef;
1702             #else
1703             RETVAL = &PL_sv_undef;
1704             #endif
1705             }
1706             OUTPUT: RETVAL