File Coverage

Dumper.xs
Criterion Covered Total %
statement 850 879 96.7
branch 746 1158 64.4
condition n/a
subroutine n/a
pod n/a
total 1596 2037 78.3


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 1448           sv_x(pTHX_ SV *sv, const char *str, STRLEN len, I32 n)
424             {
425 1448 100         if (!sv)
426 1427           sv = newSVpvs("");
427             #ifdef DEBUGGING
428             else
429             assert(SvTYPE(sv) >= SVt_PV);
430             #endif
431              
432 1448 100         if (n > 0) {
433 1168 50         SvGROW(sv, len*n + SvCUR(sv) + 1);
    100          
434 1168 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 2559 100         while (n > 0) {
443 1658           sv_catpvn(sv, str, len);
444 1658           --n;
445             }
446             }
447 1448           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 2607           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 2607           char *const id = (char *)&id_buffer;
662             SV **svp;
663             SV *sv, *ipad, *ival;
664 2607           SV *blesspad = Nullsv;
665 2607           AV *seenentry = NULL;
666             char *iname;
667 2607           STRLEN inamelen, idlen = 0;
668             U32 realtype;
669 2607           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 2607           bool is_regex = 0; /* we are dumping a regex, we need to know this before we bless */
674              
675 2607 50         if (!val)
676 0           return 0;
677              
678 2607 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 2606 50         if (SvTYPE(retval) >= SVt_PV && (SvLEN(retval) - SvCUR(retval)) < 42) {
    100          
686 2147           sv_grow(retval, SvCUR(retval) * 3 / 2);
687             }
688              
689 2606           realtype = SvTYPE(val);
690              
691 2606 50         if (SvGMAGICAL(val))
692 0           mg_get(val);
693 2606 100         if (SvROK(val)) {
694              
695             /* If a freeze method is provided and the object has it, call
696             it. Warn on errors. */
697 1080 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 1080           ival = SvRV(val);
712 1080           realtype = SvTYPE(ival);
713 1080           id_buffer = PTR2UV(ival);
714 1080           idlen = sizeof(id_buffer);
715 1080 100         if (SvOBJECT(ival))
716 70 50         realpack = HvNAME_get(SvSTASH(ival));
    50          
    50          
    0          
    50          
    50          
717             else
718 1010           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 1080 50         if (namelen) {
724 1080 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 757 100         if (name[0] == '@' || name[0] == '%') {
    100          
772 35           namesv = newSVpvs("\\");
773 35           sv_catpvn(namesv, name, namelen);
774             }
775 722 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 720           namesv = newSVpvn(name, namelen);
782 757           seenentry = newAV();
783 757           av_push(seenentry, namesv);
784 757           (void)SvREFCNT_inc(val);
785 757           av_push(seenentry, val);
786 757           (void)hv_store(seenhv, id, idlen,
787             newRV_inc((SV*)seenentry), 0);
788 757           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 757 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 757 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 751 100         if (style->maxrecurse > 0 && level >= style->maxrecurse) {
    100          
822 4           style->maxrecursed = TRUE;
823             }
824              
825 751 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 751           ipad = sv_x(aTHX_ Nullsv, SvPVX_const(style->xpad), SvCUR(style->xpad), level+1);
838 751           sv_2mortal(ipad);
839              
840 751 100         if (is_regex) {
841 54           dump_regexp(aTHX_ retval, val);
842             }
843 697 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 618 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 564 100         else if (realtype == SVt_PVAV) {
875             SV *totpad;
876 322           SSize_t ix = 0;
877 322           const SSize_t ixmax = av_len((AV *)ival);
878            
879 322           SV * const ixsv = sv_2mortal(newSViv(0));
880             /* allowing for a 24 char wide array index */
881 322           New(0, iname, namelen+28, char);
882 322           SAVEFREEPV(iname);
883 322           (void) strlcpy(iname, name, namelen+28);
884 322           inamelen = namelen;
885 322 100         if (name[0] == '@') {
886 24           sv_catpvs(retval, "(");
887 24           iname[0] = '$';
888             }
889             else {
890 298           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 298 50         if ((namelen > 0
896 298 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 120           iname[inamelen++] = '-'; iname[inamelen++] = '>';
902 120           iname[inamelen] = '\0';
903             }
904             }
905 322 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 322           iname[inamelen++] = '['; iname[inamelen] = '\0';
912 322           totpad = sv_2mortal(newSVsv(style->sep));
913 322           sv_catsv(totpad, style->pad);
914 322           sv_catsv(totpad, apad);
915              
916 902 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 322 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 322 100         if (name[0] == '@')
953 24           sv_catpvs(retval, ")");
954             else
955 322           sv_catpvs(retval, "]");
956             }
957 242 100         else if (realtype == SVt_PVHV) {
958             SV *totpad, *newapad;
959             SV *sname;
960 231           HE *entry = NULL;
961             char *key;
962             SV *hval;
963 231           AV *keys = NULL;
964            
965 231           SV * const iname = newSVpvn_flags(name, namelen, SVs_TEMP);
966 231 100         if (name[0] == '%') {
967 11           sv_catpvs(retval, "(");
968 11           (SvPVX(iname))[0] = '$';
969             }
970             else {
971 220           sv_catpvs(retval, "{");
972             /* omit "->" in $foo[0]->{bar}, but not in ${$foo}->{bar} */
973 220 50         if ((namelen > 0
974 220 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 132           sv_catpvs(iname, "->");
980             }
981             }
982 231 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 231           sv_catpvs(iname, "{");
989 231           totpad = sv_2mortal(newSVsv(style->sep));
990 231           sv_catsv(totpad, style->pad);
991 231           sv_catsv(totpad, apad);
992            
993             /* If requested, get a sorted/filtered array of hash keys */
994 231 100         if (style->sortkeys) {
995 116 100         if (style->sortkeys == &PL_sv_yes) {
996 101           keys = newAV();
997 101           (void)hv_iterinit((HV*)ival);
998 388 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 101 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 101           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 116 100         if (keys)
1038 116           sv_2mortal((SV*)keys);
1039             }
1040             else
1041 115           (void)hv_iterinit((HV*)ival);
1042              
1043             /* foreach (keys %hash) */
1044 231           for (i = 0; 1; i++) {
1045             char *nkey;
1046 953           char *nkey_buffer = NULL;
1047 953           STRLEN nticks = 0;
1048             SV* keysv;
1049             STRLEN klen;
1050             STRLEN keylen;
1051             STRLEN nlen;
1052 953           bool do_utf8 = FALSE;
1053              
1054 953 100         if (style->sortkeys) {
1055 582 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 231 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 231 100         if (name[0] == '%')
1167 11           sv_catpvs(retval, ")");
1168             else
1169 231           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 751 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 751           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 2269 50         if (idlen) {
1423 2269 100         if (style->deepcopy)
1424 90           (void)hv_delete(seenhv, id, idlen, G_DISCARD);
1425 2179 50         else if (namelen && seenentry) {
    100          
1426 2163           SV *mark = *av_fetch(seenentry, 2, TRUE);
1427 2163           sv_setiv(mark,1);
1428             }
1429             }
1430 2607           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 371           HV *seenhv = NULL;
1451             AV *postav, *todumpav, *namesav;
1452 371           I32 terse = 0;
1453             SSize_t i, imax, postlen;
1454             SV **svp;
1455 371           SV *apad = &PL_sv_undef;
1456             Style style;
1457              
1458 371           SV *name, *val = &PL_sv_undef, *varname = &PL_sv_undef;
1459             char tmpbuf[1024];
1460 371 100         I32 gimme = GIMME_V;
1461              
1462 371 100         if (!SvROK(href)) { /* call new to get an object first */
1463 151 50         if (items < 2)
1464 0           croak("Usage: Data::Dumper::Dumpxs(PACKAGE, VAL_ARY_REF, [NAME_ARY_REF])");
1465            
1466 151           ENTER;
1467 151           SAVETMPS;
1468            
1469 151 50         PUSHMARK(sp);
1470 151 50         EXTEND(SP, 3); /* 3 == max of all branches below */
1471 151           PUSHs(href);
1472 151           PUSHs(sv_2mortal(newSVsv(ST(1))));
1473 151 100         if (items >= 3)
1474 54           PUSHs(sv_2mortal(newSVsv(ST(2))));
1475 151           PUTBACK;
1476 151           i = perl_call_method("new", G_SCALAR);
1477 151           SPAGAIN;
1478 151 50         if (i)
1479 151           href = newSVsv(POPs);
1480              
1481 151           PUTBACK;
1482 151 50         FREETMPS;
1483 151           LEAVE;
1484 151 50         if (i)
1485 151           (void)sv_2mortal(href);
1486             }
1487              
1488 371           todumpav = namesav = NULL;
1489 371           style.indent = 2;
1490 371           style.quotekeys = 1;
1491 371           style.maxrecurse = 1000;
1492 371           style.maxrecursed = FALSE;
1493 371           style.purity = style.deepcopy = style.useqq = style.maxdepth
1494 371           = style.use_sparse_seen_hash = style.trailingcomma = 0;
1495 371           style.pad = style.xpad = style.sep = style.pair = style.sortkeys
1496 371           = style.freezer = style.toaster = style.bless = &PL_sv_undef;
1497 371           seenhv = NULL;
1498 371           name = sv_newmortal();
1499            
1500 371           retval = newSVpvs_flags("", SVs_TEMP);
1501 371 50         if (SvROK(href)
1502 371 50         && (hv = (HV*)SvRV((SV*)href))
1503 371 50         && SvTYPE(hv) == SVt_PVHV) {
1504              
1505 371 50         if ((svp = hv_fetchs(hv, "seen", FALSE)) && SvROK(*svp))
    50          
1506 371           seenhv = (HV*)SvRV(*svp);
1507             else
1508 0           style.use_sparse_seen_hash = 1;
1509 371 50         if ((svp = hv_fetchs(hv, "noseen", FALSE)))
1510 371 100         style.use_sparse_seen_hash = (SvOK(*svp) && SvIV(*svp) != 0);
    50          
    50          
    50          
    100          
    0          
1511 371 50         if ((svp = hv_fetchs(hv, "todump", FALSE)) && SvROK(*svp))
    50          
1512 371           todumpav = (AV*)SvRV(*svp);
1513 371 50         if ((svp = hv_fetchs(hv, "names", FALSE)) && SvROK(*svp))
    50          
1514 371           namesav = (AV*)SvRV(*svp);
1515 371 50         if ((svp = hv_fetchs(hv, "indent", FALSE)))
1516 371 50         style.indent = SvIV(*svp);
1517 371 50         if ((svp = hv_fetchs(hv, "purity", FALSE)))
1518 371 50         style.purity = SvIV(*svp);
1519 371 50         if ((svp = hv_fetchs(hv, "terse", FALSE)))
1520 371 50         terse = SvTRUE(*svp);
    50          
    0          
    100          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
1521 371 50         if ((svp = hv_fetchs(hv, "useqq", FALSE)))
1522 371 50         style.useqq = SvTRUE(*svp);
    50          
    0          
    100          
    50          
    50          
    100          
    50          
    50          
    50          
    0          
    50          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
1523 371 50         if ((svp = hv_fetchs(hv, "pad", FALSE)))
1524 371           style.pad = *svp;
1525 371 50         if ((svp = hv_fetchs(hv, "xpad", FALSE)))
1526 371           style.xpad = *svp;
1527 371 50         if ((svp = hv_fetchs(hv, "apad", FALSE)))
1528 371           apad = *svp;
1529 371 50         if ((svp = hv_fetchs(hv, "sep", FALSE)))
1530 371           style.sep = *svp;
1531 371 50         if ((svp = hv_fetchs(hv, "pair", FALSE)))
1532 371           style.pair = *svp;
1533 371 50         if ((svp = hv_fetchs(hv, "varname", FALSE)))
1534 371           varname = *svp;
1535 371 50         if ((svp = hv_fetchs(hv, "freezer", FALSE)))
1536 371           style.freezer = *svp;
1537 371 50         if ((svp = hv_fetchs(hv, "toaster", FALSE)))
1538 371           style.toaster = *svp;
1539 371 50         if ((svp = hv_fetchs(hv, "deepcopy", FALSE)))
1540 371 50         style.deepcopy = SvTRUE(*svp);
    50          
    0          
    100          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
1541 371 50         if ((svp = hv_fetchs(hv, "quotekeys", FALSE)))
1542 371 50         style.quotekeys = SvTRUE(*svp);
    50          
    0          
    100          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
1543 371 50         if ((svp = hv_fetchs(hv, "trailingcomma", FALSE)))
1544 371 50         style.trailingcomma = SvTRUE(*svp);
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
1545 371 50         if ((svp = hv_fetchs(hv, "deparse", FALSE)))
1546 371 50         style.deparse = SvTRUE(*svp);
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
1547 371 50         if ((svp = hv_fetchs(hv, "bless", FALSE)))
1548 371           style.bless = *svp;
1549 371 50         if ((svp = hv_fetchs(hv, "maxdepth", FALSE)))
1550 371 50         style.maxdepth = SvIV(*svp);
1551 371 50         if ((svp = hv_fetchs(hv, "maxrecurse", FALSE)))
1552 371 50         style.maxrecurse = SvIV(*svp);
1553 371 50         if ((svp = hv_fetchs(hv, "sortkeys", FALSE))) {
1554 371           SV *sv = *svp;
1555 371 50         if (! SvTRUE(sv))
    50          
    0          
    100          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    100          
    50          
    100          
    50          
    0          
    100          
    50          
1556 177           style.sortkeys = NULL;
1557 194 100         else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVCV)
    50          
1558 10           style.sortkeys = sv;
1559             else
1560             /* flag to use sortsv() for sorting hash keys */
1561 184           style.sortkeys = &PL_sv_yes;
1562             }
1563 371           postav = newAV();
1564 371           sv_2mortal((SV*)postav);
1565              
1566 371 50         if (todumpav)
1567 371           imax = av_len(todumpav);
1568             else
1569 0           imax = -1;
1570 371           valstr = newSVpvs_flags("", SVs_TEMP);
1571 1499 100         for (i = 0; i <= imax; ++i) {
1572             SV *newapad;
1573            
1574 1128           av_clear(postav);
1575 1128 50         if ((svp = av_fetch(todumpav, i, FALSE)))
1576 1128           val = *svp;
1577             else
1578 0           val = &PL_sv_undef;
1579 1128 50         if ((svp = av_fetch(namesav, i, TRUE))) {
1580 1128           sv_setsv(name, *svp);
1581 1128 100         if (SvOK(*svp) && !SvPOK(*svp))
    50          
    50          
    100          
1582 1128 50         (void)SvPV_nolen_const(name);
1583             }
1584             else
1585 0 0         (void)SvOK_off(name);
1586            
1587 1128 100         if (SvPOK(name)) {
1588 266 100         if ((SvPVX_const(name))[0] == '*') {
1589 81 100         if (SvROK(val)) {
1590 79           switch (SvTYPE(SvRV(val))) {
1591             case SVt_PVAV:
1592 28           (SvPVX(name))[0] = '@';
1593 28           break;
1594             case SVt_PVHV:
1595 37           (SvPVX(name))[0] = '%';
1596 37           break;
1597             case SVt_PVCV:
1598 4           (SvPVX(name))[0] = '*';
1599 4           break;
1600             default:
1601 10           (SvPVX(name))[0] = '$';
1602 79           break;
1603             }
1604             }
1605             else
1606 81           (SvPVX(name))[0] = '$';
1607             }
1608 185 100         else if ((SvPVX_const(name))[0] != '$')
1609 266           sv_insert(name, 0, 0, "$", 1);
1610             }
1611             else {
1612             STRLEN nchars;
1613 862           sv_setpvs(name, "$");
1614 862           sv_catsv(name, varname);
1615 862 50         nchars = my_snprintf(tmpbuf, sizeof(tmpbuf), "%" IVdf,
1616             (IV)(i+1));
1617 862           sv_catpvn(name, tmpbuf, nchars);
1618             }
1619            
1620 1374 100         if (style.indent >= 2 && !terse) {
    100          
1621 246           SV * const tmpsv = sv_x(aTHX_ NULL, " ", 1, SvCUR(name)+3);
1622 246           newapad = sv_2mortal(newSVsv(apad));
1623 246           sv_catsv(newapad, tmpsv);
1624 246           SvREFCNT_dec(tmpsv);
1625             }
1626             else
1627 882           newapad = apad;
1628            
1629 1128           ENTER;
1630 1128           SAVETMPS;
1631 1128           PUTBACK;
1632 1128           DD_dump(aTHX_ val, SvPVX_const(name), SvCUR(name), valstr, seenhv,
1633             postav, 0, newapad, &style);
1634 1128           SPAGAIN;
1635 1128 100         FREETMPS;
1636 1128           LEAVE;
1637              
1638 1128           postlen = av_len(postav);
1639 1128 100         if (postlen >= 0 || !terse) {
    100          
1640 1119           sv_insert(valstr, 0, 0, " = ", 3);
1641 1119           sv_insert(valstr, 0, 0, SvPVX_const(name), SvCUR(name));
1642 1119           sv_catpvs(valstr, ";");
1643             }
1644 1128           sv_catsv(retval, style.pad);
1645 1128           sv_catsv(retval, valstr);
1646 1128           sv_catsv(retval, style.sep);
1647 1128 100         if (postlen >= 0) {
1648             SSize_t i;
1649 36           sv_catsv(retval, style.pad);
1650 168 100         for (i = 0; i <= postlen; ++i) {
1651             SV *elem;
1652 132           svp = av_fetch(postav, i, FALSE);
1653 132 50         if (svp && (elem = *svp)) {
    50          
1654 132           sv_catsv(retval, elem);
1655 132 100         if (i < postlen) {
1656 96           sv_catpvs(retval, ";");
1657 96           sv_catsv(retval, style.sep);
1658 96           sv_catsv(retval, style.pad);
1659             }
1660             }
1661             }
1662 36           sv_catpvs(retval, ";");
1663 36           sv_catsv(retval, style.sep);
1664             }
1665 1128           SvPVCLEAR(valstr);
1666 1128 100         if (gimme == G_ARRAY) {
1667 241 50         XPUSHs(retval);
1668 241 100         if (i < imax) /* not the last time thro ? */
1669 79           retval = newSVpvs_flags("", SVs_TEMP);
1670             }
1671             }
1672              
1673             /* we defer croaking until here so that temporary SVs and
1674             * buffers won't be leaked */
1675 371 100         if (style.maxrecursed)
1676 4           croak("Recursion limit of %" IVdf " exceeded",
1677             style.maxrecurse);
1678            
1679             }
1680             else
1681 0           croak("Call to new() method failed to return HASH ref");
1682 367 100         if (gimme != G_ARRAY)
1683 205 50         XPUSHs(retval);
1684             }
1685              
1686             SV *
1687             Data_Dumper__vstring(sv)
1688             SV *sv;
1689             PROTOTYPE: $
1690             CODE:
1691             {
1692             #ifdef SvVOK
1693             const MAGIC *mg;
1694 1711           RETVAL =
1695 6 50         SvMAGICAL(sv) && (mg = mg_find(sv, 'V'))
1696 6           ? newSVpvn((const char *)mg->mg_ptr, mg->mg_len)
1697 1717 100         : &PL_sv_undef;
1698             #else
1699             RETVAL = &PL_sv_undef;
1700             #endif
1701             }
1702             OUTPUT: RETVAL