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