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