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