40c0e778bde537636e3f2031a16a6fe458779f06
[p5sagit/p5-mst-13.2.git] / pp.c
1 /*    pp.c
2  *
3  *    Copyright (c) 1991-1994, 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  * "It's a big house this, and very peculiar.  Always a bit more to discover,
12  * and no knowing what you'll find around a corner.  And Elves, sir!" --Samwise
13  */
14
15 #include "EXTERN.h"
16 #include "perl.h"
17
18 static void doencodes _((SV *sv, char *s, I32 len));
19
20 /* variations on pp_null */
21
22 PP(pp_stub)
23 {
24     dSP;
25     if (GIMME != G_ARRAY) {
26         XPUSHs(&sv_undef);
27     }
28     RETURN;
29 }
30
31 PP(pp_scalar)
32 {
33     return NORMAL;
34 }
35
36 /* Pushy stuff. */
37
38 PP(pp_padav)
39 {
40     dSP; dTARGET;
41     if (op->op_private & OPpLVAL_INTRO)
42         SAVECLEARSV(curpad[op->op_targ]);
43     EXTEND(SP, 1);
44     if (op->op_flags & OPf_REF) {
45         PUSHs(TARG);
46         RETURN;
47     }
48     if (GIMME == G_ARRAY) {
49         I32 maxarg = AvFILL((AV*)TARG) + 1;
50         EXTEND(SP, maxarg);
51         Copy(AvARRAY((AV*)TARG), SP+1, maxarg, SV*);
52         SP += maxarg;
53     }
54     else {
55         SV* sv = sv_newmortal();
56         I32 maxarg = AvFILL((AV*)TARG) + 1;
57         sv_setiv(sv, maxarg);
58         PUSHs(sv);
59     }
60     RETURN;
61 }
62
63 PP(pp_padhv)
64 {
65     dSP; dTARGET;
66     XPUSHs(TARG);
67     if (op->op_private & OPpLVAL_INTRO)
68         SAVECLEARSV(curpad[op->op_targ]);
69     if (op->op_flags & OPf_REF)
70         RETURN;
71     if (GIMME == G_ARRAY) { /* array wanted */
72         RETURNOP(do_kv(ARGS));
73     }
74     else {
75         SV* sv = sv_newmortal();
76         if (HvFILL((HV*)TARG)) {
77             sprintf(buf, "%d/%d", HvFILL((HV*)TARG), HvMAX((HV*)TARG)+1);
78             sv_setpv(sv, buf);
79         }
80         else
81             sv_setiv(sv, 0);
82         SETs(sv);
83         RETURN;
84     }
85 }
86
87 PP(pp_padany)
88 {
89     DIE("NOT IMPL LINE %d",__LINE__);
90 }
91
92 /* Translations. */
93
94 PP(pp_rv2gv)
95 {
96     dSP; dTOPss;
97     
98     if (SvROK(sv)) {
99       wasref:
100         sv = SvRV(sv);
101         if (SvTYPE(sv) != SVt_PVGV)
102             DIE("Not a GLOB reference");
103     }
104     else {
105         if (SvTYPE(sv) != SVt_PVGV) {
106             char *sym;
107
108             if (SvGMAGICAL(sv)) {
109                 mg_get(sv);
110                 if (SvROK(sv))
111                     goto wasref;
112             }
113             if (!SvOK(sv)) {
114                 if (op->op_flags & OPf_REF ||
115                     op->op_private & HINT_STRICT_REFS)
116                     DIE(no_usym, "a symbol");
117                 RETSETUNDEF;
118             }
119             sym = SvPV(sv, na);
120             if (op->op_private & HINT_STRICT_REFS)
121                 DIE(no_symref, sym, "a symbol");
122             sv = (SV*)gv_fetchpv(sym, TRUE, SVt_PVGV);
123         }
124     }
125     if (op->op_private & OPpLVAL_INTRO) {
126         GP *ogp = GvGP(sv);
127
128         SSCHECK(3);
129         SSPUSHPTR(SvREFCNT_inc(sv));
130         SSPUSHPTR(ogp);
131         SSPUSHINT(SAVEt_GP);
132
133         if (op->op_flags & OPf_SPECIAL) {
134             GvGP(sv)->gp_refcnt++;              /* will soon be assigned */
135             GvINTRO_on(sv);
136         }
137         else {
138             GP *gp;
139             Newz(602,gp, 1, GP);
140             GvGP(sv) = gp;
141             GvREFCNT(sv) = 1;
142             GvSV(sv) = NEWSV(72,0);
143             GvLINE(sv) = curcop->cop_line;
144             GvEGV(sv) = sv;
145         }
146     }
147     SETs(sv);
148     RETURN;
149 }
150
151 PP(pp_rv2sv)
152 {
153     dSP; dTOPss;
154
155     if (SvROK(sv)) {
156       wasref:
157         sv = SvRV(sv);
158         switch (SvTYPE(sv)) {
159         case SVt_PVAV:
160         case SVt_PVHV:
161         case SVt_PVCV:
162             DIE("Not a SCALAR reference");
163         }
164     }
165     else {
166         GV *gv = sv;
167         char *sym;
168
169         if (SvTYPE(gv) != SVt_PVGV) {
170             if (SvGMAGICAL(sv)) {
171                 mg_get(sv);
172                 if (SvROK(sv))
173                     goto wasref;
174             }
175             if (!SvOK(sv)) {
176                 if (op->op_flags & OPf_REF ||
177                     op->op_private & HINT_STRICT_REFS)
178                     DIE(no_usym, "a SCALAR");
179                 RETSETUNDEF;
180             }
181             sym = SvPV(sv, na);
182             if (op->op_private & HINT_STRICT_REFS)
183                 DIE(no_symref, sym, "a SCALAR");
184             gv = (SV*)gv_fetchpv(sym, TRUE, SVt_PV);
185         }
186         sv = GvSV(gv);
187     }
188     if (op->op_flags & OPf_MOD) {
189         if (op->op_private & OPpLVAL_INTRO)
190             sv = save_scalar((GV*)TOPs);
191         else if (op->op_private & (OPpDEREF_HV|OPpDEREF_AV))
192             provide_ref(op, sv);
193     }
194     SETs(sv);
195     RETURN;
196 }
197
198 PP(pp_av2arylen)
199 {
200     dSP;
201     AV *av = (AV*)TOPs;
202     SV *sv = AvARYLEN(av);
203     if (!sv) {
204         AvARYLEN(av) = sv = NEWSV(0,0);
205         sv_upgrade(sv, SVt_IV);
206         sv_magic(sv, (SV*)av, '#', Nullch, 0);
207     }
208     SETs(sv);
209     RETURN;
210 }
211
212 PP(pp_pos)
213 {
214     dSP; dTARGET; dPOPss;
215     
216     if (op->op_flags & OPf_MOD) {
217         LvTYPE(TARG) = '<';
218         LvTARG(TARG) = sv;
219         PUSHs(TARG);    /* no SvSETMAGIC */
220         RETURN;
221     }
222     else {
223         MAGIC* mg; 
224
225         if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) {
226             mg = mg_find(sv, 'g');
227             if (mg && mg->mg_len >= 0) {
228                 PUSHi(mg->mg_len + curcop->cop_arybase);
229                 RETURN;
230             }
231         }
232         RETPUSHUNDEF;
233     }
234 }
235
236 PP(pp_rv2cv)
237 {
238     dSP;
239     GV *gv;
240     HV *stash;
241
242     /* We usually try to add a non-existent subroutine in case of AUTOLOAD. */
243     /* (But not in defined().) */
244     CV *cv = sv_2cv(TOPs, &stash, &gv, !(op->op_flags & OPf_SPECIAL));
245
246     if (!cv)
247         cv = (CV*)&sv_undef;
248     SETs((SV*)cv);
249     RETURN;
250 }
251
252 PP(pp_prototype)
253 {
254     dSP;
255     CV *cv;
256     HV *stash;
257     GV *gv;
258     SV *ret;
259
260     ret = &sv_undef;
261     cv = sv_2cv(TOPs, &stash, &gv, FALSE);
262     if (cv && SvPOK(cv)) {
263         char *p = SvPVX(cv);
264         ret = sv_2mortal(newSVpv(p ? p : "", SvLEN(cv)));
265     }
266     SETs(ret);
267     RETURN;
268 }
269
270 PP(pp_anoncode)
271 {
272     dSP;
273     CV* cv = (CV*)cSVOP->op_sv;
274     EXTEND(SP,1);
275
276     if (CvCLONE(cv))
277         cv = (CV*)sv_2mortal((SV*)cv_clone(cv));
278
279     PUSHs((SV*)cv);
280     RETURN;
281 }
282
283 PP(pp_srefgen)
284 {
285     dSP; dTOPss;
286     SV* rv;
287     rv = sv_newmortal();
288     sv_upgrade(rv, SVt_RV);
289     if (SvPADTMP(sv))
290         sv = newSVsv(sv);
291     else {
292         SvTEMP_off(sv);
293         (void)SvREFCNT_inc(sv);
294     }
295     SvRV(rv) = sv;
296     SvROK_on(rv);
297     SETs(rv);
298     RETURN;
299
300
301 PP(pp_refgen)
302 {
303     dSP; dMARK;
304     SV* sv;
305     SV* rv;
306     if (GIMME != G_ARRAY) {
307         MARK[1] = *SP;
308         SP = MARK + 1;
309     }
310     while (MARK < SP) {
311         sv = *++MARK;
312         rv = sv_newmortal();
313         sv_upgrade(rv, SVt_RV);
314         if (SvPADTMP(sv))
315             sv = newSVsv(sv);
316         else {
317             SvTEMP_off(sv);
318             (void)SvREFCNT_inc(sv);
319         }
320         SvRV(rv) = sv;
321         SvROK_on(rv);
322         *MARK = rv;
323     }
324     RETURN;
325 }
326
327 PP(pp_ref)
328 {
329     dSP; dTARGET;
330     SV *sv;
331     char *pv;
332
333     sv = POPs;
334     if (!sv || !SvROK(sv))
335         RETPUSHNO;
336
337     sv = SvRV(sv);
338     pv = sv_reftype(sv,TRUE);
339     PUSHp(pv, strlen(pv));
340     RETURN;
341 }
342
343 PP(pp_bless)
344 {
345     dSP;
346     HV *stash;
347
348     if (MAXARG == 1)
349         stash = curcop->cop_stash;
350     else
351         stash = gv_stashsv(POPs, TRUE);
352
353     (void)sv_bless(TOPs, stash);
354     RETURN;
355 }
356
357 /* Pattern matching */
358
359 PP(pp_study)
360 {
361     dSP; dPOPss;
362     register unsigned char *s;
363     register I32 pos;
364     register I32 ch;
365     register I32 *sfirst;
366     register I32 *snext;
367     I32 retval;
368     STRLEN len;
369
370     s = (unsigned char*)(SvPV(sv, len));
371     pos = len;
372     if (sv == lastscream)
373         SvSCREAM_off(sv);
374     else {
375         if (lastscream) {
376             SvSCREAM_off(lastscream);
377             SvREFCNT_dec(lastscream);
378         }
379         lastscream = SvREFCNT_inc(sv);
380     }
381     if (pos <= 0) {
382         retval = 0;
383         goto ret;
384     }
385     if (pos > maxscream) {
386         if (maxscream < 0) {
387             maxscream = pos + 80;
388             New(301, screamfirst, 256, I32);
389             New(302, screamnext, maxscream, I32);
390         }
391         else {
392             maxscream = pos + pos / 4;
393             Renew(screamnext, maxscream, I32);
394         }
395     }
396
397     sfirst = screamfirst;
398     snext = screamnext;
399
400     if (!sfirst || !snext)
401         DIE("do_study: out of memory");
402
403     for (ch = 256; ch; --ch)
404         *sfirst++ = -1;
405     sfirst -= 256;
406
407     while (--pos >= 0) {
408         ch = s[pos];
409         if (sfirst[ch] >= 0)
410             snext[pos] = sfirst[ch] - pos;
411         else
412             snext[pos] = -pos;
413         sfirst[ch] = pos;
414
415         /* If there were any case insensitive searches, we must assume they
416          * all are.  This speeds up insensitive searches much more than
417          * it slows down sensitive ones.
418          */
419         if (sawi)
420             sfirst[fold[ch]] = pos;
421     }
422
423     SvSCREAM_on(sv);
424     sv_magic(sv, Nullsv, 'g', Nullch, 0);       /* piggyback on m//g magic */
425     retval = 1;
426   ret:
427     XPUSHs(sv_2mortal(newSViv((I32)retval)));
428     RETURN;
429 }
430
431 PP(pp_trans)
432 {
433     dSP; dTARG;
434     SV *sv;
435
436     if (op->op_flags & OPf_STACKED)
437         sv = POPs;
438     else {
439         sv = GvSV(defgv);
440         EXTEND(SP,1);
441     }
442     TARG = sv_newmortal();
443     PUSHi(do_trans(sv, op));
444     RETURN;
445 }
446
447 /* Lvalue operators. */
448
449 PP(pp_schop)
450 {
451     dSP; dTARGET;
452     do_chop(TARG, TOPs);
453     SETTARG;
454     RETURN;
455 }
456
457 PP(pp_chop)
458 {
459     dSP; dMARK; dTARGET;
460     while (SP > MARK)
461         do_chop(TARG, POPs);
462     PUSHTARG;
463     RETURN;
464 }
465
466 PP(pp_schomp)
467 {
468     dSP; dTARGET;
469     SETi(do_chomp(TOPs));
470     RETURN;
471 }
472
473 PP(pp_chomp)
474 {
475     dSP; dMARK; dTARGET;
476     register I32 count = 0;
477     
478     while (SP > MARK)
479         count += do_chomp(POPs);
480     PUSHi(count);
481     RETURN;
482 }
483
484 PP(pp_defined)
485 {
486     dSP;
487     register SV* sv;
488
489     sv = POPs;
490     if (!sv || !SvANY(sv))
491         RETPUSHNO;
492     switch (SvTYPE(sv)) {
493     case SVt_PVAV:
494         if (AvMAX(sv) >= 0 || SvRMAGICAL(sv))
495             RETPUSHYES;
496         break;
497     case SVt_PVHV:
498         if (HvARRAY(sv) || SvRMAGICAL(sv))
499             RETPUSHYES;
500         break;
501     case SVt_PVCV:
502         if (CvROOT(sv) || CvXSUB(sv))
503             RETPUSHYES;
504         break;
505     default:
506         if (SvGMAGICAL(sv))
507             mg_get(sv);
508         if (SvOK(sv))
509             RETPUSHYES;
510     }
511     RETPUSHNO;
512 }
513
514 PP(pp_undef)
515 {
516     dSP;
517     SV *sv;
518
519     if (!op->op_private)
520         RETPUSHUNDEF;
521
522     sv = POPs;
523     if (!sv)
524         RETPUSHUNDEF;
525
526     if (SvTHINKFIRST(sv)) {
527         if (SvREADONLY(sv))
528             RETPUSHUNDEF;
529         if (SvROK(sv))
530             sv_unref(sv);
531     }
532
533     switch (SvTYPE(sv)) {
534     case SVt_NULL:
535         break;
536     case SVt_PVAV:
537         av_undef((AV*)sv);
538         break;
539     case SVt_PVHV:
540         hv_undef((HV*)sv);
541         break;
542     case SVt_PVCV:
543         cv_undef((CV*)sv);
544         sub_generation++;
545         break;
546     case SVt_PVGV:
547         if (SvFAKE(sv)) {
548             sv_setsv(sv, &sv_undef);
549             break;
550         }
551     default:
552         if (SvPOK(sv) && SvLEN(sv)) {
553             (void)SvOOK_off(sv);
554             Safefree(SvPVX(sv));
555             SvPV_set(sv, Nullch);
556             SvLEN_set(sv, 0);
557         }
558         (void)SvOK_off(sv);
559         SvSETMAGIC(sv);
560     }
561
562     RETPUSHUNDEF;
563 }
564
565 PP(pp_predec)
566 {
567     dSP;
568     if (SvIOK(TOPs)) {
569         --SvIVX(TOPs);
570         SvFLAGS(TOPs) &= ~(SVf_NOK|SVf_POK|SVp_NOK|SVp_POK);
571     }
572     else
573         sv_dec(TOPs);
574     SvSETMAGIC(TOPs);
575     return NORMAL;
576 }
577
578 PP(pp_postinc)
579 {
580     dSP; dTARGET;
581     sv_setsv(TARG, TOPs);
582     if (SvIOK(TOPs)) {
583         ++SvIVX(TOPs);
584         SvFLAGS(TOPs) &= ~(SVf_NOK|SVf_POK|SVp_NOK|SVp_POK);
585     }
586     else
587         sv_inc(TOPs);
588     SvSETMAGIC(TOPs);
589     if (!SvOK(TARG))
590         sv_setiv(TARG, 0);
591     SETs(TARG);
592     return NORMAL;
593 }
594
595 PP(pp_postdec)
596 {
597     dSP; dTARGET;
598     sv_setsv(TARG, TOPs);
599     if (SvIOK(TOPs)) {
600         --SvIVX(TOPs);
601         SvFLAGS(TOPs) &= ~(SVf_NOK|SVf_POK|SVp_NOK|SVp_POK);
602     }
603     else
604         sv_dec(TOPs);
605     SvSETMAGIC(TOPs);
606     SETs(TARG);
607     return NORMAL;
608 }
609
610 /* Ordinary operators. */
611
612 PP(pp_pow)
613 {
614     dSP; dATARGET; tryAMAGICbin(pow,opASSIGN); 
615     {
616       dPOPTOPnnrl;
617       SETn( pow( left, right) );
618       RETURN;
619     }
620 }
621
622 PP(pp_multiply)
623 {
624     dSP; dATARGET; tryAMAGICbin(mult,opASSIGN); 
625     {
626       dPOPTOPnnrl;
627       SETn( left * right );
628       RETURN;
629     }
630 }
631
632 PP(pp_divide)
633 {
634     dSP; dATARGET; tryAMAGICbin(div,opASSIGN); 
635     {
636       dPOPnv;
637       if (value == 0.0)
638         DIE("Illegal division by zero");
639 #ifdef SLOPPYDIVIDE
640       /* insure that 20./5. == 4. */
641       {
642         double x;
643         I32    k;
644         x =  POPn;
645         if ((double)I_32(x)     == x &&
646             (double)I_32(value) == value &&
647             (k = I_32(x)/I_32(value))*I_32(value) == I_32(x)) {
648             value = k;
649         } else {
650             value = x/value;
651         }
652       }
653 #else
654       value = POPn / value;
655 #endif
656       PUSHn( value );
657       RETURN;
658     }
659 }
660
661 PP(pp_modulo)
662 {
663     dSP; dATARGET; tryAMAGICbin(mod,opASSIGN);
664     {
665       register unsigned long tmpulong;
666       register long tmplong;
667       I32 value;
668
669       tmpulong = (unsigned long) POPn;
670       if (tmpulong == 0L)
671         DIE("Illegal modulus zero");
672       value = TOPn;
673       if (value >= 0.0)
674         value = (I32)(((unsigned long)value) % tmpulong);
675       else {
676         tmplong = (long)value;
677         value = (I32)(tmpulong - ((-tmplong - 1) % tmpulong)) - 1;
678       }
679       SETi(value);
680       RETURN;
681     }
682 }
683
684 PP(pp_repeat)
685 {
686   dSP; dATARGET; tryAMAGICbin(repeat,opASSIGN);
687   {
688     register I32 count = POPi;
689     if (GIMME == G_ARRAY && op->op_private & OPpREPEAT_DOLIST) {
690         dMARK;
691         I32 items = SP - MARK;
692         I32 max;
693
694         max = items * count;
695         MEXTEND(MARK, max);
696         if (count > 1) {
697             while (SP > MARK) {
698                 if (*SP)
699                     SvTEMP_off((*SP));
700                 SP--;
701             }
702             MARK++;
703             repeatcpy((char*)(MARK + items), (char*)MARK,
704                 items * sizeof(SV*), count - 1);
705             SP += max;
706         }
707         else if (count <= 0)
708             SP -= items;
709     }
710     else {      /* Note: mark already snarfed by pp_list */
711         SV *tmpstr;
712         STRLEN len;
713
714         tmpstr = POPs;
715         if (TARG == tmpstr && SvTHINKFIRST(tmpstr)) {
716             if (SvREADONLY(tmpstr) && curcop != &compiling)
717                 DIE("Can't x= to readonly value");
718             if (SvROK(tmpstr))
719                 sv_unref(tmpstr);
720         }
721         SvSetSV(TARG, tmpstr);
722         SvPV_force(TARG, len);
723         if (count >= 1) {
724             SvGROW(TARG, (count * len) + 1);
725             if (count > 1)
726                 repeatcpy(SvPVX(TARG) + len, SvPVX(TARG), len, count - 1);
727             SvCUR(TARG) *= count;
728             *SvEND(TARG) = '\0';
729             (void)SvPOK_only(TARG);
730         }
731         else
732             sv_setsv(TARG, &sv_no);
733         PUSHTARG;
734     }
735     RETURN;
736   }
737 }
738
739 PP(pp_subtract)
740 {
741     dSP; dATARGET; tryAMAGICbin(subtr,opASSIGN); 
742     {
743       dPOPTOPnnrl;
744       SETn( left - right );
745       RETURN;
746     }
747 }
748
749 PP(pp_left_shift)
750 {
751     dSP; dATARGET; tryAMAGICbin(lshift,opASSIGN); 
752     {
753         dPOPTOPiirl;
754         SETi( left << right );
755         RETURN;
756     }
757 }
758
759 PP(pp_right_shift)
760 {
761     dSP; dATARGET; tryAMAGICbin(rshift,opASSIGN); 
762     {
763       dPOPTOPiirl;
764       SETi( left >> right );
765       RETURN;
766     }
767 }
768
769 PP(pp_lt)
770 {
771     dSP; tryAMAGICbinSET(lt,0); 
772     {
773       dPOPnv;
774       SETs((TOPn < value) ? &sv_yes : &sv_no);
775       RETURN;
776     }
777 }
778
779 PP(pp_gt)
780 {
781     dSP; tryAMAGICbinSET(gt,0); 
782     {
783       dPOPnv;
784       SETs((TOPn > value) ? &sv_yes : &sv_no);
785       RETURN;
786     }
787 }
788
789 PP(pp_le)
790 {
791     dSP; tryAMAGICbinSET(le,0); 
792     {
793       dPOPnv;
794       SETs((TOPn <= value) ? &sv_yes : &sv_no);
795       RETURN;
796     }
797 }
798
799 PP(pp_ge)
800 {
801     dSP; tryAMAGICbinSET(ge,0); 
802     {
803       dPOPnv;
804       SETs((TOPn >= value) ? &sv_yes : &sv_no);
805       RETURN;
806     }
807 }
808
809 PP(pp_ne)
810 {
811     dSP; tryAMAGICbinSET(ne,0); 
812     {
813       dPOPnv;
814       SETs((TOPn != value) ? &sv_yes : &sv_no);
815       RETURN;
816     }
817 }
818
819 PP(pp_ncmp)
820 {
821     dSP; dTARGET; tryAMAGICbin(ncmp,0); 
822     {
823       dPOPTOPnnrl;
824       I32 value;
825
826       if (left > right)
827         value = 1;
828       else if (left < right)
829         value = -1;
830       else
831         value = 0;
832       SETi(value);
833       RETURN;
834     }
835 }
836
837 PP(pp_slt)
838 {
839     dSP; tryAMAGICbinSET(slt,0); 
840     {
841       dPOPTOPssrl;
842       SETs( sv_cmp(left, right) < 0 ? &sv_yes : &sv_no );
843       RETURN;
844     }
845 }
846
847 PP(pp_sgt)
848 {
849     dSP; tryAMAGICbinSET(sgt,0); 
850     {
851       dPOPTOPssrl;
852       SETs( sv_cmp(left, right) > 0 ? &sv_yes : &sv_no );
853       RETURN;
854     }
855 }
856
857 PP(pp_sle)
858 {
859     dSP; tryAMAGICbinSET(sle,0); 
860     {
861       dPOPTOPssrl;
862       SETs( sv_cmp(left, right) <= 0 ? &sv_yes : &sv_no );
863       RETURN;
864     }
865 }
866
867 PP(pp_sge)
868 {
869     dSP; tryAMAGICbinSET(sge,0); 
870     {
871       dPOPTOPssrl;
872       SETs( sv_cmp(left, right) >= 0 ? &sv_yes : &sv_no );
873       RETURN;
874     }
875 }
876
877 PP(pp_sne)
878 {
879     dSP; tryAMAGICbinSET(sne,0); 
880     {
881       dPOPTOPssrl;
882       SETs( !sv_eq(left, right) ? &sv_yes : &sv_no );
883       RETURN;
884     }
885 }
886
887 PP(pp_scmp)
888 {
889     dSP; dTARGET;  tryAMAGICbin(scmp,0);
890     {
891       dPOPTOPssrl;
892       SETi( sv_cmp(left, right) );
893       RETURN;
894     }
895 }
896
897 PP(pp_bit_and) {
898     dSP; dATARGET; tryAMAGICbin(band,opASSIGN); 
899     {
900       dPOPTOPssrl;
901       if (SvNIOKp(left) || SvNIOKp(right)) {
902         unsigned long value = U_L(SvNV(left));
903         value = value & U_L(SvNV(right));
904         SETn((double)value);
905       }
906       else {
907         do_vop(op->op_type, TARG, left, right);
908         SETTARG;
909       }
910       RETURN;
911     }
912 }
913
914 PP(pp_bit_xor)
915 {
916     dSP; dATARGET; tryAMAGICbin(bxor,opASSIGN); 
917     {
918       dPOPTOPssrl;
919       if (SvNIOKp(left) || SvNIOKp(right)) {
920         unsigned long value = U_L(SvNV(left));
921         value = value ^ U_L(SvNV(right));
922         SETn((double)value);
923       }
924       else {
925         do_vop(op->op_type, TARG, left, right);
926         SETTARG;
927       }
928       RETURN;
929     }
930 }
931
932 PP(pp_bit_or)
933 {
934     dSP; dATARGET; tryAMAGICbin(bor,opASSIGN); 
935     {
936       dPOPTOPssrl;
937       if (SvNIOKp(left) || SvNIOKp(right)) {
938         unsigned long value = U_L(SvNV(left));
939         value = value | U_L(SvNV(right));
940         SETn((double)value);
941       }
942       else {
943         do_vop(op->op_type, TARG, left, right);
944         SETTARG;
945       }
946       RETURN;
947     }
948 }
949
950 PP(pp_negate)
951 {
952     dSP; dTARGET; tryAMAGICun(neg);
953     {
954         dTOPss;
955         if (SvGMAGICAL(sv))
956             mg_get(sv);
957         if (SvNIOKp(sv))
958             SETn(-SvNV(sv));
959         else if (SvPOKp(sv)) {
960             STRLEN len;
961             char *s = SvPV(sv, len);
962             if (isALPHA(*s) || *s == '_') {
963                 sv_setpvn(TARG, "-", 1);
964                 sv_catsv(TARG, sv);
965             }
966             else if (*s == '+' || *s == '-') {
967                 sv_setsv(TARG, sv);
968                 *SvPV_force(TARG, len) = *s == '-' ? '+' : '-';
969             }
970             else
971                 sv_setnv(TARG, -SvNV(sv));
972             SETTARG;
973         }
974         else
975             SETn(-SvNV(sv));
976     }
977     RETURN;
978 }
979
980 PP(pp_not)
981 {
982 #ifdef OVERLOAD
983     dSP; tryAMAGICunSET(not);
984 #endif /* OVERLOAD */
985     *stack_sp = SvTRUE(*stack_sp) ? &sv_no : &sv_yes;
986     return NORMAL;
987 }
988
989 PP(pp_complement)
990 {
991     dSP; dTARGET; tryAMAGICun(compl); 
992     {
993       dTOPss;
994       register I32 anum;
995
996       if (SvNIOKp(sv)) {
997         IV iv = ~SvIV(sv);
998         if (iv < 0)
999             SETn( (double) ~U_L(SvNV(sv)) );
1000         else
1001             SETi( iv );
1002       }
1003       else {
1004         register char *tmps;
1005         register long *tmpl;
1006         STRLEN len;
1007
1008         SvSetSV(TARG, sv);
1009         tmps = SvPV_force(TARG, len);
1010         anum = len;
1011 #ifdef LIBERAL
1012         for ( ; anum && (unsigned long)tmps % sizeof(long); anum--, tmps++)
1013             *tmps = ~*tmps;
1014         tmpl = (long*)tmps;
1015         for ( ; anum >= sizeof(long); anum -= sizeof(long), tmpl++)
1016             *tmpl = ~*tmpl;
1017         tmps = (char*)tmpl;
1018 #endif
1019         for ( ; anum > 0; anum--, tmps++)
1020             *tmps = ~*tmps;
1021
1022         SETs(TARG);
1023       }
1024       RETURN;
1025     }
1026 }
1027
1028 /* integer versions of some of the above */
1029
1030 PP(pp_i_multiply)
1031 {
1032     dSP; dATARGET; tryAMAGICbin(mult,opASSIGN); 
1033     {
1034       dPOPTOPiirl;
1035       SETi( left * right );
1036       RETURN;
1037     }
1038 }
1039
1040 PP(pp_i_divide)
1041 {
1042     dSP; dATARGET; tryAMAGICbin(div,opASSIGN); 
1043     {
1044       dPOPiv;
1045       if (value == 0)
1046         DIE("Illegal division by zero");
1047       value = POPi / value;
1048       PUSHi( value );
1049       RETURN;
1050     }
1051 }
1052
1053 PP(pp_i_modulo)
1054 {
1055     dSP; dATARGET; tryAMAGICbin(mod,opASSIGN); 
1056     {
1057       dPOPTOPiirl;
1058       SETi( left % right );
1059       RETURN;
1060     }
1061 }
1062
1063 PP(pp_i_add)
1064 {
1065     dSP; dATARGET; tryAMAGICbin(add,opASSIGN); 
1066     {
1067       dPOPTOPiirl;
1068       SETi( left + right );
1069       RETURN;
1070     }
1071 }
1072
1073 PP(pp_i_subtract)
1074 {
1075     dSP; dATARGET; tryAMAGICbin(subtr,opASSIGN); 
1076     {
1077       dPOPTOPiirl;
1078       SETi( left - right );
1079       RETURN;
1080     }
1081 }
1082
1083 PP(pp_i_lt)
1084 {
1085     dSP; tryAMAGICbinSET(lt,0); 
1086     {
1087       dPOPTOPiirl;
1088       SETs((left < right) ? &sv_yes : &sv_no);
1089       RETURN;
1090     }
1091 }
1092
1093 PP(pp_i_gt)
1094 {
1095     dSP; tryAMAGICbinSET(gt,0); 
1096     {
1097       dPOPTOPiirl;
1098       SETs((left > right) ? &sv_yes : &sv_no);
1099       RETURN;
1100     }
1101 }
1102
1103 PP(pp_i_le)
1104 {
1105     dSP; tryAMAGICbinSET(le,0); 
1106     {
1107       dPOPTOPiirl;
1108       SETs((left <= right) ? &sv_yes : &sv_no);
1109       RETURN;
1110     }
1111 }
1112
1113 PP(pp_i_ge)
1114 {
1115     dSP; tryAMAGICbinSET(ge,0); 
1116     {
1117       dPOPTOPiirl;
1118       SETs((left >= right) ? &sv_yes : &sv_no);
1119       RETURN;
1120     }
1121 }
1122
1123 PP(pp_i_eq)
1124 {
1125     dSP; tryAMAGICbinSET(eq,0); 
1126     {
1127       dPOPTOPiirl;
1128       SETs((left == right) ? &sv_yes : &sv_no);
1129       RETURN;
1130     }
1131 }
1132
1133 PP(pp_i_ne)
1134 {
1135     dSP; tryAMAGICbinSET(ne,0); 
1136     {
1137       dPOPTOPiirl;
1138       SETs((left != right) ? &sv_yes : &sv_no);
1139       RETURN;
1140     }
1141 }
1142
1143 PP(pp_i_ncmp)
1144 {
1145     dSP; dTARGET; tryAMAGICbin(ncmp,0); 
1146     {
1147       dPOPTOPiirl;
1148       I32 value;
1149
1150       if (left > right)
1151         value = 1;
1152       else if (left < right)
1153         value = -1;
1154       else
1155         value = 0;
1156       SETi(value);
1157       RETURN;
1158     }
1159 }
1160
1161 PP(pp_i_negate)
1162 {
1163     dSP; dTARGET; tryAMAGICun(neg);
1164     SETi(-TOPi);
1165     RETURN;
1166 }
1167
1168 /* High falutin' math. */
1169
1170 PP(pp_atan2)
1171 {
1172     dSP; dTARGET; tryAMAGICbin(atan2,0); 
1173     {
1174       dPOPTOPnnrl;
1175       SETn(atan2(left, right));
1176       RETURN;
1177     }
1178 }
1179
1180 PP(pp_sin)
1181 {
1182     dSP; dTARGET; tryAMAGICun(sin);
1183     {
1184       double value;
1185       value = POPn;
1186       value = sin(value);
1187       XPUSHn(value);
1188       RETURN;
1189     }
1190 }
1191
1192 PP(pp_cos)
1193 {
1194     dSP; dTARGET; tryAMAGICun(cos);
1195     {
1196       double value;
1197       value = POPn;
1198       value = cos(value);
1199       XPUSHn(value);
1200       RETURN;
1201     }
1202 }
1203
1204 PP(pp_rand)
1205 {
1206     dSP; dTARGET;
1207     double value;
1208     if (MAXARG < 1)
1209         value = 1.0;
1210     else
1211         value = POPn;
1212     if (value == 0.0)
1213         value = 1.0;
1214 #if RANDBITS == 31
1215     value = rand() * value / 2147483648.0;
1216 #else
1217 #if RANDBITS == 16
1218     value = rand() * value / 65536.0;
1219 #else
1220 #if RANDBITS == 15
1221     value = rand() * value / 32768.0;
1222 #else
1223     value = rand() * value / (double)(((unsigned long)1) << RANDBITS);
1224 #endif
1225 #endif
1226 #endif
1227     XPUSHn(value);
1228     RETURN;
1229 }
1230
1231 PP(pp_srand)
1232 {
1233     dSP;
1234     I32 anum;
1235     Time_t when;
1236
1237     if (MAXARG < 1) {
1238         (void)time(&when);
1239         anum = when;
1240     }
1241     else
1242         anum = POPi;
1243     (void)srand(anum);
1244     EXTEND(SP, 1);
1245     RETPUSHYES;
1246 }
1247
1248 PP(pp_exp)
1249 {
1250     dSP; dTARGET; tryAMAGICun(exp);
1251     {
1252       double value;
1253       value = POPn;
1254       value = exp(value);
1255       XPUSHn(value);
1256       RETURN;
1257     }
1258 }
1259
1260 PP(pp_log)
1261 {
1262     dSP; dTARGET; tryAMAGICun(log);
1263     {
1264       double value;
1265       value = POPn;
1266       if (value <= 0.0)
1267         DIE("Can't take log of %g", value);
1268       value = log(value);
1269       XPUSHn(value);
1270       RETURN;
1271     }
1272 }
1273
1274 PP(pp_sqrt)
1275 {
1276     dSP; dTARGET; tryAMAGICun(sqrt);
1277     {
1278       double value;
1279       value = POPn;
1280       if (value < 0.0)
1281         DIE("Can't take sqrt of %g", value);
1282       value = sqrt(value);
1283       XPUSHn(value);
1284       RETURN;
1285     }
1286 }
1287
1288 PP(pp_int)
1289 {
1290     dSP; dTARGET;
1291     double value;
1292     value = POPn;
1293     if (value >= 0.0)
1294         (void)modf(value, &value);
1295     else {
1296         (void)modf(-value, &value);
1297         value = -value;
1298     }
1299     XPUSHn(value);
1300     RETURN;
1301 }
1302
1303 PP(pp_abs)
1304 {
1305     dSP; dTARGET; tryAMAGICun(abs);
1306     {
1307       double value;
1308       value = POPn;
1309
1310       if (value < 0.0)
1311         value = -value;
1312
1313       XPUSHn(value);
1314       RETURN;
1315     }
1316 }
1317
1318 PP(pp_hex)
1319 {
1320     dSP; dTARGET;
1321     char *tmps;
1322     unsigned long value;
1323     I32 argtype;
1324
1325     tmps = POPp;
1326     value = scan_hex(tmps, 99, &argtype);
1327     if ((IV)value >= 0)
1328         XPUSHi(value);
1329     else
1330         XPUSHn(U_V(value));
1331     RETURN;
1332 }
1333
1334 PP(pp_oct)
1335 {
1336     dSP; dTARGET;
1337     unsigned long value;
1338     I32 argtype;
1339     char *tmps;
1340
1341     tmps = POPp;
1342     while (*tmps && isSPACE(*tmps))
1343         tmps++;
1344     if (*tmps == '0')
1345         tmps++;
1346     if (*tmps == 'x')
1347         value = scan_hex(++tmps, 99, &argtype);
1348     else
1349         value = scan_oct(tmps, 99, &argtype);
1350     if ((IV)value >= 0)
1351         XPUSHi(value);
1352     else
1353         XPUSHn(U_V(value));
1354     RETURN;
1355 }
1356
1357 /* String stuff. */
1358
1359 PP(pp_length)
1360 {
1361     dSP; dTARGET;
1362     SETi( sv_len(TOPs) );
1363     RETURN;
1364 }
1365
1366 PP(pp_substr)
1367 {
1368     dSP; dTARGET;
1369     SV *sv;
1370     I32 len;
1371     STRLEN curlen;
1372     I32 pos;
1373     I32 rem;
1374     I32 lvalue = op->op_flags & OPf_MOD;
1375     char *tmps;
1376     I32 arybase = curcop->cop_arybase;
1377
1378     if (MAXARG > 2)
1379         len = POPi;
1380     pos = POPi - arybase;
1381     sv = POPs;
1382     tmps = SvPV(sv, curlen);
1383     if (pos < 0)
1384         pos += curlen + arybase;
1385     if (pos < 0 || pos > curlen) {
1386         if (dowarn || lvalue)
1387             warn("substr outside of string");
1388         RETPUSHUNDEF;
1389     }
1390     else {
1391         if (MAXARG < 3)
1392             len = curlen;
1393         else if (len < 0) {
1394             len += curlen - pos;
1395             if (len < 0)
1396                 len = 0;
1397         }
1398         tmps += pos;
1399         rem = curlen - pos;     /* rem=how many bytes left*/
1400         if (rem > len)
1401             rem = len;
1402         sv_setpvn(TARG, tmps, rem);
1403         if (lvalue) {                   /* it's an lvalue! */
1404             if (!SvGMAGICAL(sv))
1405                 (void)SvPOK_only(sv);
1406             if (SvTYPE(TARG) < SVt_PVLV) {
1407                 sv_upgrade(TARG, SVt_PVLV);
1408                 sv_magic(TARG, Nullsv, 'x', Nullch, 0);
1409             }
1410
1411             LvTYPE(TARG) = 's';
1412             LvTARG(TARG) = sv;
1413             LvTARGOFF(TARG) = pos;
1414             LvTARGLEN(TARG) = rem; 
1415         }
1416     }
1417     PUSHs(TARG);                /* avoid SvSETMAGIC here */
1418     RETURN;
1419 }
1420
1421 PP(pp_vec)
1422 {
1423     dSP; dTARGET;
1424     register I32 size = POPi;
1425     register I32 offset = POPi;
1426     register SV *src = POPs;
1427     I32 lvalue = op->op_flags & OPf_MOD;
1428     STRLEN srclen;
1429     unsigned char *s = (unsigned char*)SvPV(src, srclen);
1430     unsigned long retnum;
1431     I32 len;
1432
1433     offset *= size;             /* turn into bit offset */
1434     len = (offset + size + 7) / 8;
1435     if (offset < 0 || size < 1)
1436         retnum = 0;
1437     else {
1438         if (lvalue) {                      /* it's an lvalue! */
1439             if (SvTYPE(TARG) < SVt_PVLV) {
1440                 sv_upgrade(TARG, SVt_PVLV);
1441                 sv_magic(TARG, Nullsv, 'v', Nullch, 0);
1442             }
1443
1444             LvTYPE(TARG) = 'v';
1445             LvTARG(TARG) = src;
1446             LvTARGOFF(TARG) = offset; 
1447             LvTARGLEN(TARG) = size; 
1448         }
1449         if (len > srclen) {
1450             if (size <= 8)
1451                 retnum = 0;
1452             else {
1453                 offset >>= 3;
1454                 if (size == 16) {
1455                     if (offset >= srclen)
1456                         retnum = 0;
1457                     else
1458                         retnum = (unsigned long) s[offset] << 8;
1459                 }
1460                 else if (size == 32) {
1461                     if (offset >= srclen)
1462                         retnum = 0;
1463                     else if (offset + 1 >= srclen)
1464                         retnum = (unsigned long) s[offset] << 24;
1465                     else if (offset + 2 >= srclen)
1466                         retnum = ((unsigned long) s[offset] << 24) +
1467                             ((unsigned long) s[offset + 1] << 16);
1468                     else
1469                         retnum = ((unsigned long) s[offset] << 24) +
1470                             ((unsigned long) s[offset + 1] << 16) +
1471                             (s[offset + 2] << 8);
1472                 }
1473             }
1474         }
1475         else if (size < 8)
1476             retnum = (s[offset >> 3] >> (offset & 7)) & ((1 << size) - 1);
1477         else {
1478             offset >>= 3;
1479             if (size == 8)
1480                 retnum = s[offset];
1481             else if (size == 16)
1482                 retnum = ((unsigned long) s[offset] << 8) + s[offset+1];
1483             else if (size == 32)
1484                 retnum = ((unsigned long) s[offset] << 24) +
1485                         ((unsigned long) s[offset + 1] << 16) +
1486                         (s[offset + 2] << 8) + s[offset+3];
1487         }
1488     }
1489
1490     sv_setiv(TARG, (I32)retnum);
1491     PUSHs(TARG);
1492     RETURN;
1493 }
1494
1495 PP(pp_index)
1496 {
1497     dSP; dTARGET;
1498     SV *big;
1499     SV *little;
1500     I32 offset;
1501     I32 retval;
1502     char *tmps;
1503     char *tmps2;
1504     STRLEN biglen;
1505     I32 arybase = curcop->cop_arybase;
1506
1507     if (MAXARG < 3)
1508         offset = 0;
1509     else
1510         offset = POPi - arybase;
1511     little = POPs;
1512     big = POPs;
1513     tmps = SvPV(big, biglen);
1514     if (offset < 0)
1515         offset = 0;
1516     else if (offset > biglen)
1517         offset = biglen;
1518     if (!(tmps2 = fbm_instr((unsigned char*)tmps + offset,
1519       (unsigned char*)tmps + biglen, little)))
1520         retval = -1 + arybase;
1521     else
1522         retval = tmps2 - tmps + arybase;
1523     PUSHi(retval);
1524     RETURN;
1525 }
1526
1527 PP(pp_rindex)
1528 {
1529     dSP; dTARGET;
1530     SV *big;
1531     SV *little;
1532     STRLEN blen;
1533     STRLEN llen;
1534     SV *offstr;
1535     I32 offset;
1536     I32 retval;
1537     char *tmps;
1538     char *tmps2;
1539     I32 arybase = curcop->cop_arybase;
1540
1541     if (MAXARG >= 3)
1542         offstr = POPs;
1543     little = POPs;
1544     big = POPs;
1545     tmps2 = SvPV(little, llen);
1546     tmps = SvPV(big, blen);
1547     if (MAXARG < 3)
1548         offset = blen;
1549     else
1550         offset = SvIV(offstr) - arybase + llen;
1551     if (offset < 0)
1552         offset = 0;
1553     else if (offset > blen)
1554         offset = blen;
1555     if (!(tmps2 = rninstr(tmps,  tmps  + offset,
1556                           tmps2, tmps2 + llen)))
1557         retval = -1 + arybase;
1558     else
1559         retval = tmps2 - tmps + arybase;
1560     PUSHi(retval);
1561     RETURN;
1562 }
1563
1564 PP(pp_sprintf)
1565 {
1566     dSP; dMARK; dORIGMARK; dTARGET;
1567     do_sprintf(TARG, SP-MARK, MARK+1);
1568     SP = ORIGMARK;
1569     PUSHTARG;
1570     RETURN;
1571 }
1572
1573 PP(pp_ord)
1574 {
1575     dSP; dTARGET;
1576     I32 value;
1577     char *tmps;
1578
1579 #ifndef I286
1580     tmps = POPp;
1581     value = (I32) (*tmps & 255);
1582 #else
1583     I32 anum;
1584     tmps = POPp;
1585     anum = (I32) *tmps;
1586     value = (I32) (anum & 255);
1587 #endif
1588     XPUSHi(value);
1589     RETURN;
1590 }
1591
1592 PP(pp_chr)
1593 {
1594     dSP; dTARGET;
1595     char *tmps;
1596
1597     (void)SvUPGRADE(TARG,SVt_PV);
1598     SvGROW(TARG,2);
1599     SvCUR_set(TARG, 1);
1600     tmps = SvPVX(TARG);
1601     *tmps++ = POPi;
1602     *tmps = '\0';
1603     (void)SvPOK_only(TARG);
1604     XPUSHs(TARG);
1605     RETURN;
1606 }
1607
1608 PP(pp_crypt)
1609 {
1610     dSP; dTARGET; dPOPTOPssrl;
1611 #ifdef HAS_CRYPT
1612     char *tmps = SvPV(left, na);
1613 #ifdef FCRYPT
1614     sv_setpv(TARG, fcrypt(tmps, SvPV(right, na)));
1615 #else
1616     sv_setpv(TARG, crypt(tmps, SvPV(right, na)));
1617 #endif
1618 #else
1619     DIE(
1620       "The crypt() function is unimplemented due to excessive paranoia.");
1621 #endif
1622     SETs(TARG);
1623     RETURN;
1624 }
1625
1626 PP(pp_ucfirst)
1627 {
1628     dSP;
1629     SV *sv = TOPs;
1630     register char *s;
1631
1632     if (!SvPADTMP(sv)) {
1633         dTARGET;
1634         sv_setsv(TARG, sv);
1635         sv = TARG;
1636         SETs(sv);
1637     }
1638     s = SvPV_force(sv, na);
1639     if (isLOWER(*s))
1640         *s = toUPPER(*s);
1641
1642     RETURN;
1643 }
1644
1645 PP(pp_lcfirst)
1646 {
1647     dSP;
1648     SV *sv = TOPs;
1649     register char *s;
1650
1651     if (!SvPADTMP(sv)) {
1652         dTARGET;
1653         sv_setsv(TARG, sv);
1654         sv = TARG;
1655         SETs(sv);
1656     }
1657     s = SvPV_force(sv, na);
1658     if (isUPPER(*s))
1659         *s = toLOWER(*s);
1660
1661     SETs(sv);
1662     RETURN;
1663 }
1664
1665 PP(pp_uc)
1666 {
1667     dSP;
1668     SV *sv = TOPs;
1669     register char *s;
1670     register char *send;
1671     STRLEN len;
1672
1673     if (!SvPADTMP(sv)) {
1674         dTARGET;
1675         sv_setsv(TARG, sv);
1676         sv = TARG;
1677         SETs(sv);
1678     }
1679     s = SvPV_force(sv, len);
1680     send = s + len;
1681     while (s < send) {
1682         if (isLOWER(*s))
1683             *s = toUPPER(*s);
1684         s++;
1685     }
1686     RETURN;
1687 }
1688
1689 PP(pp_lc)
1690 {
1691     dSP;
1692     SV *sv = TOPs;
1693     register char *s;
1694     register char *send;
1695     STRLEN len;
1696
1697     if (!SvPADTMP(sv)) {
1698         dTARGET;
1699         sv_setsv(TARG, sv);
1700         sv = TARG;
1701         SETs(sv);
1702     }
1703     s = SvPV_force(sv, len);
1704     send = s + len;
1705     while (s < send) {
1706         if (isUPPER(*s))
1707             *s = toLOWER(*s);
1708         s++;
1709     }
1710     RETURN;
1711 }
1712
1713 PP(pp_quotemeta)
1714 {
1715     dSP; dTARGET;
1716     SV *sv = TOPs;
1717     STRLEN len;
1718     register char *s = SvPV(sv,len);
1719     register char *d;
1720
1721     if (len) {
1722         (void)SvUPGRADE(TARG, SVt_PV);
1723         SvGROW(TARG, (len * 2) + 1);
1724         d = SvPVX(TARG);
1725         while (len--) {
1726             if (!isALNUM(*s))
1727                 *d++ = '\\';
1728             *d++ = *s++;
1729         }
1730         *d = '\0';
1731         SvCUR_set(TARG, d - SvPVX(TARG));
1732         (void)SvPOK_only(TARG);
1733     }
1734     else
1735         sv_setpvn(TARG, s, len);
1736     SETs(TARG);
1737     RETURN;
1738 }
1739
1740 /* Arrays. */
1741
1742 PP(pp_aslice)
1743 {
1744     dSP; dMARK; dORIGMARK;
1745     register SV** svp;
1746     register AV* av = (AV*)POPs;
1747     register I32 lval = op->op_flags & OPf_MOD;
1748     I32 arybase = curcop->cop_arybase;
1749     I32 elem;
1750
1751     if (SvTYPE(av) == SVt_PVAV) {
1752         if (lval && op->op_private & OPpLVAL_INTRO) {
1753             I32 max = -1;
1754             for (svp = mark + 1; svp <= sp; svp++) {
1755                 elem = SvIVx(*svp);
1756                 if (elem > max)
1757                     max = elem;
1758             }
1759             if (max > AvMAX(av))
1760                 av_extend(av, max);
1761         }
1762         while (++MARK <= SP) {
1763             elem = SvIVx(*MARK);
1764
1765             if (elem > 0)
1766                 elem -= arybase;
1767             svp = av_fetch(av, elem, lval);
1768             if (lval) {
1769                 if (!svp || *svp == &sv_undef)
1770                     DIE(no_aelem, elem);
1771                 if (op->op_private & OPpLVAL_INTRO)
1772                     save_svref(svp);
1773             }
1774             *MARK = svp ? *svp : &sv_undef;
1775         }
1776     }
1777     if (GIMME != G_ARRAY) {
1778         MARK = ORIGMARK;
1779         *++MARK = *SP;
1780         SP = MARK;
1781     }
1782     RETURN;
1783 }
1784
1785 /* Associative arrays. */
1786
1787 PP(pp_each)
1788 {
1789     dSP; dTARGET;
1790     HV *hash = (HV*)POPs;
1791     HE *entry;
1792     I32 i;
1793     char *tmps;
1794     I32 realhv = (SvTYPE(hash) == SVt_PVHV);
1795     
1796     PUTBACK;
1797     /* might clobber stack_sp */
1798     entry = realhv ? hv_iternext(hash) : avhv_iternext((AV*)hash);
1799     SPAGAIN;
1800
1801     EXTEND(SP, 2);
1802     if (entry) {
1803         tmps = hv_iterkey(entry, &i);              /* won't clobber stack_sp */
1804         if (!i)
1805             tmps = "";
1806         PUSHs(sv_2mortal(newSVpv(tmps, i)));
1807         if (GIMME == G_ARRAY) {
1808             PUTBACK;
1809             /* might clobber stack_sp */
1810             sv_setsv(TARG, realhv ?
1811                      hv_iterval(hash, entry) : avhv_iterval((AV*)hash, entry));
1812             SPAGAIN;
1813             PUSHs(TARG);
1814         }
1815     }
1816     else if (GIMME == G_SCALAR)
1817         RETPUSHUNDEF;
1818
1819     RETURN;
1820 }
1821
1822 PP(pp_values)
1823 {
1824     return do_kv(ARGS);
1825 }
1826
1827 PP(pp_keys)
1828 {
1829     return do_kv(ARGS);
1830 }
1831
1832 PP(pp_delete)
1833 {
1834     dSP;
1835     SV *sv;
1836     SV *tmpsv = POPs;
1837     HV *hv = (HV*)POPs;
1838     char *tmps;
1839     STRLEN len;
1840     I32 flags = op->op_private & OPpLEAVE_VOID ? G_DISCARD : 0;
1841     
1842     tmps = SvPV(tmpsv, len);
1843     if (SvTYPE(hv) == SVt_PVHV)
1844         sv = hv_delete(hv, tmps, len, flags);
1845     else if (SvTYPE(hv) == SVt_PVAV) {
1846         sv = avhv_delete((AV*)hv, tmps, len, flags);
1847     } else {
1848         DIE("Not a HASH reference");
1849     }
1850     if (!sv)
1851         RETPUSHUNDEF;
1852     PUSHs(sv);
1853     RETURN;
1854 }
1855
1856 PP(pp_exists)
1857 {
1858     dSP;
1859     SV *tmpsv = POPs;
1860     HV *hv = (HV*)POPs;
1861     char *tmps;
1862     STRLEN len;
1863     tmps = SvPV(tmpsv, len);
1864     if (SvTYPE(hv) == SVt_PVHV) {
1865         if (hv_exists(hv, tmps, len))
1866             RETPUSHYES;
1867     } else if (SvTYPE(hv) == SVt_PVAV) {
1868         if (avhv_exists((AV*)hv, tmps, len))
1869             RETPUSHYES;
1870     } else {
1871         DIE("Not a HASH reference");
1872     }
1873     RETPUSHNO;
1874 }
1875
1876 PP(pp_hslice)
1877 {
1878     dSP; dMARK; dORIGMARK;
1879     register SV **svp;
1880     register HV *hv = (HV*)POPs;
1881     register I32 lval = op->op_flags & OPf_MOD;
1882     I32 realhv = (SvTYPE(hv) == SVt_PVHV);
1883
1884     if (realhv || SvTYPE(hv) == SVt_PVAV) {
1885         while (++MARK <= SP) {
1886             STRLEN keylen;
1887             char *key = SvPV(*MARK, keylen);
1888
1889             svp = realhv ? hv_fetch(hv, key, keylen, lval)
1890                 : avhv_fetch((AV*)hv, key, keylen, lval);
1891             if (lval) {
1892                 if (!svp || *svp == &sv_undef)
1893                     DIE(no_helem, key);
1894                 if (op->op_private & OPpLVAL_INTRO)
1895                     save_svref(svp);
1896             }
1897             *MARK = svp ? *svp : &sv_undef;
1898         }
1899     }
1900     if (GIMME != G_ARRAY) {
1901         MARK = ORIGMARK;
1902         *++MARK = *SP;
1903         SP = MARK;
1904     }
1905     RETURN;
1906 }
1907
1908 /* List operators. */
1909
1910 PP(pp_list)
1911 {
1912     dSP; dMARK;
1913     if (GIMME != G_ARRAY) {
1914         if (++MARK <= SP)
1915             *MARK = *SP;                /* unwanted list, return last item */
1916         else
1917             *MARK = &sv_undef;
1918         SP = MARK;
1919     }
1920     RETURN;
1921 }
1922
1923 PP(pp_lslice)
1924 {
1925     dSP;
1926     SV **lastrelem = stack_sp;
1927     SV **lastlelem = stack_base + POPMARK;
1928     SV **firstlelem = stack_base + POPMARK + 1;
1929     register SV **firstrelem = lastlelem + 1;
1930     I32 arybase = curcop->cop_arybase;
1931     I32 lval = op->op_flags & OPf_MOD;
1932     I32 is_something_there = lval;
1933
1934     register I32 max = lastrelem - lastlelem;
1935     register SV **lelem;
1936     register I32 ix;
1937
1938     if (GIMME != G_ARRAY) {
1939         ix = SvIVx(*lastlelem);
1940         if (ix < 0)
1941             ix += max;
1942         else
1943             ix -= arybase;
1944         if (ix < 0 || ix >= max)
1945             *firstlelem = &sv_undef;
1946         else
1947             *firstlelem = firstrelem[ix];
1948         SP = firstlelem;
1949         RETURN;
1950     }
1951
1952     if (max == 0) {
1953         SP = firstlelem - 1;
1954         RETURN;
1955     }
1956
1957     for (lelem = firstlelem; lelem <= lastlelem; lelem++) {
1958         ix = SvIVx(*lelem);
1959         if (ix < 0) {
1960             ix += max;
1961             if (ix < 0)
1962                 *lelem = &sv_undef;
1963             else if (!(*lelem = firstrelem[ix]))
1964                 *lelem = &sv_undef;
1965         }
1966         else {
1967             ix -= arybase;
1968             if (ix >= max || !(*lelem = firstrelem[ix]))
1969                 *lelem = &sv_undef;
1970         }
1971         if (!is_something_there && (SvOKp(*lelem) || SvGMAGICAL(*lelem)))
1972             is_something_there = TRUE;
1973     }
1974     if (is_something_there)
1975         SP = lastlelem;
1976     else
1977         SP = firstlelem - 1;
1978     RETURN;
1979 }
1980
1981 PP(pp_anonlist)
1982 {
1983     dSP; dMARK;
1984     I32 items = SP - MARK;
1985     SP = MARK;
1986     XPUSHs((SV*)sv_2mortal((SV*)av_make(items, MARK+1)));
1987     RETURN;
1988 }
1989
1990 PP(pp_anonhash)
1991 {
1992     dSP; dMARK; dORIGMARK;
1993     STRLEN len;
1994     HV* hv = (HV*)sv_2mortal((SV*)newHV());
1995
1996     while (MARK < SP) {
1997         SV* key = *++MARK;
1998         char *tmps;
1999         SV *val = NEWSV(46, 0);
2000         if (MARK < SP)
2001             sv_setsv(val, *++MARK);
2002         else
2003             warn("Odd number of elements in hash list");
2004         tmps = SvPV(key,len);
2005         (void)hv_store(hv,tmps,len,val,0);
2006     }
2007     SP = ORIGMARK;
2008     XPUSHs((SV*)hv);
2009     RETURN;
2010 }
2011
2012 PP(pp_splice)
2013 {
2014     dSP; dMARK; dORIGMARK;
2015     register AV *ary = (AV*)*++MARK;
2016     register SV **src;
2017     register SV **dst;
2018     register I32 i;
2019     register I32 offset;
2020     register I32 length;
2021     I32 newlen;
2022     I32 after;
2023     I32 diff;
2024     SV **tmparyval = 0;
2025
2026     SP++;
2027
2028     if (++MARK < SP) {
2029         offset = SvIVx(*MARK);
2030         if (offset < 0)
2031             offset += AvFILL(ary) + 1;
2032         else
2033             offset -= curcop->cop_arybase;
2034         if (++MARK < SP) {
2035             length = SvIVx(*MARK++);
2036             if (length < 0)
2037                 length = 0;
2038         }
2039         else
2040             length = AvMAX(ary) + 1;            /* close enough to infinity */
2041     }
2042     else {
2043         offset = 0;
2044         length = AvMAX(ary) + 1;
2045     }
2046     if (offset < 0) {
2047         length += offset;
2048         offset = 0;
2049         if (length < 0)
2050             length = 0;
2051     }
2052     if (offset > AvFILL(ary) + 1)
2053         offset = AvFILL(ary) + 1;
2054     after = AvFILL(ary) + 1 - (offset + length);
2055     if (after < 0) {                            /* not that much array */
2056         length += after;                        /* offset+length now in array */
2057         after = 0;
2058         if (!AvALLOC(ary))
2059             av_extend(ary, 0);
2060     }
2061
2062     /* At this point, MARK .. SP-1 is our new LIST */
2063
2064     newlen = SP - MARK;
2065     diff = newlen - length;
2066
2067     if (diff < 0) {                             /* shrinking the area */
2068         if (newlen) {
2069             New(451, tmparyval, newlen, SV*);   /* so remember insertion */
2070             Copy(MARK, tmparyval, newlen, SV*);
2071         }
2072
2073         MARK = ORIGMARK + 1;
2074         if (GIMME == G_ARRAY) {                 /* copy return vals to stack */
2075             MEXTEND(MARK, length);
2076             Copy(AvARRAY(ary)+offset, MARK, length, SV*);
2077             if (AvREAL(ary)) {
2078                 for (i = length, dst = MARK; i; i--)
2079                     sv_2mortal(*dst++); /* free them eventualy */
2080             }
2081             MARK += length - 1;
2082         }
2083         else {
2084             *MARK = AvARRAY(ary)[offset+length-1];
2085             if (AvREAL(ary)) {
2086                 sv_2mortal(*MARK);
2087                 for (i = length - 1, dst = &AvARRAY(ary)[offset]; i > 0; i--)
2088                     SvREFCNT_dec(*dst++);       /* free them now */
2089             }
2090         }
2091         AvFILL(ary) += diff;
2092
2093         /* pull up or down? */
2094
2095         if (offset < after) {                   /* easier to pull up */
2096             if (offset) {                       /* esp. if nothing to pull */
2097                 src = &AvARRAY(ary)[offset-1];
2098                 dst = src - diff;               /* diff is negative */
2099                 for (i = offset; i > 0; i--)    /* can't trust Copy */
2100                     *dst-- = *src--;
2101             }
2102             dst = AvARRAY(ary);
2103             SvPVX(ary) = (char*)(AvARRAY(ary) - diff); /* diff is negative */
2104             AvMAX(ary) += diff;
2105         }
2106         else {
2107             if (after) {                        /* anything to pull down? */
2108                 src = AvARRAY(ary) + offset + length;
2109                 dst = src + diff;               /* diff is negative */
2110                 Move(src, dst, after, SV*);
2111             }
2112             dst = &AvARRAY(ary)[AvFILL(ary)+1];
2113                                                 /* avoid later double free */
2114         }
2115         i = -diff;
2116         while (i)
2117             dst[--i] = &sv_undef;
2118         
2119         if (newlen) {
2120             for (src = tmparyval, dst = AvARRAY(ary) + offset;
2121               newlen; newlen--) {
2122                 *dst = NEWSV(46, 0);
2123                 sv_setsv(*dst++, *src++);
2124             }
2125             Safefree(tmparyval);
2126         }
2127     }
2128     else {                                      /* no, expanding (or same) */
2129         if (length) {
2130             New(452, tmparyval, length, SV*);   /* so remember deletion */
2131             Copy(AvARRAY(ary)+offset, tmparyval, length, SV*);
2132         }
2133
2134         if (diff > 0) {                         /* expanding */
2135
2136             /* push up or down? */
2137
2138             if (offset < after && diff <= AvARRAY(ary) - AvALLOC(ary)) {
2139                 if (offset) {
2140                     src = AvARRAY(ary);
2141                     dst = src - diff;
2142                     Move(src, dst, offset, SV*);
2143                 }
2144                 SvPVX(ary) = (char*)(AvARRAY(ary) - diff);/* diff is positive */
2145                 AvMAX(ary) += diff;
2146                 AvFILL(ary) += diff;
2147             }
2148             else {
2149                 if (AvFILL(ary) + diff >= AvMAX(ary))   /* oh, well */
2150                     av_extend(ary, AvFILL(ary) + diff);
2151                 AvFILL(ary) += diff;
2152
2153                 if (after) {
2154                     dst = AvARRAY(ary) + AvFILL(ary);
2155                     src = dst - diff;
2156                     for (i = after; i; i--) {
2157                         *dst-- = *src--;
2158                     }
2159                 }
2160             }
2161         }
2162
2163         for (src = MARK, dst = AvARRAY(ary) + offset; newlen; newlen--) {
2164             *dst = NEWSV(46, 0);
2165             sv_setsv(*dst++, *src++);
2166         }
2167         MARK = ORIGMARK + 1;
2168         if (GIMME == G_ARRAY) {                 /* copy return vals to stack */
2169             if (length) {
2170                 Copy(tmparyval, MARK, length, SV*);
2171                 if (AvREAL(ary)) {
2172                     for (i = length, dst = MARK; i; i--)
2173                         sv_2mortal(*dst++);     /* free them eventualy */
2174                 }
2175                 Safefree(tmparyval);
2176             }
2177             MARK += length - 1;
2178         }
2179         else if (length--) {
2180             *MARK = tmparyval[length];
2181             if (AvREAL(ary)) {
2182                 sv_2mortal(*MARK);
2183                 while (length-- > 0)
2184                     SvREFCNT_dec(tmparyval[length]);
2185             }
2186             Safefree(tmparyval);
2187         }
2188         else
2189             *MARK = &sv_undef;
2190     }
2191     SP = MARK;
2192     RETURN;
2193 }
2194
2195 PP(pp_push)
2196 {
2197     dSP; dMARK; dORIGMARK; dTARGET;
2198     register AV *ary = (AV*)*++MARK;
2199     register SV *sv = &sv_undef;
2200
2201     for (++MARK; MARK <= SP; MARK++) {
2202         sv = NEWSV(51, 0);
2203         if (*MARK)
2204             sv_setsv(sv, *MARK);
2205         av_push(ary, sv);
2206     }
2207     SP = ORIGMARK;
2208     PUSHi( AvFILL(ary) + 1 );
2209     RETURN;
2210 }
2211
2212 PP(pp_pop)
2213 {
2214     dSP;
2215     AV *av = (AV*)POPs;
2216     SV *sv = av_pop(av);
2217     if (sv != &sv_undef && AvREAL(av))
2218         (void)sv_2mortal(sv);
2219     PUSHs(sv);
2220     RETURN;
2221 }
2222
2223 PP(pp_shift)
2224 {
2225     dSP;
2226     AV *av = (AV*)POPs;
2227     SV *sv = av_shift(av);
2228     EXTEND(SP, 1);
2229     if (!sv)
2230         RETPUSHUNDEF;
2231     if (sv != &sv_undef && AvREAL(av))
2232         (void)sv_2mortal(sv);
2233     PUSHs(sv);
2234     RETURN;
2235 }
2236
2237 PP(pp_unshift)
2238 {
2239     dSP; dMARK; dORIGMARK; dTARGET;
2240     register AV *ary = (AV*)*++MARK;
2241     register SV *sv;
2242     register I32 i = 0;
2243
2244     av_unshift(ary, SP - MARK);
2245     while (MARK < SP) {
2246         sv = NEWSV(27, 0);
2247         sv_setsv(sv, *++MARK);
2248         (void)av_store(ary, i++, sv);
2249     }
2250
2251     SP = ORIGMARK;
2252     PUSHi( AvFILL(ary) + 1 );
2253     RETURN;
2254 }
2255
2256 PP(pp_reverse)
2257 {
2258     dSP; dMARK;
2259     register SV *tmp;
2260     SV **oldsp = SP;
2261
2262     if (GIMME == G_ARRAY) {
2263         MARK++;
2264         while (MARK < SP) {
2265             tmp = *MARK;
2266             *MARK++ = *SP;
2267             *SP-- = tmp;
2268         }
2269         SP = oldsp;
2270     }
2271     else {
2272         register char *up;
2273         register char *down;
2274         register I32 tmp;
2275         dTARGET;
2276         STRLEN len;
2277
2278         if (SP - MARK > 1)
2279             do_join(TARG, &sv_no, MARK, SP);
2280         else
2281             sv_setsv(TARG, *SP);
2282         up = SvPV_force(TARG, len);
2283         if (len > 1) {
2284             down = SvPVX(TARG) + len - 1;
2285             while (down > up) {
2286                 tmp = *up;
2287                 *up++ = *down;
2288                 *down-- = tmp;
2289             }
2290             (void)SvPOK_only(TARG);
2291         }
2292         SP = MARK + 1;
2293         SETTARG;
2294     }
2295     RETURN;
2296 }
2297
2298 /* Explosives and implosives. */
2299
2300 PP(pp_unpack)
2301 {
2302     dSP;
2303     dPOPPOPssrl;
2304     SV *sv;
2305     STRLEN llen;
2306     STRLEN rlen;
2307     register char *pat = SvPV(left, llen);
2308     register char *s = SvPV(right, rlen);
2309     char *strend = s + rlen;
2310     char *strbeg = s;
2311     register char *patend = pat + llen;
2312     I32 datumtype;
2313     register I32 len;
2314     register I32 bits;
2315
2316     /* These must not be in registers: */
2317     I16 ashort;
2318     int aint;
2319     I32 along;
2320 #ifdef HAS_QUAD
2321     Quad_t aquad;
2322 #endif
2323     U16 aushort;
2324     unsigned int auint;
2325     U32 aulong;
2326 #ifdef HAS_QUAD
2327     unsigned Quad_t auquad;
2328 #endif
2329     char *aptr;
2330     float afloat;
2331     double adouble;
2332     I32 checksum = 0;
2333     register U32 culong;
2334     double cdouble;
2335     static char* bitcount = 0;
2336
2337     if (GIMME != G_ARRAY) {             /* arrange to do first one only */
2338         /*SUPPRESS 530*/
2339         for (patend = pat; !isALPHA(*patend) || *patend == 'x'; patend++) ;
2340         if (strchr("aAbBhHP", *patend) || *pat == '%') {
2341             patend++;
2342             while (isDIGIT(*patend) || *patend == '*')
2343                 patend++;
2344         }
2345         else
2346             patend++;
2347     }
2348     while (pat < patend) {
2349       reparse:
2350         datumtype = *pat++;
2351         if (pat >= patend)
2352             len = 1;
2353         else if (*pat == '*') {
2354             len = strend - strbeg;      /* long enough */
2355             pat++;
2356         }
2357         else if (isDIGIT(*pat)) {
2358             len = *pat++ - '0';
2359             while (isDIGIT(*pat))
2360                 len = (len * 10) + (*pat++ - '0');
2361         }
2362         else
2363             len = (datumtype != '@');
2364         switch(datumtype) {
2365         default:
2366             break;
2367         case '%':
2368             if (len == 1 && pat[-1] != '1')
2369                 len = 16;
2370             checksum = len;
2371             culong = 0;
2372             cdouble = 0;
2373             if (pat < patend)
2374                 goto reparse;
2375             break;
2376         case '@':
2377             if (len > strend - strbeg)
2378                 DIE("@ outside of string");
2379             s = strbeg + len;
2380             break;
2381         case 'X':
2382             if (len > s - strbeg)
2383                 DIE("X outside of string");
2384             s -= len;
2385             break;
2386         case 'x':
2387             if (len > strend - s)
2388                 DIE("x outside of string");
2389             s += len;
2390             break;
2391         case 'A':
2392         case 'a':
2393             if (len > strend - s)
2394                 len = strend - s;
2395             if (checksum)
2396                 goto uchar_checksum;
2397             sv = NEWSV(35, len);
2398             sv_setpvn(sv, s, len);
2399             s += len;
2400             if (datumtype == 'A') {
2401                 aptr = s;       /* borrow register */
2402                 s = SvPVX(sv) + len - 1;
2403                 while (s >= SvPVX(sv) && (!*s || isSPACE(*s)))
2404                     s--;
2405                 *++s = '\0';
2406                 SvCUR_set(sv, s - SvPVX(sv));
2407                 s = aptr;       /* unborrow register */
2408             }
2409             XPUSHs(sv_2mortal(sv));
2410             break;
2411         case 'B':
2412         case 'b':
2413             if (pat[-1] == '*' || len > (strend - s) * 8)
2414                 len = (strend - s) * 8;
2415             if (checksum) {
2416                 if (!bitcount) {
2417                     Newz(601, bitcount, 256, char);
2418                     for (bits = 1; bits < 256; bits++) {
2419                         if (bits & 1)   bitcount[bits]++;
2420                         if (bits & 2)   bitcount[bits]++;
2421                         if (bits & 4)   bitcount[bits]++;
2422                         if (bits & 8)   bitcount[bits]++;
2423                         if (bits & 16)  bitcount[bits]++;
2424                         if (bits & 32)  bitcount[bits]++;
2425                         if (bits & 64)  bitcount[bits]++;
2426                         if (bits & 128) bitcount[bits]++;
2427                     }
2428                 }
2429                 while (len >= 8) {
2430                     culong += bitcount[*(unsigned char*)s++];
2431                     len -= 8;
2432                 }
2433                 if (len) {
2434                     bits = *s;
2435                     if (datumtype == 'b') {
2436                         while (len-- > 0) {
2437                             if (bits & 1) culong++;
2438                             bits >>= 1;
2439                         }
2440                     }
2441                     else {
2442                         while (len-- > 0) {
2443                             if (bits & 128) culong++;
2444                             bits <<= 1;
2445                         }
2446                     }
2447                 }
2448                 break;
2449             }
2450             sv = NEWSV(35, len + 1);
2451             SvCUR_set(sv, len);
2452             SvPOK_on(sv);
2453             aptr = pat;                 /* borrow register */
2454             pat = SvPVX(sv);
2455             if (datumtype == 'b') {
2456                 aint = len;
2457                 for (len = 0; len < aint; len++) {
2458                     if (len & 7)                /*SUPPRESS 595*/
2459                         bits >>= 1;
2460                     else
2461                         bits = *s++;
2462                     *pat++ = '0' + (bits & 1);
2463                 }
2464             }
2465             else {
2466                 aint = len;
2467                 for (len = 0; len < aint; len++) {
2468                     if (len & 7)
2469                         bits <<= 1;
2470                     else
2471                         bits = *s++;
2472                     *pat++ = '0' + ((bits & 128) != 0);
2473                 }
2474             }
2475             *pat = '\0';
2476             pat = aptr;                 /* unborrow register */
2477             XPUSHs(sv_2mortal(sv));
2478             break;
2479         case 'H':
2480         case 'h':
2481             if (pat[-1] == '*' || len > (strend - s) * 2)
2482                 len = (strend - s) * 2;
2483             sv = NEWSV(35, len + 1);
2484             SvCUR_set(sv, len);
2485             SvPOK_on(sv);
2486             aptr = pat;                 /* borrow register */
2487             pat = SvPVX(sv);
2488             if (datumtype == 'h') {
2489                 aint = len;
2490                 for (len = 0; len < aint; len++) {
2491                     if (len & 1)
2492                         bits >>= 4;
2493                     else
2494                         bits = *s++;
2495                     *pat++ = hexdigit[bits & 15];
2496                 }
2497             }
2498             else {
2499                 aint = len;
2500                 for (len = 0; len < aint; len++) {
2501                     if (len & 1)
2502                         bits <<= 4;
2503                     else
2504                         bits = *s++;
2505                     *pat++ = hexdigit[(bits >> 4) & 15];
2506                 }
2507             }
2508             *pat = '\0';
2509             pat = aptr;                 /* unborrow register */
2510             XPUSHs(sv_2mortal(sv));
2511             break;
2512         case 'c':
2513             if (len > strend - s)
2514                 len = strend - s;
2515             if (checksum) {
2516                 while (len-- > 0) {
2517                     aint = *s++;
2518                     if (aint >= 128)    /* fake up signed chars */
2519                         aint -= 256;
2520                     culong += aint;
2521                 }
2522             }
2523             else {
2524                 EXTEND(SP, len);
2525                 while (len-- > 0) {
2526                     aint = *s++;
2527                     if (aint >= 128)    /* fake up signed chars */
2528                         aint -= 256;
2529                     sv = NEWSV(36, 0);
2530                     sv_setiv(sv, (I32)aint);
2531                     PUSHs(sv_2mortal(sv));
2532                 }
2533             }
2534             break;
2535         case 'C':
2536             if (len > strend - s)
2537                 len = strend - s;
2538             if (checksum) {
2539               uchar_checksum:
2540                 while (len-- > 0) {
2541                     auint = *s++ & 255;
2542                     culong += auint;
2543                 }
2544             }
2545             else {
2546                 EXTEND(SP, len);
2547                 while (len-- > 0) {
2548                     auint = *s++ & 255;
2549                     sv = NEWSV(37, 0);
2550                     sv_setiv(sv, (I32)auint);
2551                     PUSHs(sv_2mortal(sv));
2552                 }
2553             }
2554             break;
2555         case 's':
2556             along = (strend - s) / sizeof(I16);
2557             if (len > along)
2558                 len = along;
2559             if (checksum) {
2560                 while (len-- > 0) {
2561                     Copy(s, &ashort, 1, I16);
2562                     s += sizeof(I16);
2563                     culong += ashort;
2564                 }
2565             }
2566             else {
2567                 EXTEND(SP, len);
2568                 while (len-- > 0) {
2569                     Copy(s, &ashort, 1, I16);
2570                     s += sizeof(I16);
2571                     sv = NEWSV(38, 0);
2572                     sv_setiv(sv, (I32)ashort);
2573                     PUSHs(sv_2mortal(sv));
2574                 }
2575             }
2576             break;
2577         case 'v':
2578         case 'n':
2579         case 'S':
2580             along = (strend - s) / sizeof(U16);
2581             if (len > along)
2582                 len = along;
2583             if (checksum) {
2584                 while (len-- > 0) {
2585                     Copy(s, &aushort, 1, U16);
2586                     s += sizeof(U16);
2587 #ifdef HAS_NTOHS
2588                     if (datumtype == 'n')
2589                         aushort = ntohs(aushort);
2590 #endif
2591 #ifdef HAS_VTOHS
2592                     if (datumtype == 'v')
2593                         aushort = vtohs(aushort);
2594 #endif
2595                     culong += aushort;
2596                 }
2597             }
2598             else {
2599                 EXTEND(SP, len);
2600                 while (len-- > 0) {
2601                     Copy(s, &aushort, 1, U16);
2602                     s += sizeof(U16);
2603                     sv = NEWSV(39, 0);
2604 #ifdef HAS_NTOHS
2605                     if (datumtype == 'n')
2606                         aushort = ntohs(aushort);
2607 #endif
2608 #ifdef HAS_VTOHS
2609                     if (datumtype == 'v')
2610                         aushort = vtohs(aushort);
2611 #endif
2612                     sv_setiv(sv, (I32)aushort);
2613                     PUSHs(sv_2mortal(sv));
2614                 }
2615             }
2616             break;
2617         case 'i':
2618             along = (strend - s) / sizeof(int);
2619             if (len > along)
2620                 len = along;
2621             if (checksum) {
2622                 while (len-- > 0) {
2623                     Copy(s, &aint, 1, int);
2624                     s += sizeof(int);
2625                     if (checksum > 32)
2626                         cdouble += (double)aint;
2627                     else
2628                         culong += aint;
2629                 }
2630             }
2631             else {
2632                 EXTEND(SP, len);
2633                 while (len-- > 0) {
2634                     Copy(s, &aint, 1, int);
2635                     s += sizeof(int);
2636                     sv = NEWSV(40, 0);
2637                     sv_setiv(sv, (I32)aint);
2638                     PUSHs(sv_2mortal(sv));
2639                 }
2640             }
2641             break;
2642         case 'I':
2643             along = (strend - s) / sizeof(unsigned int);
2644             if (len > along)
2645                 len = along;
2646             if (checksum) {
2647                 while (len-- > 0) {
2648                     Copy(s, &auint, 1, unsigned int);
2649                     s += sizeof(unsigned int);
2650                     if (checksum > 32)
2651                         cdouble += (double)auint;
2652                     else
2653                         culong += auint;
2654                 }
2655             }
2656             else {
2657                 EXTEND(SP, len);
2658                 while (len-- > 0) {
2659                     Copy(s, &auint, 1, unsigned int);
2660                     s += sizeof(unsigned int);
2661                     sv = NEWSV(41, 0);
2662                     sv_setiv(sv, (I32)auint);
2663                     PUSHs(sv_2mortal(sv));
2664                 }
2665             }
2666             break;
2667         case 'l':
2668             along = (strend - s) / sizeof(I32);
2669             if (len > along)
2670                 len = along;
2671             if (checksum) {
2672                 while (len-- > 0) {
2673                     Copy(s, &along, 1, I32);
2674                     s += sizeof(I32);
2675                     if (checksum > 32)
2676                         cdouble += (double)along;
2677                     else
2678                         culong += along;
2679                 }
2680             }
2681             else {
2682                 EXTEND(SP, len);
2683                 while (len-- > 0) {
2684                     Copy(s, &along, 1, I32);
2685                     s += sizeof(I32);
2686                     sv = NEWSV(42, 0);
2687                     sv_setiv(sv, (I32)along);
2688                     PUSHs(sv_2mortal(sv));
2689                 }
2690             }
2691             break;
2692         case 'V':
2693         case 'N':
2694         case 'L':
2695             along = (strend - s) / sizeof(U32);
2696             if (len > along)
2697                 len = along;
2698             if (checksum) {
2699                 while (len-- > 0) {
2700                     Copy(s, &aulong, 1, U32);
2701                     s += sizeof(U32);
2702 #ifdef HAS_NTOHL
2703                     if (datumtype == 'N')
2704                         aulong = ntohl(aulong);
2705 #endif
2706 #ifdef HAS_VTOHL
2707                     if (datumtype == 'V')
2708                         aulong = vtohl(aulong);
2709 #endif
2710                     if (checksum > 32)
2711                         cdouble += (double)aulong;
2712                     else
2713                         culong += aulong;
2714                 }
2715             }
2716             else {
2717                 EXTEND(SP, len);
2718                 while (len-- > 0) {
2719                     Copy(s, &aulong, 1, U32);
2720                     s += sizeof(U32);
2721                     sv = NEWSV(43, 0);
2722 #ifdef HAS_NTOHL
2723                     if (datumtype == 'N')
2724                         aulong = ntohl(aulong);
2725 #endif
2726 #ifdef HAS_VTOHL
2727                     if (datumtype == 'V')
2728                         aulong = vtohl(aulong);
2729 #endif
2730                     sv_setnv(sv, (double)aulong);
2731                     PUSHs(sv_2mortal(sv));
2732                 }
2733             }
2734             break;
2735         case 'p':
2736             along = (strend - s) / sizeof(char*);
2737             if (len > along)
2738                 len = along;
2739             EXTEND(SP, len);
2740             while (len-- > 0) {
2741                 if (sizeof(char*) > strend - s)
2742                     break;
2743                 else {
2744                     Copy(s, &aptr, 1, char*);
2745                     s += sizeof(char*);
2746                 }
2747                 sv = NEWSV(44, 0);
2748                 if (aptr)
2749                     sv_setpv(sv, aptr);
2750                 PUSHs(sv_2mortal(sv));
2751             }
2752             break;
2753         case 'P':
2754             EXTEND(SP, 1);
2755             if (sizeof(char*) > strend - s)
2756                 break;
2757             else {
2758                 Copy(s, &aptr, 1, char*);
2759                 s += sizeof(char*);
2760             }
2761             sv = NEWSV(44, 0);
2762             if (aptr)
2763                 sv_setpvn(sv, aptr, len);
2764             PUSHs(sv_2mortal(sv));
2765             break;
2766 #ifdef HAS_QUAD
2767         case 'q':
2768             EXTEND(SP, len);
2769             while (len-- > 0) {
2770                 if (s + sizeof(Quad_t) > strend)
2771                     aquad = 0;
2772                 else {
2773                     Copy(s, &aquad, 1, Quad_t);
2774                     s += sizeof(Quad_t);
2775                 }
2776                 sv = NEWSV(42, 0);
2777                 sv_setiv(sv, (IV)aquad);
2778                 PUSHs(sv_2mortal(sv));
2779             }
2780             break;
2781         case 'Q':
2782             EXTEND(SP, len);
2783             while (len-- > 0) {
2784                 if (s + sizeof(unsigned Quad_t) > strend)
2785                     auquad = 0;
2786                 else {
2787                     Copy(s, &auquad, 1, unsigned Quad_t);
2788                     s += sizeof(unsigned Quad_t);
2789                 }
2790                 sv = NEWSV(43, 0);
2791                 sv_setiv(sv, (IV)auquad);
2792                 PUSHs(sv_2mortal(sv));
2793             }
2794             break;
2795 #endif
2796         /* float and double added gnb@melba.bby.oz.au 22/11/89 */
2797         case 'f':
2798         case 'F':
2799             along = (strend - s) / sizeof(float);
2800             if (len > along)
2801                 len = along;
2802             if (checksum) {
2803                 while (len-- > 0) {
2804                     Copy(s, &afloat, 1, float);
2805                     s += sizeof(float);
2806                     cdouble += afloat;
2807                 }
2808             }
2809             else {
2810                 EXTEND(SP, len);
2811                 while (len-- > 0) {
2812                     Copy(s, &afloat, 1, float);
2813                     s += sizeof(float);
2814                     sv = NEWSV(47, 0);
2815                     sv_setnv(sv, (double)afloat);
2816                     PUSHs(sv_2mortal(sv));
2817                 }
2818             }
2819             break;
2820         case 'd':
2821         case 'D':
2822             along = (strend - s) / sizeof(double);
2823             if (len > along)
2824                 len = along;
2825             if (checksum) {
2826                 while (len-- > 0) {
2827                     Copy(s, &adouble, 1, double);
2828                     s += sizeof(double);
2829                     cdouble += adouble;
2830                 }
2831             }
2832             else {
2833                 EXTEND(SP, len);
2834                 while (len-- > 0) {
2835                     Copy(s, &adouble, 1, double);
2836                     s += sizeof(double);
2837                     sv = NEWSV(48, 0);
2838                     sv_setnv(sv, (double)adouble);
2839                     PUSHs(sv_2mortal(sv));
2840                 }
2841             }
2842             break;
2843         case 'u':
2844             along = (strend - s) * 3 / 4;
2845             sv = NEWSV(42, along);
2846             while (s < strend && *s > ' ' && *s < 'a') {
2847                 I32 a, b, c, d;
2848                 char hunk[4];
2849
2850                 hunk[3] = '\0';
2851                 len = (*s++ - ' ') & 077;
2852                 while (len > 0) {
2853                     if (s < strend && *s >= ' ')
2854                         a = (*s++ - ' ') & 077;
2855                     else
2856                         a = 0;
2857                     if (s < strend && *s >= ' ')
2858                         b = (*s++ - ' ') & 077;
2859                     else
2860                         b = 0;
2861                     if (s < strend && *s >= ' ')
2862                         c = (*s++ - ' ') & 077;
2863                     else
2864                         c = 0;
2865                     if (s < strend && *s >= ' ')
2866                         d = (*s++ - ' ') & 077;
2867                     else
2868                         d = 0;
2869                     hunk[0] = a << 2 | b >> 4;
2870                     hunk[1] = b << 4 | c >> 2;
2871                     hunk[2] = c << 6 | d;
2872                     sv_catpvn(sv, hunk, len > 3 ? 3 : len);
2873                     len -= 3;
2874                 }
2875                 if (*s == '\n')
2876                     s++;
2877                 else if (s[1] == '\n')          /* possible checksum byte */
2878                     s += 2;
2879             }
2880             XPUSHs(sv_2mortal(sv));
2881             break;
2882         }
2883         if (checksum) {
2884             sv = NEWSV(42, 0);
2885             if (strchr("fFdD", datumtype) ||
2886               (checksum > 32 && strchr("iIlLN", datumtype)) ) {
2887                 double trouble;
2888
2889                 adouble = 1.0;
2890                 while (checksum >= 16) {
2891                     checksum -= 16;
2892                     adouble *= 65536.0;
2893                 }
2894                 while (checksum >= 4) {
2895                     checksum -= 4;
2896                     adouble *= 16.0;
2897                 }
2898                 while (checksum--)
2899                     adouble *= 2.0;
2900                 along = (1 << checksum) - 1;
2901                 while (cdouble < 0.0)
2902                     cdouble += adouble;
2903                 cdouble = modf(cdouble / adouble, &trouble) * adouble;
2904                 sv_setnv(sv, cdouble);
2905             }
2906             else {
2907                 if (checksum < 32) {
2908                     along = (1 << checksum) - 1;
2909                     culong &= (U32)along;
2910                 }
2911                 sv_setnv(sv, (double)culong);
2912             }
2913             XPUSHs(sv_2mortal(sv));
2914             checksum = 0;
2915         }
2916     }
2917     RETURN;
2918 }
2919
2920 static void
2921 doencodes(sv, s, len)
2922 register SV *sv;
2923 register char *s;
2924 register I32 len;
2925 {
2926     char hunk[5];
2927
2928     *hunk = len + ' ';
2929     sv_catpvn(sv, hunk, 1);
2930     hunk[4] = '\0';
2931     while (len > 0) {
2932         hunk[0] = ' ' + (077 & (*s >> 2));
2933         hunk[1] = ' ' + (077 & ((*s << 4) & 060 | (s[1] >> 4) & 017));
2934         hunk[2] = ' ' + (077 & ((s[1] << 2) & 074 | (s[2] >> 6) & 03));
2935         hunk[3] = ' ' + (077 & (s[2] & 077));
2936         sv_catpvn(sv, hunk, 4);
2937         s += 3;
2938         len -= 3;
2939     }
2940     for (s = SvPVX(sv); *s; s++) {
2941         if (*s == ' ')
2942             *s = '`';
2943     }
2944     sv_catpvn(sv, "\n", 1);
2945 }
2946
2947 PP(pp_pack)
2948 {
2949     dSP; dMARK; dORIGMARK; dTARGET;
2950     register SV *cat = TARG;
2951     register I32 items;
2952     STRLEN fromlen;
2953     register char *pat = SvPVx(*++MARK, fromlen);
2954     register char *patend = pat + fromlen;
2955     register I32 len;
2956     I32 datumtype;
2957     SV *fromstr;
2958     /*SUPPRESS 442*/
2959     static char null10[] = {0,0,0,0,0,0,0,0,0,0};
2960     static char *space10 = "          ";
2961
2962     /* These must not be in registers: */
2963     char achar;
2964     I16 ashort;
2965     int aint;
2966     unsigned int auint;
2967     I32 along;
2968     U32 aulong;
2969 #ifdef HAS_QUAD
2970     Quad_t aquad;
2971     unsigned Quad_t auquad;
2972 #endif
2973     char *aptr;
2974     float afloat;
2975     double adouble;
2976
2977     items = SP - MARK;
2978     MARK++;
2979     sv_setpvn(cat, "", 0);
2980     while (pat < patend) {
2981 #define NEXTFROM (items-- > 0 ? *MARK++ : &sv_no)
2982         datumtype = *pat++;
2983         if (*pat == '*') {
2984             len = strchr("@Xxu", datumtype) ? 0 : items;
2985             pat++;
2986         }
2987         else if (isDIGIT(*pat)) {
2988             len = *pat++ - '0';
2989             while (isDIGIT(*pat))
2990                 len = (len * 10) + (*pat++ - '0');
2991         }
2992         else
2993             len = 1;
2994         switch(datumtype) {
2995         default:
2996             break;
2997         case '%':
2998             DIE("%% may only be used in unpack");
2999         case '@':
3000             len -= SvCUR(cat);
3001             if (len > 0)
3002                 goto grow;
3003             len = -len;
3004             if (len > 0)
3005                 goto shrink;
3006             break;
3007         case 'X':
3008           shrink:
3009             if (SvCUR(cat) < len)
3010                 DIE("X outside of string");
3011             SvCUR(cat) -= len;
3012             *SvEND(cat) = '\0';
3013             break;
3014         case 'x':
3015           grow:
3016             while (len >= 10) {
3017                 sv_catpvn(cat, null10, 10);
3018                 len -= 10;
3019             }
3020             sv_catpvn(cat, null10, len);
3021             break;
3022         case 'A':
3023         case 'a':
3024             fromstr = NEXTFROM;
3025             aptr = SvPV(fromstr, fromlen);
3026             if (pat[-1] == '*')
3027                 len = fromlen;
3028             if (fromlen > len)
3029                 sv_catpvn(cat, aptr, len);
3030             else {
3031                 sv_catpvn(cat, aptr, fromlen);
3032                 len -= fromlen;
3033                 if (datumtype == 'A') {
3034                     while (len >= 10) {
3035                         sv_catpvn(cat, space10, 10);
3036                         len -= 10;
3037                     }
3038                     sv_catpvn(cat, space10, len);
3039                 }
3040                 else {
3041                     while (len >= 10) {
3042                         sv_catpvn(cat, null10, 10);
3043                         len -= 10;
3044                     }
3045                     sv_catpvn(cat, null10, len);
3046                 }
3047             }
3048             break;
3049         case 'B':
3050         case 'b':
3051             {
3052                 char *savepat = pat;
3053                 I32 saveitems;
3054
3055                 fromstr = NEXTFROM;
3056                 saveitems = items;
3057                 aptr = SvPV(fromstr, fromlen);
3058                 if (pat[-1] == '*')
3059                     len = fromlen;
3060                 pat = aptr;
3061                 aint = SvCUR(cat);
3062                 SvCUR(cat) += (len+7)/8;
3063                 SvGROW(cat, SvCUR(cat) + 1);
3064                 aptr = SvPVX(cat) + aint;
3065                 if (len > fromlen)
3066                     len = fromlen;
3067                 aint = len;
3068                 items = 0;
3069                 if (datumtype == 'B') {
3070                     for (len = 0; len++ < aint;) {
3071                         items |= *pat++ & 1;
3072                         if (len & 7)
3073                             items <<= 1;
3074                         else {
3075                             *aptr++ = items & 0xff;
3076                             items = 0;
3077                         }
3078                     }
3079                 }
3080                 else {
3081                     for (len = 0; len++ < aint;) {
3082                         if (*pat++ & 1)
3083                             items |= 128;
3084                         if (len & 7)
3085                             items >>= 1;
3086                         else {
3087                             *aptr++ = items & 0xff;
3088                             items = 0;
3089                         }
3090                     }
3091                 }
3092                 if (aint & 7) {
3093                     if (datumtype == 'B')
3094                         items <<= 7 - (aint & 7);
3095                     else
3096                         items >>= 7 - (aint & 7);
3097                     *aptr++ = items & 0xff;
3098                 }
3099                 pat = SvPVX(cat) + SvCUR(cat);
3100                 while (aptr <= pat)
3101                     *aptr++ = '\0';
3102
3103                 pat = savepat;
3104                 items = saveitems;
3105             }
3106             break;
3107         case 'H':
3108         case 'h':
3109             {
3110                 char *savepat = pat;
3111                 I32 saveitems;
3112
3113                 fromstr = NEXTFROM;
3114                 saveitems = items;
3115                 aptr = SvPV(fromstr, fromlen);
3116                 if (pat[-1] == '*')
3117                     len = fromlen;
3118                 pat = aptr;
3119                 aint = SvCUR(cat);
3120                 SvCUR(cat) += (len+1)/2;
3121                 SvGROW(cat, SvCUR(cat) + 1);
3122                 aptr = SvPVX(cat) + aint;
3123                 if (len > fromlen)
3124                     len = fromlen;
3125                 aint = len;
3126                 items = 0;
3127                 if (datumtype == 'H') {
3128                     for (len = 0; len++ < aint;) {
3129                         if (isALPHA(*pat))
3130                             items |= ((*pat++ & 15) + 9) & 15;
3131                         else
3132                             items |= *pat++ & 15;
3133                         if (len & 1)
3134                             items <<= 4;
3135                         else {
3136                             *aptr++ = items & 0xff;
3137                             items = 0;
3138                         }
3139                     }
3140                 }
3141                 else {
3142                     for (len = 0; len++ < aint;) {
3143                         if (isALPHA(*pat))
3144                             items |= (((*pat++ & 15) + 9) & 15) << 4;
3145                         else
3146                             items |= (*pat++ & 15) << 4;
3147                         if (len & 1)
3148                             items >>= 4;
3149                         else {
3150                             *aptr++ = items & 0xff;
3151                             items = 0;
3152                         }
3153                     }
3154                 }
3155                 if (aint & 1)
3156                     *aptr++ = items & 0xff;
3157                 pat = SvPVX(cat) + SvCUR(cat);
3158                 while (aptr <= pat)
3159                     *aptr++ = '\0';
3160
3161                 pat = savepat;
3162                 items = saveitems;
3163             }
3164             break;
3165         case 'C':
3166         case 'c':
3167             while (len-- > 0) {
3168                 fromstr = NEXTFROM;
3169                 aint = SvIV(fromstr);
3170                 achar = aint;
3171                 sv_catpvn(cat, &achar, sizeof(char));
3172             }
3173             break;
3174         /* Float and double added by gnb@melba.bby.oz.au  22/11/89 */
3175         case 'f':
3176         case 'F':
3177             while (len-- > 0) {
3178                 fromstr = NEXTFROM;
3179                 afloat = (float)SvNV(fromstr);
3180                 sv_catpvn(cat, (char *)&afloat, sizeof (float));
3181             }
3182             break;
3183         case 'd':
3184         case 'D':
3185             while (len-- > 0) {
3186                 fromstr = NEXTFROM;
3187                 adouble = (double)SvNV(fromstr);
3188                 sv_catpvn(cat, (char *)&adouble, sizeof (double));
3189             }
3190             break;
3191         case 'n':
3192             while (len-- > 0) {
3193                 fromstr = NEXTFROM;
3194                 ashort = (I16)SvIV(fromstr);
3195 #ifdef HAS_HTONS
3196                 ashort = htons(ashort);
3197 #endif
3198                 sv_catpvn(cat, (char*)&ashort, sizeof(I16));
3199             }
3200             break;
3201         case 'v':
3202             while (len-- > 0) {
3203                 fromstr = NEXTFROM;
3204                 ashort = (I16)SvIV(fromstr);
3205 #ifdef HAS_HTOVS
3206                 ashort = htovs(ashort);
3207 #endif
3208                 sv_catpvn(cat, (char*)&ashort, sizeof(I16));
3209             }
3210             break;
3211         case 'S':
3212         case 's':
3213             while (len-- > 0) {
3214                 fromstr = NEXTFROM;
3215                 ashort = (I16)SvIV(fromstr);
3216                 sv_catpvn(cat, (char*)&ashort, sizeof(I16));
3217             }
3218             break;
3219         case 'I':
3220             while (len-- > 0) {
3221                 fromstr = NEXTFROM;
3222                 auint = U_I(SvNV(fromstr));
3223                 sv_catpvn(cat, (char*)&auint, sizeof(unsigned int));
3224             }
3225             break;
3226         case 'i':
3227             while (len-- > 0) {
3228                 fromstr = NEXTFROM;
3229                 aint = SvIV(fromstr);
3230                 sv_catpvn(cat, (char*)&aint, sizeof(int));
3231             }
3232             break;
3233         case 'N':
3234             while (len-- > 0) {
3235                 fromstr = NEXTFROM;
3236                 aulong = U_L(SvNV(fromstr));
3237 #ifdef HAS_HTONL
3238                 aulong = htonl(aulong);
3239 #endif
3240                 sv_catpvn(cat, (char*)&aulong, sizeof(U32));
3241             }
3242             break;
3243         case 'V':
3244             while (len-- > 0) {
3245                 fromstr = NEXTFROM;
3246                 aulong = U_L(SvNV(fromstr));
3247 #ifdef HAS_HTOVL
3248                 aulong = htovl(aulong);
3249 #endif
3250                 sv_catpvn(cat, (char*)&aulong, sizeof(U32));
3251             }
3252             break;
3253         case 'L':
3254             while (len-- > 0) {
3255                 fromstr = NEXTFROM;
3256                 aulong = U_L(SvNV(fromstr));
3257                 sv_catpvn(cat, (char*)&aulong, sizeof(U32));
3258             }
3259             break;
3260         case 'l':
3261             while (len-- > 0) {
3262                 fromstr = NEXTFROM;
3263                 along = SvIV(fromstr);
3264                 sv_catpvn(cat, (char*)&along, sizeof(I32));
3265             }
3266             break;
3267 #ifdef HAS_QUAD
3268         case 'Q':
3269             while (len-- > 0) {
3270                 fromstr = NEXTFROM;
3271                 auquad = (unsigned Quad_t)SvIV(fromstr);
3272                 sv_catpvn(cat, (char*)&auquad, sizeof(unsigned Quad_t));
3273             }
3274             break;
3275         case 'q':
3276             while (len-- > 0) {
3277                 fromstr = NEXTFROM;
3278                 aquad = (Quad_t)SvIV(fromstr);
3279                 sv_catpvn(cat, (char*)&aquad, sizeof(Quad_t));
3280             }
3281             break;
3282 #endif /* HAS_QUAD */
3283         case 'P':
3284             len = 1;            /* assume SV is correct length */
3285             /* FALL THROUGH */
3286         case 'p':
3287             while (len-- > 0) {
3288                 fromstr = NEXTFROM;
3289                 aptr = SvPV_force(fromstr, na); /* XXX Error if TEMP? */
3290                 sv_catpvn(cat, (char*)&aptr, sizeof(char*));
3291             }
3292             break;
3293         case 'u':
3294             fromstr = NEXTFROM;
3295             aptr = SvPV(fromstr, fromlen);
3296             SvGROW(cat, fromlen * 4 / 3);
3297             if (len <= 1)
3298                 len = 45;
3299             else
3300                 len = len / 3 * 3;
3301             while (fromlen > 0) {
3302                 I32 todo;
3303
3304                 if (fromlen > len)
3305                     todo = len;
3306                 else
3307                     todo = fromlen;
3308                 doencodes(cat, aptr, todo);
3309                 fromlen -= todo;
3310                 aptr += todo;
3311             }
3312             break;
3313         }
3314     }
3315     SvSETMAGIC(cat);
3316     SP = ORIGMARK;
3317     PUSHs(cat);
3318     RETURN;
3319 }
3320 #undef NEXTFROM
3321
3322 PP(pp_split)
3323 {
3324     dSP; dTARG;
3325     AV *ary;
3326     register I32 limit = POPi;                  /* note, negative is forever */
3327     SV *sv = POPs;
3328     STRLEN len;
3329     register char *s = SvPV(sv, len);
3330     char *strend = s + len;
3331     register PMOP *pm = (PMOP*)POPs;
3332     register SV *dstr;
3333     register char *m;
3334     I32 iters = 0;
3335     I32 maxiters = (strend - s) + 10;
3336     I32 i;
3337     char *orig;
3338     I32 origlimit = limit;
3339     I32 realarray = 0;
3340     I32 base;
3341     AV *oldstack = stack;
3342     register REGEXP *rx = pm->op_pmregexp;
3343     I32 gimme = GIMME;
3344     I32 oldsave = savestack_ix;
3345
3346     if (!pm || !s)
3347         DIE("panic: do_split");
3348     if (pm->op_pmreplroot)
3349         ary = GvAVn((GV*)pm->op_pmreplroot);
3350     else if (gimme != G_ARRAY)
3351         ary = GvAVn(defgv);
3352     else
3353         ary = Nullav;
3354     if (ary && (gimme != G_ARRAY || (pm->op_pmflags & PMf_ONCE))) {
3355         realarray = 1;
3356         if (!AvREAL(ary)) {
3357             AvREAL_on(ary);
3358             for (i = AvFILL(ary); i >= 0; i--)
3359                 AvARRAY(ary)[i] = &sv_undef;    /* don't free mere refs */
3360         }
3361         av_extend(ary,0);
3362         av_clear(ary);
3363         /* temporarily switch stacks */
3364         SWITCHSTACK(stack, ary);
3365     }
3366     base = SP - stack_base;
3367     orig = s;
3368     if (pm->op_pmflags & PMf_SKIPWHITE) {
3369         while (isSPACE(*s))
3370             s++;
3371     }
3372     if (pm->op_pmflags & (PMf_MULTILINE|PMf_SINGLELINE)) {
3373         SAVEINT(multiline);
3374         multiline = pm->op_pmflags & PMf_MULTILINE;
3375     }
3376
3377     if (!limit)
3378         limit = maxiters + 2;
3379     if (pm->op_pmflags & PMf_WHITE) {
3380         while (--limit) {
3381             /*SUPPRESS 530*/
3382             for (m = s; m < strend && !isSPACE(*m); m++) ;
3383             if (m >= strend)
3384                 break;
3385             dstr = NEWSV(30, m-s);
3386             sv_setpvn(dstr, s, m-s);
3387             if (!realarray)
3388                 sv_2mortal(dstr);
3389             XPUSHs(dstr);
3390             /*SUPPRESS 530*/
3391             for (s = m + 1; s < strend && isSPACE(*s); s++) ;
3392         }
3393     }
3394     else if (strEQ("^", rx->precomp)) {
3395         while (--limit) {
3396             /*SUPPRESS 530*/
3397             for (m = s; m < strend && *m != '\n'; m++) ;
3398             m++;
3399             if (m >= strend)
3400                 break;
3401             dstr = NEWSV(30, m-s);
3402             sv_setpvn(dstr, s, m-s);
3403             if (!realarray)
3404                 sv_2mortal(dstr);
3405             XPUSHs(dstr);
3406             s = m;
3407         }
3408     }
3409     else if (pm->op_pmshort) {
3410         i = SvCUR(pm->op_pmshort);
3411         if (i == 1) {
3412             I32 fold = (pm->op_pmflags & PMf_FOLD);
3413             i = *SvPVX(pm->op_pmshort);
3414             if (fold && isUPPER(i))
3415                 i = toLOWER(i);
3416             while (--limit) {
3417                 if (fold) {
3418                     for ( m = s;
3419                           m < strend && *m != i &&
3420                             (!isUPPER(*m) || toLOWER(*m) != i);
3421                           m++)                  /*SUPPRESS 530*/
3422                         ;
3423                 }
3424                 else                            /*SUPPRESS 530*/
3425                     for (m = s; m < strend && *m != i; m++) ;
3426                 if (m >= strend)
3427                     break;
3428                 dstr = NEWSV(30, m-s);
3429                 sv_setpvn(dstr, s, m-s);
3430                 if (!realarray)
3431                     sv_2mortal(dstr);
3432                 XPUSHs(dstr);
3433                 s = m + 1;
3434             }
3435         }
3436         else {
3437 #ifndef lint
3438             while (s < strend && --limit &&
3439               (m=fbm_instr((unsigned char*)s, (unsigned char*)strend,
3440                     pm->op_pmshort)) )
3441 #endif
3442             {
3443                 dstr = NEWSV(31, m-s);
3444                 sv_setpvn(dstr, s, m-s);
3445                 if (!realarray)
3446                     sv_2mortal(dstr);
3447                 XPUSHs(dstr);
3448                 s = m + i;
3449             }
3450         }
3451     }
3452     else {
3453         maxiters += (strend - s) * rx->nparens;
3454         while (s < strend && --limit &&
3455             pregexec(rx, s, strend, orig, 1, Nullsv, TRUE) ) {
3456             if (rx->subbase
3457               && rx->subbase != orig) {
3458                 m = s;
3459                 s = orig;
3460                 orig = rx->subbase;
3461                 s = orig + (m - s);
3462                 strend = s + (strend - m);
3463             }
3464             m = rx->startp[0];
3465             dstr = NEWSV(32, m-s);
3466             sv_setpvn(dstr, s, m-s);
3467             if (!realarray)
3468                 sv_2mortal(dstr);
3469             XPUSHs(dstr);
3470             if (rx->nparens) {
3471                 for (i = 1; i <= rx->nparens; i++) {
3472                     s = rx->startp[i];
3473                     m = rx->endp[i];
3474                     if (m && s) {
3475                         dstr = NEWSV(33, m-s);
3476                         sv_setpvn(dstr, s, m-s);
3477                     }
3478                     else
3479                         dstr = NEWSV(33, 0);
3480                     if (!realarray)
3481                         sv_2mortal(dstr);
3482                     XPUSHs(dstr);
3483                 }
3484             }
3485             s = rx->endp[0];
3486         }
3487     }
3488     LEAVE_SCOPE(oldsave);
3489     iters = (SP - stack_base) - base;
3490     if (iters > maxiters)
3491         DIE("Split loop");
3492     
3493     /* keep field after final delim? */
3494     if (s < strend || (iters && origlimit)) {
3495         dstr = NEWSV(34, strend-s);
3496         sv_setpvn(dstr, s, strend-s);
3497         if (!realarray)
3498             sv_2mortal(dstr);
3499         XPUSHs(dstr);
3500         iters++;
3501     }
3502     else if (!origlimit) {
3503         while (iters > 0 && SvCUR(TOPs) == 0)
3504             iters--, SP--;
3505     }
3506     if (realarray) {
3507         SWITCHSTACK(ary, oldstack);
3508         if (gimme == G_ARRAY) {
3509             EXTEND(SP, iters);
3510             Copy(AvARRAY(ary), SP + 1, iters, SV*);
3511             SP += iters;
3512             RETURN;
3513         }
3514     }
3515     else {
3516         if (gimme == G_ARRAY)
3517             RETURN;
3518     }
3519     if (iters || !pm->op_pmreplroot) {
3520         GETTARGET;
3521         PUSHi(iters);
3522         RETURN;
3523     }
3524     RETPUSHUNDEF;
3525 }
3526