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