Documentation typo fix for mro.
[p5sagit/p5-mst-13.2.git] / ext / Data / Dumper / Dumper.xs
CommitLineData
c5be433b 1#define PERL_NO_GET_CONTEXT
823edd99 2#include "EXTERN.h"
3#include "perl.h"
4#include "XSUB.h"
171b7b3b 5#ifdef USE_PPPORT_H
6# include "ppport.h"
7#endif
823edd99 8
e52c0e5a 9#if PERL_VERSION < 6
10# define DD_USE_OLD_ID_FORMAT
11#endif
12
9061c4b9 13static I32 num_q (const char *s, STRLEN slen);
14static I32 esc_q (char *dest, const char *src, STRLEN slen);
15static I32 esc_q_utf8 (pTHX_ SV *sv, const char *src, STRLEN slen);
16static I32 needs_quote(register const char *s);
aa07b2f6 17static SV *sv_x (pTHX_ SV *sv, const char *str, STRLEN len, I32 n);
18static I32 DD_dump (pTHX_ SV *val, const char *name, STRLEN namelen, SV *retval,
20ce7b12 19 HV *seenhv, AV *postav, I32 *levelp, I32 indent,
30b4f386 20 SV *pad, SV *xpad, SV *apad, SV *sep, SV *pair,
20ce7b12 21 SV *freezer, SV *toaster,
a2126434 22 I32 purity, I32 deepcopy, I32 quotekeys, SV *bless,
e9105f86 23 I32 maxdepth, SV *sortkeys);
823edd99 24
bfcb3514 25#ifndef HvNAME_get
26#define HvNAME_get HvNAME
27#endif
28
fec5e1eb 29#if PERL_VERSION <= 6 /* Perl 5.6 and earlier */
30
31# ifdef EBCDIC
32# define UNI_TO_NATIVE(ch) (((ch) > 255) ? (ch) : ASCII_TO_NATIVE(ch))
33# else
34# define UNI_TO_NATIVE(ch) (ch)
35# endif
36
37UV
38Perl_utf8_to_uvchr(pTHX_ U8 *s, STRLEN *retlen)
39{
9061c4b9 40 const UV uv = utf8_to_uv(s, UTF8_MAXLEN, retlen,
fec5e1eb 41 ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANY);
42 return UNI_TO_NATIVE(uv);
43}
44
45# if !defined(PERL_IMPLICIT_CONTEXT)
46# define utf8_to_uvchr Perl_utf8_to_uvchr
47# else
48# define utf8_to_uvchr(a,b) Perl_utf8_to_uvchr(aTHX_ a,b)
49# endif
50
51#endif /* PERL_VERSION <= 6 */
52
53/* Changes in 5.7 series mean that now IOK is only set if scalar is
54 precisely integer but in 5.6 and earlier we need to do a more
55 complex test */
56#if PERL_VERSION <= 6
57#define DD_is_integer(sv) (SvIOK(sv) && (SvIsUV(val) ? SvUV(sv) == SvNV(sv) : SvIV(sv) == SvNV(sv)))
58#else
59#define DD_is_integer(sv) SvIOK(sv)
60#endif
61
823edd99 62/* does a string need to be protected? */
63static I32
9061c4b9 64needs_quote(register const char *s)
823edd99 65{
66TOP:
67 if (s[0] == ':') {
68 if (*++s) {
69 if (*s++ != ':')
70 return 1;
71 }
72 else
73 return 1;
74 }
75 if (isIDFIRST(*s)) {
76 while (*++s)
7b0972df 77 if (!isALNUM(*s)) {
823edd99 78 if (*s == ':')
79 goto TOP;
80 else
81 return 1;
7b0972df 82 }
823edd99 83 }
6cde4e94 84 else
823edd99 85 return 1;
86 return 0;
87}
88
89/* count the number of "'"s and "\"s in string */
90static I32
9061c4b9 91num_q(register const char *s, register STRLEN slen)
823edd99 92{
93 register I32 ret = 0;
6c1ab3c2 94
95 while (slen > 0) {
823edd99 96 if (*s == '\'' || *s == '\\')
97 ++ret;
98 ++s;
6c1ab3c2 99 --slen;
823edd99 100 }
101 return ret;
102}
103
104
105/* returns number of chars added to escape "'"s and "\"s in s */
106/* slen number of characters in s will be escaped */
107/* destination must be long enough for additional chars */
108static I32
9061c4b9 109esc_q(register char *d, register const char *s, register STRLEN slen)
823edd99 110{
111 register I32 ret = 0;
6cde4e94 112
823edd99 113 while (slen > 0) {
114 switch (*s) {
115 case '\'':
116 case '\\':
117 *d = '\\';
118 ++d; ++ret;
119 default:
120 *d = *s;
121 ++d; ++s; --slen;
122 break;
123 }
124 }
125 return ret;
126}
127
dc71dc59 128static I32
9061c4b9 129esc_q_utf8(pTHX_ SV* sv, register const char *src, register STRLEN slen)
dc71dc59 130{
9061c4b9 131 char *r, *rstart;
132 const char *s = src;
133 const char * const send = src + slen;
f052740f 134 STRLEN j, cur = SvCUR(sv);
135 /* Could count 128-255 and 256+ in two variables, if we want to
136 be like &qquote and make a distinction. */
137 STRLEN grow = 0; /* bytes needed to represent chars 128+ */
138 /* STRLEN topbit_grow = 0; bytes needed to represent chars 128-255 */
139 STRLEN backslashes = 0;
140 STRLEN single_quotes = 0;
141 STRLEN qq_escapables = 0; /* " $ @ will need a \ in "" strings. */
142 STRLEN normal = 0;
6cde4e94 143
dc71dc59 144 /* this will need EBCDICification */
9061c4b9 145 for (s = src; s < send; s += UTF8SKIP(s)) {
146 const UV k = utf8_to_uvchr((U8*)s, NULL);
f052740f 147
cf0d1c66 148#ifdef EBCDIC
149 if (!isprint(k) || k > 256) {
150#else
151 if (k > 127) {
152#endif
f052740f 153 /* 4: \x{} then count the number of hex digits. */
154 grow += 4 + (k <= 0xFF ? 2 : k <= 0xFFF ? 3 : k <= 0xFFFF ? 4 :
155#if UVSIZE == 4
156 8 /* We may allocate a bit more than the minimum here. */
157#else
158 k <= 0xFFFFFFFF ? 8 : UVSIZE * 4
159#endif
160 );
161 } else if (k == '\\') {
162 backslashes++;
163 } else if (k == '\'') {
164 single_quotes++;
165 } else if (k == '"' || k == '$' || k == '@') {
166 qq_escapables++;
167 } else {
168 normal++;
169 }
dc71dc59 170 }
f052740f 171 if (grow) {
172 /* We have something needing hex. 3 is ""\0 */
34231210 173 sv_grow(sv, cur + 3 + grow + 2*backslashes + single_quotes
174 + 2*qq_escapables + normal);
f052740f 175 rstart = r = SvPVX(sv) + cur;
176
177 *r++ = '"';
178
179 for (s = src; s < send; s += UTF8SKIP(s)) {
9061c4b9 180 const UV k = utf8_to_uvchr((U8*)s, NULL);
f052740f 181
182 if (k == '"' || k == '\\' || k == '$' || k == '@') {
183 *r++ = '\\';
7c436af3 184 *r++ = (char)k;
f052740f 185 }
cf0d1c66 186 else
187#ifdef EBCDIC
188 if (isprint(k) && k < 256)
189#else
190 if (k < 0x80)
191#endif
7c436af3 192 *r++ = (char)k;
f052740f 193 else {
f5def3a2 194 r = r + my_sprintf(r, "\\x{%"UVxf"}", k);
f052740f 195 }
196 }
197 *r++ = '"';
198 } else {
199 /* Single quotes. */
34231210 200 sv_grow(sv, cur + 3 + 2*backslashes + 2*single_quotes
201 + qq_escapables + normal);
f052740f 202 rstart = r = SvPVX(sv) + cur;
203 *r++ = '\'';
204 for (s = src; s < send; s ++) {
9061c4b9 205 const char k = *s;
f052740f 206 if (k == '\'' || k == '\\')
207 *r++ = '\\';
208 *r++ = k;
209 }
210 *r++ = '\'';
dc71dc59 211 }
f052740f 212 *r = '\0';
213 j = r - rstart;
214 SvCUR_set(sv, cur + j);
dc71dc59 215
216 return j;
217}
218
823edd99 219/* append a repeated string to an SV */
220static SV *
aa07b2f6 221sv_x(pTHX_ SV *sv, const char *str, STRLEN len, I32 n)
823edd99 222{
9061c4b9 223 if (!sv)
7820172a 224 sv = newSVpvn("", 0);
65e66c80 225#ifdef DEBUGGING
823edd99 226 else
227 assert(SvTYPE(sv) >= SVt_PV);
65e66c80 228#endif
823edd99 229
230 if (n > 0) {
231 SvGROW(sv, len*n + SvCUR(sv) + 1);
232 if (len == 1) {
9061c4b9 233 char * const start = SvPVX(sv) + SvCUR(sv);
b162af07 234 SvCUR_set(sv, SvCUR(sv) + n);
823edd99 235 start[n] = '\0';
236 while (n > 0)
237 start[--n] = str[0];
238 }
239 else
240 while (n > 0) {
241 sv_catpvn(sv, str, len);
242 --n;
243 }
244 }
245 return sv;
246}
247
248/*
249 * This ought to be split into smaller functions. (it is one long function since
250 * it exactly parallels the perl version, which was one long thing for
251 * efficiency raisins.) Ugggh!
252 */
253static I32
aa07b2f6 254DD_dump(pTHX_ SV *val, const char *name, STRLEN namelen, SV *retval, HV *seenhv,
823edd99 255 AV *postav, I32 *levelp, I32 indent, SV *pad, SV *xpad,
30b4f386 256 SV *apad, SV *sep, SV *pair, SV *freezer, SV *toaster, I32 purity,
e9105f86 257 I32 deepcopy, I32 quotekeys, SV *bless, I32 maxdepth, SV *sortkeys)
823edd99 258{
259 char tmpbuf[128];
260 U32 i;
e52c0e5a 261 char *c, *r, *realpack;
262#ifdef DD_USE_OLD_ID_FORMAT
263 char id[128];
264#else
265 UV id_buffer;
266 char *const id = (char *)&id_buffer;
267#endif
823edd99 268 SV **svp;
7820172a 269 SV *sv, *ipad, *ival;
823edd99 270 SV *blesspad = Nullsv;
7d49f689 271 AV *seenentry = NULL;
823edd99 272 char *iname;
273 STRLEN inamelen, idlen = 0;
823edd99 274 U32 realtype;
4ab99479 275 bool no_bless = 0; /* when a qr// is blessed into Regexp we dont want to bless it.
276 in later perls we should actually check the classname of the
277 engine. this gets tricky as it involves lexical issues that arent so
278 easy to resolve */
279 bool is_regex = 0; /* we are dumping a regex, we need to know this before we bless */
823edd99 280
281 if (!val)
282 return 0;
283
a4e0d239 284 /* If the ouput buffer has less than some arbitary amount of space
285 remaining, then enlarge it. For the test case (25M of output),
286 *1.1 was slower, *2.0 was the same, so the first guess of 1.5 is
287 deemed to be good enough. */
288 if (SvTYPE(retval) >= SVt_PV && (SvLEN(retval) - SvCUR(retval)) < 42) {
97c52c3c 289 sv_grow(retval, SvCUR(retval) * 3 / 2);
9fa5cce2 290 }
a4e0d239 291
823edd99 292 realtype = SvTYPE(val);
6cde4e94 293
823edd99 294 if (SvGMAGICAL(val))
295 mg_get(val);
823edd99 296 if (SvROK(val)) {
297
c5f7c514 298 /* If a freeze method is provided and the object has it, call
299 it. Warn on errors. */
823edd99 300 if (SvOBJECT(SvRV(val)) && freezer &&
c5f7c514 301 SvPOK(freezer) && SvCUR(freezer) &&
aa07b2f6 302 gv_fetchmeth(SvSTASH(SvRV(val)), SvPVX_const(freezer),
c5f7c514 303 SvCUR(freezer), -1) != NULL)
823edd99 304 {
305 dSP; ENTER; SAVETMPS; PUSHMARK(sp);
306 XPUSHs(val); PUTBACK;
aa07b2f6 307 i = perl_call_method(SvPVX_const(freezer), G_EVAL|G_VOID);
823edd99 308 SPAGAIN;
7820172a 309 if (SvTRUE(ERRSV))
35c1215d 310 warn("WARNING(Freezer method call failed): %"SVf"", ERRSV);
823edd99 311 PUTBACK; FREETMPS; LEAVE;
823edd99 312 }
313
314 ival = SvRV(val);
823edd99 315 realtype = SvTYPE(ival);
e52c0e5a 316#ifdef DD_USE_OLD_ID_FORMAT
f5def3a2 317 idlen = my_snprintf(id, sizeof(id), "0x%"UVxf, PTR2UV(ival));
e52c0e5a 318#else
319 id_buffer = PTR2UV(ival);
320 idlen = sizeof(id_buffer);
321#endif
823edd99 322 if (SvOBJECT(ival))
bfcb3514 323 realpack = HvNAME_get(SvSTASH(ival));
823edd99 324 else
9849c14c 325 realpack = NULL;
7820172a 326
327 /* if it has a name, we need to either look it up, or keep a tab
328 * on it so we know when we hit it later
329 */
330 if (namelen) {
331 if ((svp = hv_fetch(seenhv, id, idlen, FALSE))
332 && (sv = *svp) && SvROK(sv) && (seenentry = (AV*)SvRV(sv)))
333 {
334 SV *othername;
335 if ((svp = av_fetch(seenentry, 0, FALSE))
336 && (othername = *svp))
337 {
338 if (purity && *levelp > 0) {
339 SV *postentry;
340
341 if (realtype == SVt_PVHV)
342 sv_catpvn(retval, "{}", 2);
343 else if (realtype == SVt_PVAV)
344 sv_catpvn(retval, "[]", 2);
345 else
5df59fb6 346 sv_catpvn(retval, "do{my $o}", 9);
7820172a 347 postentry = newSVpvn(name, namelen);
348 sv_catpvn(postentry, " = ", 3);
349 sv_catsv(postentry, othername);
350 av_push(postav, postentry);
351 }
352 else {
353 if (name[0] == '@' || name[0] == '%') {
aa07b2f6 354 if ((SvPVX_const(othername))[0] == '\\' &&
355 (SvPVX_const(othername))[1] == name[0]) {
356 sv_catpvn(retval, SvPVX_const(othername)+1,
7820172a 357 SvCUR(othername)-1);
358 }
359 else {
360 sv_catpvn(retval, name, 1);
361 sv_catpvn(retval, "{", 1);
362 sv_catsv(retval, othername);
363 sv_catpvn(retval, "}", 1);
364 }
823edd99 365 }
7820172a 366 else
823edd99 367 sv_catsv(retval, othername);
823edd99 368 }
7820172a 369 return 1;
370 }
371 else {
e52c0e5a 372#ifdef DD_USE_OLD_ID_FORMAT
7820172a 373 warn("ref name not found for %s", id);
e52c0e5a 374#else
375 warn("ref name not found for 0x%"UVxf, PTR2UV(ival));
376#endif
7820172a 377 return 0;
823edd99 378 }
823edd99 379 }
7820172a 380 else { /* store our name and continue */
381 SV *namesv;
382 if (name[0] == '@' || name[0] == '%') {
383 namesv = newSVpvn("\\", 1);
384 sv_catpvn(namesv, name, namelen);
385 }
386 else if (realtype == SVt_PVCV && name[0] == '*') {
387 namesv = newSVpvn("\\", 2);
388 sv_catpvn(namesv, name, namelen);
389 (SvPVX(namesv))[1] = '&';
390 }
391 else
392 namesv = newSVpvn(name, namelen);
393 seenentry = newAV();
394 av_push(seenentry, namesv);
395 (void)SvREFCNT_inc(val);
396 av_push(seenentry, val);
383d9087 397 (void)hv_store(seenhv, id, idlen,
fec5e1eb 398 newRV_inc((SV*)seenentry), 0);
7820172a 399 SvREFCNT_dec(seenentry);
823edd99 400 }
823edd99 401 }
4ab99479 402 /* regexps dont have to be blessed into package "Regexp"
403 * they can be blessed into any package.
404 */
405#if PERL_VERSION < 8
406 if (realpack && *realpack == 'R' && strEQ(realpack, "Regexp"))
407#elif PERL_VERSION < 11
408 if (realpack && realtype == SVt_PVMG && mg_find(sv, PERL_MAGIC_qr))
409#else
410 if (realpack && realtype == SVt_REGEXP)
411#endif
412 {
413 is_regex = 1;
414 if (strEQ(realpack, "Regexp"))
415 no_bless = 1;
416 else
417 no_bless = 0;
418 }
a2126434 419
420 /* If purity is not set and maxdepth is set, then check depth:
421 * if we have reached maximum depth, return the string
422 * representation of the thing we are currently examining
6cde4e94 423 * at this depth (i.e., 'Foo=ARRAY(0xdeadbeef)').
a2126434 424 */
425 if (!purity && maxdepth > 0 && *levelp >= maxdepth) {
426 STRLEN vallen;
9061c4b9 427 const char * const valstr = SvPV(val,vallen);
a2126434 428 sv_catpvn(retval, "'", 1);
429 sv_catpvn(retval, valstr, vallen);
430 sv_catpvn(retval, "'", 1);
431 return 1;
432 }
433
4ab99479 434 if (realpack && !no_bless) { /* we have a blessed ref */
a2126434 435 STRLEN blesslen;
9061c4b9 436 const char * const blessstr = SvPV(bless, blesslen);
a2126434 437 sv_catpvn(retval, blessstr, blesslen);
438 sv_catpvn(retval, "( ", 2);
439 if (indent >= 2) {
440 blesspad = apad;
441 apad = newSVsv(apad);
442 sv_x(aTHX_ apad, " ", 1, blesslen+2);
823edd99 443 }
444 }
445
7894fbab 446 (*levelp)++;
aa07b2f6 447 ipad = sv_x(aTHX_ Nullsv, SvPVX_const(xpad), SvCUR(xpad), *levelp);
7894fbab 448
4ab99479 449 if (is_regex)
450 {
451 STRLEN rlen;
452 const char *rval = SvPV(val, rlen);
453 const char *slash = strchr(rval, '/');
454 sv_catpvn(retval, "qr/", 3);
455 while (slash) {
456 sv_catpvn(retval, rval, slash-rval);
457 sv_catpvn(retval, "\\/", 2);
458 rlen -= slash-rval+1;
459 rval = slash+1;
460 slash = strchr(rval, '/');
461 }
462 sv_catpvn(retval, rval, rlen);
463 sv_catpvn(retval, "/", 1);
464 }
465 else if (
d1dd14d1 466#if PERL_VERSION < 9
467 realtype <= SVt_PVBM
468#else
469 realtype <= SVt_PVMG
470#endif
471 ) { /* scalar ref */
9061c4b9 472 SV * const namesv = newSVpvn("${", 2);
7820172a 473 sv_catpvn(namesv, name, namelen);
474 sv_catpvn(namesv, "}", 1);
6cde4e94 475 if (realpack) { /* blessed */
823edd99 476 sv_catpvn(retval, "do{\\(my $o = ", 13);
aa07b2f6 477 DD_dump(aTHX_ ival, SvPVX_const(namesv), SvCUR(namesv), retval, seenhv,
30b4f386 478 postav, levelp, indent, pad, xpad, apad, sep, pair,
a2126434 479 freezer, toaster, purity, deepcopy, quotekeys, bless,
e9105f86 480 maxdepth, sortkeys);
823edd99 481 sv_catpvn(retval, ")}", 2);
7820172a 482 } /* plain */
823edd99 483 else {
484 sv_catpvn(retval, "\\", 1);
aa07b2f6 485 DD_dump(aTHX_ ival, SvPVX_const(namesv), SvCUR(namesv), retval, seenhv,
30b4f386 486 postav, levelp, indent, pad, xpad, apad, sep, pair,
a2126434 487 freezer, toaster, purity, deepcopy, quotekeys, bless,
e9105f86 488 maxdepth, sortkeys);
823edd99 489 }
7820172a 490 SvREFCNT_dec(namesv);
491 }
492 else if (realtype == SVt_PVGV) { /* glob ref */
9061c4b9 493 SV * const namesv = newSVpvn("*{", 2);
7820172a 494 sv_catpvn(namesv, name, namelen);
495 sv_catpvn(namesv, "}", 1);
496 sv_catpvn(retval, "\\", 1);
aa07b2f6 497 DD_dump(aTHX_ ival, SvPVX_const(namesv), SvCUR(namesv), retval, seenhv,
30b4f386 498 postav, levelp, indent, pad, xpad, apad, sep, pair,
a2126434 499 freezer, toaster, purity, deepcopy, quotekeys, bless,
e9105f86 500 maxdepth, sortkeys);
7820172a 501 SvREFCNT_dec(namesv);
823edd99 502 }
503 else if (realtype == SVt_PVAV) {
504 SV *totpad;
505 I32 ix = 0;
9061c4b9 506 const I32 ixmax = av_len((AV *)ival);
6cde4e94 507
9061c4b9 508 SV * const ixsv = newSViv(0);
823edd99 509 /* allowing for a 24 char wide array index */
510 New(0, iname, namelen+28, char);
511 (void)strcpy(iname, name);
512 inamelen = namelen;
513 if (name[0] == '@') {
514 sv_catpvn(retval, "(", 1);
515 iname[0] = '$';
516 }
517 else {
518 sv_catpvn(retval, "[", 1);
7820172a 519 /* omit "->" in $foo{bar}->[0], but not in ${$foo}->[0] */
520 /*if (namelen > 0
521 && name[namelen-1] != ']' && name[namelen-1] != '}'
522 && (namelen < 4 || (name[1] != '{' && name[2] != '{')))*/
523 if ((namelen > 0
524 && name[namelen-1] != ']' && name[namelen-1] != '}')
525 || (namelen > 4
526 && (name[1] == '{'
527 || (name[0] == '\\' && name[2] == '{'))))
528 {
823edd99 529 iname[inamelen++] = '-'; iname[inamelen++] = '>';
530 iname[inamelen] = '\0';
531 }
532 }
533 if (iname[0] == '*' && iname[inamelen-1] == '}' && inamelen >= 8 &&
534 (instr(iname+inamelen-8, "{SCALAR}") ||
535 instr(iname+inamelen-7, "{ARRAY}") ||
536 instr(iname+inamelen-6, "{HASH}"))) {
537 iname[inamelen++] = '-'; iname[inamelen++] = '>';
538 }
539 iname[inamelen++] = '['; iname[inamelen] = '\0';
540 totpad = newSVsv(sep);
541 sv_catsv(totpad, pad);
542 sv_catsv(totpad, apad);
543
544 for (ix = 0; ix <= ixmax; ++ix) {
545 STRLEN ilen;
546 SV *elem;
547 svp = av_fetch((AV*)ival, ix, FALSE);
548 if (svp)
549 elem = *svp;
550 else
3280af22 551 elem = &PL_sv_undef;
823edd99 552
553 ilen = inamelen;
554 sv_setiv(ixsv, ix);
f5def3a2 555 ilen = ilen + my_sprintf(iname+ilen, "%"IVdf, (IV)ix);
823edd99 556 iname[ilen++] = ']'; iname[ilen] = '\0';
557 if (indent >= 3) {
558 sv_catsv(retval, totpad);
559 sv_catsv(retval, ipad);
560 sv_catpvn(retval, "#", 1);
561 sv_catsv(retval, ixsv);
562 }
563 sv_catsv(retval, totpad);
564 sv_catsv(retval, ipad);
cea2e8a9 565 DD_dump(aTHX_ elem, iname, ilen, retval, seenhv, postav,
30b4f386 566 levelp, indent, pad, xpad, apad, sep, pair,
a2126434 567 freezer, toaster, purity, deepcopy, quotekeys, bless,
e9105f86 568 maxdepth, sortkeys);
823edd99 569 if (ix < ixmax)
570 sv_catpvn(retval, ",", 1);
571 }
572 if (ixmax >= 0) {
9061c4b9 573 SV * const opad = sv_x(aTHX_ Nullsv, SvPVX_const(xpad), SvCUR(xpad), (*levelp)-1);
823edd99 574 sv_catsv(retval, totpad);
575 sv_catsv(retval, opad);
576 SvREFCNT_dec(opad);
577 }
578 if (name[0] == '@')
579 sv_catpvn(retval, ")", 1);
580 else
581 sv_catpvn(retval, "]", 1);
582 SvREFCNT_dec(ixsv);
583 SvREFCNT_dec(totpad);
584 Safefree(iname);
585 }
586 else if (realtype == SVt_PVHV) {
587 SV *totpad, *newapad;
9061c4b9 588 SV *sname;
823edd99 589 HE *entry;
590 char *key;
591 I32 klen;
592 SV *hval;
7d49f689 593 AV *keys = NULL;
6cde4e94 594
9061c4b9 595 SV * const iname = newSVpvn(name, namelen);
823edd99 596 if (name[0] == '%') {
597 sv_catpvn(retval, "(", 1);
598 (SvPVX(iname))[0] = '$';
599 }
600 else {
601 sv_catpvn(retval, "{", 1);
7820172a 602 /* omit "->" in $foo[0]->{bar}, but not in ${$foo}->{bar} */
603 if ((namelen > 0
604 && name[namelen-1] != ']' && name[namelen-1] != '}')
605 || (namelen > 4
606 && (name[1] == '{'
607 || (name[0] == '\\' && name[2] == '{'))))
608 {
823edd99 609 sv_catpvn(iname, "->", 2);
610 }
611 }
612 if (name[0] == '*' && name[namelen-1] == '}' && namelen >= 8 &&
613 (instr(name+namelen-8, "{SCALAR}") ||
614 instr(name+namelen-7, "{ARRAY}") ||
615 instr(name+namelen-6, "{HASH}"))) {
616 sv_catpvn(iname, "->", 2);
617 }
618 sv_catpvn(iname, "{", 1);
619 totpad = newSVsv(sep);
620 sv_catsv(totpad, pad);
621 sv_catsv(totpad, apad);
6cde4e94 622
e9105f86 623 /* If requested, get a sorted/filtered array of hash keys */
624 if (sortkeys) {
625 if (sortkeys == &PL_sv_yes) {
fec5e1eb 626#if PERL_VERSION < 8
627 sortkeys = sv_2mortal(newSVpvn("Data::Dumper::_sortkeys", 23));
628#else
e9105f86 629 keys = newAV();
630 (void)hv_iterinit((HV*)ival);
20d72259 631 while ((entry = hv_iternext((HV*)ival))) {
e9105f86 632 sv = hv_iterkeysv(entry);
633 SvREFCNT_inc(sv);
634 av_push(keys, sv);
635 }
fec5e1eb 636# ifdef USE_LOCALE_NUMERIC
e9105f86 637 sortsv(AvARRAY(keys),
638 av_len(keys)+1,
3c253d0e 639 IN_LOCALE ? Perl_sv_cmp_locale : Perl_sv_cmp);
fec5e1eb 640# else
503ec68f 641 sortsv(AvARRAY(keys),
642 av_len(keys)+1,
643 Perl_sv_cmp);
fec5e1eb 644# endif
02a99678 645#endif
e9105f86 646 }
fec5e1eb 647 if (sortkeys != &PL_sv_yes) {
e9105f86 648 dSP; ENTER; SAVETMPS; PUSHMARK(sp);
649 XPUSHs(sv_2mortal(newRV_inc(ival))); PUTBACK;
650 i = perl_call_sv(sortkeys, G_SCALAR | G_EVAL);
651 SPAGAIN;
652 if (i) {
653 sv = POPs;
654 if (SvROK(sv) && (SvTYPE(SvRV(sv)) == SVt_PVAV))
655 keys = (AV*)SvREFCNT_inc(SvRV(sv));
656 }
657 if (! keys)
658 warn("Sortkeys subroutine did not return ARRAYREF\n");
659 PUTBACK; FREETMPS; LEAVE;
660 }
661 if (keys)
662 sv_2mortal((SV*)keys);
663 }
664 else
665 (void)hv_iterinit((HV*)ival);
ecfc8647 666
667 /* foreach (keys %hash) */
668 for (i = 0; 1; i++) {
fdce9ba9 669 char *nkey;
670 char *nkey_buffer = NULL;
823edd99 671 I32 nticks = 0;
dc71dc59 672 SV* keysv;
673 STRLEN keylen;
fdce9ba9 674 I32 nlen;
dc71dc59 675 bool do_utf8 = FALSE;
ecfc8647 676
27688d77 677 if (sortkeys) {
678 if (!(keys && (I32)i <= av_len(keys))) break;
679 } else {
680 if (!(entry = hv_iternext((HV *)ival))) break;
681 }
ecfc8647 682
823edd99 683 if (i)
684 sv_catpvn(retval, ",", 1);
e9105f86 685
686 if (sortkeys) {
687 char *key;
688 svp = av_fetch(keys, i, FALSE);
689 keysv = svp ? *svp : sv_mortalcopy(&PL_sv_undef);
690 key = SvPV(keysv, keylen);
d075f8ed 691 svp = hv_fetch((HV*)ival, key,
6e21dc91 692 SvUTF8(keysv) ? -(I32)keylen : keylen, 0);
e9105f86 693 hval = svp ? *svp : sv_mortalcopy(&PL_sv_undef);
694 }
695 else {
696 keysv = hv_iterkeysv(entry);
697 hval = hv_iterval((HV*)ival, entry);
698 }
699
dc71dc59 700 key = SvPV(keysv, keylen);
8738e0c0 701 do_utf8 = DO_UTF8(keysv);
dc71dc59 702 klen = keylen;
703
fdce9ba9 704 sv_catsv(retval, totpad);
705 sv_catsv(retval, ipad);
706 /* old logic was first to check utf8 flag, and if utf8 always
707 call esc_q_utf8. This caused test to break under -Mutf8,
708 because there even strings like 'c' have utf8 flag on.
709 Hence with quotekeys == 0 the XS code would still '' quote
710 them based on flags, whereas the perl code would not,
711 based on regexps.
712 The perl code is correct.
713 needs_quote() decides that anything that isn't a valid
714 perl identifier needs to be quoted, hence only correctly
715 formed strings with no characters outside [A-Za-z0-9_:]
716 won't need quoting. None of those characters are used in
717 the byte encoding of utf8, so anything with utf8
718 encoded characters in will need quoting. Hence strings
719 with utf8 encoded characters in will end up inside do_utf8
720 just like before, but now strings with utf8 flag set but
721 only ascii characters will end up in the unquoted section.
722
723 There should also be less tests for the (probably currently)
724 more common doesn't need quoting case.
725 The code is also smaller (22044 vs 22260) because I've been
30b4f386 726 able to pull the common logic out to both sides. */
fdce9ba9 727 if (quotekeys || needs_quote(key)) {
728 if (do_utf8) {
729 STRLEN ocur = SvCUR(retval);
730 nlen = esc_q_utf8(aTHX_ retval, key, klen);
731 nkey = SvPVX(retval) + ocur;
732 }
733 else {
dc71dc59 734 nticks = num_q(key, klen);
fdce9ba9 735 New(0, nkey_buffer, klen+nticks+3, char);
736 nkey = nkey_buffer;
dc71dc59 737 nkey[0] = '\'';
738 if (nticks)
739 klen += esc_q(nkey+1, key, klen);
740 else
741 (void)Copy(key, nkey+1, klen, char);
742 nkey[++klen] = '\'';
743 nkey[++klen] = '\0';
fdce9ba9 744 nlen = klen;
745 sv_catpvn(retval, nkey, klen);
dc71dc59 746 }
fdce9ba9 747 }
748 else {
749 nkey = key;
750 nlen = klen;
751 sv_catpvn(retval, nkey, klen);
dc71dc59 752 }
fdce9ba9 753 sname = newSVsv(iname);
754 sv_catpvn(sname, nkey, nlen);
755 sv_catpvn(sname, "}", 1);
756
30b4f386 757 sv_catsv(retval, pair);
823edd99 758 if (indent >= 2) {
759 char *extra;
760 I32 elen = 0;
761 newapad = newSVsv(apad);
762 New(0, extra, klen+4+1, char);
763 while (elen < (klen+4))
764 extra[elen++] = ' ';
765 extra[elen] = '\0';
766 sv_catpvn(newapad, extra, elen);
767 Safefree(extra);
768 }
769 else
770 newapad = apad;
771
aa07b2f6 772 DD_dump(aTHX_ hval, SvPVX_const(sname), SvCUR(sname), retval, seenhv,
30b4f386 773 postav, levelp, indent, pad, xpad, newapad, sep, pair,
a2126434 774 freezer, toaster, purity, deepcopy, quotekeys, bless,
e9105f86 775 maxdepth, sortkeys);
823edd99 776 SvREFCNT_dec(sname);
fdce9ba9 777 Safefree(nkey_buffer);
823edd99 778 if (indent >= 2)
779 SvREFCNT_dec(newapad);
780 }
781 if (i) {
aa07b2f6 782 SV *opad = sv_x(aTHX_ Nullsv, SvPVX_const(xpad), SvCUR(xpad), *levelp-1);
823edd99 783 sv_catsv(retval, totpad);
784 sv_catsv(retval, opad);
785 SvREFCNT_dec(opad);
786 }
787 if (name[0] == '%')
788 sv_catpvn(retval, ")", 1);
789 else
790 sv_catpvn(retval, "}", 1);
791 SvREFCNT_dec(iname);
792 SvREFCNT_dec(totpad);
793 }
794 else if (realtype == SVt_PVCV) {
795 sv_catpvn(retval, "sub { \"DUMMY\" }", 15);
796 if (purity)
797 warn("Encountered CODE ref, using dummy placeholder");
798 }
799 else {
800 warn("cannot handle ref type %ld", realtype);
801 }
802
4ab99479 803 if (realpack && !no_bless) { /* free blessed allocs */
d0c214fd 804 I32 plen;
805 I32 pticks;
806
823edd99 807 if (indent >= 2) {
808 SvREFCNT_dec(apad);
809 apad = blesspad;
810 }
811 sv_catpvn(retval, ", '", 3);
d0c214fd 812
813 plen = strlen(realpack);
814 pticks = num_q(realpack, plen);
34baf60a 815 if (pticks) { /* needs escaping */
d0c214fd 816 char *npack;
817 char *npack_buffer = NULL;
818
819 New(0, npack_buffer, plen+pticks+1, char);
820 npack = npack_buffer;
821 plen += esc_q(npack, realpack, plen);
822 npack[plen] = '\0';
823
824 sv_catpvn(retval, npack, plen);
825 Safefree(npack_buffer);
826 }
827 else {
828 sv_catpvn(retval, realpack, strlen(realpack));
829 }
823edd99 830 sv_catpvn(retval, "' )", 3);
831 if (toaster && SvPOK(toaster) && SvCUR(toaster)) {
832 sv_catpvn(retval, "->", 2);
833 sv_catsv(retval, toaster);
834 sv_catpvn(retval, "()", 2);
835 }
836 }
837 SvREFCNT_dec(ipad);
838 (*levelp)--;
839 }
840 else {
841 STRLEN i;
842
843 if (namelen) {
e52c0e5a 844#ifdef DD_USE_OLD_ID_FORMAT
f5def3a2 845 idlen = my_snprintf(id, sizeof(id), "0x%"UVxf, PTR2UV(val));
e52c0e5a 846#else
847 id_buffer = PTR2UV(val);
848 idlen = sizeof(id_buffer);
849#endif
f5def3a2 850 if ((svp = hv_fetch(seenhv, id, idlen, FALSE)) &&
823edd99 851 (sv = *svp) && SvROK(sv) &&
7820172a 852 (seenentry = (AV*)SvRV(sv)))
853 {
823edd99 854 SV *othername;
7820172a 855 if ((svp = av_fetch(seenentry, 0, FALSE)) && (othername = *svp)
856 && (svp = av_fetch(seenentry, 2, FALSE)) && *svp && SvIV(*svp) > 0)
857 {
858 sv_catpvn(retval, "${", 2);
823edd99 859 sv_catsv(retval, othername);
7820172a 860 sv_catpvn(retval, "}", 1);
823edd99 861 return 1;
862 }
863 }
3bef8b4a 864 else if (val != &PL_sv_undef) {
9061c4b9 865 SV * const namesv = newSVpvn("\\", 1);
823edd99 866 sv_catpvn(namesv, name, namelen);
867 seenentry = newAV();
868 av_push(seenentry, namesv);
fec5e1eb 869 av_push(seenentry, newRV_inc(val));
383d9087 870 (void)hv_store(seenhv, id, idlen, newRV_inc((SV*)seenentry), 0);
823edd99 871 SvREFCNT_dec(seenentry);
872 }
873 }
7820172a 874
fec5e1eb 875 if (DD_is_integer(val)) {
823edd99 876 STRLEN len;
0e8b3009 877 if (SvIsUV(val))
f5def3a2 878 len = my_snprintf(tmpbuf, sizeof(tmpbuf), "%"UVuf, SvUV(val));
0e8b3009 879 else
f5def3a2 880 len = my_snprintf(tmpbuf, sizeof(tmpbuf), "%"IVdf, SvIV(val));
c4cce848 881 if (SvPOK(val)) {
882 /* Need to check to see if this is a string such as " 0".
883 I'm assuming from sprintf isn't going to clash with utf8.
884 Is this valid on EBCDIC? */
885 STRLEN pvlen;
9061c4b9 886 const char * const pv = SvPV(val, pvlen);
c4cce848 887 if (pvlen != len || memNE(pv, tmpbuf, len))
888 goto integer_came_from_string;
889 }
890 if (len > 10) {
891 /* Looks like we're on a 64 bit system. Make it a string so that
892 if a 32 bit system reads the number it will cope better. */
893 sv_catpvf(retval, "'%s'", tmpbuf);
894 } else
895 sv_catpvn(retval, tmpbuf, len);
823edd99 896 }
897 else if (realtype == SVt_PVGV) {/* GLOBs can end up with scribbly names */
898 c = SvPV(val, i);
899 ++c; --i; /* just get the name */
900 if (i >= 6 && strncmp(c, "main::", 6) == 0) {
901 c += 4;
902 i -= 4;
903 }
904 if (needs_quote(c)) {
905 sv_grow(retval, SvCUR(retval)+6+2*i);
906 r = SvPVX(retval)+SvCUR(retval);
907 r[0] = '*'; r[1] = '{'; r[2] = '\'';
908 i += esc_q(r+3, c, i);
909 i += 3;
910 r[i++] = '\''; r[i++] = '}';
911 r[i] = '\0';
912 }
913 else {
914 sv_grow(retval, SvCUR(retval)+i+2);
915 r = SvPVX(retval)+SvCUR(retval);
916 r[0] = '*'; strcpy(r+1, c);
917 i++;
918 }
7820172a 919 SvCUR_set(retval, SvCUR(retval)+i);
823edd99 920
921 if (purity) {
27da23d5 922 static const char* const entries[] = { "{SCALAR}", "{ARRAY}", "{HASH}" };
923 static const STRLEN sizes[] = { 8, 7, 6 };
823edd99 924 SV *e;
9061c4b9 925 SV * const nname = newSVpvn("", 0);
926 SV * const newapad = newSVpvn("", 0);
927 GV * const gv = (GV*)val;
823edd99 928 I32 j;
929
930 for (j=0; j<3; j++) {
931 e = ((j == 0) ? GvSV(gv) : (j == 1) ? (SV*)GvAV(gv) : (SV*)GvHV(gv));
7820172a 932 if (!e)
933 continue;
934 if (j == 0 && !SvOK(e))
935 continue;
936
937 {
823edd99 938 I32 nlevel = 0;
7820172a 939 SV *postentry = newSVpvn(r,i);
823edd99 940
941 sv_setsv(nname, postentry);
942 sv_catpvn(nname, entries[j], sizes[j]);
943 sv_catpvn(postentry, " = ", 3);
944 av_push(postav, postentry);
fec5e1eb 945 e = newRV_inc(e);
823edd99 946
b162af07 947 SvCUR_set(newapad, 0);
823edd99 948 if (indent >= 2)
cea2e8a9 949 (void)sv_x(aTHX_ newapad, " ", 1, SvCUR(postentry));
823edd99 950
aa07b2f6 951 DD_dump(aTHX_ e, SvPVX_const(nname), SvCUR(nname), postentry,
823edd99 952 seenhv, postav, &nlevel, indent, pad, xpad,
30b4f386 953 newapad, sep, pair, freezer, toaster, purity,
e9105f86 954 deepcopy, quotekeys, bless, maxdepth,
955 sortkeys);
823edd99 956 SvREFCNT_dec(e);
957 }
958 }
959
960 SvREFCNT_dec(newapad);
961 SvREFCNT_dec(nname);
962 }
963 }
7820172a 964 else if (val == &PL_sv_undef || !SvOK(val)) {
965 sv_catpvn(retval, "undef", 5);
966 }
823edd99 967 else {
c4cce848 968 integer_came_from_string:
823edd99 969 c = SvPV(val, i);
dc71dc59 970 if (DO_UTF8(val))
6cde4e94 971 i += esc_q_utf8(aTHX_ retval, c, i);
dc71dc59 972 else {
973 sv_grow(retval, SvCUR(retval)+3+2*i); /* 3: ""\0 */
974 r = SvPVX(retval) + SvCUR(retval);
975 r[0] = '\'';
976 i += esc_q(r+1, c, i);
977 ++i;
978 r[i++] = '\'';
979 r[i] = '\0';
980 SvCUR_set(retval, SvCUR(retval)+i);
981 }
823edd99 982 }
823edd99 983 }
984
7820172a 985 if (idlen) {
986 if (deepcopy)
987 (void)hv_delete(seenhv, id, idlen, G_DISCARD);
988 else if (namelen && seenentry) {
989 SV *mark = *av_fetch(seenentry, 2, TRUE);
990 sv_setiv(mark,1);
991 }
992 }
823edd99 993 return 1;
994}
995
996
997MODULE = Data::Dumper PACKAGE = Data::Dumper PREFIX = Data_Dumper_
998
999#
1000# This is the exact equivalent of Dump. Well, almost. The things that are
1001# different as of now (due to Laziness):
1002# * doesnt do double-quotes yet.
1003#
1004
1005void
1006Data_Dumper_Dumpxs(href, ...)
1007 SV *href;
1008 PROTOTYPE: $;$$
1009 PPCODE:
1010 {
1011 HV *hv;
1012 SV *retval, *valstr;
5c284bb0 1013 HV *seenhv = NULL;
823edd99 1014 AV *postav, *todumpav, *namesav;
1015 I32 level = 0;
497b47a8 1016 I32 indent, terse, i, imax, postlen;
823edd99 1017 SV **svp;
30b4f386 1018 SV *val, *name, *pad, *xpad, *apad, *sep, *pair, *varname;
e9105f86 1019 SV *freezer, *toaster, *bless, *sortkeys;
7b0972df 1020 I32 purity, deepcopy, quotekeys, maxdepth = 0;
823edd99 1021 char tmpbuf[1024];
1022 I32 gimme = GIMME;
1023
1024 if (!SvROK(href)) { /* call new to get an object first */
0f1923bd 1025 if (items < 2)
1026 croak("Usage: Data::Dumper::Dumpxs(PACKAGE, VAL_ARY_REF, [NAME_ARY_REF])");
823edd99 1027
1028 ENTER;
1029 SAVETMPS;
1030
1031 PUSHMARK(sp);
1032 XPUSHs(href);
0f1923bd 1033 XPUSHs(sv_2mortal(newSVsv(ST(1))));
1034 if (items >= 3)
1035 XPUSHs(sv_2mortal(newSVsv(ST(2))));
823edd99 1036 PUTBACK;
1037 i = perl_call_method("new", G_SCALAR);
1038 SPAGAIN;
1039 if (i)
1040 href = newSVsv(POPs);
1041
1042 PUTBACK;
1043 FREETMPS;
1044 LEAVE;
1045 if (i)
1046 (void)sv_2mortal(href);
1047 }
1048
7d49f689 1049 todumpav = namesav = NULL;
5c284bb0 1050 seenhv = NULL;
30b4f386 1051 val = pad = xpad = apad = sep = pair = varname
65e66c80 1052 = freezer = toaster = bless = sortkeys = &PL_sv_undef;
823edd99 1053 name = sv_newmortal();
1054 indent = 2;
497b47a8 1055 terse = purity = deepcopy = 0;
823edd99 1056 quotekeys = 1;
6cde4e94 1057
7820172a 1058 retval = newSVpvn("", 0);
823edd99 1059 if (SvROK(href)
1060 && (hv = (HV*)SvRV((SV*)href))
1061 && SvTYPE(hv) == SVt_PVHV) {
1062
1063 if ((svp = hv_fetch(hv, "seen", 4, FALSE)) && SvROK(*svp))
1064 seenhv = (HV*)SvRV(*svp);
1065 if ((svp = hv_fetch(hv, "todump", 6, FALSE)) && SvROK(*svp))
1066 todumpav = (AV*)SvRV(*svp);
1067 if ((svp = hv_fetch(hv, "names", 5, FALSE)) && SvROK(*svp))
1068 namesav = (AV*)SvRV(*svp);
1069 if ((svp = hv_fetch(hv, "indent", 6, FALSE)))
1070 indent = SvIV(*svp);
1071 if ((svp = hv_fetch(hv, "purity", 6, FALSE)))
1072 purity = SvIV(*svp);
1073 if ((svp = hv_fetch(hv, "terse", 5, FALSE)))
1074 terse = SvTRUE(*svp);
497b47a8 1075#if 0 /* useqq currently unused */
823edd99 1076 if ((svp = hv_fetch(hv, "useqq", 5, FALSE)))
1077 useqq = SvTRUE(*svp);
497b47a8 1078#endif
823edd99 1079 if ((svp = hv_fetch(hv, "pad", 3, FALSE)))
1080 pad = *svp;
1081 if ((svp = hv_fetch(hv, "xpad", 4, FALSE)))
1082 xpad = *svp;
1083 if ((svp = hv_fetch(hv, "apad", 4, FALSE)))
1084 apad = *svp;
1085 if ((svp = hv_fetch(hv, "sep", 3, FALSE)))
1086 sep = *svp;
30b4f386 1087 if ((svp = hv_fetch(hv, "pair", 4, FALSE)))
1088 pair = *svp;
823edd99 1089 if ((svp = hv_fetch(hv, "varname", 7, FALSE)))
1090 varname = *svp;
1091 if ((svp = hv_fetch(hv, "freezer", 7, FALSE)))
1092 freezer = *svp;
1093 if ((svp = hv_fetch(hv, "toaster", 7, FALSE)))
1094 toaster = *svp;
1095 if ((svp = hv_fetch(hv, "deepcopy", 8, FALSE)))
1096 deepcopy = SvTRUE(*svp);
1097 if ((svp = hv_fetch(hv, "quotekeys", 9, FALSE)))
1098 quotekeys = SvTRUE(*svp);
1099 if ((svp = hv_fetch(hv, "bless", 5, FALSE)))
1100 bless = *svp;
a2126434 1101 if ((svp = hv_fetch(hv, "maxdepth", 8, FALSE)))
1102 maxdepth = SvIV(*svp);
e9105f86 1103 if ((svp = hv_fetch(hv, "sortkeys", 8, FALSE))) {
1104 sortkeys = *svp;
1105 if (! SvTRUE(sortkeys))
1106 sortkeys = NULL;
1107 else if (! (SvROK(sortkeys) &&
1108 SvTYPE(SvRV(sortkeys)) == SVt_PVCV) )
1109 {
1110 /* flag to use qsortsv() for sorting hash keys */
1111 sortkeys = &PL_sv_yes;
1112 }
1113 }
823edd99 1114 postav = newAV();
1115
1116 if (todumpav)
1117 imax = av_len(todumpav);
1118 else
1119 imax = -1;
7820172a 1120 valstr = newSVpvn("",0);
823edd99 1121 for (i = 0; i <= imax; ++i) {
1122 SV *newapad;
6cde4e94 1123
823edd99 1124 av_clear(postav);
1125 if ((svp = av_fetch(todumpav, i, FALSE)))
1126 val = *svp;
1127 else
3280af22 1128 val = &PL_sv_undef;
d20128b8 1129 if ((svp = av_fetch(namesav, i, TRUE))) {
823edd99 1130 sv_setsv(name, *svp);
d20128b8 1131 if (SvOK(*svp) && !SvPOK(*svp))
1132 (void)SvPV_nolen_const(name);
1133 }
823edd99 1134 else
8063af02 1135 (void)SvOK_off(name);
6cde4e94 1136
d20128b8 1137 if (SvPOK(name)) {
aa07b2f6 1138 if ((SvPVX_const(name))[0] == '*') {
823edd99 1139 if (SvROK(val)) {
1140 switch (SvTYPE(SvRV(val))) {
1141 case SVt_PVAV:
1142 (SvPVX(name))[0] = '@';
1143 break;
1144 case SVt_PVHV:
1145 (SvPVX(name))[0] = '%';
1146 break;
1147 case SVt_PVCV:
1148 (SvPVX(name))[0] = '*';
1149 break;
1150 default:
1151 (SvPVX(name))[0] = '$';
1152 break;
1153 }
1154 }
1155 else
1156 (SvPVX(name))[0] = '$';
1157 }
aa07b2f6 1158 else if ((SvPVX_const(name))[0] != '$')
823edd99 1159 sv_insert(name, 0, 0, "$", 1);
1160 }
1161 else {
9061c4b9 1162 STRLEN nchars;
823edd99 1163 sv_setpvn(name, "$", 1);
1164 sv_catsv(name, varname);
f5def3a2 1165 nchars = my_snprintf(tmpbuf, sizeof(tmpbuf), "%"IVdf, (IV)(i+1));
823edd99 1166 sv_catpvn(name, tmpbuf, nchars);
1167 }
6cde4e94 1168
823edd99 1169 if (indent >= 2) {
9061c4b9 1170 SV * const tmpsv = sv_x(aTHX_ NULL, " ", 1, SvCUR(name)+3);
823edd99 1171 newapad = newSVsv(apad);
1172 sv_catsv(newapad, tmpsv);
1173 SvREFCNT_dec(tmpsv);
1174 }
1175 else
1176 newapad = apad;
6cde4e94 1177
aa07b2f6 1178 DD_dump(aTHX_ val, SvPVX_const(name), SvCUR(name), valstr, seenhv,
30b4f386 1179 postav, &level, indent, pad, xpad, newapad, sep, pair,
823edd99 1180 freezer, toaster, purity, deepcopy, quotekeys,
e9105f86 1181 bless, maxdepth, sortkeys);
6cde4e94 1182
823edd99 1183 if (indent >= 2)
1184 SvREFCNT_dec(newapad);
1185
1186 postlen = av_len(postav);
1187 if (postlen >= 0 || !terse) {
1188 sv_insert(valstr, 0, 0, " = ", 3);
aa07b2f6 1189 sv_insert(valstr, 0, 0, SvPVX_const(name), SvCUR(name));
823edd99 1190 sv_catpvn(valstr, ";", 1);
1191 }
1192 sv_catsv(retval, pad);
1193 sv_catsv(retval, valstr);
1194 sv_catsv(retval, sep);
1195 if (postlen >= 0) {
1196 I32 i;
1197 sv_catsv(retval, pad);
1198 for (i = 0; i <= postlen; ++i) {
1199 SV *elem;
1200 svp = av_fetch(postav, i, FALSE);
1201 if (svp && (elem = *svp)) {
1202 sv_catsv(retval, elem);
1203 if (i < postlen) {
1204 sv_catpvn(retval, ";", 1);
1205 sv_catsv(retval, sep);
1206 sv_catsv(retval, pad);
1207 }
1208 }
1209 }
1210 sv_catpvn(retval, ";", 1);
1211 sv_catsv(retval, sep);
1212 }
1213 sv_setpvn(valstr, "", 0);
1214 if (gimme == G_ARRAY) {
1215 XPUSHs(sv_2mortal(retval));
1216 if (i < imax) /* not the last time thro ? */
7820172a 1217 retval = newSVpvn("",0);
823edd99 1218 }
1219 }
1220 SvREFCNT_dec(postav);
1221 SvREFCNT_dec(valstr);
1222 }
1223 else
1224 croak("Call to new() method failed to return HASH ref");
1225 if (gimme == G_SCALAR)
1226 XPUSHs(sv_2mortal(retval));
1227 }