[revert some function caching changes]
[p5sagit/p5-mst-13.2.git] / doop.c
CommitLineData
a0d0e21e 1/* doop.c
79072805 2 *
a0d0e21e 3 * Copyright (c) 1991-1994, 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
79072805 21I32
22do_trans(sv,arg)
23SV *sv;
24OP *arg;
25{
26 register short *tbl;
1476d272 27 register U8 *s;
28 register U8 *send;
29 register U8 *d;
79072805 30 register I32 ch;
1476d272 31 register I32 matches = 0;
79072805 32 register I32 squash = op->op_private & OPpTRANS_SQUASH;
463ee0b2 33 STRLEN len;
79072805 34
a0d0e21e 35 if (SvREADONLY(sv))
36 croak(no_modify);
1476d272 37 tbl = (short*)cPVOP->op_pv;
38 s = (U8*)SvPV(sv, len);
a0d0e21e 39 if (!len)
40 return 0;
41 if (!SvPOKp(sv))
1476d272 42 s = (U8*)SvPV_force(sv, len);
a0d0e21e 43 (void)SvPOK_only(sv);
463ee0b2 44 send = s + len;
79072805 45 if (!tbl || !s)
463ee0b2 46 croak("panic: do_trans");
79072805 47 DEBUG_t( deb("2.TBL\n"));
48 if (!op->op_private) {
49 while (s < send) {
1476d272 50 if ((ch = tbl[*s]) >= 0) {
79072805 51 matches++;
52 *s = ch;
53 }
54 s++;
55 }
56 }
57 else {
58 d = s;
59 while (s < send) {
1476d272 60 if ((ch = tbl[*s]) >= 0) {
79072805 61 *d = ch;
62 if (matches++ && squash) {
63 if (d[-1] == *d)
64 matches--;
65 else
66 d++;
67 }
68 else
69 d++;
70 }
71 else if (ch == -1) /* -1 is unmapped character */
72 *d++ = *s; /* -2 is delete character */
73 s++;
74 }
75 matches += send - d; /* account for disappeared chars */
76 *d = '\0';
1476d272 77 SvCUR_set(sv, d - (U8*)SvPVX(sv));
79072805 78 }
79 SvSETMAGIC(sv);
80 return matches;
81}
82
83void
84do_join(sv,del,mark,sp)
85register SV *sv;
86SV *del;
87register SV **mark;
88register SV **sp;
89{
90 SV **oldmark = mark;
91 register I32 items = sp - mark;
79072805 92 register STRLEN len;
463ee0b2 93 STRLEN delimlen;
94 register char *delim = SvPV(del, delimlen);
95 STRLEN tmplen;
79072805 96
97 mark++;
98 len = (items > 0 ? (delimlen * (items - 1) ) : 0);
99 if (SvTYPE(sv) < SVt_PV)
100 sv_upgrade(sv, SVt_PV);
101 if (SvLEN(sv) < len + items) { /* current length is way too short */
102 while (items-- > 0) {
103 if (*mark) {
463ee0b2 104 SvPV(*mark, tmplen);
105 len += tmplen;
79072805 106 }
107 mark++;
108 }
109 SvGROW(sv, len + 1); /* so try to pre-extend */
110
111 mark = oldmark;
112 items = sp - mark;;
113 ++mark;
114 }
115
463ee0b2 116 if (items-- > 0) {
8990e307 117 char *s;
118
119 if (*mark) {
120 s = SvPV(*mark, tmplen);
121 sv_setpvn(sv, s, tmplen);
122 }
123 else
124 sv_setpv(sv, "");
463ee0b2 125 mark++;
126 }
79072805 127 else
128 sv_setpv(sv,"");
129 len = delimlen;
130 if (len) {
131 for (; items > 0; items--,mark++) {
132 sv_catpvn(sv,delim,len);
133 sv_catsv(sv,*mark);
134 }
135 }
136 else {
137 for (; items > 0; items--,mark++)
138 sv_catsv(sv,*mark);
139 }
140 SvSETMAGIC(sv);
141}
142
143void
144do_sprintf(sv,len,sarg)
145register SV *sv;
146register I32 len;
147register SV **sarg;
148{
149 register char *s;
150 register char *t;
151 register char *f;
152 bool dolong;
ecfc5424 153#ifdef HAS_QUAD
79072805 154 bool doquad;
ecfc5424 155#endif /* HAS_QUAD */
79072805 156 char ch;
157 register char *send;
158 register SV *arg;
159 char *xs;
160 I32 xlen;
161 I32 pre;
162 I32 post;
163 double value;
463ee0b2 164 STRLEN arglen;
79072805 165
166 sv_setpv(sv,"");
167 len--; /* don't count pattern string */
a0d0e21e 168 t = s = SvPV(*sarg, arglen); /* XXX Don't know t is writeable */
463ee0b2 169 send = s + arglen;
79072805 170 sarg++;
171 for ( ; ; len--) {
172
173 /*SUPPRESS 560*/
174 if (len <= 0 || !(arg = *sarg++))
175 arg = &sv_no;
176
177 /*SUPPRESS 530*/
178 for ( ; t < send && *t != '%'; t++) ;
179 if (t >= send)
180 break; /* end of run_format string, ignore extra args */
181 f = t;
182 *buf = '\0';
183 xs = buf;
ecfc5424 184#ifdef HAS_QUAD
79072805 185 doquad =
ecfc5424 186#endif /* HAS_QUAD */
79072805 187 dolong = FALSE;
188 pre = post = 0;
189 for (t++; t < send; t++) {
190 switch (*t) {
191 default:
192 ch = *(++t);
193 *t = '\0';
194 (void)sprintf(xs,f);
195 len++, sarg--;
196 xlen = strlen(xs);
197 break;
748a9306 198 case 'n': case '*':
199 croak("Use of %c in printf format not supported", *t);
200
79072805 201 case '0': case '1': case '2': case '3': case '4':
202 case '5': case '6': case '7': case '8': case '9':
203 case '.': case '#': case '-': case '+': case ' ':
204 continue;
463ee0b2 205 case 'l':
ecfc5424 206#ifdef HAS_QUAD
79072805 207 if (dolong) {
208 dolong = FALSE;
209 doquad = TRUE;
210 } else
211#endif
212 dolong = TRUE;
213 continue;
214 case 'c':
215 ch = *(++t);
216 *t = '\0';
463ee0b2 217 xlen = SvIV(arg);
79072805 218 if (strEQ(f,"%c")) { /* some printfs fail on null chars */
219 *xs = xlen;
220 xs[1] = '\0';
221 xlen = 1;
222 }
223 else {
224 (void)sprintf(xs,f,xlen);
225 xlen = strlen(xs);
226 }
227 break;
228 case 'D':
229 dolong = TRUE;
230 /* FALL THROUGH */
231 case 'd':
232 ch = *(++t);
233 *t = '\0';
ecfc5424 234#ifdef HAS_QUAD
79072805 235 if (doquad)
ecfc5424 236 (void)sprintf(buf,s,(Quad_t)SvNV(arg));
79072805 237 else
238#endif
239 if (dolong)
463ee0b2 240 (void)sprintf(xs,f,(long)SvNV(arg));
79072805 241 else
463ee0b2 242 (void)sprintf(xs,f,SvIV(arg));
79072805 243 xlen = strlen(xs);
244 break;
245 case 'X': case 'O':
246 dolong = TRUE;
247 /* FALL THROUGH */
248 case 'x': case 'o': case 'u':
249 ch = *(++t);
250 *t = '\0';
463ee0b2 251 value = SvNV(arg);
ecfc5424 252#ifdef HAS_QUAD
79072805 253 if (doquad)
ecfc5424 254 (void)sprintf(buf,s,(unsigned Quad_t)value);
79072805 255 else
256#endif
257 if (dolong)
258 (void)sprintf(xs,f,U_L(value));
259 else
260 (void)sprintf(xs,f,U_I(value));
261 xlen = strlen(xs);
262 break;
263 case 'E': case 'e': case 'f': case 'G': case 'g':
264 ch = *(++t);
265 *t = '\0';
463ee0b2 266 (void)sprintf(xs,f,SvNV(arg));
79072805 267 xlen = strlen(xs);
bbce6d69 268#ifdef LC_NUMERIC
ff68c719 269 /*
270 * User-defined locales may include arbitrary characters.
271 * And, unfortunately, some system may alloc the "C" locale
272 * to be overridden by a malicious user.
273 */
274 if (op->op_type == OP_SPRINTF)
bbce6d69 275 SvTAINTED_on(sv);
ff68c719 276#endif /* LC_NUMERIC */
79072805 277 break;
278 case 's':
279 ch = *(++t);
280 *t = '\0';
463ee0b2 281 xs = SvPV(arg, arglen);
282 xlen = (I32)arglen;
79072805 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 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 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 323 if (xs == buf && xlen >= sizeof(buf)) { /* Ooops! */
760ac839 324 PerlIO_puts(PerlIO_stderr(),"panic: sprintf overflow - memory corrupted!\n");
4633a7c4 325 my_exit(1);
326 }
79072805 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 331 SvCUR(sv) += pre;
332 }
333 sv_catpvn(sv, xs, xlen);
334 if (post) {
463ee0b2 335 repeatcpy(SvPVX(sv) + SvCUR(sv), " ", 1, post);
79072805 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 353 register unsigned char *s;
354 register unsigned long lval;
79072805 355 I32 mask;
a0d0e21e 356 STRLEN targlen;
357 STRLEN len;
79072805 358
8990e307 359 if (!targ)
360 return;
a0d0e21e 361 s = (unsigned char*)SvPV_force(targ, targlen);
8990e307 362 lval = U_L(SvNV(sv));
79072805 363 offset = LvTARGOFF(sv);
364 size = LvTARGLEN(sv);
a0d0e21e 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 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 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 404 char *s;
405
79072805 406 if (SvTYPE(sv) == SVt_PVAV) {
a0d0e21e 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 417 }
418 if (SvTYPE(sv) == SVt_PVHV) {
a0d0e21e 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 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 436 }
437 else
a0d0e21e 438 sv_setpvn(astr, "", 0);
439 SvSETMAGIC(sv);
440}
441
442I32
443do_chomp(sv)
444register SV *sv;
445{
c07a80fd 446 register I32 count;
a0d0e21e 447 STRLEN len;
448 char *s;
c07a80fd 449
450 if (RsSNARF(rs))
451 return 0;
452 count = 0;
a0d0e21e 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 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 {
8c2cee6f 498 if (len < rslen - 1)
c07a80fd 499 goto nope;
500 len -= rslen - 1;
501 s -= rslen - 1;
36477c24 502 if (memNE(s, rsptr, rslen))
c07a80fd 503 goto nope;
504 count += rslen;
505 }
a0d0e21e 506 }
a0d0e21e 507 *s = '\0';
508 SvCUR_set(sv, len);
509 SvNIOK_off(sv);
510 }
511 nope:
512 SvSETMAGIC(sv);
513 return count;
514}
79072805 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 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;
e963928e 535 char *lsave = lc;
536 char *rsave = rc;
79072805 537
93a17b20 538 len = leftlen < rightlen ? leftlen : rightlen;
a0d0e21e 539 lensave = len;
ff68c719 540 if (SvOK(sv)) {
541 dc = SvPV_force(sv, na);
542 if (SvCUR(sv) < len) {
543 dc = SvGROW(sv, len + 1);
544 (void)memzero(dc + SvCUR(sv), len - SvCUR(sv) + 1);
545 }
546 }
547 else {
548 I32 needlen = ((optype == OP_BIT_AND)
549 ? len : (leftlen > rightlen ? leftlen : rightlen));
550 Newz(801, dc, needlen + 1, char);
551 (void)sv_usepvn(sv, dc, needlen);
552 dc = SvPVX(sv); /* sv_usepvn() calls Renew() */
79072805 553 }
a0d0e21e 554 SvCUR_set(sv, len);
555 (void)SvPOK_only(sv);
79072805 556#ifdef LIBERAL
557 if (len >= sizeof(long)*4 &&
558 !((long)dc % sizeof(long)) &&
559 !((long)lc % sizeof(long)) &&
560 !((long)rc % sizeof(long))) /* It's almost always aligned... */
561 {
562 I32 remainder = len % (sizeof(long)*4);
563 len /= (sizeof(long)*4);
564
565 dl = (long*)dc;
566 ll = (long*)lc;
567 rl = (long*)rc;
568
569 switch (optype) {
570 case OP_BIT_AND:
571 while (len--) {
572 *dl++ = *ll++ & *rl++;
573 *dl++ = *ll++ & *rl++;
574 *dl++ = *ll++ & *rl++;
575 *dl++ = *ll++ & *rl++;
576 }
577 break;
a0d0e21e 578 case OP_BIT_XOR:
79072805 579 while (len--) {
580 *dl++ = *ll++ ^ *rl++;
581 *dl++ = *ll++ ^ *rl++;
582 *dl++ = *ll++ ^ *rl++;
583 *dl++ = *ll++ ^ *rl++;
584 }
585 break;
586 case OP_BIT_OR:
587 while (len--) {
588 *dl++ = *ll++ | *rl++;
589 *dl++ = *ll++ | *rl++;
590 *dl++ = *ll++ | *rl++;
591 *dl++ = *ll++ | *rl++;
592 }
593 }
594
595 dc = (char*)dl;
596 lc = (char*)ll;
597 rc = (char*)rl;
598
599 len = remainder;
600 }
601#endif
a0d0e21e 602 {
a0d0e21e 603 switch (optype) {
604 case OP_BIT_AND:
605 while (len--)
606 *dc++ = *lc++ & *rc++;
607 break;
608 case OP_BIT_XOR:
609 while (len--)
610 *dc++ = *lc++ ^ *rc++;
611 goto mop_up;
612 case OP_BIT_OR:
613 while (len--)
614 *dc++ = *lc++ | *rc++;
615 mop_up:
616 len = lensave;
617 if (rightlen > len)
618 sv_catpvn(sv, rsave + len, rightlen - len);
619 else if (leftlen > len)
620 sv_catpvn(sv, lsave + len, leftlen - len);
4633a7c4 621 else
622 *SvEND(sv) = '\0';
a0d0e21e 623 break;
624 }
79072805 625 }
626}
463ee0b2 627
628OP *
629do_kv(ARGS)
630dARGS
631{
632 dSP;
633 HV *hv = (HV*)POPs;
463ee0b2 634 register HE *entry;
463ee0b2 635 SV *tmpstr;
a0d0e21e 636 I32 dokeys = (op->op_type == OP_KEYS);
637 I32 dovalues = (op->op_type == OP_VALUES);
638
639 if (op->op_type == OP_RV2HV || op->op_type == OP_PADHV)
640 dokeys = dovalues = TRUE;
463ee0b2 641
85581909 642 if (!hv) {
643 if (op->op_flags & OPf_MOD) { /* lvalue */
644 dTARGET; /* make sure to clear its target here */
645 if (SvTYPE(TARG) == SVt_PVLV)
646 LvTARG(TARG) = Nullsv;
647 PUSHs(TARG);
648 }
463ee0b2 649 RETURN;
85581909 650 }
748a9306 651
652 (void)hv_iterinit(hv); /* always reset iterator regardless */
653
463ee0b2 654 if (GIMME != G_ARRAY) {
8c2cee6f 655 I32 i;
463ee0b2 656 dTARGET;
657
85581909 658 if (op->op_flags & OPf_MOD) { /* lvalue */
659 if (SvTYPE(TARG) < SVt_PVLV) {
660 sv_upgrade(TARG, SVt_PVLV);
661 sv_magic(TARG, Nullsv, 'k', Nullch, 0);
662 }
663 LvTYPE(TARG) = 'k';
664 LvTARG(TARG) = (SV*)hv;
665 PUSHs(TARG);
666 RETURN;
667 }
668
8990e307 669 if (!SvRMAGICAL(hv) || !mg_find((SV*)hv,'P'))
463ee0b2 670 i = HvKEYS(hv);
671 else {
672 i = 0;
463ee0b2 673 /*SUPPRESS 560*/
674 while (entry = hv_iternext(hv)) {
675 i++;
676 }
677 }
678 PUSHi( i );
679 RETURN;
680 }
681
682 /* Guess how much room we need. hv_max may be a few too many. Oh well. */
683 EXTEND(sp, HvMAX(hv) * (dokeys + dovalues));
684
463ee0b2 685 PUTBACK; /* hv_iternext and hv_iterval might clobber stack_sp */
686 while (entry = hv_iternext(hv)) {
687 SPAGAIN;
8c2cee6f 688 if (dokeys)
689 XPUSHs(hv_iterkeysv(entry)); /* won't clobber stack_sp */
463ee0b2 690 if (dovalues) {
691 tmpstr = NEWSV(45,0);
692 PUTBACK;
693 sv_setsv(tmpstr,hv_iterval(hv,entry));
694 SPAGAIN;
695 DEBUG_H( {
8c2cee6f 696 sprintf(buf,"%d%%%d=%d\n", HeHASH(entry),
697 HvMAX(hv)+1, HeHASH(entry) & HvMAX(hv));
698 sv_setpv(tmpstr,buf);
463ee0b2 699 } )
700 XPUSHs(sv_2mortal(tmpstr));
701 }
702 PUTBACK;
703 }
704 return NORMAL;
705}
706