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