make overload, Data::Dumper, and dumpvar understand qr// stringify
[p5sagit/p5-mst-13.2.git] / mg.c
1 /*    mg.c
2  *
3  *    Copyright (c) 1991-1999, 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  * "Sam sat on the ground and put his head in his hands.  'I wish I had never
12  * come here, and I don't want to see no more magic,' he said, and fell silent."
13  */
14
15 #include "EXTERN.h"
16 #define PERL_IN_MG_C
17 #include "perl.h"
18
19 /* XXX If this causes problems, set i_unistd=undef in the hint file.  */
20 #ifdef I_UNISTD
21 # include <unistd.h>
22 #endif
23
24 #if defined(HAS_GETGROUPS) || defined(HAS_SETGROUPS)
25 #  ifndef NGROUPS
26 #    define NGROUPS 32
27 #  endif
28 #endif
29
30 #ifdef PERL_OBJECT
31 #  define VTBL            this->*vtbl
32 #else
33 #  define VTBL                  *vtbl
34 #endif
35
36 /*
37  * Use the "DESTRUCTOR" scope cleanup to reinstate magic.
38  */
39
40 struct magic_state {
41     SV* mgs_sv;
42     U32 mgs_flags;
43     I32 mgs_ss_ix;
44 };
45 /* MGS is typedef'ed to struct magic_state in perl.h */
46
47 STATIC void
48 S_save_magic(pTHX_ I32 mgs_ix, SV *sv)
49 {
50     dTHR;
51     MGS* mgs;
52     assert(SvMAGICAL(sv));
53
54     SAVEDESTRUCTOR(S_restore_magic, (void*)mgs_ix);
55
56     mgs = SSPTR(mgs_ix, MGS*);
57     mgs->mgs_sv = sv;
58     mgs->mgs_flags = SvMAGICAL(sv) | SvREADONLY(sv);
59     mgs->mgs_ss_ix = PL_savestack_ix;   /* points after the saved destructor */
60
61     SvMAGICAL_off(sv);
62     SvREADONLY_off(sv);
63     SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT;
64 }
65
66 STATIC void
67 S_restore_magic(pTHX_ void *p)
68 {
69     dTHR;
70     MGS* mgs = SSPTR((I32)p, MGS*);
71     SV* sv = mgs->mgs_sv;
72
73     if (!sv)
74         return;
75
76     if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv))
77     {
78         if (mgs->mgs_flags)
79             SvFLAGS(sv) |= mgs->mgs_flags;
80         else
81             mg_magical(sv);
82         if (SvGMAGICAL(sv))
83             SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK|SVf_POK);
84     }
85
86     mgs->mgs_sv = NULL;  /* mark the MGS structure as restored */
87
88     /* If we're still on top of the stack, pop us off.  (That condition
89      * will be satisfied if restore_magic was called explicitly, but *not*
90      * if it's being called via leave_scope.)
91      * The reason for doing this is that otherwise, things like sv_2cv()
92      * may leave alloc gunk on the savestack, and some code
93      * (e.g. sighandler) doesn't expect that...
94      */
95     if (PL_savestack_ix == mgs->mgs_ss_ix)
96     {
97         I32 popval = SSPOPINT;
98         assert(popval == SAVEt_DESTRUCTOR);
99         PL_savestack_ix -= 2;
100         popval = SSPOPINT;
101         assert(popval == SAVEt_ALLOC);
102         popval = SSPOPINT;
103         PL_savestack_ix -= popval;
104     }
105
106 }
107
108 void
109 Perl_mg_magical(pTHX_ SV *sv)
110 {
111     MAGIC* mg;
112     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
113         MGVTBL* vtbl = mg->mg_virtual;
114         if (vtbl) {
115             if ((vtbl->svt_get != NULL) && !(mg->mg_flags & MGf_GSKIP))
116                 SvGMAGICAL_on(sv);
117             if (vtbl->svt_set)
118                 SvSMAGICAL_on(sv);
119             if (!(SvFLAGS(sv) & (SVs_GMG|SVs_SMG)) || (vtbl->svt_clear != NULL))
120                 SvRMAGICAL_on(sv);
121         }
122     }
123 }
124
125 int
126 Perl_mg_get(pTHX_ SV *sv)
127 {
128     dTHR;
129     I32 mgs_ix;
130     MAGIC* mg;
131     MAGIC** mgp;
132     int mgp_valid = 0;
133
134     mgs_ix = SSNEW(sizeof(MGS));
135     save_magic(mgs_ix, sv);
136
137     mgp = &SvMAGIC(sv);
138     while ((mg = *mgp) != 0) {
139         MGVTBL* vtbl = mg->mg_virtual;
140         if (!(mg->mg_flags & MGf_GSKIP) && vtbl && (vtbl->svt_get != NULL)) {
141             (VTBL->svt_get)(aTHX_ sv, mg);
142             /* Ignore this magic if it's been deleted */
143             if ((mg == (mgp_valid ? *mgp : SvMAGIC(sv))) &&
144                   (mg->mg_flags & MGf_GSKIP))
145                 (SSPTR(mgs_ix, MGS*))->mgs_flags = 0;
146         }
147         /* Advance to next magic (complicated by possible deletion) */
148         if (mg == (mgp_valid ? *mgp : SvMAGIC(sv))) {
149             mgp = &mg->mg_moremagic;
150             mgp_valid = 1;
151         }
152         else
153             mgp = &SvMAGIC(sv); /* Re-establish pointer after sv_upgrade */
154     }
155
156     restore_magic((void*)mgs_ix);
157     return 0;
158 }
159
160 int
161 Perl_mg_set(pTHX_ SV *sv)
162 {
163     dTHR;
164     I32 mgs_ix;
165     MAGIC* mg;
166     MAGIC* nextmg;
167
168     mgs_ix = SSNEW(sizeof(MGS));
169     save_magic(mgs_ix, sv);
170
171     for (mg = SvMAGIC(sv); mg; mg = nextmg) {
172         MGVTBL* vtbl = mg->mg_virtual;
173         nextmg = mg->mg_moremagic;      /* it may delete itself */
174         if (mg->mg_flags & MGf_GSKIP) {
175             mg->mg_flags &= ~MGf_GSKIP; /* setting requires another read */
176             (SSPTR(mgs_ix, MGS*))->mgs_flags = 0;
177         }
178         if (vtbl && (vtbl->svt_set != NULL))
179             (VTBL->svt_set)(aTHX_ sv, mg);
180     }
181
182     restore_magic((void*)mgs_ix);
183     return 0;
184 }
185
186 U32
187 Perl_mg_length(pTHX_ SV *sv)
188 {
189     MAGIC* mg;
190     char *junk;
191     STRLEN len;
192
193     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
194         MGVTBL* vtbl = mg->mg_virtual;
195         if (vtbl && (vtbl->svt_len != NULL)) {
196             I32 mgs_ix;
197
198             mgs_ix = SSNEW(sizeof(MGS));
199             save_magic(mgs_ix, sv);
200             /* omit MGf_GSKIP -- not changed here */
201             len = (VTBL->svt_len)(aTHX_ sv, mg);
202             restore_magic((void*)mgs_ix);
203             return len;
204         }
205     }
206
207     junk = SvPV(sv, len);
208     return len;
209 }
210
211 I32
212 Perl_mg_size(pTHX_ SV *sv)
213 {
214     MAGIC* mg;
215     I32 len;
216     
217     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
218         MGVTBL* vtbl = mg->mg_virtual;
219         if (vtbl && (vtbl->svt_len != NULL)) {
220             I32 mgs_ix;
221
222             mgs_ix = SSNEW(sizeof(MGS));
223             save_magic(mgs_ix, sv);
224             /* omit MGf_GSKIP -- not changed here */
225             len = (VTBL->svt_len)(aTHX_ sv, mg);
226             restore_magic((void*)mgs_ix);
227             return len;
228         }
229     }
230
231     switch(SvTYPE(sv)) {
232         case SVt_PVAV:
233             len = AvFILLp((AV *) sv); /* Fallback to non-tied array */
234             return len;
235         case SVt_PVHV:
236             /* FIXME */
237         default:
238             Perl_croak(aTHX_ "Size magic not implemented");
239             break;
240     }
241     return 0;
242 }
243
244 int
245 Perl_mg_clear(pTHX_ SV *sv)
246 {
247     I32 mgs_ix;
248     MAGIC* mg;
249
250     mgs_ix = SSNEW(sizeof(MGS));
251     save_magic(mgs_ix, sv);
252
253     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
254         MGVTBL* vtbl = mg->mg_virtual;
255         /* omit GSKIP -- never set here */
256         
257         if (vtbl && (vtbl->svt_clear != NULL))
258             (VTBL->svt_clear)(aTHX_ sv, mg);
259     }
260
261     restore_magic((void*)mgs_ix);
262     return 0;
263 }
264
265 MAGIC*
266 Perl_mg_find(pTHX_ SV *sv, int type)
267 {
268     MAGIC* mg;
269     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
270         if (mg->mg_type == type)
271             return mg;
272     }
273     return 0;
274 }
275
276 int
277 Perl_mg_copy(pTHX_ SV *sv, SV *nsv, const char *key, I32 klen)
278 {
279     int count = 0;
280     MAGIC* mg;
281     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
282         if (isUPPER(mg->mg_type)) {
283             sv_magic(nsv,
284                      mg->mg_type == 'P' ? SvTIED_obj(sv, mg) : mg->mg_obj,
285                      toLOWER(mg->mg_type), key, klen);
286             count++;
287         }
288     }
289     return count;
290 }
291
292 int
293 Perl_mg_free(pTHX_ SV *sv)
294 {
295     MAGIC* mg;
296     MAGIC* moremagic;
297     for (mg = SvMAGIC(sv); mg; mg = moremagic) {
298         MGVTBL* vtbl = mg->mg_virtual;
299         moremagic = mg->mg_moremagic;
300         if (vtbl && (vtbl->svt_free != NULL))
301             (VTBL->svt_free)(aTHX_ sv, mg);
302         if (mg->mg_ptr && mg->mg_type != 'g')
303             if (mg->mg_len >= 0)
304                 Safefree(mg->mg_ptr);
305             else if (mg->mg_len == HEf_SVKEY)
306                 SvREFCNT_dec((SV*)mg->mg_ptr);
307         if (mg->mg_flags & MGf_REFCOUNTED)
308             SvREFCNT_dec(mg->mg_obj);
309         Safefree(mg);
310     }
311     SvMAGIC(sv) = 0;
312     return 0;
313 }
314
315 #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
316 #include <signal.h>
317 #endif
318
319 U32
320 Perl_magic_regdata_cnt(pTHX_ SV *sv, MAGIC *mg)
321 {
322     dTHR;
323     register char *s;
324     register I32 i;
325     register REGEXP *rx;
326     char *t;
327
328     if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
329         if (mg->mg_obj)         /* @+ */
330             return rx->nparens;
331         else                    /* @- */
332             return rx->lastparen;
333     }
334     
335     return (U32)-1;
336 }
337
338 int
339 Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg)
340 {
341     dTHR;
342     register I32 paren;
343     register I32 s;
344     register I32 i;
345     register REGEXP *rx;
346     I32 t;
347
348     if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
349         paren = mg->mg_len;
350         if (paren < 0)
351             return 0;
352         if (paren <= rx->nparens &&
353             (s = rx->startp[paren]) != -1 &&
354             (t = rx->endp[paren]) != -1)
355             {
356                 if (mg->mg_obj)         /* @+ */
357                     i = t;
358                 else                    /* @- */
359                     i = s;
360                 sv_setiv(sv,i);
361             }
362     }
363     return 0;
364 }
365
366 U32
367 Perl_magic_len(pTHX_ SV *sv, MAGIC *mg)
368 {
369     dTHR;
370     register I32 paren;
371     register char *s;
372     register I32 i;
373     register REGEXP *rx;
374     char *t;
375
376     switch (*mg->mg_ptr) {
377     case '1': case '2': case '3': case '4':
378     case '5': case '6': case '7': case '8': case '9': case '&':
379         if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
380             I32 s1, t1;
381
382             paren = atoi(mg->mg_ptr);
383           getparen:
384             if (paren <= rx->nparens &&
385                 (s1 = rx->startp[paren]) != -1 &&
386                 (t1 = rx->endp[paren]) != -1)
387             {
388                 i = t1 - s1;
389                 if (i >= 0)
390                     return i;
391             }
392         }
393         return 0;
394     case '+':
395         if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
396             paren = rx->lastparen;
397             if (paren)
398                 goto getparen;
399         }
400         return 0;
401     case '`':
402         if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
403             if (rx->startp[0] != -1) {
404                 i = rx->startp[0];
405                 if (i >= 0)
406                     return i;
407             }
408         }
409         return 0;
410     case '\'':
411         if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
412             if (rx->endp[0] != -1) {
413                 i = rx->sublen - rx->endp[0];
414                 if (i >= 0)
415                     return i;
416             }
417         }
418         return 0;
419     case ',':
420         return (STRLEN)PL_ofslen;
421     case '\\':
422         return (STRLEN)PL_orslen;
423     }
424     magic_get(sv,mg);
425     if (!SvPOK(sv) && SvNIOK(sv)) {
426         STRLEN n_a;
427         sv_2pv(sv, &n_a);
428     }
429     if (SvPOK(sv))
430         return SvCUR(sv);
431     return 0;
432 }
433
434 #if 0
435 static char * 
436 printW(SV *sv)
437 {
438 #if 1
439     return "" ;
440
441 #else
442     int i ;
443     static char buffer[50] ;
444     char buf1[20] ;
445     char * p ;
446
447
448     sprintf(buffer, "Buffer %d, Length = %d - ", sv, SvCUR(sv)) ;
449     p = SvPVX(sv) ;
450     for (i = 0; i < SvCUR(sv) ; ++ i) {
451         sprintf (buf1, " %x [%x]", (p+i), *(p+i)) ;
452         strcat(buffer, buf1) ;
453     } 
454
455     return buffer ;
456
457 #endif
458 }
459 #endif
460
461 int
462 Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
463 {
464     dTHR;
465     register I32 paren;
466     register char *s;
467     register I32 i;
468     register REGEXP *rx;
469     char *t;
470
471     switch (*mg->mg_ptr) {
472     case '\001':                /* ^A */
473         sv_setsv(sv, PL_bodytarget);
474         break;
475     case '\002':                /* ^B */
476         /* printf("magic_get $^B: ") ; */
477         if (PL_curcop->cop_warnings == WARN_NONE)
478             /* printf("WARN_NONE\n"), */
479             sv_setpvn(sv, WARN_NONEstring, WARNsize) ;
480         else if (PL_curcop->cop_warnings == WARN_ALL)
481             /* printf("WARN_ALL\n"), */
482             sv_setpvn(sv, WARN_ALLstring, WARNsize) ;
483         else 
484             /* printf("some %s\n", printW(PL_curcop->cop_warnings)), */
485             sv_setsv(sv, PL_curcop->cop_warnings);
486         break;
487     case '\003':                /* ^C */
488         sv_setiv(sv, (IV)PL_minus_c);
489         break;
490
491     case '\004':                /* ^D */
492         sv_setiv(sv, (IV)(PL_debug & 32767));
493         break;
494     case '\005':  /* ^E */
495 #ifdef VMS
496         {
497 #           include <descrip.h>
498 #           include <starlet.h>
499             char msg[255];
500             $DESCRIPTOR(msgdsc,msg);
501             sv_setnv(sv,(double) vaxc$errno);
502             if (sys$getmsg(vaxc$errno,&msgdsc.dsc$w_length,&msgdsc,0,0) & 1)
503                 sv_setpvn(sv,msgdsc.dsc$a_pointer,msgdsc.dsc$w_length);
504             else
505                 sv_setpv(sv,"");
506         }
507 #else
508 #ifdef OS2
509         if (!(_emx_env & 0x200)) {      /* Under DOS */
510             sv_setnv(sv, (double)errno);
511             sv_setpv(sv, errno ? Strerror(errno) : "");
512         } else {
513             if (errno != errno_isOS2) {
514                 int tmp = _syserrno();
515                 if (tmp)        /* 2nd call to _syserrno() makes it 0 */
516                     Perl_rc = tmp;
517             }
518             sv_setnv(sv, (double)Perl_rc);
519             sv_setpv(sv, os2error(Perl_rc));
520         }
521 #else
522 #ifdef WIN32
523         {
524             DWORD dwErr = GetLastError();
525             sv_setnv(sv, (double)dwErr);
526             if (dwErr)
527             {
528                 PerlProc_GetOSError(sv, dwErr);
529             }
530             else
531                 sv_setpv(sv, "");
532             SetLastError(dwErr);
533         }
534 #else
535         sv_setnv(sv, (double)errno);
536         sv_setpv(sv, errno ? Strerror(errno) : "");
537 #endif
538 #endif
539 #endif
540         SvNOK_on(sv);   /* what a wonderful hack! */
541         break;
542     case '\006':                /* ^F */
543         sv_setiv(sv, (IV)PL_maxsysfd);
544         break;
545     case '\010':                /* ^H */
546         sv_setiv(sv, (IV)PL_hints);
547         break;
548     case '\011':                /* ^I */ /* NOT \t in EBCDIC */
549         if (PL_inplace)
550             sv_setpv(sv, PL_inplace);
551         else
552             sv_setsv(sv, &PL_sv_undef);
553         break;
554     case '\017':                /* ^O */
555         sv_setpv(sv, PL_osname);
556         break;
557     case '\020':                /* ^P */
558         sv_setiv(sv, (IV)PL_perldb);
559         break;
560     case '\023':                /* ^S */
561         {
562             dTHR;
563             if (PL_lex_state != LEX_NOTPARSING)
564                 SvOK_off(sv);
565             else if (PL_in_eval)
566                 sv_setiv(sv, 1);
567             else
568                 sv_setiv(sv, 0);
569         }
570         break;
571     case '\024':                /* ^T */
572 #ifdef BIG_TIME
573         sv_setnv(sv, PL_basetime);
574 #else
575         sv_setiv(sv, (IV)PL_basetime);
576 #endif
577         break;
578     case '\027':                /* ^W */
579         sv_setiv(sv, (IV)((PL_dowarn & G_WARN_ON) == G_WARN_ON));
580         break;
581     case '1': case '2': case '3': case '4':
582     case '5': case '6': case '7': case '8': case '9': case '&':
583         if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
584             I32 s1, t1;
585
586             /*
587              * Pre-threads, this was paren = atoi(GvENAME((GV*)mg->mg_obj));
588              * XXX Does the new way break anything?
589              */
590             paren = atoi(mg->mg_ptr);
591           getparen:
592             if (paren <= rx->nparens &&
593                 (s1 = rx->startp[paren]) != -1 &&
594                 (t1 = rx->endp[paren]) != -1)
595             {
596                 i = t1 - s1;
597                 s = rx->subbeg + s1;
598               getrx:
599                 if (i >= 0) {
600                     bool was_tainted;
601                     if (PL_tainting) {
602                         was_tainted = PL_tainted;
603                         PL_tainted = FALSE;
604                     }
605                     sv_setpvn(sv, s, i);
606                     if (PL_tainting)
607                         PL_tainted = (was_tainted || RX_MATCH_TAINTED(rx));
608                     break;
609                 }
610             }
611         }
612         sv_setsv(sv,&PL_sv_undef);
613         break;
614     case '+':
615         if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
616             paren = rx->lastparen;
617             if (paren)
618                 goto getparen;
619         }
620         sv_setsv(sv,&PL_sv_undef);
621         break;
622     case '`':
623         if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
624             if ((s = rx->subbeg) && rx->startp[0] != -1) {
625                 i = rx->startp[0];
626                 goto getrx;
627             }
628         }
629         sv_setsv(sv,&PL_sv_undef);
630         break;
631     case '\'':
632         if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
633             if (rx->subbeg && rx->endp[0] != -1) {
634                 s = rx->subbeg + rx->endp[0];
635                 i = rx->sublen - rx->endp[0];
636                 goto getrx;
637             }
638         }
639         sv_setsv(sv,&PL_sv_undef);
640         break;
641     case '.':
642 #ifndef lint
643         if (GvIO(PL_last_in_gv)) {
644             sv_setiv(sv, (IV)IoLINES(GvIO(PL_last_in_gv)));
645         }
646 #endif
647         break;
648     case '?':
649         {
650             sv_setiv(sv, (IV)STATUS_CURRENT);
651 #ifdef COMPLEX_STATUS
652             LvTARGOFF(sv) = PL_statusvalue;
653             LvTARGLEN(sv) = PL_statusvalue_vms;
654 #endif
655         }
656         break;
657     case '^':
658         s = IoTOP_NAME(GvIOp(PL_defoutgv));
659         if (s)
660             sv_setpv(sv,s);
661         else {
662             sv_setpv(sv,GvENAME(PL_defoutgv));
663             sv_catpv(sv,"_TOP");
664         }
665         break;
666     case '~':
667         s = IoFMT_NAME(GvIOp(PL_defoutgv));
668         if (!s)
669             s = GvENAME(PL_defoutgv);
670         sv_setpv(sv,s);
671         break;
672 #ifndef lint
673     case '=':
674         sv_setiv(sv, (IV)IoPAGE_LEN(GvIOp(PL_defoutgv)));
675         break;
676     case '-':
677         sv_setiv(sv, (IV)IoLINES_LEFT(GvIOp(PL_defoutgv)));
678         break;
679     case '%':
680         sv_setiv(sv, (IV)IoPAGE(GvIOp(PL_defoutgv)));
681         break;
682 #endif
683     case ':':
684         break;
685     case '/':
686         break;
687     case '[':
688         WITH_THR(sv_setiv(sv, (IV)PL_curcop->cop_arybase));
689         break;
690     case '|':
691         sv_setiv(sv, (IV)(IoFLAGS(GvIOp(PL_defoutgv)) & IOf_FLUSH) != 0 );
692         break;
693     case ',':
694         sv_setpvn(sv,PL_ofs,PL_ofslen);
695         break;
696     case '\\':
697         sv_setpvn(sv,PL_ors,PL_orslen);
698         break;
699     case '#':
700         sv_setpv(sv,PL_ofmt);
701         break;
702     case '!':
703 #ifdef VMS
704         sv_setnv(sv, (double)((errno == EVMSERR) ? vaxc$errno : errno));
705         sv_setpv(sv, errno ? Strerror(errno) : "");
706 #else
707         {
708         int saveerrno = errno;
709         sv_setnv(sv, (double)errno);
710 #ifdef OS2
711         if (errno == errno_isOS2) sv_setpv(sv, os2error(Perl_rc));
712         else
713 #endif
714         sv_setpv(sv, errno ? Strerror(errno) : "");
715         errno = saveerrno;
716         }
717 #endif
718         SvNOK_on(sv);   /* what a wonderful hack! */
719         break;
720     case '<':
721         sv_setiv(sv, (IV)PL_uid);
722         break;
723     case '>':
724         sv_setiv(sv, (IV)PL_euid);
725         break;
726     case '(':
727         sv_setiv(sv, (IV)PL_gid);
728         Perl_sv_setpvf(aTHX_ sv, "%Vd", (IV)PL_gid);
729         goto add_groups;
730     case ')':
731         sv_setiv(sv, (IV)PL_egid);
732         Perl_sv_setpvf(aTHX_ sv, "%Vd", (IV)PL_egid);
733       add_groups:
734 #ifdef HAS_GETGROUPS
735         {
736             Groups_t gary[NGROUPS];
737             i = getgroups(NGROUPS,gary);
738             while (--i >= 0)
739                 Perl_sv_catpvf(aTHX_ sv, " %Vd", (IV)gary[i]);
740         }
741 #endif
742         SvIOK_on(sv);   /* what a wonderful hack! */
743         break;
744     case '*':
745         break;
746     case '0':
747         break;
748 #ifdef USE_THREADS
749     case '@':
750         sv_setsv(sv, thr->errsv);
751         break;
752 #endif /* USE_THREADS */
753     }
754     return 0;
755 }
756
757 int
758 Perl_magic_getuvar(pTHX_ SV *sv, MAGIC *mg)
759 {
760     struct ufuncs *uf = (struct ufuncs *)mg->mg_ptr;
761
762     if (uf && uf->uf_val)
763         (*uf->uf_val)(uf->uf_index, sv);
764     return 0;
765 }
766
767 int
768 Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg)
769 {
770     register char *s;
771     char *ptr;
772     STRLEN len, klen;
773     I32 i;
774
775     s = SvPV(sv,len);
776     ptr = MgPV(mg,klen);
777     my_setenv(ptr, s);
778
779 #ifdef DYNAMIC_ENV_FETCH
780      /* We just undefd an environment var.  Is a replacement */
781      /* waiting in the wings? */
782     if (!len) {
783         SV **valp;
784         if ((valp = hv_fetch(GvHVn(PL_envgv), ptr, klen, FALSE)))
785             s = SvPV(*valp, len);
786     }
787 #endif
788
789 #if !defined(OS2) && !defined(AMIGAOS) && !defined(WIN32) && !defined(MSDOS)
790                             /* And you'll never guess what the dog had */
791                             /*   in its mouth... */
792     if (PL_tainting) {
793         MgTAINTEDDIR_off(mg);
794 #ifdef VMS
795         if (s && klen == 8 && strEQ(ptr, "DCL$PATH")) {
796             char pathbuf[256], eltbuf[256], *cp, *elt = s;
797             struct stat sbuf;
798             int i = 0, j = 0;
799
800             do {          /* DCL$PATH may be a search list */
801                 while (1) {   /* as may dev portion of any element */
802                     if ( ((cp = strchr(elt,'[')) || (cp = strchr(elt,'<'))) ) {
803                         if ( *(cp+1) == '.' || *(cp+1) == '-' ||
804                              cando_by_name(S_IWUSR,0,elt) ) {
805                             MgTAINTEDDIR_on(mg);
806                             return 0;
807                         }
808                     }
809                     if ((cp = strchr(elt, ':')) != Nullch)
810                         *cp = '\0';
811                     if (my_trnlnm(elt, eltbuf, j++))
812                         elt = eltbuf;
813                     else
814                         break;
815                 }
816                 j = 0;
817             } while (my_trnlnm(s, pathbuf, i++) && (elt = pathbuf));
818         }
819 #endif /* VMS */
820         if (s && klen == 4 && strEQ(ptr,"PATH")) {
821             char *strend = s + len;
822
823             while (s < strend) {
824                 char tmpbuf[256];
825                 struct stat st;
826                 s = delimcpy(tmpbuf, tmpbuf + sizeof tmpbuf,
827                              s, strend, ':', &i);
828                 s++;
829                 if (i >= sizeof tmpbuf   /* too long -- assume the worst */
830                       || *tmpbuf != '/'
831                       || (PerlLIO_stat(tmpbuf, &st) == 0 && (st.st_mode & 2)) ) {
832                     MgTAINTEDDIR_on(mg);
833                     return 0;
834                 }
835             }
836         }
837     }
838 #endif /* neither OS2 nor AMIGAOS nor WIN32 nor MSDOS */
839
840     return 0;
841 }
842
843 int
844 Perl_magic_clearenv(pTHX_ SV *sv, MAGIC *mg)
845 {
846     STRLEN n_a;
847     my_setenv(MgPV(mg,n_a),Nullch);
848     return 0;
849 }
850
851 int
852 Perl_magic_set_all_env(pTHX_ SV *sv, MAGIC *mg)
853 {
854 #if defined(VMS)
855     Perl_die(aTHX_ "Can't make list assignment to %%ENV on this system");
856 #else
857     dTHR;
858     if (PL_localizing) {
859         HE* entry;
860         STRLEN n_a;
861         magic_clear_all_env(sv,mg);
862         hv_iterinit((HV*)sv);
863         while (entry = hv_iternext((HV*)sv)) {
864             I32 keylen;
865             my_setenv(hv_iterkey(entry, &keylen),
866                       SvPV(hv_iterval((HV*)sv, entry), n_a));
867         }
868     }
869 #endif
870     return 0;
871 }
872
873 int
874 Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg)
875 {
876 #if defined(VMS)
877     Perl_die(aTHX_ "Can't make list assignment to %%ENV on this system");
878 #else
879 #  ifdef WIN32
880     char *envv = GetEnvironmentStrings();
881     char *cur = envv;
882     STRLEN len;
883     while (*cur) {
884         char *end = strchr(cur,'=');
885         if (end && end != cur) {
886             *end = '\0';
887             my_setenv(cur,Nullch);
888             *end = '=';
889             cur = end + strlen(end+1)+2;
890         }
891         else if ((len = strlen(cur)))
892             cur += len+1;
893     }
894     FreeEnvironmentStrings(envv);
895 #  else
896 #    ifndef PERL_USE_SAFE_PUTENV
897     I32 i;
898
899     if (environ == PL_origenviron)
900         environ = (char**)safesysmalloc(sizeof(char*));
901     else
902         for (i = 0; environ[i]; i++)
903             safesysfree(environ[i]);
904 #    endif /* PERL_USE_SAFE_PUTENV */
905
906     environ[0] = Nullch;
907
908 #  endif /* WIN32 */
909 #endif /* VMS */
910     return 0;
911 }
912
913 int
914 Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg)
915 {
916     I32 i;
917     STRLEN n_a;
918     /* Are we fetching a signal entry? */
919     i = whichsig(MgPV(mg,n_a));
920     if (i) {
921         if(PL_psig_ptr[i])
922             sv_setsv(sv,PL_psig_ptr[i]);
923         else {
924             Sighandler_t sigstate = rsignal_state(i);
925
926             /* cache state so we don't fetch it again */
927             if(sigstate == SIG_IGN)
928                 sv_setpv(sv,"IGNORE");
929             else
930                 sv_setsv(sv,&PL_sv_undef);
931             PL_psig_ptr[i] = SvREFCNT_inc(sv);
932             SvTEMP_off(sv);
933         }
934     }
935     return 0;
936 }
937 int
938 Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg)
939 {
940     I32 i;
941     STRLEN n_a;
942     /* Are we clearing a signal entry? */
943     i = whichsig(MgPV(mg,n_a));
944     if (i) {
945         if(PL_psig_ptr[i]) {
946             SvREFCNT_dec(PL_psig_ptr[i]);
947             PL_psig_ptr[i]=0;
948         }
949         if(PL_psig_name[i]) {
950             SvREFCNT_dec(PL_psig_name[i]);
951             PL_psig_name[i]=0;
952         }
953     }
954     return 0;
955 }
956
957 int
958 Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
959 {
960     dTHR;
961     register char *s;
962     I32 i;
963     SV** svp;
964     STRLEN len;
965
966     s = MgPV(mg,len);
967     if (*s == '_') {
968         if (strEQ(s,"__DIE__"))
969             svp = &PL_diehook;
970         else if (strEQ(s,"__WARN__"))
971             svp = &PL_warnhook;
972         else if (strEQ(s,"__PARSE__"))
973             svp = &PL_parsehook;
974         else
975             Perl_croak(aTHX_ "No such hook: %s", s);
976         i = 0;
977         if (*svp) {
978             SvREFCNT_dec(*svp);
979             *svp = 0;
980         }
981     }
982     else {
983         i = whichsig(s);        /* ...no, a brick */
984         if (!i) {
985             if (ckWARN(WARN_SIGNAL) || strEQ(s,"ALARM"))
986                 Perl_warner(aTHX_ WARN_SIGNAL, "No such signal: SIG%s", s);
987             return 0;
988         }
989         SvREFCNT_dec(PL_psig_name[i]);
990         SvREFCNT_dec(PL_psig_ptr[i]);
991         PL_psig_ptr[i] = SvREFCNT_inc(sv);
992         SvTEMP_off(sv); /* Make sure it doesn't go away on us */
993         PL_psig_name[i] = newSVpvn(s, len);
994         SvREADONLY_on(PL_psig_name[i]);
995     }
996     if (SvTYPE(sv) == SVt_PVGV || SvROK(sv)) {
997         if (i)
998             (void)rsignal(i, PL_sighandlerp);
999         else
1000             *svp = SvREFCNT_inc(sv);
1001         return 0;
1002     }
1003     s = SvPV_force(sv,len);
1004     if (strEQ(s,"IGNORE")) {
1005         if (i)
1006             (void)rsignal(i, SIG_IGN);
1007         else
1008             *svp = 0;
1009     }
1010     else if (strEQ(s,"DEFAULT") || !*s) {
1011         if (i)
1012             (void)rsignal(i, SIG_DFL);
1013         else
1014             *svp = 0;
1015     }
1016     else {
1017         /*
1018          * We should warn if HINT_STRICT_REFS, but without
1019          * access to a known hint bit in a known OP, we can't
1020          * tell whether HINT_STRICT_REFS is in force or not.
1021          */
1022         if (!strchr(s,':') && !strchr(s,'\''))
1023             sv_insert(sv, 0, 0, "main::", 6);
1024         if (i)
1025             (void)rsignal(i, PL_sighandlerp);
1026         else
1027             *svp = SvREFCNT_inc(sv);
1028     }
1029     return 0;
1030 }
1031
1032 int
1033 Perl_magic_setisa(pTHX_ SV *sv, MAGIC *mg)
1034 {
1035     PL_sub_generation++;
1036     return 0;
1037 }
1038
1039 int
1040 Perl_magic_setamagic(pTHX_ SV *sv, MAGIC *mg)
1041 {
1042     /* HV_badAMAGIC_on(Sv_STASH(sv)); */
1043     PL_amagic_generation++;
1044
1045     return 0;
1046 }
1047
1048 int
1049 Perl_magic_getnkeys(pTHX_ SV *sv, MAGIC *mg)
1050 {
1051     HV *hv = (HV*)LvTARG(sv);
1052     HE *entry;
1053     I32 i = 0;
1054
1055     if (hv) {
1056         (void) hv_iterinit(hv);
1057         if (! SvTIED_mg((SV*)hv, 'P'))
1058             i = HvKEYS(hv);
1059         else {
1060             /*SUPPRESS 560*/
1061             while (entry = hv_iternext(hv)) {
1062                 i++;
1063             }
1064         }
1065     }
1066
1067     sv_setiv(sv, (IV)i);
1068     return 0;
1069 }
1070
1071 int
1072 Perl_magic_setnkeys(pTHX_ SV *sv, MAGIC *mg)
1073 {
1074     if (LvTARG(sv)) {
1075         hv_ksplit((HV*)LvTARG(sv), SvIV(sv));
1076     }
1077     return 0;
1078 }          
1079
1080 /* caller is responsible for stack switching/cleanup */
1081 STATIC int
1082 S_magic_methcall(pTHX_ SV *sv, MAGIC *mg, char *meth, I32 flags, int n, SV *val)
1083 {
1084     dSP;
1085
1086     PUSHMARK(SP);
1087     EXTEND(SP, n);
1088     PUSHs(SvTIED_obj(sv, mg));
1089     if (n > 1) { 
1090         if (mg->mg_ptr) {
1091             if (mg->mg_len >= 0)
1092                 PUSHs(sv_2mortal(newSVpvn(mg->mg_ptr, mg->mg_len)));
1093             else if (mg->mg_len == HEf_SVKEY)
1094                 PUSHs((SV*)mg->mg_ptr);
1095         }
1096         else if (mg->mg_type == 'p') {
1097             PUSHs(sv_2mortal(newSViv(mg->mg_len)));
1098         }
1099     }
1100     if (n > 2) {
1101         PUSHs(val);
1102     }
1103     PUTBACK;
1104
1105     return call_method(meth, flags);
1106 }
1107
1108 STATIC int
1109 S_magic_methpack(pTHX_ SV *sv, MAGIC *mg, char *meth)
1110 {
1111     dSP;
1112
1113     ENTER;
1114     SAVETMPS;
1115     PUSHSTACKi(PERLSI_MAGIC);
1116
1117     if (magic_methcall(sv, mg, meth, G_SCALAR, 2, NULL)) {
1118         sv_setsv(sv, *PL_stack_sp--);
1119     }
1120
1121     POPSTACK;
1122     FREETMPS;
1123     LEAVE;
1124     return 0;
1125 }
1126
1127 int
1128 Perl_magic_getpack(pTHX_ SV *sv, MAGIC *mg)
1129 {
1130     magic_methpack(sv,mg,"FETCH");
1131     if (mg->mg_ptr)
1132         mg->mg_flags |= MGf_GSKIP;
1133     return 0;
1134 }
1135
1136 int
1137 Perl_magic_setpack(pTHX_ SV *sv, MAGIC *mg)
1138 {
1139     dSP;
1140     ENTER;
1141     PUSHSTACKi(PERLSI_MAGIC);
1142     magic_methcall(sv, mg, "STORE", G_SCALAR|G_DISCARD, 3, sv);
1143     POPSTACK;
1144     LEAVE;
1145     return 0;
1146 }
1147
1148 int
1149 Perl_magic_clearpack(pTHX_ SV *sv, MAGIC *mg)
1150 {
1151     return magic_methpack(sv,mg,"DELETE");
1152 }
1153
1154
1155 U32
1156 Perl_magic_sizepack(pTHX_ SV *sv, MAGIC *mg)
1157 {         
1158     dSP;
1159     U32 retval = 0;
1160
1161     ENTER;
1162     SAVETMPS;
1163     PUSHSTACKi(PERLSI_MAGIC);
1164     if (magic_methcall(sv, mg, "FETCHSIZE", G_SCALAR, 2, NULL)) {
1165         sv = *PL_stack_sp--;
1166         retval = (U32) SvIV(sv)-1;
1167     }
1168     POPSTACK;
1169     FREETMPS;
1170     LEAVE;
1171     return retval;
1172 }
1173
1174 int
1175 Perl_magic_wipepack(pTHX_ SV *sv, MAGIC *mg)
1176 {
1177     dSP;
1178
1179     ENTER;
1180     PUSHSTACKi(PERLSI_MAGIC);
1181     PUSHMARK(SP);
1182     XPUSHs(SvTIED_obj(sv, mg));
1183     PUTBACK;
1184     call_method("CLEAR", G_SCALAR|G_DISCARD);
1185     POPSTACK;
1186     LEAVE;
1187     return 0;
1188 }
1189
1190 int
1191 Perl_magic_nextpack(pTHX_ SV *sv, MAGIC *mg, SV *key)
1192 {
1193     dSP;
1194     char *meth = SvOK(key) ? "NEXTKEY" : "FIRSTKEY";
1195
1196     ENTER;
1197     SAVETMPS;
1198     PUSHSTACKi(PERLSI_MAGIC);
1199     PUSHMARK(SP);
1200     EXTEND(SP, 2);
1201     PUSHs(SvTIED_obj(sv, mg));
1202     if (SvOK(key))
1203         PUSHs(key);
1204     PUTBACK;
1205
1206     if (call_method(meth, G_SCALAR))
1207         sv_setsv(key, *PL_stack_sp--);
1208
1209     POPSTACK;
1210     FREETMPS;
1211     LEAVE;
1212     return 0;
1213 }
1214
1215 int
1216 Perl_magic_existspack(pTHX_ SV *sv, MAGIC *mg)
1217 {
1218     return magic_methpack(sv,mg,"EXISTS");
1219
1220
1221 int
1222 Perl_magic_setdbline(pTHX_ SV *sv, MAGIC *mg)
1223 {
1224     dTHR;
1225     OP *o;
1226     I32 i;
1227     GV* gv;
1228     SV** svp;
1229     STRLEN n_a;
1230
1231     gv = PL_DBline;
1232     i = SvTRUE(sv);
1233     svp = av_fetch(GvAV(gv),
1234                      atoi(MgPV(mg,n_a)), FALSE);
1235     if (svp && SvIOKp(*svp) && (o = (OP*)SvSTASH(*svp)))
1236         o->op_private = i;
1237     else
1238         Perl_warn(aTHX_ "Can't break at that line\n");
1239     return 0;
1240 }
1241
1242 int
1243 Perl_magic_getarylen(pTHX_ SV *sv, MAGIC *mg)
1244 {
1245     dTHR;
1246     sv_setiv(sv, AvFILL((AV*)mg->mg_obj) + PL_curcop->cop_arybase);
1247     return 0;
1248 }
1249
1250 int
1251 Perl_magic_setarylen(pTHX_ SV *sv, MAGIC *mg)
1252 {
1253     dTHR;
1254     av_fill((AV*)mg->mg_obj, SvIV(sv) - PL_curcop->cop_arybase);
1255     return 0;
1256 }
1257
1258 int
1259 Perl_magic_getpos(pTHX_ SV *sv, MAGIC *mg)
1260 {
1261     SV* lsv = LvTARG(sv);
1262     
1263     if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv)) {
1264         mg = mg_find(lsv, 'g');
1265         if (mg && mg->mg_len >= 0) {
1266             dTHR;
1267             I32 i = mg->mg_len;
1268             if (IN_UTF8)
1269                 sv_pos_b2u(lsv, &i);
1270             sv_setiv(sv, i + PL_curcop->cop_arybase);
1271             return 0;
1272         }
1273     }
1274     (void)SvOK_off(sv);
1275     return 0;
1276 }
1277
1278 int
1279 Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg)
1280 {
1281     SV* lsv = LvTARG(sv);
1282     SSize_t pos;
1283     STRLEN len;
1284     STRLEN ulen;
1285     dTHR;
1286
1287     mg = 0;
1288     
1289     if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv))
1290         mg = mg_find(lsv, 'g');
1291     if (!mg) {
1292         if (!SvOK(sv))
1293             return 0;
1294         sv_magic(lsv, (SV*)0, 'g', Nullch, 0);
1295         mg = mg_find(lsv, 'g');
1296     }
1297     else if (!SvOK(sv)) {
1298         mg->mg_len = -1;
1299         return 0;
1300     }
1301     len = SvPOK(lsv) ? SvCUR(lsv) : sv_len(lsv);
1302
1303     pos = SvIV(sv) - PL_curcop->cop_arybase;
1304
1305     if (IN_UTF8) {
1306         ulen = sv_len_utf8(lsv);
1307         if (ulen)
1308             len = ulen;
1309         else
1310             ulen = 0;
1311     }
1312
1313     if (pos < 0) {
1314         pos += len;
1315         if (pos < 0)
1316             pos = 0;
1317     }
1318     else if (pos > len)
1319         pos = len;
1320
1321     if (ulen) {
1322         I32 p = pos;
1323         sv_pos_u2b(lsv, &p, 0);
1324         pos = p;
1325     }
1326         
1327     mg->mg_len = pos;
1328     mg->mg_flags &= ~MGf_MINMATCH;
1329
1330     return 0;
1331 }
1332
1333 int
1334 Perl_magic_getglob(pTHX_ SV *sv, MAGIC *mg)
1335 {
1336     if (SvFAKE(sv)) {                   /* FAKE globs can get coerced */
1337         SvFAKE_off(sv);
1338         gv_efullname3(sv,((GV*)sv), "*");
1339         SvFAKE_on(sv);
1340     }
1341     else
1342         gv_efullname3(sv,((GV*)sv), "*");       /* a gv value, be nice */
1343     return 0;
1344 }
1345
1346 int
1347 Perl_magic_setglob(pTHX_ SV *sv, MAGIC *mg)
1348 {
1349     register char *s;
1350     GV* gv;
1351     STRLEN n_a;
1352
1353     if (!SvOK(sv))
1354         return 0;
1355     s = SvPV(sv, n_a);
1356     if (*s == '*' && s[1])
1357         s++;
1358     gv = gv_fetchpv(s,TRUE, SVt_PVGV);
1359     if (sv == (SV*)gv)
1360         return 0;
1361     if (GvGP(sv))
1362         gp_free((GV*)sv);
1363     GvGP(sv) = gp_ref(GvGP(gv));
1364     return 0;
1365 }
1366
1367 int
1368 Perl_magic_getsubstr(pTHX_ SV *sv, MAGIC *mg)
1369 {
1370     STRLEN len;
1371     SV *lsv = LvTARG(sv);
1372     char *tmps = SvPV(lsv,len);
1373     I32 offs = LvTARGOFF(sv);
1374     I32 rem = LvTARGLEN(sv);
1375
1376     if (offs > len)
1377         offs = len;
1378     if (rem + offs > len)
1379         rem = len - offs;
1380     sv_setpvn(sv, tmps + offs, (STRLEN)rem);
1381     return 0;
1382 }
1383
1384 int
1385 Perl_magic_setsubstr(pTHX_ SV *sv, MAGIC *mg)
1386 {
1387     STRLEN len;
1388     char *tmps = SvPV(sv,len);
1389     sv_insert(LvTARG(sv),LvTARGOFF(sv),LvTARGLEN(sv), tmps, len);
1390     return 0;
1391 }
1392
1393 int
1394 Perl_magic_gettaint(pTHX_ SV *sv, MAGIC *mg)
1395 {
1396     dTHR;
1397     TAINT_IF((mg->mg_len & 1) ||
1398              (mg->mg_len & 2) && mg->mg_obj == sv);     /* kludge */
1399     return 0;
1400 }
1401
1402 int
1403 Perl_magic_settaint(pTHX_ SV *sv, MAGIC *mg)
1404 {
1405     dTHR;
1406     if (PL_localizing) {
1407         if (PL_localizing == 1)
1408             mg->mg_len <<= 1;
1409         else
1410             mg->mg_len >>= 1;
1411     }
1412     else if (PL_tainted)
1413         mg->mg_len |= 1;
1414     else
1415         mg->mg_len &= ~1;
1416     return 0;
1417 }
1418
1419 int
1420 Perl_magic_getvec(pTHX_ SV *sv, MAGIC *mg)
1421 {
1422     SV *lsv = LvTARG(sv);
1423     unsigned char *s;
1424     unsigned long retnum;
1425     STRLEN lsvlen;
1426     I32 len;
1427     I32 offset;
1428     I32 size;
1429
1430     if (!lsv) {
1431         SvOK_off(sv);
1432         return 0;
1433     }
1434     s = (unsigned char *) SvPV(lsv, lsvlen);
1435     offset = LvTARGOFF(sv);
1436     size = LvTARGLEN(sv);
1437     len = (offset + size + 7) / 8;
1438
1439     /* Copied from pp_vec() */
1440
1441     if (len > lsvlen) {
1442         if (size <= 8)
1443             retnum = 0;
1444         else {
1445             offset >>= 3;
1446             if (size == 16) {
1447                 if (offset >= lsvlen)
1448                     retnum = 0;
1449                 else
1450                     retnum = (unsigned long) s[offset] << 8;
1451             }
1452             else if (size == 32) {
1453                 if (offset >= lsvlen)
1454                     retnum = 0;
1455                 else if (offset + 1 >= lsvlen)
1456                     retnum = (unsigned long) s[offset] << 24;
1457                 else if (offset + 2 >= lsvlen)
1458                     retnum = ((unsigned long) s[offset] << 24) +
1459                         ((unsigned long) s[offset + 1] << 16);
1460                 else
1461                     retnum = ((unsigned long) s[offset] << 24) +
1462                         ((unsigned long) s[offset + 1] << 16) +
1463                         (s[offset + 2] << 8);
1464             }
1465         }
1466     }
1467     else if (size < 8)
1468         retnum = (s[offset >> 3] >> (offset & 7)) & ((1 << size) - 1);
1469     else {
1470         offset >>= 3;
1471         if (size == 8)
1472             retnum = s[offset];
1473         else if (size == 16)
1474             retnum = ((unsigned long) s[offset] << 8) + s[offset+1];
1475         else if (size == 32)
1476             retnum = ((unsigned long) s[offset] << 24) +
1477                 ((unsigned long) s[offset + 1] << 16) +
1478                 (s[offset + 2] << 8) + s[offset+3];
1479     }
1480
1481     sv_setuv(sv, (UV)retnum);
1482     return 0;
1483 }
1484
1485 int
1486 Perl_magic_setvec(pTHX_ SV *sv, MAGIC *mg)
1487 {
1488     do_vecset(sv);      /* XXX slurp this routine */
1489     return 0;
1490 }
1491
1492 int
1493 Perl_magic_getdefelem(pTHX_ SV *sv, MAGIC *mg)
1494 {
1495     SV *targ = Nullsv;
1496     if (LvTARGLEN(sv)) {
1497         if (mg->mg_obj) {
1498             SV *ahv = LvTARG(sv);
1499             if (SvTYPE(ahv) == SVt_PVHV) {
1500                 HE *he = hv_fetch_ent((HV*)ahv, mg->mg_obj, FALSE, 0);
1501                 if (he)
1502                     targ = HeVAL(he);
1503             }
1504             else {
1505                 SV **svp = avhv_fetch_ent((AV*)ahv, mg->mg_obj, FALSE, 0);
1506                 if (svp)
1507                     targ = *svp;
1508             }
1509         }
1510         else {
1511             AV* av = (AV*)LvTARG(sv);
1512             if ((I32)LvTARGOFF(sv) <= AvFILL(av))
1513                 targ = AvARRAY(av)[LvTARGOFF(sv)];
1514         }
1515         if (targ && targ != &PL_sv_undef) {
1516             dTHR;               /* just for SvREFCNT_dec */
1517             /* somebody else defined it for us */
1518             SvREFCNT_dec(LvTARG(sv));
1519             LvTARG(sv) = SvREFCNT_inc(targ);
1520             LvTARGLEN(sv) = 0;
1521             SvREFCNT_dec(mg->mg_obj);
1522             mg->mg_obj = Nullsv;
1523             mg->mg_flags &= ~MGf_REFCOUNTED;
1524         }
1525     }
1526     else
1527         targ = LvTARG(sv);
1528     sv_setsv(sv, targ ? targ : &PL_sv_undef);
1529     return 0;
1530 }
1531
1532 int
1533 Perl_magic_setdefelem(pTHX_ SV *sv, MAGIC *mg)
1534 {
1535     if (LvTARGLEN(sv))
1536         vivify_defelem(sv);
1537     if (LvTARG(sv)) {
1538         sv_setsv(LvTARG(sv), sv);
1539         SvSETMAGIC(LvTARG(sv));
1540     }
1541     return 0;
1542 }
1543
1544 void
1545 Perl_vivify_defelem(pTHX_ SV *sv)
1546 {
1547     dTHR;                       /* just for SvREFCNT_inc and SvREFCNT_dec*/
1548     MAGIC *mg;
1549     SV *value = Nullsv;
1550
1551     if (!LvTARGLEN(sv) || !(mg = mg_find(sv, 'y')))
1552         return;
1553     if (mg->mg_obj) {
1554         SV *ahv = LvTARG(sv);
1555         STRLEN n_a;
1556         if (SvTYPE(ahv) == SVt_PVHV) {
1557             HE *he = hv_fetch_ent((HV*)ahv, mg->mg_obj, TRUE, 0);
1558             if (he)
1559                 value = HeVAL(he);
1560         }
1561         else {
1562             SV **svp = avhv_fetch_ent((AV*)ahv, mg->mg_obj, TRUE, 0);
1563             if (svp)
1564                 value = *svp;
1565         }
1566         if (!value || value == &PL_sv_undef)
1567             Perl_croak(aTHX_ PL_no_helem, SvPV(mg->mg_obj, n_a));
1568     }
1569     else {
1570         AV* av = (AV*)LvTARG(sv);
1571         if ((I32)LvTARGLEN(sv) < 0 && (I32)LvTARGOFF(sv) > AvFILL(av))
1572             LvTARG(sv) = Nullsv;        /* array can't be extended */
1573         else {
1574             SV** svp = av_fetch(av, LvTARGOFF(sv), TRUE);
1575             if (!svp || (value = *svp) == &PL_sv_undef)
1576                 Perl_croak(aTHX_ PL_no_aelem, (I32)LvTARGOFF(sv));
1577         }
1578     }
1579     (void)SvREFCNT_inc(value);
1580     SvREFCNT_dec(LvTARG(sv));
1581     LvTARG(sv) = value;
1582     LvTARGLEN(sv) = 0;
1583     SvREFCNT_dec(mg->mg_obj);
1584     mg->mg_obj = Nullsv;
1585     mg->mg_flags &= ~MGf_REFCOUNTED;
1586 }
1587
1588 int
1589 Perl_magic_killbackrefs(pTHX_ SV *sv, MAGIC *mg)
1590 {
1591     AV *av = (AV*)mg->mg_obj;
1592     SV **svp = AvARRAY(av);
1593     I32 i = AvFILLp(av);
1594     while (i >= 0) {
1595         if (svp[i] && svp[i] != &PL_sv_undef) {
1596             if (!SvWEAKREF(svp[i]))
1597                 Perl_croak(aTHX_ "panic: magic_killbackrefs");
1598             /* XXX Should we check that it hasn't changed? */
1599             SvRV(svp[i]) = 0;
1600             SvOK_off(svp[i]);
1601             SvWEAKREF_off(svp[i]);
1602             svp[i] = &PL_sv_undef;
1603         }
1604         i--;
1605     }
1606     return 0;
1607 }
1608
1609 int
1610 Perl_magic_setmglob(pTHX_ SV *sv, MAGIC *mg)
1611 {
1612     mg->mg_len = -1;
1613     SvSCREAM_off(sv);
1614     return 0;
1615 }
1616
1617 int
1618 Perl_magic_setbm(pTHX_ SV *sv, MAGIC *mg)
1619 {
1620     sv_unmagic(sv, 'B');
1621     SvVALID_off(sv);
1622     return 0;
1623 }
1624
1625 int
1626 Perl_magic_setfm(pTHX_ SV *sv, MAGIC *mg)
1627 {
1628     sv_unmagic(sv, 'f');
1629     SvCOMPILED_off(sv);
1630     return 0;
1631 }
1632
1633 int
1634 Perl_magic_setuvar(pTHX_ SV *sv, MAGIC *mg)
1635 {
1636     struct ufuncs *uf = (struct ufuncs *)mg->mg_ptr;
1637
1638     if (uf && uf->uf_set)
1639         (*uf->uf_set)(uf->uf_index, sv);
1640     return 0;
1641 }
1642
1643 int
1644 Perl_magic_freeregexp(pTHX_ SV *sv, MAGIC *mg)
1645 {
1646     regexp *re = (regexp *)mg->mg_obj;
1647     ReREFCNT_dec(re);
1648     return 0;
1649 }
1650
1651 #ifdef USE_LOCALE_COLLATE
1652 int
1653 Perl_magic_setcollxfrm(pTHX_ SV *sv, MAGIC *mg)
1654 {
1655     /*
1656      * RenE<eacute> Descartes said "I think not."
1657      * and vanished with a faint plop.
1658      */
1659     if (mg->mg_ptr) {
1660         Safefree(mg->mg_ptr);
1661         mg->mg_ptr = NULL;
1662         mg->mg_len = -1;
1663     }
1664     return 0;
1665 }
1666 #endif /* USE_LOCALE_COLLATE */
1667
1668 int
1669 Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
1670 {
1671     dTHR;
1672     register char *s;
1673     I32 i;
1674     STRLEN len;
1675     switch (*mg->mg_ptr) {
1676     case '\001':        /* ^A */
1677         sv_setsv(PL_bodytarget, sv);
1678         break;
1679     case '\002':        /* ^B */
1680         if ( ! (PL_dowarn & G_WARN_ALL_MASK)) {
1681             if (memEQ(SvPVX(sv), WARN_ALLstring, WARNsize))
1682                 PL_compiling.cop_warnings = WARN_ALL;
1683             else if (memEQ(SvPVX(sv), WARN_NONEstring, WARNsize))
1684                 PL_compiling.cop_warnings = WARN_NONE;
1685             else {
1686                 if (PL_compiling.cop_warnings != WARN_NONE && 
1687                     PL_compiling.cop_warnings != WARN_ALL)
1688                     sv_setsv(PL_compiling.cop_warnings, sv);
1689                 else
1690                     PL_compiling.cop_warnings = newSVsv(sv) ;
1691             }
1692         }
1693         break;
1694
1695     case '\003':        /* ^C */
1696         PL_minus_c = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1697         break;
1698
1699     case '\004':        /* ^D */
1700         PL_debug = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) | 0x80000000;
1701         DEBUG_x(dump_all());
1702         break;
1703     case '\005':  /* ^E */
1704 #ifdef VMS
1705         set_vaxc_errno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1706 #else
1707 #ifdef WIN32
1708         SetLastError( SvIV(sv) );
1709 #else
1710         /* will anyone ever use this? */
1711         SETERRNO(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv), 4);
1712 #endif
1713 #endif
1714         break;
1715     case '\006':        /* ^F */
1716         PL_maxsysfd = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1717         break;
1718     case '\010':        /* ^H */
1719         PL_hints = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1720         break;
1721     case '\011':        /* ^I */ /* NOT \t in EBCDIC */
1722         if (PL_inplace)
1723             Safefree(PL_inplace);
1724         if (SvOK(sv))
1725             PL_inplace = savepv(SvPV(sv,len));
1726         else
1727             PL_inplace = Nullch;
1728         break;
1729     case '\017':        /* ^O */
1730         if (PL_osname)
1731             Safefree(PL_osname);
1732         if (SvOK(sv))
1733             PL_osname = savepv(SvPV(sv,len));
1734         else
1735             PL_osname = Nullch;
1736         break;
1737     case '\020':        /* ^P */
1738         PL_perldb = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1739         break;
1740     case '\024':        /* ^T */
1741 #ifdef BIG_TIME
1742         PL_basetime = (Time_t)(SvNOK(sv) ? SvNVX(sv) : sv_2nv(sv));
1743 #else
1744         PL_basetime = (Time_t)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1745 #endif
1746         break;
1747     case '\027':        /* ^W */
1748         if ( ! (PL_dowarn & G_WARN_ALL_MASK)) {
1749             i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1750             PL_dowarn = (i ? G_WARN_ON : G_WARN_OFF) ;
1751         }
1752         break;
1753     case '.':
1754         if (PL_localizing) {
1755             if (PL_localizing == 1)
1756                 save_sptr((SV**)&PL_last_in_gv);
1757         }
1758         else if (SvOK(sv) && GvIO(PL_last_in_gv))
1759             IoLINES(GvIOp(PL_last_in_gv)) = (long)SvIV(sv);
1760         break;
1761     case '^':
1762         Safefree(IoTOP_NAME(GvIOp(PL_defoutgv)));
1763         IoTOP_NAME(GvIOp(PL_defoutgv)) = s = savepv(SvPV(sv,len));
1764         IoTOP_GV(GvIOp(PL_defoutgv)) = gv_fetchpv(s,TRUE, SVt_PVIO);
1765         break;
1766     case '~':
1767         Safefree(IoFMT_NAME(GvIOp(PL_defoutgv)));
1768         IoFMT_NAME(GvIOp(PL_defoutgv)) = s = savepv(SvPV(sv,len));
1769         IoFMT_GV(GvIOp(PL_defoutgv)) = gv_fetchpv(s,TRUE, SVt_PVIO);
1770         break;
1771     case '=':
1772         IoPAGE_LEN(GvIOp(PL_defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1773         break;
1774     case '-':
1775         IoLINES_LEFT(GvIOp(PL_defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1776         if (IoLINES_LEFT(GvIOp(PL_defoutgv)) < 0L)
1777             IoLINES_LEFT(GvIOp(PL_defoutgv)) = 0L;
1778         break;
1779     case '%':
1780         IoPAGE(GvIOp(PL_defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1781         break;
1782     case '|':
1783         {
1784             IO *io = GvIOp(PL_defoutgv);
1785             if ((SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) == 0)
1786                 IoFLAGS(io) &= ~IOf_FLUSH;
1787             else {
1788                 if (!(IoFLAGS(io) & IOf_FLUSH)) {
1789                     PerlIO *ofp = IoOFP(io);
1790                     if (ofp)
1791                         (void)PerlIO_flush(ofp);
1792                     IoFLAGS(io) |= IOf_FLUSH;
1793                 }
1794             }
1795         }
1796         break;
1797     case '*':
1798         i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1799         PL_multiline = (i != 0);
1800         break;
1801     case '/':
1802         SvREFCNT_dec(PL_nrs);
1803         PL_nrs = newSVsv(sv);
1804         SvREFCNT_dec(PL_rs);
1805         PL_rs = SvREFCNT_inc(PL_nrs);
1806         break;
1807     case '\\':
1808         if (PL_ors)
1809             Safefree(PL_ors);
1810         if (SvOK(sv) || SvGMAGICAL(sv))
1811             PL_ors = savepv(SvPV(sv,PL_orslen));
1812         else {
1813             PL_ors = Nullch;
1814             PL_orslen = 0;
1815         }
1816         break;
1817     case ',':
1818         if (PL_ofs)
1819             Safefree(PL_ofs);
1820         PL_ofs = savepv(SvPV(sv, PL_ofslen));
1821         break;
1822     case '#':
1823         if (PL_ofmt)
1824             Safefree(PL_ofmt);
1825         PL_ofmt = savepv(SvPV(sv,len));
1826         break;
1827     case '[':
1828         PL_compiling.cop_arybase = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1829         break;
1830     case '?':
1831 #ifdef COMPLEX_STATUS
1832         if (PL_localizing == 2) {
1833             PL_statusvalue = LvTARGOFF(sv);
1834             PL_statusvalue_vms = LvTARGLEN(sv);
1835         }
1836         else
1837 #endif
1838 #ifdef VMSISH_STATUS
1839         if (VMSISH_STATUS)
1840             STATUS_NATIVE_SET((U32)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)));
1841         else
1842 #endif
1843             STATUS_POSIX_SET(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1844         break;
1845     case '!':
1846         SETERRNO(SvIOK(sv) ? SvIVX(sv) : SvOK(sv) ? sv_2iv(sv) : 0,
1847                  (SvIV(sv) == EVMSERR) ? 4 : vaxc$errno);
1848         break;
1849     case '<':
1850         PL_uid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1851         if (PL_delaymagic) {
1852             PL_delaymagic |= DM_RUID;
1853             break;                              /* don't do magic till later */
1854         }
1855 #ifdef HAS_SETRUID
1856         (void)setruid((Uid_t)PL_uid);
1857 #else
1858 #ifdef HAS_SETREUID
1859         (void)setreuid((Uid_t)PL_uid, (Uid_t)-1);
1860 #else
1861 #ifdef HAS_SETRESUID
1862       (void)setresuid((Uid_t)PL_uid, (Uid_t)-1, (Uid_t)-1);
1863 #else
1864         if (PL_uid == PL_euid)          /* special case $< = $> */
1865             (void)PerlProc_setuid(PL_uid);
1866         else {
1867             PL_uid = (I32)PerlProc_getuid();
1868             Perl_croak(aTHX_ "setruid() not implemented");
1869         }
1870 #endif
1871 #endif
1872 #endif
1873         PL_uid = (I32)PerlProc_getuid();
1874         PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid));
1875         break;
1876     case '>':
1877         PL_euid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1878         if (PL_delaymagic) {
1879             PL_delaymagic |= DM_EUID;
1880             break;                              /* don't do magic till later */
1881         }
1882 #ifdef HAS_SETEUID
1883         (void)seteuid((Uid_t)PL_euid);
1884 #else
1885 #ifdef HAS_SETREUID
1886         (void)setreuid((Uid_t)-1, (Uid_t)PL_euid);
1887 #else
1888 #ifdef HAS_SETRESUID
1889         (void)setresuid((Uid_t)-1, (Uid_t)PL_euid, (Uid_t)-1);
1890 #else
1891         if (PL_euid == PL_uid)          /* special case $> = $< */
1892             PerlProc_setuid(PL_euid);
1893         else {
1894             PL_euid = (I32)PerlProc_geteuid();
1895             Perl_croak(aTHX_ "seteuid() not implemented");
1896         }
1897 #endif
1898 #endif
1899 #endif
1900         PL_euid = (I32)PerlProc_geteuid();
1901         PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid));
1902         break;
1903     case '(':
1904         PL_gid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1905         if (PL_delaymagic) {
1906             PL_delaymagic |= DM_RGID;
1907             break;                              /* don't do magic till later */
1908         }
1909 #ifdef HAS_SETRGID
1910         (void)setrgid((Gid_t)PL_gid);
1911 #else
1912 #ifdef HAS_SETREGID
1913         (void)setregid((Gid_t)PL_gid, (Gid_t)-1);
1914 #else
1915 #ifdef HAS_SETRESGID
1916       (void)setresgid((Gid_t)PL_gid, (Gid_t)-1, (Gid_t) 1);
1917 #else
1918         if (PL_gid == PL_egid)                  /* special case $( = $) */
1919             (void)PerlProc_setgid(PL_gid);
1920         else {
1921             PL_gid = (I32)PerlProc_getgid();
1922             Perl_croak(aTHX_ "setrgid() not implemented");
1923         }
1924 #endif
1925 #endif
1926 #endif
1927         PL_gid = (I32)PerlProc_getgid();
1928         PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid));
1929         break;
1930     case ')':
1931 #ifdef HAS_SETGROUPS
1932         {
1933             char *p = SvPV(sv, len);
1934             Groups_t gary[NGROUPS];
1935
1936             while (isSPACE(*p))
1937                 ++p;
1938             PL_egid = I_V(atol(p));
1939             for (i = 0; i < NGROUPS; ++i) {
1940                 while (*p && !isSPACE(*p))
1941                     ++p;
1942                 while (isSPACE(*p))
1943                     ++p;
1944                 if (!*p)
1945                     break;
1946                 gary[i] = I_V(atol(p));
1947             }
1948             if (i)
1949                 (void)setgroups(i, gary);
1950         }
1951 #else  /* HAS_SETGROUPS */
1952         PL_egid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1953 #endif /* HAS_SETGROUPS */
1954         if (PL_delaymagic) {
1955             PL_delaymagic |= DM_EGID;
1956             break;                              /* don't do magic till later */
1957         }
1958 #ifdef HAS_SETEGID
1959         (void)setegid((Gid_t)PL_egid);
1960 #else
1961 #ifdef HAS_SETREGID
1962         (void)setregid((Gid_t)-1, (Gid_t)PL_egid);
1963 #else
1964 #ifdef HAS_SETRESGID
1965         (void)setresgid((Gid_t)-1, (Gid_t)PL_egid, (Gid_t)-1);
1966 #else
1967         if (PL_egid == PL_gid)                  /* special case $) = $( */
1968             (void)PerlProc_setgid(PL_egid);
1969         else {
1970             PL_egid = (I32)PerlProc_getegid();
1971             Perl_croak(aTHX_ "setegid() not implemented");
1972         }
1973 #endif
1974 #endif
1975 #endif
1976         PL_egid = (I32)PerlProc_getegid();
1977         PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid));
1978         break;
1979     case ':':
1980         PL_chopset = SvPV_force(sv,len);
1981         break;
1982     case '0':
1983         if (!PL_origalen) {
1984             s = PL_origargv[0];
1985             s += strlen(s);
1986             /* See if all the arguments are contiguous in memory */
1987             for (i = 1; i < PL_origargc; i++) {
1988                 if (PL_origargv[i] == s + 1
1989 #ifdef OS2
1990                     || PL_origargv[i] == s + 2
1991 #endif 
1992                    )
1993                 {
1994                     ++s;
1995                     s += strlen(s);     /* this one is ok too */
1996                 }
1997                 else
1998                     break;
1999             }
2000             /* can grab env area too? */
2001             if (PL_origenviron && (PL_origenviron[0] == s + 1
2002 #ifdef OS2
2003                                 || (PL_origenviron[0] == s + 9 && (s += 8))
2004 #endif 
2005                )) {
2006                 my_setenv("NoNe  SuCh", Nullch);
2007                                             /* force copy of environment */
2008                 for (i = 0; PL_origenviron[i]; i++)
2009                     if (PL_origenviron[i] == s + 1) {
2010                         ++s;
2011                         s += strlen(s);
2012                     }
2013                     else
2014                         break;
2015             }
2016             PL_origalen = s - PL_origargv[0];
2017         }
2018         s = SvPV_force(sv,len);
2019         i = len;
2020         if (i >= PL_origalen) {
2021             i = PL_origalen;
2022             /* don't allow system to limit $0 seen by script */
2023             /* SvCUR_set(sv, i); *SvEND(sv) = '\0'; */
2024             Copy(s, PL_origargv[0], i, char);
2025             s = PL_origargv[0]+i;
2026             *s = '\0';
2027         }
2028         else {
2029             Copy(s, PL_origargv[0], i, char);
2030             s = PL_origargv[0]+i;
2031             *s++ = '\0';
2032             while (++i < PL_origalen)
2033                 *s++ = ' ';
2034             s = PL_origargv[0]+i;
2035             for (i = 1; i < PL_origargc; i++)
2036                 PL_origargv[i] = Nullch;
2037         }
2038         break;
2039 #ifdef USE_THREADS
2040     case '@':
2041         sv_setsv(thr->errsv, sv);
2042         break;
2043 #endif /* USE_THREADS */
2044     }
2045     return 0;
2046 }
2047
2048 #ifdef USE_THREADS
2049 int
2050 Perl_magic_mutexfree(pTHX_ SV *sv, MAGIC *mg)
2051 {
2052     dTHR;
2053     DEBUG_S(PerlIO_printf(PerlIO_stderr(), "0x%lx: magic_mutexfree 0x%lx\n",
2054                           (unsigned long)thr, (unsigned long)sv);)
2055     if (MgOWNER(mg))
2056         Perl_croak(aTHX_ "panic: magic_mutexfree");
2057     MUTEX_DESTROY(MgMUTEXP(mg));
2058     COND_DESTROY(MgCONDP(mg));
2059     return 0;
2060 }
2061 #endif /* USE_THREADS */
2062
2063 I32
2064 Perl_whichsig(pTHX_ char *sig)
2065 {
2066     register char **sigv;
2067
2068     for (sigv = PL_sig_name+1; *sigv; sigv++)
2069         if (strEQ(sig,*sigv))
2070             return PL_sig_num[sigv - PL_sig_name];
2071 #ifdef SIGCLD
2072     if (strEQ(sig,"CHLD"))
2073         return SIGCLD;
2074 #endif
2075 #ifdef SIGCHLD
2076     if (strEQ(sig,"CLD"))
2077         return SIGCHLD;
2078 #endif
2079     return 0;
2080 }
2081
2082 static SV* sig_sv;
2083
2084 STATIC void
2085 S_unwind_handler_stack(pTHX_ void *p)
2086 {
2087     dTHR;
2088     U32 flags = *(U32*)p;
2089
2090     if (flags & 1)
2091         PL_savestack_ix -= 5; /* Unprotect save in progress. */
2092     /* cxstack_ix-- Not needed, die already unwound it. */
2093     if (flags & 64)
2094         SvREFCNT_dec(sig_sv);
2095 }
2096
2097 Signal_t
2098 Perl_sighandler(int sig)
2099 {
2100     dTHX;
2101     dSP;
2102     GV *gv = Nullgv;
2103     HV *st;
2104     SV *sv, *tSv = PL_Sv;
2105     CV *cv = Nullcv;
2106     OP *myop = PL_op;
2107     U32 flags = 0;
2108     I32 o_save_i = PL_savestack_ix, type;
2109     XPV *tXpv = PL_Xpv;
2110     
2111     if (PL_savestack_ix + 15 <= PL_savestack_max)
2112         flags |= 1;
2113     if (PL_markstack_ptr < PL_markstack_max - 2)
2114         flags |= 4;
2115     if (PL_retstack_ix < PL_retstack_max - 2)
2116         flags |= 8;
2117     if (PL_scopestack_ix < PL_scopestack_max - 3)
2118         flags |= 16;
2119
2120     if (!PL_psig_ptr[sig])
2121         Perl_die(aTHX_ "Signal SIG%s received, but no signal handler set.\n",
2122             PL_sig_name[sig]);
2123
2124     /* Max number of items pushed there is 3*n or 4. We cannot fix
2125        infinity, so we fix 4 (in fact 5): */
2126     if (flags & 1) {
2127         PL_savestack_ix += 5;           /* Protect save in progress. */
2128         o_save_i = PL_savestack_ix;
2129         SAVEDESTRUCTOR(S_unwind_handler_stack, (void*)&flags);
2130     }
2131     if (flags & 4) 
2132         PL_markstack_ptr++;             /* Protect mark. */
2133     if (flags & 8) {
2134         PL_retstack_ix++;
2135         PL_retstack[PL_retstack_ix] = NULL;
2136     }
2137     if (flags & 16)
2138         PL_scopestack_ix += 1;
2139     /* sv_2cv is too complicated, try a simpler variant first: */
2140     if (!SvROK(PL_psig_ptr[sig]) || !(cv = (CV*)SvRV(PL_psig_ptr[sig])) 
2141         || SvTYPE(cv) != SVt_PVCV)
2142         cv = sv_2cv(PL_psig_ptr[sig],&st,&gv,TRUE);
2143
2144     if (!cv || !CvROOT(cv)) {
2145         if (ckWARN(WARN_SIGNAL))
2146             Perl_warner(aTHX_ WARN_SIGNAL, "SIG%s handler \"%s\" not defined.\n",
2147                 PL_sig_name[sig], (gv ? GvENAME(gv)
2148                                 : ((cv && CvGV(cv))
2149                                    ? GvENAME(CvGV(cv))
2150                                    : "__ANON__")));
2151         goto cleanup;
2152     }
2153
2154     if(PL_psig_name[sig]) {
2155         sv = SvREFCNT_inc(PL_psig_name[sig]);
2156         flags |= 64;
2157         sig_sv = sv;
2158     } else {
2159         sv = sv_newmortal();
2160         sv_setpv(sv,PL_sig_name[sig]);
2161     }
2162
2163     PUSHSTACKi(PERLSI_SIGNAL);
2164     PUSHMARK(SP);
2165     PUSHs(sv);
2166     PUTBACK;
2167
2168     call_sv((SV*)cv, G_DISCARD);
2169
2170     POPSTACK;
2171 cleanup:
2172     if (flags & 1)
2173         PL_savestack_ix -= 8; /* Unprotect save in progress. */
2174     if (flags & 4) 
2175         PL_markstack_ptr--;
2176     if (flags & 8) 
2177         PL_retstack_ix--;
2178     if (flags & 16)
2179         PL_scopestack_ix -= 1;
2180     if (flags & 64)
2181         SvREFCNT_dec(sv);
2182     PL_op = myop;                       /* Apparently not needed... */
2183     
2184     PL_Sv = tSv;                        /* Restore global temporaries. */
2185     PL_Xpv = tXpv;
2186     return;
2187 }
2188
2189