More EBCDIC fixes.
[p5sagit/p5-mst-13.2.git] / doop.c
CommitLineData
a0d0e21e 1/* doop.c
79072805 2 *
bc89e66f 3 * Copyright (c) 1991-2001, Larry Wall
79072805 4 *
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
7 *
a0d0e21e 8 */
9
10/*
11 * "'So that was the job I felt I had to do when I started,' thought Sam."
79072805 12 */
13
14#include "EXTERN.h"
864dbfa3 15#define PERL_IN_DOOP_C
79072805 16#include "perl.h"
17
64ca3a65 18#ifndef PERL_MICRO
79072805 19#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
20#include <signal.h>
21#endif
64ca3a65 22#endif
79072805 23
942e002e 24STATIC I32
b250498f 25S_do_trans_simple(pTHX_ SV *sv)
79072805 26{
4757a243 27 U8 *s;
b250498f 28 U8 *d;
4757a243 29 U8 *send;
b250498f 30 U8 *dstart;
4757a243 31 I32 matches = 0;
9b877dbb 32 I32 grows = PL_op->op_private & OPpTRANS_GROWS;
463ee0b2 33 STRLEN len;
4757a243 34 short *tbl;
35 I32 ch;
79072805 36
4757a243 37 tbl = (short*)cPVOP->op_pv;
38 if (!tbl)
2269b42e 39 Perl_croak(aTHX_ "panic: do_trans_simple");
a0ed51b3 40
4757a243 41 s = (U8*)SvPV(sv, len);
42 send = s + len;
43
b250498f 44 /* First, take care of non-UTF8 input strings, because they're easy */
1aa99e6b 45 if (!SvUTF8(sv)) {
01ec43d0 46 while (s < send) {
036b4402 47 if ((ch = tbl[*s]) >= 0) {
01ec43d0 48 matches++;
49 *s++ = ch;
50 }
51 else
52 s++;
53 }
54 SvSETMAGIC(sv);
b250498f 55 return matches;
56 }
4757a243 57
b250498f 58 /* Allow for expansion: $_="a".chr(400); tr/a/\xFE/, FE needs encoding */
9b877dbb 59 if (grows)
60 New(0, d, len*2+1, U8);
61 else
62 d = s;
b250498f 63 dstart = d;
64 while (s < send) {
ba210ebe 65 STRLEN ulen;
9b877dbb 66 UV c;
b250498f 67
b250498f 68 /* Need to check this, otherwise 128..255 won't match */
9041c2e3 69 c = utf8n_to_uvchr(s, send - s, &ulen, 0);
9b877dbb 70 if (c < 0x100 && (ch = tbl[c]) >= 0) {
b250498f 71 matches++;
9041c2e3 72 d = uvchr_to_utf8(d, ch);
b250498f 73 s += ulen;
01ec43d0 74 }
75 else { /* No match -> copy */
9b877dbb 76 Copy(s, d, ulen, U8);
77 d += ulen;
78 s += ulen;
b250498f 79 }
80 }
9b877dbb 81 if (grows) {
82 sv_setpvn(sv, (char*)dstart, d - dstart);
83 Safefree(dstart);
84 }
85 else {
86 *d = '\0';
87 SvCUR_set(sv, d - dstart);
88 }
b250498f 89 SvUTF8_on(sv);
b250498f 90 SvSETMAGIC(sv);
4757a243 91 return matches;
92}
93
942e002e 94STATIC I32
036b4402 95S_do_trans_count(pTHX_ SV *sv)/* SPC - OK */
4757a243 96{
4757a243 97 U8 *s;
98 U8 *send;
99 I32 matches = 0;
100 STRLEN len;
101 short *tbl;
8973db79 102 I32 complement = PL_op->op_private & OPpTRANS_COMPLEMENT;
4757a243 103
104 tbl = (short*)cPVOP->op_pv;
105 if (!tbl)
2269b42e 106 Perl_croak(aTHX_ "panic: do_trans_count");
4757a243 107
108 s = (U8*)SvPV(sv, len);
109 send = s + len;
110
1aa99e6b 111 if (!SvUTF8(sv))
112 while (s < send) {
113 if (tbl[*s++] >= 0)
036b4402 114 matches++;
1aa99e6b 115 }
116 else
117 while (s < send) {
118 UV c;
119 STRLEN ulen;
9041c2e3 120 c = utf8n_to_uvchr(s, send - s, &ulen, 0);
8973db79 121 if (c < 0x100) {
122 if (tbl[c] >= 0)
123 matches++;
124 } else if (complement)
1aa99e6b 125 matches++;
126 s += ulen;
127 }
4757a243 128
129 return matches;
130}
131
942e002e 132STATIC I32
b250498f 133S_do_trans_complex(pTHX_ SV *sv)/* SPC - NOT OK */
4757a243 134{
4757a243 135 U8 *s;
136 U8 *send;
137 U8 *d;
5e44153e 138 U8 *dstart;
1aa99e6b 139 I32 isutf8;
4757a243 140 I32 matches = 0;
9b877dbb 141 I32 grows = PL_op->op_private & OPpTRANS_GROWS;
8973db79 142 I32 complement = PL_op->op_private & OPpTRANS_COMPLEMENT;
143 I32 del = PL_op->op_private & OPpTRANS_DELETE;
144 STRLEN len, rlen;
4757a243 145 short *tbl;
146 I32 ch;
147
148 tbl = (short*)cPVOP->op_pv;
149 if (!tbl)
2269b42e 150 Perl_croak(aTHX_ "panic: do_trans_complex");
4757a243 151
152 s = (U8*)SvPV(sv, len);
1aa99e6b 153 isutf8 = SvUTF8(sv);
4757a243 154 send = s + len;
155
1aa99e6b 156 if (!isutf8) {
157 dstart = d = s;
158 if (PL_op->op_private & OPpTRANS_SQUASH) {
159 U8* p = send;
160 while (s < send) {
161 if ((ch = tbl[*s]) >= 0) {
036b4402 162 *d = ch;
163 matches++;
1aa99e6b 164 if (p != d - 1 || *p != *d)
165 p = d++;
166 }
167 else if (ch == -1) /* -1 is unmapped character */
168 *d++ = *s;
169 else if (ch == -2) /* -2 is delete character */
170 matches++;
171 s++;
172 }
a0ed51b3 173 }
1aa99e6b 174 else {
175 while (s < send) {
176 if ((ch = tbl[*s]) >= 0) {
177 matches++;
178 *d++ = ch;
179 }
180 else if (ch == -1) /* -1 is unmapped character */
181 *d++ = *s;
182 else if (ch == -2) /* -2 is delete character */
183 matches++;
184 s++;
185 }
186 }
187 SvCUR_set(sv, d - dstart);
4757a243 188 }
1aa99e6b 189 else { /* isutf8 */
9b877dbb 190 if (grows)
191 New(0, d, len*2+1, U8);
192 else
193 d = s;
1aa99e6b 194 dstart = d;
8973db79 195 if (complement && !del)
196 rlen = tbl[0x100];
1aa99e6b 197
4aecb5b5 198#ifdef MACOS_TRADITIONAL
199#define comp CoMP /* "comp" is a keyword in some compilers ... */
200#endif
201
1aa99e6b 202 if (PL_op->op_private & OPpTRANS_SQUASH) {
1aa99e6b 203 UV pch = 0xfeedface;
204 while (s < send) {
205 STRLEN len;
9041c2e3 206 UV comp = utf8_to_uvchr(s, &len);
1aa99e6b 207
8973db79 208 if (comp > 0xff) {
209 if (!complement) {
210 Copy(s, d, len, U8);
211 d += len;
212 }
213 else {
214 matches++;
215 if (!del) {
05d340b8 216 ch = (rlen == 0) ? comp :
217 (comp - 0x100 < rlen) ?
8973db79 218 tbl[comp+1] : tbl[0x100+rlen];
219 if (ch != pch) {
9041c2e3 220 d = uvchr_to_utf8(d, ch);
8973db79 221 pch = ch;
222 }
223 s += len;
224 continue;
225 }
226 }
9b877dbb 227 }
1aa99e6b 228 else if ((ch = tbl[comp]) >= 0) {
229 matches++;
230 if (ch != pch) {
9041c2e3 231 d = uvchr_to_utf8(d, ch);
1aa99e6b 232 pch = ch;
233 }
234 s += len;
235 continue;
236 }
9b877dbb 237 else if (ch == -1) { /* -1 is unmapped character */
238 Copy(s, d, len, U8);
239 d += len;
240 }
1aa99e6b 241 else if (ch == -2) /* -2 is delete character */
242 matches++;
243 s += len;
244 pch = 0xfeedface;
245 }
5d06d08e 246 }
1aa99e6b 247 else {
248 while (s < send) {
249 STRLEN len;
9041c2e3 250 UV comp = utf8_to_uvchr(s, &len);
8973db79 251 if (comp > 0xff) {
252 if (!complement) {
253 Copy(s, d, len, U8);
254 d += len;
255 }
256 else {
257 matches++;
258 if (!del) {
9041c2e3 259 if (comp - 0x100 < rlen)
260 d = uvchr_to_utf8(d, tbl[comp+1]);
8973db79 261 else
9041c2e3 262 d = uvchr_to_utf8(d, tbl[0x100+rlen]);
8973db79 263 }
264 }
9b877dbb 265 }
1aa99e6b 266 else if ((ch = tbl[comp]) >= 0) {
9041c2e3 267 d = uvchr_to_utf8(d, ch);
1aa99e6b 268 matches++;
269 }
270 else if (ch == -1) { /* -1 is unmapped character */
9b877dbb 271 Copy(s, d, len, U8);
272 d += len;
1aa99e6b 273 }
274 else if (ch == -2) /* -2 is delete character */
275 matches++;
276 s += len;
277 }
278 }
9b877dbb 279 if (grows) {
280 sv_setpvn(sv, (char*)dstart, d - dstart);
281 Safefree(dstart);
282 }
283 else {
284 *d = '\0';
285 SvCUR_set(sv, d - dstart);
286 }
1aa99e6b 287 SvUTF8_on(sv);
4757a243 288 }
5e44153e 289 SvSETMAGIC(sv);
4757a243 290 return matches;
291}
292
942e002e 293STATIC I32
036b4402 294S_do_trans_simple_utf8(pTHX_ SV *sv)/* SPC - OK */
4757a243 295{
4757a243 296 U8 *s;
297 U8 *send;
298 U8 *d;
036b4402 299 U8 *start;
1aa99e6b 300 U8 *dstart, *dend;
4757a243 301 I32 matches = 0;
9b877dbb 302 I32 grows = PL_op->op_private & OPpTRANS_GROWS;
4757a243 303 STRLEN len;
304
305 SV* rv = (SV*)cSVOP->op_sv;
306 HV* hv = (HV*)SvRV(rv);
307 SV** svp = hv_fetch(hv, "NONE", 4, FALSE);
308 UV none = svp ? SvUV(*svp) : 0x7fffffff;
309 UV extra = none + 1;
310 UV final;
311 UV uv;
1aa99e6b 312 I32 isutf8;
313 U8 hibit = 0;
4757a243 314
315 s = (U8*)SvPV(sv, len);
1aa99e6b 316 isutf8 = SvUTF8(sv);
317 if (!isutf8) {
318 U8 *t = s, *e = s + len;
c4d5f83a 319 while (t < e) {
320 U8 ch = *t++;
321 if ((hibit = !NATIVE_IS_INVARIANT(ch)))
1aa99e6b 322 break;
c4d5f83a 323 }
1aa99e6b 324 if (hibit)
325 s = bytes_to_utf8(s, &len);
326 }
4757a243 327 send = s + len;
036b4402 328 start = s;
4757a243 329
330 svp = hv_fetch(hv, "FINAL", 5, FALSE);
331 if (svp)
332 final = SvUV(*svp);
333
9b877dbb 334 if (grows) {
335 /* d needs to be bigger than s, in case e.g. upgrading is required */
336 New(0, d, len*3+UTF8_MAXLEN, U8);
337 dend = d + len * 3;
338 dstart = d;
339 }
340 else {
341 dstart = d = s;
342 dend = d + len;
343 }
1aa99e6b 344
4757a243 345 while (s < send) {
346 if ((uv = swash_fetch(rv, s)) < none) {
347 s += UTF8SKIP(s);
348 matches++;
9041c2e3 349 d = uvchr_to_utf8(d, uv);
4757a243 350 }
351 else if (uv == none) {
1aa99e6b 352 int i = UTF8SKIP(s);
9b877dbb 353 Copy(s, d, i, U8);
354 d += i;
355 s += i;
4757a243 356 }
357 else if (uv == extra) {
1aa99e6b 358 int i = UTF8SKIP(s);
036b4402 359 s += i;
4757a243 360 matches++;
9041c2e3 361 d = uvchr_to_utf8(d, final);
4757a243 362 }
363 else
364 s += UTF8SKIP(s);
1aa99e6b 365
9b877dbb 366 if (d > dend) {
1aa99e6b 367 STRLEN clen = d - dstart;
368 STRLEN nlen = dend - dstart + len + UTF8_MAXLEN;
9b877dbb 369 if (!grows)
370 Perl_croak(aTHX_ "panic: do_trans_complex_utf8");
1aa99e6b 371 Renew(dstart, nlen+UTF8_MAXLEN, U8);
372 d = dstart + clen;
373 dend = dstart + nlen;
374 }
4757a243 375 }
16ec844d 376 if (grows || hibit) {
9b877dbb 377 sv_setpvn(sv, (char*)dstart, d - dstart);
378 Safefree(dstart);
16ec844d 379 if (grows && hibit)
380 Safefree(start);
9b877dbb 381 }
382 else {
383 *d = '\0';
384 SvCUR_set(sv, d - dstart);
385 }
4757a243 386 SvSETMAGIC(sv);
1aa99e6b 387 SvUTF8_on(sv);
9041c2e3 388 /* Downgrading just 'cos it will is suspect - NI-S */
1aa99e6b 389 if (!isutf8 && !(PL_hints & HINT_UTF8))
390 sv_utf8_downgrade(sv, TRUE);
4757a243 391
392 return matches;
393}
394
942e002e 395STATIC I32
036b4402 396S_do_trans_count_utf8(pTHX_ SV *sv)/* SPC - OK */
4757a243 397{
4757a243 398 U8 *s;
1aa99e6b 399 U8 *start, *send;
4757a243 400 I32 matches = 0;
401 STRLEN len;
402
403 SV* rv = (SV*)cSVOP->op_sv;
404 HV* hv = (HV*)SvRV(rv);
405 SV** svp = hv_fetch(hv, "NONE", 4, FALSE);
406 UV none = svp ? SvUV(*svp) : 0x7fffffff;
407 UV uv;
1aa99e6b 408 U8 hibit = 0;
4757a243 409
410 s = (U8*)SvPV(sv, len);
1aa99e6b 411 if (!SvUTF8(sv)) {
412 U8 *t = s, *e = s + len;
c4d5f83a 413 while (t < e) {
414 U8 ch = *t++;
415 if ((hibit = !NATIVE_IS_INVARIANT(ch)))
1aa99e6b 416 break;
c4d5f83a 417 }
1aa99e6b 418 if (hibit)
419 start = s = bytes_to_utf8(s, &len);
420 }
4757a243 421 send = s + len;
422
423 while (s < send) {
834a4ddd 424 if ((uv = swash_fetch(rv, s)) < none)
4757a243 425 matches++;
834a4ddd 426 s += UTF8SKIP(s);
4757a243 427 }
1aa99e6b 428 if (hibit)
429 Safefree(start);
4757a243 430
431 return matches;
432}
433
942e002e 434STATIC I32
036b4402 435S_do_trans_complex_utf8(pTHX_ SV *sv) /* SPC - NOT OK */
4757a243 436{
4757a243 437 U8 *s;
1aa99e6b 438 U8 *start, *send;
4757a243 439 U8 *d;
440 I32 matches = 0;
441 I32 squash = PL_op->op_private & OPpTRANS_SQUASH;
4757a243 442 I32 del = PL_op->op_private & OPpTRANS_DELETE;
9b877dbb 443 I32 grows = PL_op->op_private & OPpTRANS_GROWS;
4757a243 444 SV* rv = (SV*)cSVOP->op_sv;
445 HV* hv = (HV*)SvRV(rv);
446 SV** svp = hv_fetch(hv, "NONE", 4, FALSE);
447 UV none = svp ? SvUV(*svp) : 0x7fffffff;
448 UV extra = none + 1;
449 UV final;
450 UV uv;
451 STRLEN len;
1aa99e6b 452 U8 *dstart, *dend;
453 I32 isutf8;
454 U8 hibit = 0;
4757a243 455
456 s = (U8*)SvPV(sv, len);
1aa99e6b 457 isutf8 = SvUTF8(sv);
458 if (!isutf8) {
459 U8 *t = s, *e = s + len;
c4d5f83a 460 while (t < e) {
461 U8 ch = *t++;
462 if ((hibit = !NATIVE_IS_INVARIANT(ch)))
1aa99e6b 463 break;
c4d5f83a 464 }
1aa99e6b 465 if (hibit)
466 s = bytes_to_utf8(s, &len);
467 }
4757a243 468 send = s + len;
1aa99e6b 469 start = s;
4757a243 470
471 svp = hv_fetch(hv, "FINAL", 5, FALSE);
472 if (svp)
473 final = SvUV(*svp);
474
9b877dbb 475 if (grows) {
476 /* d needs to be bigger than s, in case e.g. upgrading is required */
477 New(0, d, len*3+UTF8_MAXLEN, U8);
478 dend = d + len * 3;
479 dstart = d;
480 }
481 else {
482 dstart = d = s;
483 dend = d + len;
484 }
4757a243 485
486 if (squash) {
487 UV puv = 0xfeedface;
488 while (s < send) {
1aa99e6b 489 uv = swash_fetch(rv, s);
9041c2e3 490
9b877dbb 491 if (d > dend) {
492 STRLEN clen = d - dstart;
493 STRLEN nlen = dend - dstart + len + UTF8_MAXLEN;
494 if (!grows)
495 Perl_croak(aTHX_ "panic: do_trans_complex_utf8");
1aa99e6b 496 Renew(dstart, nlen+UTF8_MAXLEN, U8);
497 d = dstart + clen;
498 dend = dstart + nlen;
4757a243 499 }
500 if (uv < none) {
501 matches++;
94472101 502 s += UTF8SKIP(s);
4757a243 503 if (uv != puv) {
9041c2e3 504 d = uvchr_to_utf8(d, uv);
4757a243 505 puv = uv;
506 }
4757a243 507 continue;
508 }
509 else if (uv == none) { /* "none" is unmapped character */
1aa99e6b 510 int i = UTF8SKIP(s);
9b877dbb 511 Copy(s, d, i, U8);
512 d += i;
513 s += i;
4757a243 514 puv = 0xfeedface;
515 continue;
a0ed51b3 516 }
4757a243 517 else if (uv == extra && !del) {
518 matches++;
94472101 519 s += UTF8SKIP(s);
4757a243 520 if (uv != puv) {
9041c2e3 521 d = uvchr_to_utf8(d, final);
4757a243 522 puv = final;
523 }
4757a243 524 continue;
525 }
01ec43d0 526 matches++; /* "none+1" is delete character */
527 s += UTF8SKIP(s);
a0ed51b3 528 }
79072805 529 }
530 else {
4757a243 531 while (s < send) {
1aa99e6b 532 uv = swash_fetch(rv, s);
9b877dbb 533 if (d > dend) {
534 STRLEN clen = d - dstart;
535 STRLEN nlen = dend - dstart + len + UTF8_MAXLEN;
536 if (!grows)
537 Perl_croak(aTHX_ "panic: do_trans_complex_utf8");
1aa99e6b 538 Renew(dstart, nlen+UTF8_MAXLEN, U8);
539 d = dstart + clen;
540 dend = dstart + nlen;
a0ed51b3 541 }
4757a243 542 if (uv < none) {
543 matches++;
01ec43d0 544 s += UTF8SKIP(s);
9041c2e3 545 d = uvchr_to_utf8(d, uv);
4757a243 546 continue;
a0ed51b3 547 }
4757a243 548 else if (uv == none) { /* "none" is unmapped character */
1aa99e6b 549 int i = UTF8SKIP(s);
9b877dbb 550 Copy(s, d, i, U8);
551 d += i;
552 s += i;
4757a243 553 continue;
79072805 554 }
4757a243 555 else if (uv == extra && !del) {
556 matches++;
01ec43d0 557 s += UTF8SKIP(s);
9041c2e3 558 d = uvchr_to_utf8(d, final);
4757a243 559 continue;
560 }
01ec43d0 561 matches++; /* "none+1" is delete character */
562 s += UTF8SKIP(s);
79072805 563 }
4757a243 564 }
16ec844d 565 if (grows || hibit) {
9b877dbb 566 sv_setpvn(sv, (char*)dstart, d - dstart);
567 Safefree(dstart);
16ec844d 568 if (grows && hibit)
569 Safefree(start);
9b877dbb 570 }
571 else {
572 *d = '\0';
573 SvCUR_set(sv, d - dstart);
574 }
1aa99e6b 575 SvUTF8_on(sv);
1aa99e6b 576 if (!isutf8 && !(PL_hints & HINT_UTF8))
577 sv_utf8_downgrade(sv, TRUE);
4757a243 578 SvSETMAGIC(sv);
579
580 return matches;
581}
582
583I32
864dbfa3 584Perl_do_trans(pTHX_ SV *sv)
4757a243 585{
586 STRLEN len;
8e84507e 587 I32 hasutf = (PL_op->op_private &
036b4402 588 (OPpTRANS_FROM_UTF|OPpTRANS_TO_UTF));
4757a243 589
590 if (SvREADONLY(sv) && !(PL_op->op_private & OPpTRANS_IDENTICAL))
cea2e8a9 591 Perl_croak(aTHX_ PL_no_modify);
4757a243 592
593 (void)SvPV(sv, len);
594 if (!len)
595 return 0;
596 if (!SvPOKp(sv))
597 (void)SvPV_force(sv, len);
2de7b02f 598 if (!(PL_op->op_private & OPpTRANS_IDENTICAL))
599 (void)SvPOK_only_UTF8(sv);
4757a243 600
cea2e8a9 601 DEBUG_t( Perl_deb(aTHX_ "2.TBL\n"));
4757a243 602
036b4402 603 switch (PL_op->op_private & ~hasutf & 63) {
4757a243 604 case 0:
01ec43d0 605 if (hasutf)
606 return do_trans_simple_utf8(sv);
607 else
608 return do_trans_simple(sv);
4757a243 609
610 case OPpTRANS_IDENTICAL:
05d340b8 611 case OPpTRANS_IDENTICAL|OPpTRANS_COMPLEMENT:
01ec43d0 612 if (hasutf)
613 return do_trans_count_utf8(sv);
614 else
615 return do_trans_count(sv);
4757a243 616
617 default:
01ec43d0 618 if (hasutf)
036b4402 619 return do_trans_complex_utf8(sv);
4757a243 620 else
036b4402 621 return do_trans_complex(sv);
79072805 622 }
79072805 623}
624
625void
864dbfa3 626Perl_do_join(pTHX_ register SV *sv, SV *del, register SV **mark, register SV **sp)
79072805 627{
628 SV **oldmark = mark;
629 register I32 items = sp - mark;
79072805 630 register STRLEN len;
463ee0b2 631 STRLEN delimlen;
632 register char *delim = SvPV(del, delimlen);
633 STRLEN tmplen;
79072805 634
635 mark++;
636 len = (items > 0 ? (delimlen * (items - 1) ) : 0);
07f14f54 637 (void)SvUPGRADE(sv, SVt_PV);
79072805 638 if (SvLEN(sv) < len + items) { /* current length is way too short */
639 while (items-- > 0) {
1426bbf4 640 if (*mark && !SvGAMAGIC(*mark) && SvOK(*mark)) {
463ee0b2 641 SvPV(*mark, tmplen);
642 len += tmplen;
79072805 643 }
644 mark++;
645 }
646 SvGROW(sv, len + 1); /* so try to pre-extend */
647
648 mark = oldmark;
db7c17d7 649 items = sp - mark;
79072805 650 ++mark;
651 }
652
463ee0b2 653 if (items-- > 0) {
92d29cee 654 sv_setpv(sv, "");
655 if (*mark)
656 sv_catsv(sv, *mark);
463ee0b2 657 mark++;
658 }
79072805 659 else
660 sv_setpv(sv,"");
c512ce4f 661 if (delimlen) {
79072805 662 for (; items > 0; items--,mark++) {
c512ce4f 663 sv_catsv(sv,del);
79072805 664 sv_catsv(sv,*mark);
665 }
666 }
667 else {
668 for (; items > 0; items--,mark++)
669 sv_catsv(sv,*mark);
670 }
671 SvSETMAGIC(sv);
672}
673
674void
864dbfa3 675Perl_do_sprintf(pTHX_ SV *sv, I32 len, SV **sarg)
79072805 676{
46fc3d4c 677 STRLEN patlen;
678 char *pat = SvPV(*sarg, patlen);
679 bool do_taint = FALSE;
680
681 sv_vsetpvfn(sv, pat, patlen, Null(va_list*), sarg + 1, len - 1, &do_taint);
79072805 682 SvSETMAGIC(sv);
46fc3d4c 683 if (do_taint)
684 SvTAINTED_on(sv);
79072805 685}
686
33b45480 687/* currently converts input to bytes if possible, but doesn't sweat failure */
81e118e0 688UV
689Perl_do_vecget(pTHX_ SV *sv, I32 offset, I32 size)
690{
691 STRLEN srclen, len;
692 unsigned char *s = (unsigned char *) SvPV(sv, srclen);
693 UV retnum = 0;
694
a50d7633 695 if (offset < 0)
81e118e0 696 return retnum;
8e84507e 697 if (size < 1 || (size & (size-1))) /* size < 1 or not a power of two */
a50d7633 698 Perl_croak(aTHX_ "Illegal number of bits in vec");
246fae53 699
dcad2880 700 if (SvUTF8(sv))
33b45480 701 (void) Perl_sv_utf8_downgrade(aTHX_ sv, TRUE);
246fae53 702
81e118e0 703 offset *= size; /* turn into bit offset */
704 len = (offset + size + 7) / 8; /* required number of bytes */
705 if (len > srclen) {
706 if (size <= 8)
707 retnum = 0;
708 else {
709 offset >>= 3; /* turn into byte offset */
710 if (size == 16) {
711 if (offset >= srclen)
712 retnum = 0;
713 else
628e1a40 714 retnum = (UV) s[offset] << 8;
81e118e0 715 }
716 else if (size == 32) {
717 if (offset >= srclen)
718 retnum = 0;
719 else if (offset + 1 >= srclen)
720 retnum =
721 ((UV) s[offset ] << 24);
722 else if (offset + 2 >= srclen)
723 retnum =
724 ((UV) s[offset ] << 24) +
725 ((UV) s[offset + 1] << 16);
726 else
727 retnum =
728 ((UV) s[offset ] << 24) +
729 ((UV) s[offset + 1] << 16) +
730 ( s[offset + 2] << 8);
731 }
d7d93a81 732#ifdef UV_IS_QUAD
c5a0f51a 733 else if (size == 64) {
c5a0f51a 734 if (ckWARN(WARN_PORTABLE))
735 Perl_warner(aTHX_ WARN_PORTABLE,
736 "Bit vector size > 32 non-portable");
737 if (offset >= srclen)
738 retnum = 0;
739 else if (offset + 1 >= srclen)
740 retnum =
741 (UV) s[offset ] << 56;
742 else if (offset + 2 >= srclen)
743 retnum =
744 ((UV) s[offset ] << 56) +
745 ((UV) s[offset + 1] << 48);
746 else if (offset + 3 >= srclen)
747 retnum =
748 ((UV) s[offset ] << 56) +
749 ((UV) s[offset + 1] << 48) +
750 ((UV) s[offset + 2] << 40);
751 else if (offset + 4 >= srclen)
752 retnum =
753 ((UV) s[offset ] << 56) +
754 ((UV) s[offset + 1] << 48) +
755 ((UV) s[offset + 2] << 40) +
756 ((UV) s[offset + 3] << 32);
757 else if (offset + 5 >= srclen)
758 retnum =
759 ((UV) s[offset ] << 56) +
760 ((UV) s[offset + 1] << 48) +
761 ((UV) s[offset + 2] << 40) +
762 ((UV) s[offset + 3] << 32) +
763 ( s[offset + 4] << 24);
764 else if (offset + 6 >= srclen)
765 retnum =
766 ((UV) s[offset ] << 56) +
767 ((UV) s[offset + 1] << 48) +
768 ((UV) s[offset + 2] << 40) +
769 ((UV) s[offset + 3] << 32) +
770 ((UV) s[offset + 4] << 24) +
771 ((UV) s[offset + 5] << 16);
772 else
8e84507e 773 retnum =
c5a0f51a 774 ((UV) s[offset ] << 56) +
775 ((UV) s[offset + 1] << 48) +
776 ((UV) s[offset + 2] << 40) +
777 ((UV) s[offset + 3] << 32) +
778 ((UV) s[offset + 4] << 24) +
779 ((UV) s[offset + 5] << 16) +
628e1a40 780 ( s[offset + 6] << 8);
c5a0f51a 781 }
782#endif
81e118e0 783 }
784 }
785 else if (size < 8)
786 retnum = (s[offset >> 3] >> (offset & 7)) & ((1 << size) - 1);
787 else {
788 offset >>= 3; /* turn into byte offset */
789 if (size == 8)
790 retnum = s[offset];
791 else if (size == 16)
792 retnum =
628e1a40 793 ((UV) s[offset] << 8) +
81e118e0 794 s[offset + 1];
795 else if (size == 32)
796 retnum =
797 ((UV) s[offset ] << 24) +
798 ((UV) s[offset + 1] << 16) +
799 ( s[offset + 2] << 8) +
800 s[offset + 3];
d7d93a81 801#ifdef UV_IS_QUAD
c5a0f51a 802 else if (size == 64) {
c5a0f51a 803 if (ckWARN(WARN_PORTABLE))
804 Perl_warner(aTHX_ WARN_PORTABLE,
805 "Bit vector size > 32 non-portable");
806 retnum =
807 ((UV) s[offset ] << 56) +
808 ((UV) s[offset + 1] << 48) +
809 ((UV) s[offset + 2] << 40) +
810 ((UV) s[offset + 3] << 32) +
811 ((UV) s[offset + 4] << 24) +
812 ((UV) s[offset + 5] << 16) +
628e1a40 813 ( s[offset + 6] << 8) +
c5a0f51a 814 s[offset + 7];
815 }
816#endif
81e118e0 817 }
818
819 return retnum;
820}
821
33b45480 822/* currently converts input to bytes if possible but doesn't sweat failures,
823 * although it does ensure that the string it clobbers is not marked as
824 * utf8-valid any more
825 */
79072805 826void
864dbfa3 827Perl_do_vecset(pTHX_ SV *sv)
79072805 828{
829 SV *targ = LvTARG(sv);
830 register I32 offset;
831 register I32 size;
8990e307 832 register unsigned char *s;
81e118e0 833 register UV lval;
79072805 834 I32 mask;
a0d0e21e 835 STRLEN targlen;
836 STRLEN len;
79072805 837
8990e307 838 if (!targ)
839 return;
a0d0e21e 840 s = (unsigned char*)SvPV_force(targ, targlen);
246fae53 841 if (SvUTF8(targ)) {
33b45480 842 /* This is handled by the SvPOK_only below...
843 if (!Perl_sv_utf8_downgrade(aTHX_ targ, TRUE))
844 SvUTF8_off(targ);
845 */
846 (void) Perl_sv_utf8_downgrade(aTHX_ targ, TRUE);
246fae53 847 }
848
4ebbc975 849 (void)SvPOK_only(targ);
81e118e0 850 lval = SvUV(sv);
79072805 851 offset = LvTARGOFF(sv);
fe58ced6 852 if (offset < 0)
853 Perl_croak(aTHX_ "Assigning to negative offset in vec");
79072805 854 size = LvTARGLEN(sv);
8e84507e 855 if (size < 1 || (size & (size-1))) /* size < 1 or not a power of two */
a50d7633 856 Perl_croak(aTHX_ "Illegal number of bits in vec");
8e84507e 857
81e118e0 858 offset *= size; /* turn into bit offset */
859 len = (offset + size + 7) / 8; /* required number of bytes */
a0d0e21e 860 if (len > targlen) {
861 s = (unsigned char*)SvGROW(targ, len + 1);
12ae5dfc 862 (void)memzero((char *)(s + targlen), len - targlen + 1);
a0d0e21e 863 SvCUR_set(targ, len);
864 }
8e84507e 865
79072805 866 if (size < 8) {
867 mask = (1 << size) - 1;
868 size = offset & 7;
869 lval &= mask;
81e118e0 870 offset >>= 3; /* turn into byte offset */
79072805 871 s[offset] &= ~(mask << size);
872 s[offset] |= lval << size;
873 }
874 else {
81e118e0 875 offset >>= 3; /* turn into byte offset */
79072805 876 if (size == 8)
c5a0f51a 877 s[offset ] = lval & 0xff;
79072805 878 else if (size == 16) {
c5a0f51a 879 s[offset ] = (lval >> 8) & 0xff;
880 s[offset+1] = lval & 0xff;
79072805 881 }
882 else if (size == 32) {
c5a0f51a 883 s[offset ] = (lval >> 24) & 0xff;
884 s[offset+1] = (lval >> 16) & 0xff;
885 s[offset+2] = (lval >> 8) & 0xff;
886 s[offset+3] = lval & 0xff;
887 }
d7d93a81 888#ifdef UV_IS_QUAD
c5a0f51a 889 else if (size == 64) {
c5a0f51a 890 if (ckWARN(WARN_PORTABLE))
891 Perl_warner(aTHX_ WARN_PORTABLE,
892 "Bit vector size > 32 non-portable");
893 s[offset ] = (lval >> 56) & 0xff;
894 s[offset+1] = (lval >> 48) & 0xff;
895 s[offset+2] = (lval >> 40) & 0xff;
896 s[offset+3] = (lval >> 32) & 0xff;
897 s[offset+4] = (lval >> 24) & 0xff;
898 s[offset+5] = (lval >> 16) & 0xff;
899 s[offset+6] = (lval >> 8) & 0xff;
900 s[offset+7] = lval & 0xff;
79072805 901 }
dc1e3f56 902#endif
79072805 903 }
7bb043c3 904 SvSETMAGIC(targ);
79072805 905}
906
907void
864dbfa3 908Perl_do_chop(pTHX_ register SV *astr, register SV *sv)
79072805 909{
463ee0b2 910 STRLEN len;
a0d0e21e 911 char *s;
8e84507e 912
79072805 913 if (SvTYPE(sv) == SVt_PVAV) {
a0d0e21e 914 register I32 i;
915 I32 max;
916 AV* av = (AV*)sv;
917 max = AvFILL(av);
918 for (i = 0; i <= max; i++) {
919 sv = (SV*)av_fetch(av, i, FALSE);
3280af22 920 if (sv && ((sv = *(SV**)sv), sv != &PL_sv_undef))
a0d0e21e 921 do_chop(astr, sv);
922 }
923 return;
79072805 924 }
aa854799 925 else if (SvTYPE(sv) == SVt_PVHV) {
a0d0e21e 926 HV* hv = (HV*)sv;
927 HE* entry;
928 (void)hv_iterinit(hv);
929 /*SUPPRESS 560*/
155aba94 930 while ((entry = hv_iternext(hv)))
a0d0e21e 931 do_chop(astr,hv_iterval(hv,entry));
932 return;
79072805 933 }
aa854799 934 else if (SvREADONLY(sv))
cea2e8a9 935 Perl_croak(aTHX_ PL_no_modify);
a0d0e21e 936 s = SvPV(sv, len);
748a9306 937 if (len && !SvPOK(sv))
a0d0e21e 938 s = SvPV_force(sv, len);
7e2040f0 939 if (DO_UTF8(sv)) {
a0ed51b3 940 if (s && len) {
941 char *send = s + len;
942 char *start = s;
943 s = send - 1;
a0dbb045 944 while (s > start && UTF8_IS_CONTINUATION(*s))
945 s--;
9041c2e3 946 if (utf8_to_uvchr((U8*)s, 0)) {
a0dbb045 947 sv_setpvn(astr, s, send - s);
948 *s = '\0';
949 SvCUR_set(sv, s - start);
950 SvNIOK_off(sv);
951 SvUTF8_on(astr);
952 }
a0ed51b3 953 }
954 else
955 sv_setpvn(astr, "", 0);
956 }
7e2040f0 957 else if (s && len) {
a0d0e21e 958 s += --len;
959 sv_setpvn(astr, s, 1);
960 *s = '\0';
961 SvCUR_set(sv, len);
2c19a612 962 SvUTF8_off(sv);
a0d0e21e 963 SvNIOK_off(sv);
79072805 964 }
965 else
a0d0e21e 966 sv_setpvn(astr, "", 0);
967 SvSETMAGIC(sv);
7e2040f0 968}
a0d0e21e 969
970I32
864dbfa3 971Perl_do_chomp(pTHX_ register SV *sv)
a0d0e21e 972{
c07a80fd 973 register I32 count;
a0d0e21e 974 STRLEN len;
975 char *s;
c07a80fd 976
3280af22 977 if (RsSNARF(PL_rs))
c07a80fd 978 return 0;
4c5a6083 979 if (RsRECORD(PL_rs))
980 return 0;
c07a80fd 981 count = 0;
a0d0e21e 982 if (SvTYPE(sv) == SVt_PVAV) {
983 register I32 i;
984 I32 max;
985 AV* av = (AV*)sv;
986 max = AvFILL(av);
987 for (i = 0; i <= max; i++) {
988 sv = (SV*)av_fetch(av, i, FALSE);
3280af22 989 if (sv && ((sv = *(SV**)sv), sv != &PL_sv_undef))
a0d0e21e 990 count += do_chomp(sv);
991 }
992 return count;
993 }
aa854799 994 else if (SvTYPE(sv) == SVt_PVHV) {
a0d0e21e 995 HV* hv = (HV*)sv;
996 HE* entry;
997 (void)hv_iterinit(hv);
998 /*SUPPRESS 560*/
155aba94 999 while ((entry = hv_iternext(hv)))
a0d0e21e 1000 count += do_chomp(hv_iterval(hv,entry));
1001 return count;
1002 }
aa854799 1003 else if (SvREADONLY(sv))
cea2e8a9 1004 Perl_croak(aTHX_ PL_no_modify);
a0d0e21e 1005 s = SvPV(sv, len);
1006 if (len && !SvPOKp(sv))
1007 s = SvPV_force(sv, len);
1008 if (s && len) {
1009 s += --len;
3280af22 1010 if (RsPARA(PL_rs)) {
a0d0e21e 1011 if (*s != '\n')
1012 goto nope;
1013 ++count;
1014 while (len && s[-1] == '\n') {
1015 --len;
1016 --s;
1017 ++count;
1018 }
1019 }
a0d0e21e 1020 else {
c07a80fd 1021 STRLEN rslen;
3280af22 1022 char *rsptr = SvPV(PL_rs, rslen);
c07a80fd 1023 if (rslen == 1) {
1024 if (*s != *rsptr)
1025 goto nope;
1026 ++count;
1027 }
1028 else {
8c2cee6f 1029 if (len < rslen - 1)
c07a80fd 1030 goto nope;
1031 len -= rslen - 1;
1032 s -= rslen - 1;
36477c24 1033 if (memNE(s, rsptr, rslen))
c07a80fd 1034 goto nope;
1035 count += rslen;
1036 }
a0d0e21e 1037 }
a0d0e21e 1038 *s = '\0';
1039 SvCUR_set(sv, len);
1040 SvNIOK_off(sv);
1041 }
1042 nope:
1043 SvSETMAGIC(sv);
1044 return count;
8e84507e 1045}
79072805 1046
1047void
864dbfa3 1048Perl_do_vop(pTHX_ I32 optype, SV *sv, SV *left, SV *right)
79072805 1049{
1050#ifdef LIBERAL
1051 register long *dl;
1052 register long *ll;
1053 register long *rl;
1054#endif
1055 register char *dc;
463ee0b2 1056 STRLEN leftlen;
1057 STRLEN rightlen;
7a4c00b4 1058 register char *lc;
1059 register char *rc;
79072805 1060 register I32 len;
a0d0e21e 1061 I32 lensave;
7a4c00b4 1062 char *lsave;
1063 char *rsave;
0c57e439 1064 bool left_utf = DO_UTF8(left);
1065 bool right_utf = DO_UTF8(right);
c9b3c8d0 1066 I32 needlen;
0c57e439 1067
1068 if (left_utf && !right_utf)
1069 sv_utf8_upgrade(right);
a1ca4561 1070 else if (!left_utf && right_utf)
0c57e439 1071 sv_utf8_upgrade(left);
79072805 1072
1fbd88dc 1073 if (sv != left || (optype != OP_BIT_AND && !SvOK(sv) && !SvGMAGICAL(sv)))
1074 sv_setpvn(sv, "", 0); /* avoid undef warning on |= and ^= */
7a4c00b4 1075 lsave = lc = SvPV(left, leftlen);
1076 rsave = rc = SvPV(right, rightlen);
93a17b20 1077 len = leftlen < rightlen ? leftlen : rightlen;
a0d0e21e 1078 lensave = len;
c9b3c8d0 1079 if ((left_utf || right_utf) && (sv == left || sv == right)) {
1080 needlen = optype == OP_BIT_AND ? len : leftlen + rightlen;
1081 Newz(801, dc, needlen + 1, char);
1082 }
1083 else if (SvOK(sv) || SvTYPE(sv) > SVt_PVMG) {
2d8e6c8d 1084 STRLEN n_a;
1085 dc = SvPV_force(sv, n_a);
ff68c719 1086 if (SvCUR(sv) < len) {
1087 dc = SvGROW(sv, len + 1);
1088 (void)memzero(dc + SvCUR(sv), len - SvCUR(sv) + 1);
1089 }
c9b3c8d0 1090 if (optype != OP_BIT_AND && (left_utf || right_utf))
1091 dc = SvGROW(sv, leftlen + rightlen + 1);
ff68c719 1092 }
1093 else {
c9b3c8d0 1094 needlen = ((optype == OP_BIT_AND)
1095 ? len : (leftlen > rightlen ? leftlen : rightlen));
ff68c719 1096 Newz(801, dc, needlen + 1, char);
1097 (void)sv_usepvn(sv, dc, needlen);
1098 dc = SvPVX(sv); /* sv_usepvn() calls Renew() */
79072805 1099 }
a0d0e21e 1100 SvCUR_set(sv, len);
1101 (void)SvPOK_only(sv);
0c57e439 1102 if (left_utf || right_utf) {
1103 UV duc, luc, ruc;
c9b3c8d0 1104 char *dcsave = dc;
0c57e439 1105 STRLEN lulen = leftlen;
1106 STRLEN rulen = rightlen;
ba210ebe 1107 STRLEN ulen;
0c57e439 1108
1109 switch (optype) {
1110 case OP_BIT_AND:
1111 while (lulen && rulen) {
9041c2e3 1112 luc = utf8n_to_uvchr((U8*)lc, lulen, &ulen, UTF8_ALLOW_ANYUV);
0c57e439 1113 lc += ulen;
1114 lulen -= ulen;
9041c2e3 1115 ruc = utf8n_to_uvchr((U8*)rc, rulen, &ulen, UTF8_ALLOW_ANYUV);
0c57e439 1116 rc += ulen;
1117 rulen -= ulen;
1118 duc = luc & ruc;
9041c2e3 1119 dc = (char*)uvchr_to_utf8((U8*)dc, duc);
0c57e439 1120 }
c9b3c8d0 1121 if (sv == left || sv == right)
1122 (void)sv_usepvn(sv, dcsave, needlen);
1123 SvCUR_set(sv, dc - dcsave);
0c57e439 1124 break;
1125 case OP_BIT_XOR:
1126 while (lulen && rulen) {
9041c2e3 1127 luc = utf8n_to_uvchr((U8*)lc, lulen, &ulen, UTF8_ALLOW_ANYUV);
0c57e439 1128 lc += ulen;
1129 lulen -= ulen;
9041c2e3 1130 ruc = utf8n_to_uvchr((U8*)rc, rulen, &ulen, UTF8_ALLOW_ANYUV);
0c57e439 1131 rc += ulen;
1132 rulen -= ulen;
1133 duc = luc ^ ruc;
9041c2e3 1134 dc = (char*)uvchr_to_utf8((U8*)dc, duc);
0c57e439 1135 }
1136 goto mop_up_utf;
1137 case OP_BIT_OR:
1138 while (lulen && rulen) {
9041c2e3 1139 luc = utf8n_to_uvchr((U8*)lc, lulen, &ulen, UTF8_ALLOW_ANYUV);
0c57e439 1140 lc += ulen;
1141 lulen -= ulen;
9041c2e3 1142 ruc = utf8n_to_uvchr((U8*)rc, rulen, &ulen, UTF8_ALLOW_ANYUV);
0c57e439 1143 rc += ulen;
1144 rulen -= ulen;
1145 duc = luc | ruc;
9041c2e3 1146 dc = (char*)uvchr_to_utf8((U8*)dc, duc);
0c57e439 1147 }
1148 mop_up_utf:
c9b3c8d0 1149 if (sv == left || sv == right)
1150 (void)sv_usepvn(sv, dcsave, needlen);
1151 SvCUR_set(sv, dc - dcsave);
0c57e439 1152 if (rulen)
1153 sv_catpvn(sv, rc, rulen);
1154 else if (lulen)
1155 sv_catpvn(sv, lc, lulen);
1156 else
1157 *SvEND(sv) = '\0';
1158 break;
1159 }
1160 SvUTF8_on(sv);
1161 goto finish;
1162 }
1163 else
79072805 1164#ifdef LIBERAL
1165 if (len >= sizeof(long)*4 &&
1166 !((long)dc % sizeof(long)) &&
1167 !((long)lc % sizeof(long)) &&
1168 !((long)rc % sizeof(long))) /* It's almost always aligned... */
1169 {
1170 I32 remainder = len % (sizeof(long)*4);
1171 len /= (sizeof(long)*4);
1172
1173 dl = (long*)dc;
1174 ll = (long*)lc;
1175 rl = (long*)rc;
1176
1177 switch (optype) {
1178 case OP_BIT_AND:
1179 while (len--) {
1180 *dl++ = *ll++ & *rl++;
1181 *dl++ = *ll++ & *rl++;
1182 *dl++ = *ll++ & *rl++;
1183 *dl++ = *ll++ & *rl++;
1184 }
1185 break;
a0d0e21e 1186 case OP_BIT_XOR:
79072805 1187 while (len--) {
1188 *dl++ = *ll++ ^ *rl++;
1189 *dl++ = *ll++ ^ *rl++;
1190 *dl++ = *ll++ ^ *rl++;
1191 *dl++ = *ll++ ^ *rl++;
1192 }
1193 break;
1194 case OP_BIT_OR:
1195 while (len--) {
1196 *dl++ = *ll++ | *rl++;
1197 *dl++ = *ll++ | *rl++;
1198 *dl++ = *ll++ | *rl++;
1199 *dl++ = *ll++ | *rl++;
1200 }
1201 }
1202
1203 dc = (char*)dl;
1204 lc = (char*)ll;
1205 rc = (char*)rl;
1206
1207 len = remainder;
1208 }
1209#endif
a0d0e21e 1210 {
a0d0e21e 1211 switch (optype) {
1212 case OP_BIT_AND:
1213 while (len--)
1214 *dc++ = *lc++ & *rc++;
1215 break;
1216 case OP_BIT_XOR:
1217 while (len--)
1218 *dc++ = *lc++ ^ *rc++;
1219 goto mop_up;
1220 case OP_BIT_OR:
1221 while (len--)
1222 *dc++ = *lc++ | *rc++;
1223 mop_up:
1224 len = lensave;
1225 if (rightlen > len)
1226 sv_catpvn(sv, rsave + len, rightlen - len);
1227 else if (leftlen > len)
1228 sv_catpvn(sv, lsave + len, leftlen - len);
4633a7c4 1229 else
1230 *SvEND(sv) = '\0';
a0d0e21e 1231 break;
1232 }
79072805 1233 }
0c57e439 1234finish:
fb73857a 1235 SvTAINT(sv);
79072805 1236}
463ee0b2 1237
1238OP *
cea2e8a9 1239Perl_do_kv(pTHX)
463ee0b2 1240{
39644a26 1241 dSP;
463ee0b2 1242 HV *hv = (HV*)POPs;
800e9ae0 1243 HV *keys;
463ee0b2 1244 register HE *entry;
463ee0b2 1245 SV *tmpstr;
54310121 1246 I32 gimme = GIMME_V;
533c011a 1247 I32 dokeys = (PL_op->op_type == OP_KEYS);
1248 I32 dovalues = (PL_op->op_type == OP_VALUES);
c750a3ec 1249 I32 realhv = (SvTYPE(hv) == SVt_PVHV);
8e84507e 1250
1251 if (PL_op->op_type == OP_RV2HV || PL_op->op_type == OP_PADHV)
a0d0e21e 1252 dokeys = dovalues = TRUE;
463ee0b2 1253
85581909 1254 if (!hv) {
78f9721b 1255 if (PL_op->op_flags & OPf_MOD || LVRET) { /* lvalue */
85581909 1256 dTARGET; /* make sure to clear its target here */
1257 if (SvTYPE(TARG) == SVt_PVLV)
1258 LvTARG(TARG) = Nullsv;
1259 PUSHs(TARG);
1260 }
463ee0b2 1261 RETURN;
85581909 1262 }
748a9306 1263
800e9ae0 1264 keys = realhv ? hv : avhv_keys((AV*)hv);
1265 (void)hv_iterinit(keys); /* always reset iterator regardless */
748a9306 1266
54310121 1267 if (gimme == G_VOID)
aa689395 1268 RETURN;
1269
54310121 1270 if (gimme == G_SCALAR) {
6ee623d5 1271 IV i;
463ee0b2 1272 dTARGET;
1273
78f9721b 1274 if (PL_op->op_flags & OPf_MOD || LVRET) { /* lvalue */
85581909 1275 if (SvTYPE(TARG) < SVt_PVLV) {
1276 sv_upgrade(TARG, SVt_PVLV);
1277 sv_magic(TARG, Nullsv, 'k', Nullch, 0);
1278 }
1279 LvTYPE(TARG) = 'k';
800e9ae0 1280 if (LvTARG(TARG) != (SV*)keys) {
6ff81951 1281 if (LvTARG(TARG))
1282 SvREFCNT_dec(LvTARG(TARG));
800e9ae0 1283 LvTARG(TARG) = SvREFCNT_inc(keys);
6ff81951 1284 }
85581909 1285 PUSHs(TARG);
1286 RETURN;
1287 }
1288
33c27489 1289 if (! SvTIED_mg((SV*)keys, 'P'))
800e9ae0 1290 i = HvKEYS(keys);
463ee0b2 1291 else {
1292 i = 0;
463ee0b2 1293 /*SUPPRESS 560*/
800e9ae0 1294 while (hv_iternext(keys)) i++;
463ee0b2 1295 }
1296 PUSHi( i );
1297 RETURN;
1298 }
1299
8ed4b672 1300 EXTEND(SP, HvKEYS(keys) * (dokeys + dovalues));
463ee0b2 1301
463ee0b2 1302 PUTBACK; /* hv_iternext and hv_iterval might clobber stack_sp */
155aba94 1303 while ((entry = hv_iternext(keys))) {
463ee0b2 1304 SPAGAIN;
6bfc225d 1305 if (dokeys)
8c2cee6f 1306 XPUSHs(hv_iterkeysv(entry)); /* won't clobber stack_sp */
463ee0b2 1307 if (dovalues) {
463ee0b2 1308 PUTBACK;
b6429b1b 1309 tmpstr = realhv ?
1310 hv_iterval(hv,entry) : avhv_iterval((AV*)hv,entry);
cea2e8a9 1311 DEBUG_H(Perl_sv_setpvf(aTHX_ tmpstr, "%lu%%%d=%lu",
46fc3d4c 1312 (unsigned long)HeHASH(entry),
800e9ae0 1313 HvMAX(keys)+1,
1314 (unsigned long)(HeHASH(entry) & HvMAX(keys))));
463ee0b2 1315 SPAGAIN;
46fc3d4c 1316 XPUSHs(tmpstr);
463ee0b2 1317 }
1318 PUTBACK;
1319 }
1320 return NORMAL;
1321}
4e35701f 1322