This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Initial 3-way merge from (5.001m, thr1m, 5.003) plus fixups.
[perl5.git] / doop.c
CommitLineData
a0d0e21e 1/* doop.c
79072805 2 *
a0d0e21e 3 * Copyright (c) 1991-1994, Larry Wall
79072805
LW
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
LW
8 */
9
10/*
11 * "'So that was the job I felt I had to do when I started,' thought Sam."
79072805
LW
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
21#ifdef BUGGY_MSC
22 #pragma function(memcmp)
23#endif /* BUGGY_MSC */
24
79072805
LW
25#ifdef BUGGY_MSC
26 #pragma intrinsic(memcmp)
27#endif /* BUGGY_MSC */
28
29I32
30do_trans(sv,arg)
31SV *sv;
32OP *arg;
33{
11343788 34 dTHR;
79072805 35 register short *tbl;
1476d272 36 register U8 *s;
37 register U8 *send;
38 register U8 *d;
79072805 39 register I32 ch;
1476d272 40 register I32 matches = 0;
79072805 41 register I32 squash = op->op_private & OPpTRANS_SQUASH;
463ee0b2 42 STRLEN len;
79072805 43
a0d0e21e
LW
44 if (SvREADONLY(sv))
45 croak(no_modify);
1476d272 46 tbl = (short*)cPVOP->op_pv;
47 s = (U8*)SvPV(sv, len);
a0d0e21e
LW
48 if (!len)
49 return 0;
50 if (!SvPOKp(sv))
1476d272 51 s = (U8*)SvPV_force(sv, len);
a0d0e21e 52 (void)SvPOK_only(sv);
463ee0b2 53 send = s + len;
79072805 54 if (!tbl || !s)
463ee0b2 55 croak("panic: do_trans");
79072805
LW
56 DEBUG_t( deb("2.TBL\n"));
57 if (!op->op_private) {
58 while (s < send) {
1476d272 59 if ((ch = tbl[*s]) >= 0) {
79072805
LW
60 matches++;
61 *s = ch;
62 }
63 s++;
64 }
65 }
66 else {
67 d = s;
68 while (s < send) {
1476d272 69 if ((ch = tbl[*s]) >= 0) {
79072805
LW
70 *d = ch;
71 if (matches++ && squash) {
72 if (d[-1] == *d)
73 matches--;
74 else
75 d++;
76 }
77 else
78 d++;
79 }
80 else if (ch == -1) /* -1 is unmapped character */
81 *d++ = *s; /* -2 is delete character */
82 s++;
83 }
84 matches += send - d; /* account for disappeared chars */
85 *d = '\0';
1476d272 86 SvCUR_set(sv, d - (U8*)SvPVX(sv));
79072805
LW
87 }
88 SvSETMAGIC(sv);
89 return matches;
90}
91
92void
93do_join(sv,del,mark,sp)
94register SV *sv;
95SV *del;
96register SV **mark;
97register SV **sp;
98{
99 SV **oldmark = mark;
100 register I32 items = sp - mark;
79072805 101 register STRLEN len;
463ee0b2
LW
102 STRLEN delimlen;
103 register char *delim = SvPV(del, delimlen);
104 STRLEN tmplen;
79072805
LW
105
106 mark++;
107 len = (items > 0 ? (delimlen * (items - 1) ) : 0);
108 if (SvTYPE(sv) < SVt_PV)
109 sv_upgrade(sv, SVt_PV);
110 if (SvLEN(sv) < len + items) { /* current length is way too short */
111 while (items-- > 0) {
112 if (*mark) {
463ee0b2
LW
113 SvPV(*mark, tmplen);
114 len += tmplen;
79072805
LW
115 }
116 mark++;
117 }
118 SvGROW(sv, len + 1); /* so try to pre-extend */
119
120 mark = oldmark;
121 items = sp - mark;;
122 ++mark;
123 }
124
463ee0b2 125 if (items-- > 0) {
8990e307
LW
126 char *s;
127
128 if (*mark) {
129 s = SvPV(*mark, tmplen);
130 sv_setpvn(sv, s, tmplen);
131 }
132 else
133 sv_setpv(sv, "");
463ee0b2
LW
134 mark++;
135 }
79072805
LW
136 else
137 sv_setpv(sv,"");
138 len = delimlen;
139 if (len) {
140 for (; items > 0; items--,mark++) {
141 sv_catpvn(sv,delim,len);
142 sv_catsv(sv,*mark);
143 }
144 }
145 else {
146 for (; items > 0; items--,mark++)
147 sv_catsv(sv,*mark);
148 }
149 SvSETMAGIC(sv);
150}
151
152void
153do_sprintf(sv,len,sarg)
154register SV *sv;
155register I32 len;
156register SV **sarg;
157{
158 register char *s;
159 register char *t;
160 register char *f;
161 bool dolong;
ecfc5424 162#ifdef HAS_QUAD
79072805 163 bool doquad;
ecfc5424 164#endif /* HAS_QUAD */
79072805
LW
165 char ch;
166 register char *send;
167 register SV *arg;
168 char *xs;
169 I32 xlen;
170 I32 pre;
171 I32 post;
172 double value;
463ee0b2 173 STRLEN arglen;
79072805
LW
174
175 sv_setpv(sv,"");
176 len--; /* don't count pattern string */
a0d0e21e 177 t = s = SvPV(*sarg, arglen); /* XXX Don't know t is writeable */
463ee0b2 178 send = s + arglen;
79072805
LW
179 sarg++;
180 for ( ; ; len--) {
181
182 /*SUPPRESS 560*/
183 if (len <= 0 || !(arg = *sarg++))
184 arg = &sv_no;
185
186 /*SUPPRESS 530*/
187 for ( ; t < send && *t != '%'; t++) ;
188 if (t >= send)
189 break; /* end of run_format string, ignore extra args */
190 f = t;
191 *buf = '\0';
192 xs = buf;
ecfc5424 193#ifdef HAS_QUAD
79072805 194 doquad =
ecfc5424 195#endif /* HAS_QUAD */
79072805
LW
196 dolong = FALSE;
197 pre = post = 0;
198 for (t++; t < send; t++) {
199 switch (*t) {
200 default:
201 ch = *(++t);
202 *t = '\0';
203 (void)sprintf(xs,f);
204 len++, sarg--;
205 xlen = strlen(xs);
206 break;
748a9306
LW
207 case 'n': case '*':
208 croak("Use of %c in printf format not supported", *t);
209
79072805
LW
210 case '0': case '1': case '2': case '3': case '4':
211 case '5': case '6': case '7': case '8': case '9':
212 case '.': case '#': case '-': case '+': case ' ':
213 continue;
463ee0b2 214 case 'l':
ecfc5424 215#ifdef HAS_QUAD
79072805
LW
216 if (dolong) {
217 dolong = FALSE;
218 doquad = TRUE;
219 } else
220#endif
221 dolong = TRUE;
222 continue;
223 case 'c':
224 ch = *(++t);
225 *t = '\0';
463ee0b2 226 xlen = SvIV(arg);
79072805
LW
227 if (strEQ(f,"%c")) { /* some printfs fail on null chars */
228 *xs = xlen;
229 xs[1] = '\0';
230 xlen = 1;
231 }
232 else {
233 (void)sprintf(xs,f,xlen);
234 xlen = strlen(xs);
235 }
236 break;
237 case 'D':
238 dolong = TRUE;
239 /* FALL THROUGH */
240 case 'd':
241 ch = *(++t);
242 *t = '\0';
ecfc5424 243#ifdef HAS_QUAD
79072805 244 if (doquad)
ecfc5424 245 (void)sprintf(buf,s,(Quad_t)SvNV(arg));
79072805
LW
246 else
247#endif
248 if (dolong)
463ee0b2 249 (void)sprintf(xs,f,(long)SvNV(arg));
79072805 250 else
463ee0b2 251 (void)sprintf(xs,f,SvIV(arg));
79072805
LW
252 xlen = strlen(xs);
253 break;
254 case 'X': case 'O':
255 dolong = TRUE;
256 /* FALL THROUGH */
257 case 'x': case 'o': case 'u':
258 ch = *(++t);
259 *t = '\0';
463ee0b2 260 value = SvNV(arg);
ecfc5424 261#ifdef HAS_QUAD
79072805 262 if (doquad)
ecfc5424 263 (void)sprintf(buf,s,(unsigned Quad_t)value);
79072805
LW
264 else
265#endif
266 if (dolong)
267 (void)sprintf(xs,f,U_L(value));
268 else
269 (void)sprintf(xs,f,U_I(value));
270 xlen = strlen(xs);
271 break;
272 case 'E': case 'e': case 'f': case 'G': case 'g':
273 ch = *(++t);
274 *t = '\0';
463ee0b2 275 (void)sprintf(xs,f,SvNV(arg));
79072805
LW
276 xlen = strlen(xs);
277 break;
278 case 's':
279 ch = *(++t);
280 *t = '\0';
463ee0b2
LW
281 xs = SvPV(arg, arglen);
282 xlen = (I32)arglen;
79072805
LW
283 if (strEQ(f,"%s")) { /* some printfs fail on >128 chars */
284 break; /* so handle simple cases */
285 }
286 else if (f[1] == '-') {
93a17b20 287 char *mp = strchr(f, '.');
79072805
LW
288 I32 min = atoi(f+2);
289
290 if (mp) {
291 I32 max = atoi(mp+1);
292
293 if (xlen > max)
294 xlen = max;
295 }
296 if (xlen < min)
297 post = min - xlen;
298 break;
299 }
300 else if (isDIGIT(f[1])) {
93a17b20 301 char *mp = strchr(f, '.');
79072805
LW
302 I32 min = atoi(f+1);
303
304 if (mp) {
305 I32 max = atoi(mp+1);
306
307 if (xlen > max)
308 xlen = max;
309 }
310 if (xlen < min)
311 pre = min - xlen;
312 break;
313 }
314 strcpy(tokenbuf+64,f); /* sprintf($s,...$s...) */
315 *t = ch;
316 (void)sprintf(buf,tokenbuf+64,xs);
317 xs = buf;
318 xlen = strlen(xs);
319 break;
320 }
321 /* end of switch, copy results */
322 *t = ch;
4633a7c4
LW
323 if (xs == buf && xlen >= sizeof(buf)) { /* Ooops! */
324 fputs("panic: sprintf overflow - memory corrupted!\n",stderr);
325 my_exit(1);
326 }
79072805
LW
327 SvGROW(sv, SvCUR(sv) + (f - s) + xlen + 1 + pre + post);
328 sv_catpvn(sv, s, f - s);
329 if (pre) {
463ee0b2 330 repeatcpy(SvPVX(sv) + SvCUR(sv), " ", 1, pre);
79072805
LW
331 SvCUR(sv) += pre;
332 }
333 sv_catpvn(sv, xs, xlen);
334 if (post) {
463ee0b2 335 repeatcpy(SvPVX(sv) + SvCUR(sv), " ", 1, post);
79072805
LW
336 SvCUR(sv) += post;
337 }
338 s = t;
339 break; /* break from for loop */
340 }
341 }
342 sv_catpvn(sv, s, t - s);
343 SvSETMAGIC(sv);
344}
345
346void
347do_vecset(sv)
348SV *sv;
349{
350 SV *targ = LvTARG(sv);
351 register I32 offset;
352 register I32 size;
8990e307
LW
353 register unsigned char *s;
354 register unsigned long lval;
79072805 355 I32 mask;
a0d0e21e
LW
356 STRLEN targlen;
357 STRLEN len;
79072805 358
8990e307
LW
359 if (!targ)
360 return;
a0d0e21e 361 s = (unsigned char*)SvPV_force(targ, targlen);
8990e307 362 lval = U_L(SvNV(sv));
79072805
LW
363 offset = LvTARGOFF(sv);
364 size = LvTARGLEN(sv);
a0d0e21e
LW
365
366 len = (offset + size + 7) / 8;
367 if (len > targlen) {
368 s = (unsigned char*)SvGROW(targ, len + 1);
369 (void)memzero(s + targlen, len - targlen + 1);
370 SvCUR_set(targ, len);
371 }
372
79072805
LW
373 if (size < 8) {
374 mask = (1 << size) - 1;
375 size = offset & 7;
376 lval &= mask;
377 offset >>= 3;
378 s[offset] &= ~(mask << size);
379 s[offset] |= lval << size;
380 }
381 else {
a0d0e21e 382 offset >>= 3;
79072805
LW
383 if (size == 8)
384 s[offset] = lval & 255;
385 else if (size == 16) {
386 s[offset] = (lval >> 8) & 255;
387 s[offset+1] = lval & 255;
388 }
389 else if (size == 32) {
390 s[offset] = (lval >> 24) & 255;
391 s[offset+1] = (lval >> 16) & 255;
392 s[offset+2] = (lval >> 8) & 255;
393 s[offset+3] = lval & 255;
394 }
395 }
396}
397
398void
399do_chop(astr,sv)
400register SV *astr;
401register SV *sv;
402{
463ee0b2 403 STRLEN len;
a0d0e21e
LW
404 char *s;
405
79072805 406 if (SvTYPE(sv) == SVt_PVAV) {
a0d0e21e
LW
407 register I32 i;
408 I32 max;
409 AV* av = (AV*)sv;
410 max = AvFILL(av);
411 for (i = 0; i <= max; i++) {
412 sv = (SV*)av_fetch(av, i, FALSE);
413 if (sv && ((sv = *(SV**)sv), sv != &sv_undef))
414 do_chop(astr, sv);
415 }
416 return;
79072805
LW
417 }
418 if (SvTYPE(sv) == SVt_PVHV) {
a0d0e21e
LW
419 HV* hv = (HV*)sv;
420 HE* entry;
421 (void)hv_iterinit(hv);
422 /*SUPPRESS 560*/
423 while (entry = hv_iternext(hv))
424 do_chop(astr,hv_iterval(hv,entry));
425 return;
79072805 426 }
a0d0e21e 427 s = SvPV(sv, len);
748a9306 428 if (len && !SvPOK(sv))
a0d0e21e
LW
429 s = SvPV_force(sv, len);
430 if (s && len) {
431 s += --len;
432 sv_setpvn(astr, s, 1);
433 *s = '\0';
434 SvCUR_set(sv, len);
435 SvNIOK_off(sv);
79072805
LW
436 }
437 else
a0d0e21e
LW
438 sv_setpvn(astr, "", 0);
439 SvSETMAGIC(sv);
440}
441
442I32
443do_chomp(sv)
444register SV *sv;
445{
c07a80fd 446 register I32 count;
a0d0e21e
LW
447 STRLEN len;
448 char *s;
c07a80fd 449
450 if (RsSNARF(rs))
451 return 0;
452 count = 0;
a0d0e21e
LW
453 if (SvTYPE(sv) == SVt_PVAV) {
454 register I32 i;
455 I32 max;
456 AV* av = (AV*)sv;
457 max = AvFILL(av);
458 for (i = 0; i <= max; i++) {
459 sv = (SV*)av_fetch(av, i, FALSE);
460 if (sv && ((sv = *(SV**)sv), sv != &sv_undef))
461 count += do_chomp(sv);
462 }
463 return count;
464 }
465 if (SvTYPE(sv) == SVt_PVHV) {
466 HV* hv = (HV*)sv;
467 HE* entry;
468 (void)hv_iterinit(hv);
469 /*SUPPRESS 560*/
470 while (entry = hv_iternext(hv))
471 count += do_chomp(hv_iterval(hv,entry));
472 return count;
473 }
474 s = SvPV(sv, len);
475 if (len && !SvPOKp(sv))
476 s = SvPV_force(sv, len);
477 if (s && len) {
478 s += --len;
c07a80fd 479 if (RsPARA(rs)) {
a0d0e21e
LW
480 if (*s != '\n')
481 goto nope;
482 ++count;
483 while (len && s[-1] == '\n') {
484 --len;
485 --s;
486 ++count;
487 }
488 }
a0d0e21e 489 else {
c07a80fd 490 STRLEN rslen;
491 char *rsptr = SvPV(rs, rslen);
492 if (rslen == 1) {
493 if (*s != *rsptr)
494 goto nope;
495 ++count;
496 }
497 else {
498 if (len < rslen)
499 goto nope;
500 len -= rslen - 1;
501 s -= rslen - 1;
502 if (bcmp(s, rsptr, rslen))
503 goto nope;
504 count += rslen;
505 }
a0d0e21e 506 }
a0d0e21e
LW
507 *s = '\0';
508 SvCUR_set(sv, len);
509 SvNIOK_off(sv);
510 }
511 nope:
512 SvSETMAGIC(sv);
513 return count;
514}
79072805
LW
515
516void
517do_vop(optype,sv,left,right)
518I32 optype;
519SV *sv;
520SV *left;
521SV *right;
522{
523#ifdef LIBERAL
524 register long *dl;
525 register long *ll;
526 register long *rl;
527#endif
528 register char *dc;
463ee0b2
LW
529 STRLEN leftlen;
530 STRLEN rightlen;
531 register char *lc = SvPV(left, leftlen);
532 register char *rc = SvPV(right, rightlen);
79072805 533 register I32 len;
a0d0e21e 534 I32 lensave;
79072805 535
a0d0e21e 536 dc = SvPV_force(sv,na);
93a17b20 537 len = leftlen < rightlen ? leftlen : rightlen;
a0d0e21e
LW
538 lensave = len;
539 if (SvCUR(sv) < len) {
540 dc = SvGROW(sv,len + 1);
541 (void)memzero(dc + SvCUR(sv), len - SvCUR(sv) + 1);
79072805 542 }
a0d0e21e
LW
543 SvCUR_set(sv, len);
544 (void)SvPOK_only(sv);
79072805
LW
545#ifdef LIBERAL
546 if (len >= sizeof(long)*4 &&
547 !((long)dc % sizeof(long)) &&
548 !((long)lc % sizeof(long)) &&
549 !((long)rc % sizeof(long))) /* It's almost always aligned... */
550 {
551 I32 remainder = len % (sizeof(long)*4);
552 len /= (sizeof(long)*4);
553
554 dl = (long*)dc;
555 ll = (long*)lc;
556 rl = (long*)rc;
557
558 switch (optype) {
559 case OP_BIT_AND:
560 while (len--) {
561 *dl++ = *ll++ & *rl++;
562 *dl++ = *ll++ & *rl++;
563 *dl++ = *ll++ & *rl++;
564 *dl++ = *ll++ & *rl++;
565 }
566 break;
a0d0e21e 567 case OP_BIT_XOR:
79072805
LW
568 while (len--) {
569 *dl++ = *ll++ ^ *rl++;
570 *dl++ = *ll++ ^ *rl++;
571 *dl++ = *ll++ ^ *rl++;
572 *dl++ = *ll++ ^ *rl++;
573 }
574 break;
575 case OP_BIT_OR:
576 while (len--) {
577 *dl++ = *ll++ | *rl++;
578 *dl++ = *ll++ | *rl++;
579 *dl++ = *ll++ | *rl++;
580 *dl++ = *ll++ | *rl++;
581 }
582 }
583
584 dc = (char*)dl;
585 lc = (char*)ll;
586 rc = (char*)rl;
587
588 len = remainder;
589 }
590#endif
a0d0e21e
LW
591 {
592 char *lsave = lc;
593 char *rsave = rc;
594
595 switch (optype) {
596 case OP_BIT_AND:
597 while (len--)
598 *dc++ = *lc++ & *rc++;
599 break;
600 case OP_BIT_XOR:
601 while (len--)
602 *dc++ = *lc++ ^ *rc++;
603 goto mop_up;
604 case OP_BIT_OR:
605 while (len--)
606 *dc++ = *lc++ | *rc++;
607 mop_up:
608 len = lensave;
609 if (rightlen > len)
610 sv_catpvn(sv, rsave + len, rightlen - len);
611 else if (leftlen > len)
612 sv_catpvn(sv, lsave + len, leftlen - len);
4633a7c4
LW
613 else
614 *SvEND(sv) = '\0';
a0d0e21e
LW
615 break;
616 }
79072805
LW
617 }
618}
463ee0b2
LW
619
620OP *
621do_kv(ARGS)
622dARGS
623{
624 dSP;
625 HV *hv = (HV*)POPs;
463ee0b2
LW
626 I32 i;
627 register HE *entry;
628 char *tmps;
629 SV *tmpstr;
a0d0e21e
LW
630 I32 dokeys = (op->op_type == OP_KEYS);
631 I32 dovalues = (op->op_type == OP_VALUES);
632
633 if (op->op_type == OP_RV2HV || op->op_type == OP_PADHV)
634 dokeys = dovalues = TRUE;
463ee0b2
LW
635
636 if (!hv)
637 RETURN;
748a9306
LW
638
639 (void)hv_iterinit(hv); /* always reset iterator regardless */
640
463ee0b2
LW
641 if (GIMME != G_ARRAY) {
642 dTARGET;
643
8990e307 644 if (!SvRMAGICAL(hv) || !mg_find((SV*)hv,'P'))
463ee0b2
LW
645 i = HvKEYS(hv);
646 else {
647 i = 0;
463ee0b2
LW
648 /*SUPPRESS 560*/
649 while (entry = hv_iternext(hv)) {
650 i++;
651 }
652 }
653 PUSHi( i );
654 RETURN;
655 }
656
657 /* Guess how much room we need. hv_max may be a few too many. Oh well. */
658 EXTEND(sp, HvMAX(hv) * (dokeys + dovalues));
659
463ee0b2
LW
660 PUTBACK; /* hv_iternext and hv_iterval might clobber stack_sp */
661 while (entry = hv_iternext(hv)) {
662 SPAGAIN;
663 if (dokeys) {
664 tmps = hv_iterkey(entry,&i); /* won't clobber stack_sp */
665 if (!i)
666 tmps = "";
667 XPUSHs(sv_2mortal(newSVpv(tmps,i)));
668 }
669 if (dovalues) {
670 tmpstr = NEWSV(45,0);
671 PUTBACK;
672 sv_setsv(tmpstr,hv_iterval(hv,entry));
673 SPAGAIN;
674 DEBUG_H( {
675 sprintf(buf,"%d%%%d=%d\n",entry->hent_hash,
676 HvMAX(hv)+1,entry->hent_hash & HvMAX(hv));
677 sv_setpv(tmpstr,buf);
678 } )
679 XPUSHs(sv_2mortal(tmpstr));
680 }
681 PUTBACK;
682 }
683 return NORMAL;
684}
685