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