Half way through moving per-thread magicals into per-thread fields
[p5sagit/p5-mst-13.2.git] / doop.c
1 /*    doop.c
2  *
3  *    Copyright (c) 1991-1997, Larry Wall
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  *
8  */
9
10 /*
11  * "'So that was the job I felt I had to do when I started,' thought Sam."
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 I32
22 do_trans(sv,arg)
23 SV *sv;
24 OP *arg;
25 {
26     dTHR;
27     register short *tbl;
28     register U8 *s;
29     register U8 *send;
30     register U8 *d;
31     register I32 ch;
32     register I32 matches = 0;
33     register I32 squash = op->op_private & OPpTRANS_SQUASH;
34     STRLEN len;
35
36     if (SvREADONLY(sv))
37         croak(no_modify);
38     tbl = (short*)cPVOP->op_pv;
39     s = (U8*)SvPV(sv, len);
40     if (!len)
41         return 0;
42     if (!SvPOKp(sv))
43         s = (U8*)SvPV_force(sv, len);
44     (void)SvPOK_only(sv);
45     send = s + len;
46     if (!tbl || !s)
47         croak("panic: do_trans");
48     DEBUG_t( deb("2.TBL\n"));
49     if (!op->op_private) {
50         while (s < send) {
51             if ((ch = tbl[*s]) >= 0) {
52                 matches++;
53                 *s = ch;
54             }
55             s++;
56         }
57     }
58     else {
59         d = s;
60         while (s < send) {
61             if ((ch = tbl[*s]) >= 0) {
62                 *d = ch;
63                 if (matches++ && squash) {
64                     if (d[-1] == *d)
65                         matches--;
66                     else
67                         d++;
68                 }
69                 else
70                     d++;
71             }
72             else if (ch == -1)          /* -1 is unmapped character */
73                 *d++ = *s;              /* -2 is delete character */
74             s++;
75         }
76         matches += send - d;    /* account for disappeared chars */
77         *d = '\0';
78         SvCUR_set(sv, d - (U8*)SvPVX(sv));
79     }
80     SvSETMAGIC(sv);
81     return matches;
82 }
83
84 void
85 do_join(sv,del,mark,sp)
86 register SV *sv;
87 SV *del;
88 register SV **mark;
89 register SV **sp;
90 {
91     SV **oldmark = mark;
92     register I32 items = sp - mark;
93     register STRLEN len;
94     STRLEN delimlen;
95     register char *delim = SvPV(del, delimlen);
96     STRLEN tmplen;
97
98     mark++;
99     len = (items > 0 ? (delimlen * (items - 1) ) : 0);
100     if (SvTYPE(sv) < SVt_PV)
101         sv_upgrade(sv, SVt_PV);
102     if (SvLEN(sv) < len + items) {      /* current length is way too short */
103         while (items-- > 0) {
104             if (*mark) {
105                 SvPV(*mark, tmplen);
106                 len += tmplen;
107             }
108             mark++;
109         }
110         SvGROW(sv, len + 1);            /* so try to pre-extend */
111
112         mark = oldmark;
113         items = sp - mark;;
114         ++mark;
115     }
116
117     if (items-- > 0) {
118         char *s;
119
120         if (*mark) {
121             s = SvPV(*mark, tmplen);
122             sv_setpvn(sv, s, tmplen);
123         }
124         else
125             sv_setpv(sv, "");
126         mark++;
127     }
128     else
129         sv_setpv(sv,"");
130     len = delimlen;
131     if (len) {
132         for (; items > 0; items--,mark++) {
133             sv_catpvn(sv,delim,len);
134             sv_catsv(sv,*mark);
135         }
136     }
137     else {
138         for (; items > 0; items--,mark++)
139             sv_catsv(sv,*mark);
140     }
141     SvSETMAGIC(sv);
142 }
143
144 void
145 do_sprintf(sv,len,sarg)
146 SV *sv;
147 I32 len;
148 SV **sarg;
149 {
150     STRLEN patlen;
151     char *pat = SvPV(*sarg, patlen);
152     bool do_taint = FALSE;
153
154     sv_vsetpvfn(sv, pat, patlen, Null(va_list*), sarg + 1, len - 1, &do_taint);
155     SvSETMAGIC(sv);
156     if (do_taint)
157         SvTAINTED_on(sv);
158 }
159
160 void
161 do_vecset(sv)
162 SV *sv;
163 {
164     SV *targ = LvTARG(sv);
165     register I32 offset;
166     register I32 size;
167     register unsigned char *s;
168     register unsigned long lval;
169     I32 mask;
170     STRLEN targlen;
171     STRLEN len;
172
173     if (!targ)
174         return;
175     s = (unsigned char*)SvPV_force(targ, targlen);
176     lval = U_L(SvNV(sv));
177     offset = LvTARGOFF(sv);
178     size = LvTARGLEN(sv);
179     
180     len = (offset + size + 7) / 8;
181     if (len > targlen) {
182         s = (unsigned char*)SvGROW(targ, len + 1);
183         (void)memzero(s + targlen, len - targlen + 1);
184         SvCUR_set(targ, len);
185     }
186     
187     if (size < 8) {
188         mask = (1 << size) - 1;
189         size = offset & 7;
190         lval &= mask;
191         offset >>= 3;
192         s[offset] &= ~(mask << size);
193         s[offset] |= lval << size;
194     }
195     else {
196         offset >>= 3;
197         if (size == 8)
198             s[offset] = lval & 255;
199         else if (size == 16) {
200             s[offset] = (lval >> 8) & 255;
201             s[offset+1] = lval & 255;
202         }
203         else if (size == 32) {
204             s[offset] = (lval >> 24) & 255;
205             s[offset+1] = (lval >> 16) & 255;
206             s[offset+2] = (lval >> 8) & 255;
207             s[offset+3] = lval & 255;
208         }
209     }
210 }
211
212 void
213 do_chop(astr,sv)
214 register SV *astr;
215 register SV *sv;
216 {
217     STRLEN len;
218     char *s;
219     
220     if (SvTYPE(sv) == SVt_PVAV) {
221         register I32 i;
222         I32 max;
223         AV* av = (AV*)sv;
224         max = AvFILL(av);
225         for (i = 0; i <= max; i++) {
226             sv = (SV*)av_fetch(av, i, FALSE);
227             if (sv && ((sv = *(SV**)sv), sv != &sv_undef))
228                 do_chop(astr, sv);
229         }
230         return;
231     }
232     if (SvTYPE(sv) == SVt_PVHV) {
233         HV* hv = (HV*)sv;
234         HE* entry;
235         (void)hv_iterinit(hv);
236         /*SUPPRESS 560*/
237         while (entry = hv_iternext(hv))
238             do_chop(astr,hv_iterval(hv,entry));
239         return;
240     }
241     s = SvPV(sv, len);
242     if (len && !SvPOK(sv))
243         s = SvPV_force(sv, len);
244     if (s && len) {
245         s += --len;
246         sv_setpvn(astr, s, 1);
247         *s = '\0';
248         SvCUR_set(sv, len);
249         SvNIOK_off(sv);
250     }
251     else
252         sv_setpvn(astr, "", 0);
253     SvSETMAGIC(sv);
254
255
256 I32
257 do_chomp(sv)
258 register SV *sv;
259 {
260     dTHR;
261     register I32 count;
262     STRLEN len;
263     char *s;
264
265     if (RsSNARF(rs))
266         return 0;
267     count = 0;
268     if (SvTYPE(sv) == SVt_PVAV) {
269         register I32 i;
270         I32 max;
271         AV* av = (AV*)sv;
272         max = AvFILL(av);
273         for (i = 0; i <= max; i++) {
274             sv = (SV*)av_fetch(av, i, FALSE);
275             if (sv && ((sv = *(SV**)sv), sv != &sv_undef))
276                 count += do_chomp(sv);
277         }
278         return count;
279     }
280     if (SvTYPE(sv) == SVt_PVHV) {
281         HV* hv = (HV*)sv;
282         HE* entry;
283         (void)hv_iterinit(hv);
284         /*SUPPRESS 560*/
285         while (entry = hv_iternext(hv))
286             count += do_chomp(hv_iterval(hv,entry));
287         return count;
288     }
289     s = SvPV(sv, len);
290     if (len && !SvPOKp(sv))
291         s = SvPV_force(sv, len);
292     if (s && len) {
293         s += --len;
294         if (RsPARA(rs)) {
295             if (*s != '\n')
296                 goto nope;
297             ++count;
298             while (len && s[-1] == '\n') {
299                 --len;
300                 --s;
301                 ++count;
302             }
303         }
304         else {
305             STRLEN rslen;
306             char *rsptr = SvPV(rs, rslen);
307             if (rslen == 1) {
308                 if (*s != *rsptr)
309                     goto nope;
310                 ++count;
311             }
312             else {
313                 if (len < rslen - 1)
314                     goto nope;
315                 len -= rslen - 1;
316                 s -= rslen - 1;
317                 if (memNE(s, rsptr, rslen))
318                     goto nope;
319                 count += rslen;
320             }
321         }
322         *s = '\0';
323         SvCUR_set(sv, len);
324         SvNIOK_off(sv);
325     }
326   nope:
327     SvSETMAGIC(sv);
328     return count;
329
330
331 void
332 do_vop(optype,sv,left,right)
333 I32 optype;
334 SV *sv;
335 SV *left;
336 SV *right;
337 {
338     dTHR;       /* just for taint */
339 #ifdef LIBERAL
340     register long *dl;
341     register long *ll;
342     register long *rl;
343 #endif
344     register char *dc;
345     STRLEN leftlen;
346     STRLEN rightlen;
347     register char *lc;
348     register char *rc;
349     register I32 len;
350     I32 lensave;
351     char *lsave;
352     char *rsave;
353
354     if (sv != left || (optype != OP_BIT_AND && !SvOK(sv) && !SvGMAGICAL(sv)))
355         sv_setpvn(sv, "", 0);   /* avoid undef warning on |= and ^= */
356     lsave = lc = SvPV(left, leftlen);
357     rsave = rc = SvPV(right, rightlen);
358     len = leftlen < rightlen ? leftlen : rightlen;
359     lensave = len;
360     if (SvOK(sv) || SvTYPE(sv) > SVt_PVMG) {
361         dc = SvPV_force(sv, na);
362         if (SvCUR(sv) < len) {
363             dc = SvGROW(sv, len + 1);
364             (void)memzero(dc + SvCUR(sv), len - SvCUR(sv) + 1);
365         }
366     }
367     else {
368         I32 needlen = ((optype == OP_BIT_AND)
369                         ? len : (leftlen > rightlen ? leftlen : rightlen));
370         Newz(801, dc, needlen + 1, char);
371         (void)sv_usepvn(sv, dc, needlen);
372         dc = SvPVX(sv);         /* sv_usepvn() calls Renew() */
373     }
374     SvCUR_set(sv, len);
375     (void)SvPOK_only(sv);
376 #ifdef LIBERAL
377     if (len >= sizeof(long)*4 &&
378         !((long)dc % sizeof(long)) &&
379         !((long)lc % sizeof(long)) &&
380         !((long)rc % sizeof(long)))     /* It's almost always aligned... */
381     {
382         I32 remainder = len % (sizeof(long)*4);
383         len /= (sizeof(long)*4);
384
385         dl = (long*)dc;
386         ll = (long*)lc;
387         rl = (long*)rc;
388
389         switch (optype) {
390         case OP_BIT_AND:
391             while (len--) {
392                 *dl++ = *ll++ & *rl++;
393                 *dl++ = *ll++ & *rl++;
394                 *dl++ = *ll++ & *rl++;
395                 *dl++ = *ll++ & *rl++;
396             }
397             break;
398         case OP_BIT_XOR:
399             while (len--) {
400                 *dl++ = *ll++ ^ *rl++;
401                 *dl++ = *ll++ ^ *rl++;
402                 *dl++ = *ll++ ^ *rl++;
403                 *dl++ = *ll++ ^ *rl++;
404             }
405             break;
406         case OP_BIT_OR:
407             while (len--) {
408                 *dl++ = *ll++ | *rl++;
409                 *dl++ = *ll++ | *rl++;
410                 *dl++ = *ll++ | *rl++;
411                 *dl++ = *ll++ | *rl++;
412             }
413         }
414
415         dc = (char*)dl;
416         lc = (char*)ll;
417         rc = (char*)rl;
418
419         len = remainder;
420     }
421 #endif
422     {
423         switch (optype) {
424         case OP_BIT_AND:
425             while (len--)
426                 *dc++ = *lc++ & *rc++;
427             break;
428         case OP_BIT_XOR:
429             while (len--)
430                 *dc++ = *lc++ ^ *rc++;
431             goto mop_up;
432         case OP_BIT_OR:
433             while (len--)
434                 *dc++ = *lc++ | *rc++;
435           mop_up:
436             len = lensave;
437             if (rightlen > len)
438                 sv_catpvn(sv, rsave + len, rightlen - len);
439             else if (leftlen > len)
440                 sv_catpvn(sv, lsave + len, leftlen - len);
441             else
442                 *SvEND(sv) = '\0';
443             break;
444         }
445     }
446     SvTAINT(sv);
447 }
448
449 OP *
450 do_kv(ARGS)
451 dARGS
452 {
453     dSP;
454     HV *hv = (HV*)POPs;
455     register HE *entry;
456     SV *tmpstr;
457     I32 gimme = GIMME_V;
458     I32 dokeys =   (op->op_type == OP_KEYS);
459     I32 dovalues = (op->op_type == OP_VALUES);
460     I32 realhv = (SvTYPE(hv) == SVt_PVHV);
461     
462     if (op->op_type == OP_RV2HV || op->op_type == OP_PADHV) 
463         dokeys = dovalues = TRUE;
464
465     if (!hv) {
466         if (op->op_flags & OPf_MOD) {   /* lvalue */
467             dTARGET;            /* make sure to clear its target here */
468             if (SvTYPE(TARG) == SVt_PVLV)
469                 LvTARG(TARG) = Nullsv;
470             PUSHs(TARG);
471         }
472         RETURN;
473     }
474
475     if (realhv)
476         (void)hv_iterinit(hv);  /* always reset iterator regardless */
477     else
478         (void)avhv_iterinit((AV*)hv);
479
480     if (gimme == G_VOID)
481         RETURN;
482
483     if (gimme == G_SCALAR) {
484         I32 i;
485         dTARGET;
486
487         if (op->op_flags & OPf_MOD) {   /* lvalue */
488             if (SvTYPE(TARG) < SVt_PVLV) {
489                 sv_upgrade(TARG, SVt_PVLV);
490                 sv_magic(TARG, Nullsv, 'k', Nullch, 0);
491             }
492             LvTYPE(TARG) = 'k';
493             LvTARG(TARG) = (SV*)hv;
494             PUSHs(TARG);
495             RETURN;
496         }
497
498         if (!SvRMAGICAL(hv) || !mg_find((SV*)hv,'P'))
499             i = HvKEYS(hv);
500         else {
501             i = 0;
502             /*SUPPRESS 560*/
503             while (entry = realhv ? hv_iternext(hv) : avhv_iternext((AV*)hv)) {
504                 i++;
505             }
506         }
507         PUSHi( i );
508         RETURN;
509     }
510
511     /* Guess how much room we need.  hv_max may be a few too many.  Oh well. */
512     EXTEND(sp, HvMAX(hv) * (dokeys + dovalues));
513
514     PUTBACK;    /* hv_iternext and hv_iterval might clobber stack_sp */
515     while (entry = realhv ? hv_iternext(hv) : avhv_iternext((AV*)hv)) {
516         SPAGAIN;
517         if (dokeys)
518             XPUSHs(hv_iterkeysv(entry));        /* won't clobber stack_sp */
519         if (dovalues) {
520             tmpstr = sv_newmortal();
521             PUTBACK;
522             sv_setsv(tmpstr,realhv ?
523                      hv_iterval(hv,entry) : avhv_iterval((AV*)hv,entry));
524             DEBUG_H(sv_setpvf(tmpstr, "%lu%%%d=%lu",
525                             (unsigned long)HeHASH(entry),
526                             HvMAX(hv)+1,
527                             (unsigned long)(HeHASH(entry) & HvMAX(hv))));
528             SPAGAIN;
529             XPUSHs(tmpstr);
530         }
531         PUTBACK;
532     }
533     return NORMAL;
534 }