initial stub implementation of implicit thread/this
[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 save_magic(pTHX_ I32 mgs_ix, SV *sv)
49 {
50     dTHR;
51     MGS* mgs;
52     assert(SvMAGICAL(sv));
53
54     SAVEDESTRUCTOR(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 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)(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)(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)(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)(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             croak("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)(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)(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 #ifdef PERL_OBJECT
529                 char *sMsg;
530                 DWORD dwLen;
531                 PerlProc_GetSysMsg(sMsg, dwLen, dwErr);
532                 sv_setpvn(sv, sMsg, dwLen);
533                 PerlProc_FreeBuf(sMsg);
534 #else
535                 win32_str_os_error(sv, dwErr);
536 #endif
537             }
538             else
539                 sv_setpv(sv, "");
540             SetLastError(dwErr);
541         }
542 #else
543         sv_setnv(sv, (double)errno);
544         sv_setpv(sv, errno ? Strerror(errno) : "");
545 #endif
546 #endif
547 #endif
548         SvNOK_on(sv);   /* what a wonderful hack! */
549         break;
550     case '\006':                /* ^F */
551         sv_setiv(sv, (IV)PL_maxsysfd);
552         break;
553     case '\010':                /* ^H */
554         sv_setiv(sv, (IV)PL_hints);
555         break;
556     case '\011':                /* ^I */ /* NOT \t in EBCDIC */
557         if (PL_inplace)
558             sv_setpv(sv, PL_inplace);
559         else
560             sv_setsv(sv, &PL_sv_undef);
561         break;
562     case '\017':                /* ^O */
563         sv_setpv(sv, PL_osname);
564         break;
565     case '\020':                /* ^P */
566         sv_setiv(sv, (IV)PL_perldb);
567         break;
568     case '\023':                /* ^S */
569         {
570             dTHR;
571             if (PL_lex_state != LEX_NOTPARSING)
572                 SvOK_off(sv);
573             else if (PL_in_eval)
574                 sv_setiv(sv, 1);
575             else
576                 sv_setiv(sv, 0);
577         }
578         break;
579     case '\024':                /* ^T */
580 #ifdef BIG_TIME
581         sv_setnv(sv, PL_basetime);
582 #else
583         sv_setiv(sv, (IV)PL_basetime);
584 #endif
585         break;
586     case '\027':                /* ^W */
587         sv_setiv(sv, (IV)((PL_dowarn & G_WARN_ON) == G_WARN_ON));
588         break;
589     case '1': case '2': case '3': case '4':
590     case '5': case '6': case '7': case '8': case '9': case '&':
591         if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
592             I32 s1, t1;
593
594             /*
595              * Pre-threads, this was paren = atoi(GvENAME((GV*)mg->mg_obj));
596              * XXX Does the new way break anything?
597              */
598             paren = atoi(mg->mg_ptr);
599           getparen:
600             if (paren <= rx->nparens &&
601                 (s1 = rx->startp[paren]) != -1 &&
602                 (t1 = rx->endp[paren]) != -1)
603             {
604                 i = t1 - s1;
605                 s = rx->subbeg + s1;
606               getrx:
607                 if (i >= 0) {
608                     bool was_tainted;
609                     if (PL_tainting) {
610                         was_tainted = PL_tainted;
611                         PL_tainted = FALSE;
612                     }
613                     sv_setpvn(sv, s, i);
614                     if (PL_tainting)
615                         PL_tainted = (was_tainted || RX_MATCH_TAINTED(rx));
616                     break;
617                 }
618             }
619         }
620         sv_setsv(sv,&PL_sv_undef);
621         break;
622     case '+':
623         if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
624             paren = rx->lastparen;
625             if (paren)
626                 goto getparen;
627         }
628         sv_setsv(sv,&PL_sv_undef);
629         break;
630     case '`':
631         if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
632             if ((s = rx->subbeg) && rx->startp[0] != -1) {
633                 i = rx->startp[0];
634                 goto getrx;
635             }
636         }
637         sv_setsv(sv,&PL_sv_undef);
638         break;
639     case '\'':
640         if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
641             if (rx->subbeg && rx->endp[0] != -1) {
642                 s = rx->subbeg + rx->endp[0];
643                 i = rx->sublen - rx->endp[0];
644                 goto getrx;
645             }
646         }
647         sv_setsv(sv,&PL_sv_undef);
648         break;
649     case '.':
650 #ifndef lint
651         if (GvIO(PL_last_in_gv)) {
652             sv_setiv(sv, (IV)IoLINES(GvIO(PL_last_in_gv)));
653         }
654 #endif
655         break;
656     case '?':
657         {
658             sv_setiv(sv, (IV)STATUS_CURRENT);
659 #ifdef COMPLEX_STATUS
660             LvTARGOFF(sv) = PL_statusvalue;
661             LvTARGLEN(sv) = PL_statusvalue_vms;
662 #endif
663         }
664         break;
665     case '^':
666         s = IoTOP_NAME(GvIOp(PL_defoutgv));
667         if (s)
668             sv_setpv(sv,s);
669         else {
670             sv_setpv(sv,GvENAME(PL_defoutgv));
671             sv_catpv(sv,"_TOP");
672         }
673         break;
674     case '~':
675         s = IoFMT_NAME(GvIOp(PL_defoutgv));
676         if (!s)
677             s = GvENAME(PL_defoutgv);
678         sv_setpv(sv,s);
679         break;
680 #ifndef lint
681     case '=':
682         sv_setiv(sv, (IV)IoPAGE_LEN(GvIOp(PL_defoutgv)));
683         break;
684     case '-':
685         sv_setiv(sv, (IV)IoLINES_LEFT(GvIOp(PL_defoutgv)));
686         break;
687     case '%':
688         sv_setiv(sv, (IV)IoPAGE(GvIOp(PL_defoutgv)));
689         break;
690 #endif
691     case ':':
692         break;
693     case '/':
694         break;
695     case '[':
696         WITH_THR(sv_setiv(sv, (IV)PL_curcop->cop_arybase));
697         break;
698     case '|':
699         sv_setiv(sv, (IV)(IoFLAGS(GvIOp(PL_defoutgv)) & IOf_FLUSH) != 0 );
700         break;
701     case ',':
702         sv_setpvn(sv,PL_ofs,PL_ofslen);
703         break;
704     case '\\':
705         sv_setpvn(sv,PL_ors,PL_orslen);
706         break;
707     case '#':
708         sv_setpv(sv,PL_ofmt);
709         break;
710     case '!':
711 #ifdef VMS
712         sv_setnv(sv, (double)((errno == EVMSERR) ? vaxc$errno : errno));
713         sv_setpv(sv, errno ? Strerror(errno) : "");
714 #else
715         {
716         int saveerrno = errno;
717         sv_setnv(sv, (double)errno);
718 #ifdef OS2
719         if (errno == errno_isOS2) sv_setpv(sv, os2error(Perl_rc));
720         else
721 #endif
722         sv_setpv(sv, errno ? Strerror(errno) : "");
723         errno = saveerrno;
724         }
725 #endif
726         SvNOK_on(sv);   /* what a wonderful hack! */
727         break;
728     case '<':
729         sv_setiv(sv, (IV)PL_uid);
730         break;
731     case '>':
732         sv_setiv(sv, (IV)PL_euid);
733         break;
734     case '(':
735         sv_setiv(sv, (IV)PL_gid);
736         sv_setpvf(sv, "%Vd", (IV)PL_gid);
737         goto add_groups;
738     case ')':
739         sv_setiv(sv, (IV)PL_egid);
740         sv_setpvf(sv, "%Vd", (IV)PL_egid);
741       add_groups:
742 #ifdef HAS_GETGROUPS
743         {
744             Groups_t gary[NGROUPS];
745             i = getgroups(NGROUPS,gary);
746             while (--i >= 0)
747                 sv_catpvf(sv, " %Vd", (IV)gary[i]);
748         }
749 #endif
750         SvIOK_on(sv);   /* what a wonderful hack! */
751         break;
752     case '*':
753         break;
754     case '0':
755         break;
756 #ifdef USE_THREADS
757     case '@':
758         sv_setsv(sv, thr->errsv);
759         break;
760 #endif /* USE_THREADS */
761     }
762     return 0;
763 }
764
765 int
766 Perl_magic_getuvar(pTHX_ SV *sv, MAGIC *mg)
767 {
768     struct ufuncs *uf = (struct ufuncs *)mg->mg_ptr;
769
770     if (uf && uf->uf_val)
771         (*uf->uf_val)(uf->uf_index, sv);
772     return 0;
773 }
774
775 int
776 Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg)
777 {
778     register char *s;
779     char *ptr;
780     STRLEN len, klen;
781     I32 i;
782
783     s = SvPV(sv,len);
784     ptr = MgPV(mg,klen);
785     my_setenv(ptr, s);
786
787 #ifdef DYNAMIC_ENV_FETCH
788      /* We just undefd an environment var.  Is a replacement */
789      /* waiting in the wings? */
790     if (!len) {
791         SV **valp;
792         if ((valp = hv_fetch(GvHVn(PL_envgv), ptr, klen, FALSE)))
793             s = SvPV(*valp, len);
794     }
795 #endif
796
797 #if !defined(OS2) && !defined(AMIGAOS) && !defined(WIN32) && !defined(MSDOS)
798                             /* And you'll never guess what the dog had */
799                             /*   in its mouth... */
800     if (PL_tainting) {
801         MgTAINTEDDIR_off(mg);
802 #ifdef VMS
803         if (s && klen == 8 && strEQ(ptr, "DCL$PATH")) {
804             char pathbuf[256], eltbuf[256], *cp, *elt = s;
805             struct stat sbuf;
806             int i = 0, j = 0;
807
808             do {          /* DCL$PATH may be a search list */
809                 while (1) {   /* as may dev portion of any element */
810                     if ( ((cp = strchr(elt,'[')) || (cp = strchr(elt,'<'))) ) {
811                         if ( *(cp+1) == '.' || *(cp+1) == '-' ||
812                              cando_by_name(S_IWUSR,0,elt) ) {
813                             MgTAINTEDDIR_on(mg);
814                             return 0;
815                         }
816                     }
817                     if ((cp = strchr(elt, ':')) != Nullch)
818                         *cp = '\0';
819                     if (my_trnlnm(elt, eltbuf, j++))
820                         elt = eltbuf;
821                     else
822                         break;
823                 }
824                 j = 0;
825             } while (my_trnlnm(s, pathbuf, i++) && (elt = pathbuf));
826         }
827 #endif /* VMS */
828         if (s && klen == 4 && strEQ(ptr,"PATH")) {
829             char *strend = s + len;
830
831             while (s < strend) {
832                 char tmpbuf[256];
833                 struct stat st;
834                 s = delimcpy(tmpbuf, tmpbuf + sizeof tmpbuf,
835                              s, strend, ':', &i);
836                 s++;
837                 if (i >= sizeof tmpbuf   /* too long -- assume the worst */
838                       || *tmpbuf != '/'
839                       || (PerlLIO_stat(tmpbuf, &st) == 0 && (st.st_mode & 2)) ) {
840                     MgTAINTEDDIR_on(mg);
841                     return 0;
842                 }
843             }
844         }
845     }
846 #endif /* neither OS2 nor AMIGAOS nor WIN32 nor MSDOS */
847
848     return 0;
849 }
850
851 int
852 Perl_magic_clearenv(pTHX_ SV *sv, MAGIC *mg)
853 {
854     STRLEN n_a;
855     my_setenv(MgPV(mg,n_a),Nullch);
856     return 0;
857 }
858
859 int
860 Perl_magic_set_all_env(pTHX_ SV *sv, MAGIC *mg)
861 {
862 #if defined(VMS)
863     die("Can't make list assignment to %%ENV on this system");
864 #else
865     dTHR;
866     if (PL_localizing) {
867         HE* entry;
868         STRLEN n_a;
869         magic_clear_all_env(sv,mg);
870         hv_iterinit((HV*)sv);
871         while (entry = hv_iternext((HV*)sv)) {
872             I32 keylen;
873             my_setenv(hv_iterkey(entry, &keylen),
874                       SvPV(hv_iterval((HV*)sv, entry), n_a));
875         }
876     }
877 #endif
878     return 0;
879 }
880
881 int
882 Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg)
883 {
884 #if defined(VMS)
885     die("Can't make list assignment to %%ENV on this system");
886 #else
887 #  ifdef WIN32
888     char *envv = GetEnvironmentStrings();
889     char *cur = envv;
890     STRLEN len;
891     while (*cur) {
892         char *end = strchr(cur,'=');
893         if (end && end != cur) {
894             *end = '\0';
895             my_setenv(cur,Nullch);
896             *end = '=';
897             cur = end + strlen(end+1)+2;
898         }
899         else if ((len = strlen(cur)))
900             cur += len+1;
901     }
902     FreeEnvironmentStrings(envv);
903 #  else
904 #    ifndef PERL_USE_SAFE_PUTENV
905     I32 i;
906
907     if (environ == PL_origenviron)
908         environ = (char**)safesysmalloc(sizeof(char*));
909     else
910         for (i = 0; environ[i]; i++)
911             safesysfree(environ[i]);
912 #    endif /* PERL_USE_SAFE_PUTENV */
913
914     environ[0] = Nullch;
915
916 #  endif /* WIN32 */
917 #endif /* VMS */
918     return 0;
919 }
920
921 int
922 Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg)
923 {
924     I32 i;
925     STRLEN n_a;
926     /* Are we fetching a signal entry? */
927     i = whichsig(MgPV(mg,n_a));
928     if (i) {
929         if(PL_psig_ptr[i])
930             sv_setsv(sv,PL_psig_ptr[i]);
931         else {
932             Sighandler_t sigstate = rsignal_state(i);
933
934             /* cache state so we don't fetch it again */
935             if(sigstate == SIG_IGN)
936                 sv_setpv(sv,"IGNORE");
937             else
938                 sv_setsv(sv,&PL_sv_undef);
939             PL_psig_ptr[i] = SvREFCNT_inc(sv);
940             SvTEMP_off(sv);
941         }
942     }
943     return 0;
944 }
945 int
946 Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg)
947 {
948     I32 i;
949     STRLEN n_a;
950     /* Are we clearing a signal entry? */
951     i = whichsig(MgPV(mg,n_a));
952     if (i) {
953         if(PL_psig_ptr[i]) {
954             SvREFCNT_dec(PL_psig_ptr[i]);
955             PL_psig_ptr[i]=0;
956         }
957         if(PL_psig_name[i]) {
958             SvREFCNT_dec(PL_psig_name[i]);
959             PL_psig_name[i]=0;
960         }
961     }
962     return 0;
963 }
964
965 int
966 Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
967 {
968     dTHR;
969     register char *s;
970     I32 i;
971     SV** svp;
972     STRLEN len;
973
974     s = MgPV(mg,len);
975     if (*s == '_') {
976         if (strEQ(s,"__DIE__"))
977             svp = &PL_diehook;
978         else if (strEQ(s,"__WARN__"))
979             svp = &PL_warnhook;
980         else if (strEQ(s,"__PARSE__"))
981             svp = &PL_parsehook;
982         else
983             croak("No such hook: %s", s);
984         i = 0;
985         if (*svp) {
986             SvREFCNT_dec(*svp);
987             *svp = 0;
988         }
989     }
990     else {
991         i = whichsig(s);        /* ...no, a brick */
992         if (!i) {
993             if (ckWARN(WARN_SIGNAL) || strEQ(s,"ALARM"))
994                 warner(WARN_SIGNAL, "No such signal: SIG%s", s);
995             return 0;
996         }
997         SvREFCNT_dec(PL_psig_name[i]);
998         SvREFCNT_dec(PL_psig_ptr[i]);
999         PL_psig_ptr[i] = SvREFCNT_inc(sv);
1000         SvTEMP_off(sv); /* Make sure it doesn't go away on us */
1001         PL_psig_name[i] = newSVpvn(s, len);
1002         SvREADONLY_on(PL_psig_name[i]);
1003     }
1004     if (SvTYPE(sv) == SVt_PVGV || SvROK(sv)) {
1005         if (i)
1006             (void)rsignal(i, PL_sighandlerp);
1007         else
1008             *svp = SvREFCNT_inc(sv);
1009         return 0;
1010     }
1011     s = SvPV_force(sv,len);
1012     if (strEQ(s,"IGNORE")) {
1013         if (i)
1014             (void)rsignal(i, SIG_IGN);
1015         else
1016             *svp = 0;
1017     }
1018     else if (strEQ(s,"DEFAULT") || !*s) {
1019         if (i)
1020             (void)rsignal(i, SIG_DFL);
1021         else
1022             *svp = 0;
1023     }
1024     else {
1025         /*
1026          * We should warn if HINT_STRICT_REFS, but without
1027          * access to a known hint bit in a known OP, we can't
1028          * tell whether HINT_STRICT_REFS is in force or not.
1029          */
1030         if (!strchr(s,':') && !strchr(s,'\''))
1031             sv_insert(sv, 0, 0, "main::", 6);
1032         if (i)
1033             (void)rsignal(i, PL_sighandlerp);
1034         else
1035             *svp = SvREFCNT_inc(sv);
1036     }
1037     return 0;
1038 }
1039
1040 int
1041 Perl_magic_setisa(pTHX_ SV *sv, MAGIC *mg)
1042 {
1043     PL_sub_generation++;
1044     return 0;
1045 }
1046
1047 int
1048 Perl_magic_setamagic(pTHX_ SV *sv, MAGIC *mg)
1049 {
1050     /* HV_badAMAGIC_on(Sv_STASH(sv)); */
1051     PL_amagic_generation++;
1052
1053     return 0;
1054 }
1055
1056 int
1057 Perl_magic_getnkeys(pTHX_ SV *sv, MAGIC *mg)
1058 {
1059     HV *hv = (HV*)LvTARG(sv);
1060     HE *entry;
1061     I32 i = 0;
1062
1063     if (hv) {
1064         (void) hv_iterinit(hv);
1065         if (! SvTIED_mg((SV*)hv, 'P'))
1066             i = HvKEYS(hv);
1067         else {
1068             /*SUPPRESS 560*/
1069             while (entry = hv_iternext(hv)) {
1070                 i++;
1071             }
1072         }
1073     }
1074
1075     sv_setiv(sv, (IV)i);
1076     return 0;
1077 }
1078
1079 int
1080 Perl_magic_setnkeys(pTHX_ SV *sv, MAGIC *mg)
1081 {
1082     if (LvTARG(sv)) {
1083         hv_ksplit((HV*)LvTARG(sv), SvIV(sv));
1084     }
1085     return 0;
1086 }          
1087
1088 /* caller is responsible for stack switching/cleanup */
1089 STATIC int
1090 magic_methcall(pTHX_ SV *sv, MAGIC *mg, char *meth, I32 flags, int n, SV *val)
1091 {
1092     dSP;
1093
1094     PUSHMARK(SP);
1095     EXTEND(SP, n);
1096     PUSHs(SvTIED_obj(sv, mg));
1097     if (n > 1) { 
1098         if (mg->mg_ptr) {
1099             if (mg->mg_len >= 0)
1100                 PUSHs(sv_2mortal(newSVpvn(mg->mg_ptr, mg->mg_len)));
1101             else if (mg->mg_len == HEf_SVKEY)
1102                 PUSHs((SV*)mg->mg_ptr);
1103         }
1104         else if (mg->mg_type == 'p') {
1105             PUSHs(sv_2mortal(newSViv(mg->mg_len)));
1106         }
1107     }
1108     if (n > 2) {
1109         PUSHs(val);
1110     }
1111     PUTBACK;
1112
1113     return call_method(meth, flags);
1114 }
1115
1116 STATIC int
1117 magic_methpack(pTHX_ SV *sv, MAGIC *mg, char *meth)
1118 {
1119     dSP;
1120
1121     ENTER;
1122     SAVETMPS;
1123     PUSHSTACKi(PERLSI_MAGIC);
1124
1125     if (magic_methcall(sv, mg, meth, G_SCALAR, 2, NULL)) {
1126         sv_setsv(sv, *PL_stack_sp--);
1127     }
1128
1129     POPSTACK;
1130     FREETMPS;
1131     LEAVE;
1132     return 0;
1133 }
1134
1135 int
1136 Perl_magic_getpack(pTHX_ SV *sv, MAGIC *mg)
1137 {
1138     magic_methpack(sv,mg,"FETCH");
1139     if (mg->mg_ptr)
1140         mg->mg_flags |= MGf_GSKIP;
1141     return 0;
1142 }
1143
1144 int
1145 Perl_magic_setpack(pTHX_ SV *sv, MAGIC *mg)
1146 {
1147     dSP;
1148     ENTER;
1149     PUSHSTACKi(PERLSI_MAGIC);
1150     magic_methcall(sv, mg, "STORE", G_SCALAR|G_DISCARD, 3, sv);
1151     POPSTACK;
1152     LEAVE;
1153     return 0;
1154 }
1155
1156 int
1157 Perl_magic_clearpack(pTHX_ SV *sv, MAGIC *mg)
1158 {
1159     return magic_methpack(sv,mg,"DELETE");
1160 }
1161
1162
1163 U32
1164 Perl_magic_sizepack(pTHX_ SV *sv, MAGIC *mg)
1165 {         
1166     dSP;
1167     U32 retval = 0;
1168
1169     ENTER;
1170     SAVETMPS;
1171     PUSHSTACKi(PERLSI_MAGIC);
1172     if (magic_methcall(sv, mg, "FETCHSIZE", G_SCALAR, 2, NULL)) {
1173         sv = *PL_stack_sp--;
1174         retval = (U32) SvIV(sv)-1;
1175     }
1176     POPSTACK;
1177     FREETMPS;
1178     LEAVE;
1179     return retval;
1180 }
1181
1182 int magic_wipepack(SV *sv, MAGIC *mg)
1183 {
1184     dSP;
1185
1186     ENTER;
1187     PUSHSTACKi(PERLSI_MAGIC);
1188     PUSHMARK(SP);
1189     XPUSHs(SvTIED_obj(sv, mg));
1190     PUTBACK;
1191     call_method("CLEAR", G_SCALAR|G_DISCARD);
1192     POPSTACK;
1193     LEAVE;
1194     return 0;
1195 }
1196
1197 int
1198 Perl_magic_nextpack(pTHX_ SV *sv, MAGIC *mg, SV *key)
1199 {
1200     dSP;
1201     char *meth = SvOK(key) ? "NEXTKEY" : "FIRSTKEY";
1202
1203     ENTER;
1204     SAVETMPS;
1205     PUSHSTACKi(PERLSI_MAGIC);
1206     PUSHMARK(SP);
1207     EXTEND(SP, 2);
1208     PUSHs(SvTIED_obj(sv, mg));
1209     if (SvOK(key))
1210         PUSHs(key);
1211     PUTBACK;
1212
1213     if (call_method(meth, G_SCALAR))
1214         sv_setsv(key, *PL_stack_sp--);
1215
1216     POPSTACK;
1217     FREETMPS;
1218     LEAVE;
1219     return 0;
1220 }
1221
1222 int
1223 Perl_magic_existspack(pTHX_ SV *sv, MAGIC *mg)
1224 {
1225     return magic_methpack(sv,mg,"EXISTS");
1226
1227
1228 int
1229 Perl_magic_setdbline(pTHX_ SV *sv, MAGIC *mg)
1230 {
1231     dTHR;
1232     OP *o;
1233     I32 i;
1234     GV* gv;
1235     SV** svp;
1236     STRLEN n_a;
1237
1238     gv = PL_DBline;
1239     i = SvTRUE(sv);
1240     svp = av_fetch(GvAV(gv),
1241                      atoi(MgPV(mg,n_a)), FALSE);
1242     if (svp && SvIOKp(*svp) && (o = (OP*)SvSTASH(*svp)))
1243         o->op_private = i;
1244     else
1245         warn("Can't break at that line\n");
1246     return 0;
1247 }
1248
1249 int
1250 Perl_magic_getarylen(pTHX_ SV *sv, MAGIC *mg)
1251 {
1252     dTHR;
1253     sv_setiv(sv, AvFILL((AV*)mg->mg_obj) + PL_curcop->cop_arybase);
1254     return 0;
1255 }
1256
1257 int
1258 Perl_magic_setarylen(pTHX_ SV *sv, MAGIC *mg)
1259 {
1260     dTHR;
1261     av_fill((AV*)mg->mg_obj, SvIV(sv) - PL_curcop->cop_arybase);
1262     return 0;
1263 }
1264
1265 int
1266 Perl_magic_getpos(pTHX_ SV *sv, MAGIC *mg)
1267 {
1268     SV* lsv = LvTARG(sv);
1269     
1270     if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv)) {
1271         mg = mg_find(lsv, 'g');
1272         if (mg && mg->mg_len >= 0) {
1273             dTHR;
1274             I32 i = mg->mg_len;
1275             if (IN_UTF8)
1276                 sv_pos_b2u(lsv, &i);
1277             sv_setiv(sv, i + PL_curcop->cop_arybase);
1278             return 0;
1279         }
1280     }
1281     (void)SvOK_off(sv);
1282     return 0;
1283 }
1284
1285 int
1286 Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg)
1287 {
1288     SV* lsv = LvTARG(sv);
1289     SSize_t pos;
1290     STRLEN len;
1291     STRLEN ulen;
1292     dTHR;
1293
1294     mg = 0;
1295     
1296     if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv))
1297         mg = mg_find(lsv, 'g');
1298     if (!mg) {
1299         if (!SvOK(sv))
1300             return 0;
1301         sv_magic(lsv, (SV*)0, 'g', Nullch, 0);
1302         mg = mg_find(lsv, 'g');
1303     }
1304     else if (!SvOK(sv)) {
1305         mg->mg_len = -1;
1306         return 0;
1307     }
1308     len = SvPOK(lsv) ? SvCUR(lsv) : sv_len(lsv);
1309
1310     pos = SvIV(sv) - PL_curcop->cop_arybase;
1311
1312     if (IN_UTF8) {
1313         ulen = sv_len_utf8(lsv);
1314         if (ulen)
1315             len = ulen;
1316         else
1317             ulen = 0;
1318     }
1319
1320     if (pos < 0) {
1321         pos += len;
1322         if (pos < 0)
1323             pos = 0;
1324     }
1325     else if (pos > len)
1326         pos = len;
1327
1328     if (ulen) {
1329         I32 p = pos;
1330         sv_pos_u2b(lsv, &p, 0);
1331         pos = p;
1332     }
1333         
1334     mg->mg_len = pos;
1335     mg->mg_flags &= ~MGf_MINMATCH;
1336
1337     return 0;
1338 }
1339
1340 int
1341 Perl_magic_getglob(pTHX_ SV *sv, MAGIC *mg)
1342 {
1343     if (SvFAKE(sv)) {                   /* FAKE globs can get coerced */
1344         SvFAKE_off(sv);
1345         gv_efullname3(sv,((GV*)sv), "*");
1346         SvFAKE_on(sv);
1347     }
1348     else
1349         gv_efullname3(sv,((GV*)sv), "*");       /* a gv value, be nice */
1350     return 0;
1351 }
1352
1353 int
1354 Perl_magic_setglob(pTHX_ SV *sv, MAGIC *mg)
1355 {
1356     register char *s;
1357     GV* gv;
1358     STRLEN n_a;
1359
1360     if (!SvOK(sv))
1361         return 0;
1362     s = SvPV(sv, n_a);
1363     if (*s == '*' && s[1])
1364         s++;
1365     gv = gv_fetchpv(s,TRUE, SVt_PVGV);
1366     if (sv == (SV*)gv)
1367         return 0;
1368     if (GvGP(sv))
1369         gp_free((GV*)sv);
1370     GvGP(sv) = gp_ref(GvGP(gv));
1371     return 0;
1372 }
1373
1374 int
1375 Perl_magic_getsubstr(pTHX_ SV *sv, MAGIC *mg)
1376 {
1377     STRLEN len;
1378     SV *lsv = LvTARG(sv);
1379     char *tmps = SvPV(lsv,len);
1380     I32 offs = LvTARGOFF(sv);
1381     I32 rem = LvTARGLEN(sv);
1382
1383     if (offs > len)
1384         offs = len;
1385     if (rem + offs > len)
1386         rem = len - offs;
1387     sv_setpvn(sv, tmps + offs, (STRLEN)rem);
1388     return 0;
1389 }
1390
1391 int
1392 Perl_magic_setsubstr(pTHX_ SV *sv, MAGIC *mg)
1393 {
1394     STRLEN len;
1395     char *tmps = SvPV(sv,len);
1396     sv_insert(LvTARG(sv),LvTARGOFF(sv),LvTARGLEN(sv), tmps, len);
1397     return 0;
1398 }
1399
1400 int
1401 Perl_magic_gettaint(pTHX_ SV *sv, MAGIC *mg)
1402 {
1403     dTHR;
1404     TAINT_IF((mg->mg_len & 1) ||
1405              (mg->mg_len & 2) && mg->mg_obj == sv);     /* kludge */
1406     return 0;
1407 }
1408
1409 int
1410 Perl_magic_settaint(pTHX_ SV *sv, MAGIC *mg)
1411 {
1412     dTHR;
1413     if (PL_localizing) {
1414         if (PL_localizing == 1)
1415             mg->mg_len <<= 1;
1416         else
1417             mg->mg_len >>= 1;
1418     }
1419     else if (PL_tainted)
1420         mg->mg_len |= 1;
1421     else
1422         mg->mg_len &= ~1;
1423     return 0;
1424 }
1425
1426 int
1427 Perl_magic_getvec(pTHX_ SV *sv, MAGIC *mg)
1428 {
1429     SV *lsv = LvTARG(sv);
1430     unsigned char *s;
1431     unsigned long retnum;
1432     STRLEN lsvlen;
1433     I32 len;
1434     I32 offset;
1435     I32 size;
1436
1437     if (!lsv) {
1438         SvOK_off(sv);
1439         return 0;
1440     }
1441     s = (unsigned char *) SvPV(lsv, lsvlen);
1442     offset = LvTARGOFF(sv);
1443     size = LvTARGLEN(sv);
1444     len = (offset + size + 7) / 8;
1445
1446     /* Copied from pp_vec() */
1447
1448     if (len > lsvlen) {
1449         if (size <= 8)
1450             retnum = 0;
1451         else {
1452             offset >>= 3;
1453             if (size == 16) {
1454                 if (offset >= lsvlen)
1455                     retnum = 0;
1456                 else
1457                     retnum = (unsigned long) s[offset] << 8;
1458             }
1459             else if (size == 32) {
1460                 if (offset >= lsvlen)
1461                     retnum = 0;
1462                 else if (offset + 1 >= lsvlen)
1463                     retnum = (unsigned long) s[offset] << 24;
1464                 else if (offset + 2 >= lsvlen)
1465                     retnum = ((unsigned long) s[offset] << 24) +
1466                         ((unsigned long) s[offset + 1] << 16);
1467                 else
1468                     retnum = ((unsigned long) s[offset] << 24) +
1469                         ((unsigned long) s[offset + 1] << 16) +
1470                         (s[offset + 2] << 8);
1471             }
1472         }
1473     }
1474     else if (size < 8)
1475         retnum = (s[offset >> 3] >> (offset & 7)) & ((1 << size) - 1);
1476     else {
1477         offset >>= 3;
1478         if (size == 8)
1479             retnum = s[offset];
1480         else if (size == 16)
1481             retnum = ((unsigned long) s[offset] << 8) + s[offset+1];
1482         else if (size == 32)
1483             retnum = ((unsigned long) s[offset] << 24) +
1484                 ((unsigned long) s[offset + 1] << 16) +
1485                 (s[offset + 2] << 8) + s[offset+3];
1486     }
1487
1488     sv_setuv(sv, (UV)retnum);
1489     return 0;
1490 }
1491
1492 int
1493 Perl_magic_setvec(pTHX_ SV *sv, MAGIC *mg)
1494 {
1495     do_vecset(sv);      /* XXX slurp this routine */
1496     return 0;
1497 }
1498
1499 int
1500 Perl_magic_getdefelem(pTHX_ SV *sv, MAGIC *mg)
1501 {
1502     SV *targ = Nullsv;
1503     if (LvTARGLEN(sv)) {
1504         if (mg->mg_obj) {
1505             SV *ahv = LvTARG(sv);
1506             if (SvTYPE(ahv) == SVt_PVHV) {
1507                 HE *he = hv_fetch_ent((HV*)ahv, mg->mg_obj, FALSE, 0);
1508                 if (he)
1509                     targ = HeVAL(he);
1510             }
1511             else {
1512                 SV **svp = avhv_fetch_ent((AV*)ahv, mg->mg_obj, FALSE, 0);
1513                 if (svp)
1514                     targ = *svp;
1515             }
1516         }
1517         else {
1518             AV* av = (AV*)LvTARG(sv);
1519             if ((I32)LvTARGOFF(sv) <= AvFILL(av))
1520                 targ = AvARRAY(av)[LvTARGOFF(sv)];
1521         }
1522         if (targ && targ != &PL_sv_undef) {
1523             dTHR;               /* just for SvREFCNT_dec */
1524             /* somebody else defined it for us */
1525             SvREFCNT_dec(LvTARG(sv));
1526             LvTARG(sv) = SvREFCNT_inc(targ);
1527             LvTARGLEN(sv) = 0;
1528             SvREFCNT_dec(mg->mg_obj);
1529             mg->mg_obj = Nullsv;
1530             mg->mg_flags &= ~MGf_REFCOUNTED;
1531         }
1532     }
1533     else
1534         targ = LvTARG(sv);
1535     sv_setsv(sv, targ ? targ : &PL_sv_undef);
1536     return 0;
1537 }
1538
1539 int
1540 Perl_magic_setdefelem(pTHX_ SV *sv, MAGIC *mg)
1541 {
1542     if (LvTARGLEN(sv))
1543         vivify_defelem(sv);
1544     if (LvTARG(sv)) {
1545         sv_setsv(LvTARG(sv), sv);
1546         SvSETMAGIC(LvTARG(sv));
1547     }
1548     return 0;
1549 }
1550
1551 void
1552 Perl_vivify_defelem(pTHX_ SV *sv)
1553 {
1554     dTHR;                       /* just for SvREFCNT_inc and SvREFCNT_dec*/
1555     MAGIC *mg;
1556     SV *value = Nullsv;
1557
1558     if (!LvTARGLEN(sv) || !(mg = mg_find(sv, 'y')))
1559         return;
1560     if (mg->mg_obj) {
1561         SV *ahv = LvTARG(sv);
1562         STRLEN n_a;
1563         if (SvTYPE(ahv) == SVt_PVHV) {
1564             HE *he = hv_fetch_ent((HV*)ahv, mg->mg_obj, TRUE, 0);
1565             if (he)
1566                 value = HeVAL(he);
1567         }
1568         else {
1569             SV **svp = avhv_fetch_ent((AV*)ahv, mg->mg_obj, TRUE, 0);
1570             if (svp)
1571                 value = *svp;
1572         }
1573         if (!value || value == &PL_sv_undef)
1574             croak(PL_no_helem, SvPV(mg->mg_obj, n_a));
1575     }
1576     else {
1577         AV* av = (AV*)LvTARG(sv);
1578         if ((I32)LvTARGLEN(sv) < 0 && (I32)LvTARGOFF(sv) > AvFILL(av))
1579             LvTARG(sv) = Nullsv;        /* array can't be extended */
1580         else {
1581             SV** svp = av_fetch(av, LvTARGOFF(sv), TRUE);
1582             if (!svp || (value = *svp) == &PL_sv_undef)
1583                 croak(PL_no_aelem, (I32)LvTARGOFF(sv));
1584         }
1585     }
1586     (void)SvREFCNT_inc(value);
1587     SvREFCNT_dec(LvTARG(sv));
1588     LvTARG(sv) = value;
1589     LvTARGLEN(sv) = 0;
1590     SvREFCNT_dec(mg->mg_obj);
1591     mg->mg_obj = Nullsv;
1592     mg->mg_flags &= ~MGf_REFCOUNTED;
1593 }
1594
1595 int
1596 Perl_magic_killbackrefs(pTHX_ SV *sv, MAGIC *mg)
1597 {
1598     AV *av = (AV*)mg->mg_obj;
1599     SV **svp = AvARRAY(av);
1600     I32 i = AvFILLp(av);
1601     while (i >= 0) {
1602         if (svp[i] && svp[i] != &PL_sv_undef) {
1603             if (!SvWEAKREF(svp[i]))
1604                 croak("panic: magic_killbackrefs");
1605             /* XXX Should we check that it hasn't changed? */
1606             SvRV(svp[i]) = 0;
1607             SvOK_off(svp[i]);
1608             SvWEAKREF_off(svp[i]);
1609             svp[i] = &PL_sv_undef;
1610         }
1611         i--;
1612     }
1613     return 0;
1614 }
1615
1616 int
1617 Perl_magic_setmglob(pTHX_ SV *sv, MAGIC *mg)
1618 {
1619     mg->mg_len = -1;
1620     SvSCREAM_off(sv);
1621     return 0;
1622 }
1623
1624 int
1625 Perl_magic_setbm(pTHX_ SV *sv, MAGIC *mg)
1626 {
1627     sv_unmagic(sv, 'B');
1628     SvVALID_off(sv);
1629     return 0;
1630 }
1631
1632 int
1633 Perl_magic_setfm(pTHX_ SV *sv, MAGIC *mg)
1634 {
1635     sv_unmagic(sv, 'f');
1636     SvCOMPILED_off(sv);
1637     return 0;
1638 }
1639
1640 int
1641 Perl_magic_setuvar(pTHX_ SV *sv, MAGIC *mg)
1642 {
1643     struct ufuncs *uf = (struct ufuncs *)mg->mg_ptr;
1644
1645     if (uf && uf->uf_set)
1646         (*uf->uf_set)(uf->uf_index, sv);
1647     return 0;
1648 }
1649
1650 int
1651 Perl_magic_freeregexp(pTHX_ SV *sv, MAGIC *mg)
1652 {
1653     regexp *re = (regexp *)mg->mg_obj;
1654     ReREFCNT_dec(re);
1655     return 0;
1656 }
1657
1658 #ifdef USE_LOCALE_COLLATE
1659 int
1660 Perl_magic_setcollxfrm(pTHX_ SV *sv, MAGIC *mg)
1661 {
1662     /*
1663      * RenE<eacute> Descartes said "I think not."
1664      * and vanished with a faint plop.
1665      */
1666     if (mg->mg_ptr) {
1667         Safefree(mg->mg_ptr);
1668         mg->mg_ptr = NULL;
1669         mg->mg_len = -1;
1670     }
1671     return 0;
1672 }
1673 #endif /* USE_LOCALE_COLLATE */
1674
1675 int
1676 Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
1677 {
1678     dTHR;
1679     register char *s;
1680     I32 i;
1681     STRLEN len;
1682     switch (*mg->mg_ptr) {
1683     case '\001':        /* ^A */
1684         sv_setsv(PL_bodytarget, sv);
1685         break;
1686     case '\002':        /* ^B */
1687         if ( ! (PL_dowarn & G_WARN_ALL_MASK)) {
1688             if (memEQ(SvPVX(sv), WARN_ALLstring, WARNsize))
1689                 PL_compiling.cop_warnings = WARN_ALL;
1690             else if (memEQ(SvPVX(sv), WARN_NONEstring, WARNsize))
1691                 PL_compiling.cop_warnings = WARN_NONE;
1692             else {
1693                 if (PL_compiling.cop_warnings != WARN_NONE && 
1694                     PL_compiling.cop_warnings != WARN_ALL)
1695                     sv_setsv(PL_compiling.cop_warnings, sv);
1696                 else
1697                     PL_compiling.cop_warnings = newSVsv(sv) ;
1698             }
1699         }
1700         break;
1701
1702     case '\003':        /* ^C */
1703         PL_minus_c = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1704         break;
1705
1706     case '\004':        /* ^D */
1707         PL_debug = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) | 0x80000000;
1708         DEBUG_x(dump_all());
1709         break;
1710     case '\005':  /* ^E */
1711 #ifdef VMS
1712         set_vaxc_errno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1713 #else
1714 #ifdef WIN32
1715         SetLastError( SvIV(sv) );
1716 #else
1717         /* will anyone ever use this? */
1718         SETERRNO(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv), 4);
1719 #endif
1720 #endif
1721         break;
1722     case '\006':        /* ^F */
1723         PL_maxsysfd = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1724         break;
1725     case '\010':        /* ^H */
1726         PL_hints = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1727         break;
1728     case '\011':        /* ^I */ /* NOT \t in EBCDIC */
1729         if (PL_inplace)
1730             Safefree(PL_inplace);
1731         if (SvOK(sv))
1732             PL_inplace = savepv(SvPV(sv,len));
1733         else
1734             PL_inplace = Nullch;
1735         break;
1736     case '\017':        /* ^O */
1737         if (PL_osname)
1738             Safefree(PL_osname);
1739         if (SvOK(sv))
1740             PL_osname = savepv(SvPV(sv,len));
1741         else
1742             PL_osname = Nullch;
1743         break;
1744     case '\020':        /* ^P */
1745         PL_perldb = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1746         break;
1747     case '\024':        /* ^T */
1748 #ifdef BIG_TIME
1749         PL_basetime = (Time_t)(SvNOK(sv) ? SvNVX(sv) : sv_2nv(sv));
1750 #else
1751         PL_basetime = (Time_t)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1752 #endif
1753         break;
1754     case '\027':        /* ^W */
1755         if ( ! (PL_dowarn & G_WARN_ALL_MASK)) {
1756             i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1757             PL_dowarn = (i ? G_WARN_ON : G_WARN_OFF) ;
1758         }
1759         break;
1760     case '.':
1761         if (PL_localizing) {
1762             if (PL_localizing == 1)
1763                 save_sptr((SV**)&PL_last_in_gv);
1764         }
1765         else if (SvOK(sv) && GvIO(PL_last_in_gv))
1766             IoLINES(GvIOp(PL_last_in_gv)) = (long)SvIV(sv);
1767         break;
1768     case '^':
1769         Safefree(IoTOP_NAME(GvIOp(PL_defoutgv)));
1770         IoTOP_NAME(GvIOp(PL_defoutgv)) = s = savepv(SvPV(sv,len));
1771         IoTOP_GV(GvIOp(PL_defoutgv)) = gv_fetchpv(s,TRUE, SVt_PVIO);
1772         break;
1773     case '~':
1774         Safefree(IoFMT_NAME(GvIOp(PL_defoutgv)));
1775         IoFMT_NAME(GvIOp(PL_defoutgv)) = s = savepv(SvPV(sv,len));
1776         IoFMT_GV(GvIOp(PL_defoutgv)) = gv_fetchpv(s,TRUE, SVt_PVIO);
1777         break;
1778     case '=':
1779         IoPAGE_LEN(GvIOp(PL_defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1780         break;
1781     case '-':
1782         IoLINES_LEFT(GvIOp(PL_defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1783         if (IoLINES_LEFT(GvIOp(PL_defoutgv)) < 0L)
1784             IoLINES_LEFT(GvIOp(PL_defoutgv)) = 0L;
1785         break;
1786     case '%':
1787         IoPAGE(GvIOp(PL_defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1788         break;
1789     case '|':
1790         {
1791             IO *io = GvIOp(PL_defoutgv);
1792             if ((SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) == 0)
1793                 IoFLAGS(io) &= ~IOf_FLUSH;
1794             else {
1795                 if (!(IoFLAGS(io) & IOf_FLUSH)) {
1796                     PerlIO *ofp = IoOFP(io);
1797                     if (ofp)
1798                         (void)PerlIO_flush(ofp);
1799                     IoFLAGS(io) |= IOf_FLUSH;
1800                 }
1801             }
1802         }
1803         break;
1804     case '*':
1805         i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1806         PL_multiline = (i != 0);
1807         break;
1808     case '/':
1809         SvREFCNT_dec(PL_nrs);
1810         PL_nrs = newSVsv(sv);
1811         SvREFCNT_dec(PL_rs);
1812         PL_rs = SvREFCNT_inc(PL_nrs);
1813         break;
1814     case '\\':
1815         if (PL_ors)
1816             Safefree(PL_ors);
1817         if (SvOK(sv) || SvGMAGICAL(sv))
1818             PL_ors = savepv(SvPV(sv,PL_orslen));
1819         else {
1820             PL_ors = Nullch;
1821             PL_orslen = 0;
1822         }
1823         break;
1824     case ',':
1825         if (PL_ofs)
1826             Safefree(PL_ofs);
1827         PL_ofs = savepv(SvPV(sv, PL_ofslen));
1828         break;
1829     case '#':
1830         if (PL_ofmt)
1831             Safefree(PL_ofmt);
1832         PL_ofmt = savepv(SvPV(sv,len));
1833         break;
1834     case '[':
1835         PL_compiling.cop_arybase = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1836         break;
1837     case '?':
1838 #ifdef COMPLEX_STATUS
1839         if (PL_localizing == 2) {
1840             PL_statusvalue = LvTARGOFF(sv);
1841             PL_statusvalue_vms = LvTARGLEN(sv);
1842         }
1843         else
1844 #endif
1845 #ifdef VMSISH_STATUS
1846         if (VMSISH_STATUS)
1847             STATUS_NATIVE_SET((U32)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)));
1848         else
1849 #endif
1850             STATUS_POSIX_SET(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1851         break;
1852     case '!':
1853         SETERRNO(SvIOK(sv) ? SvIVX(sv) : SvOK(sv) ? sv_2iv(sv) : 0,
1854                  (SvIV(sv) == EVMSERR) ? 4 : vaxc$errno);
1855         break;
1856     case '<':
1857         PL_uid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1858         if (PL_delaymagic) {
1859             PL_delaymagic |= DM_RUID;
1860             break;                              /* don't do magic till later */
1861         }
1862 #ifdef HAS_SETRUID
1863         (void)setruid((Uid_t)PL_uid);
1864 #else
1865 #ifdef HAS_SETREUID
1866         (void)setreuid((Uid_t)PL_uid, (Uid_t)-1);
1867 #else
1868 #ifdef HAS_SETRESUID
1869       (void)setresuid((Uid_t)PL_uid, (Uid_t)-1, (Uid_t)-1);
1870 #else
1871         if (PL_uid == PL_euid)          /* special case $< = $> */
1872             (void)PerlProc_setuid(PL_uid);
1873         else {
1874             PL_uid = (I32)PerlProc_getuid();
1875             croak("setruid() not implemented");
1876         }
1877 #endif
1878 #endif
1879 #endif
1880         PL_uid = (I32)PerlProc_getuid();
1881         PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid));
1882         break;
1883     case '>':
1884         PL_euid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1885         if (PL_delaymagic) {
1886             PL_delaymagic |= DM_EUID;
1887             break;                              /* don't do magic till later */
1888         }
1889 #ifdef HAS_SETEUID
1890         (void)seteuid((Uid_t)PL_euid);
1891 #else
1892 #ifdef HAS_SETREUID
1893         (void)setreuid((Uid_t)-1, (Uid_t)PL_euid);
1894 #else
1895 #ifdef HAS_SETRESUID
1896         (void)setresuid((Uid_t)-1, (Uid_t)PL_euid, (Uid_t)-1);
1897 #else
1898         if (PL_euid == PL_uid)          /* special case $> = $< */
1899             PerlProc_setuid(PL_euid);
1900         else {
1901             PL_euid = (I32)PerlProc_geteuid();
1902             croak("seteuid() not implemented");
1903         }
1904 #endif
1905 #endif
1906 #endif
1907         PL_euid = (I32)PerlProc_geteuid();
1908         PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid));
1909         break;
1910     case '(':
1911         PL_gid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1912         if (PL_delaymagic) {
1913             PL_delaymagic |= DM_RGID;
1914             break;                              /* don't do magic till later */
1915         }
1916 #ifdef HAS_SETRGID
1917         (void)setrgid((Gid_t)PL_gid);
1918 #else
1919 #ifdef HAS_SETREGID
1920         (void)setregid((Gid_t)PL_gid, (Gid_t)-1);
1921 #else
1922 #ifdef HAS_SETRESGID
1923       (void)setresgid((Gid_t)PL_gid, (Gid_t)-1, (Gid_t) 1);
1924 #else
1925         if (PL_gid == PL_egid)                  /* special case $( = $) */
1926             (void)PerlProc_setgid(PL_gid);
1927         else {
1928             PL_gid = (I32)PerlProc_getgid();
1929             croak("setrgid() not implemented");
1930         }
1931 #endif
1932 #endif
1933 #endif
1934         PL_gid = (I32)PerlProc_getgid();
1935         PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid));
1936         break;
1937     case ')':
1938 #ifdef HAS_SETGROUPS
1939         {
1940             char *p = SvPV(sv, len);
1941             Groups_t gary[NGROUPS];
1942
1943             SET_NUMERIC_STANDARD();
1944             while (isSPACE(*p))
1945                 ++p;
1946             PL_egid = I_V(atof(p));
1947             for (i = 0; i < NGROUPS; ++i) {
1948                 while (*p && !isSPACE(*p))
1949                     ++p;
1950                 while (isSPACE(*p))
1951                     ++p;
1952                 if (!*p)
1953                     break;
1954                 gary[i] = I_V(atof(p));
1955             }
1956             if (i)
1957                 (void)setgroups(i, gary);
1958         }
1959 #else  /* HAS_SETGROUPS */
1960         PL_egid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1961 #endif /* HAS_SETGROUPS */
1962         if (PL_delaymagic) {
1963             PL_delaymagic |= DM_EGID;
1964             break;                              /* don't do magic till later */
1965         }
1966 #ifdef HAS_SETEGID
1967         (void)setegid((Gid_t)PL_egid);
1968 #else
1969 #ifdef HAS_SETREGID
1970         (void)setregid((Gid_t)-1, (Gid_t)PL_egid);
1971 #else
1972 #ifdef HAS_SETRESGID
1973         (void)setresgid((Gid_t)-1, (Gid_t)PL_egid, (Gid_t)-1);
1974 #else
1975         if (PL_egid == PL_gid)                  /* special case $) = $( */
1976             (void)PerlProc_setgid(PL_egid);
1977         else {
1978             PL_egid = (I32)PerlProc_getegid();
1979             croak("setegid() not implemented");
1980         }
1981 #endif
1982 #endif
1983 #endif
1984         PL_egid = (I32)PerlProc_getegid();
1985         PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid));
1986         break;
1987     case ':':
1988         PL_chopset = SvPV_force(sv,len);
1989         break;
1990     case '0':
1991         if (!PL_origalen) {
1992             s = PL_origargv[0];
1993             s += strlen(s);
1994             /* See if all the arguments are contiguous in memory */
1995             for (i = 1; i < PL_origargc; i++) {
1996                 if (PL_origargv[i] == s + 1
1997 #ifdef OS2
1998                     || PL_origargv[i] == s + 2
1999 #endif 
2000                    )
2001                 {
2002                     ++s;
2003                     s += strlen(s);     /* this one is ok too */
2004                 }
2005                 else
2006                     break;
2007             }
2008             /* can grab env area too? */
2009             if (PL_origenviron && (PL_origenviron[0] == s + 1
2010 #ifdef OS2
2011                                 || (PL_origenviron[0] == s + 9 && (s += 8))
2012 #endif 
2013                )) {
2014                 my_setenv("NoNe  SuCh", Nullch);
2015                                             /* force copy of environment */
2016                 for (i = 0; PL_origenviron[i]; i++)
2017                     if (PL_origenviron[i] == s + 1) {
2018                         ++s;
2019                         s += strlen(s);
2020                     }
2021                     else
2022                         break;
2023             }
2024             PL_origalen = s - PL_origargv[0];
2025         }
2026         s = SvPV_force(sv,len);
2027         i = len;
2028         if (i >= PL_origalen) {
2029             i = PL_origalen;
2030             /* don't allow system to limit $0 seen by script */
2031             /* SvCUR_set(sv, i); *SvEND(sv) = '\0'; */
2032             Copy(s, PL_origargv[0], i, char);
2033             s = PL_origargv[0]+i;
2034             *s = '\0';
2035         }
2036         else {
2037             Copy(s, PL_origargv[0], i, char);
2038             s = PL_origargv[0]+i;
2039             *s++ = '\0';
2040             while (++i < PL_origalen)
2041                 *s++ = ' ';
2042             s = PL_origargv[0]+i;
2043             for (i = 1; i < PL_origargc; i++)
2044                 PL_origargv[i] = Nullch;
2045         }
2046         break;
2047 #ifdef USE_THREADS
2048     case '@':
2049         sv_setsv(thr->errsv, sv);
2050         break;
2051 #endif /* USE_THREADS */
2052     }
2053     return 0;
2054 }
2055
2056 #ifdef USE_THREADS
2057 int
2058 Perl_magic_mutexfree(pTHX_ SV *sv, MAGIC *mg)
2059 {
2060     dTHR;
2061     DEBUG_S(PerlIO_printf(PerlIO_stderr(), "0x%lx: magic_mutexfree 0x%lx\n",
2062                           (unsigned long)thr, (unsigned long)sv);)
2063     if (MgOWNER(mg))
2064         croak("panic: magic_mutexfree");
2065     MUTEX_DESTROY(MgMUTEXP(mg));
2066     COND_DESTROY(MgCONDP(mg));
2067     return 0;
2068 }
2069 #endif /* USE_THREADS */
2070
2071 I32
2072 Perl_whichsig(pTHX_ char *sig)
2073 {
2074     register char **sigv;
2075
2076     for (sigv = PL_sig_name+1; *sigv; sigv++)
2077         if (strEQ(sig,*sigv))
2078             return PL_sig_num[sigv - PL_sig_name];
2079 #ifdef SIGCLD
2080     if (strEQ(sig,"CHLD"))
2081         return SIGCLD;
2082 #endif
2083 #ifdef SIGCHLD
2084     if (strEQ(sig,"CLD"))
2085         return SIGCHLD;
2086 #endif
2087     return 0;
2088 }
2089
2090 static SV* sig_sv;
2091
2092 STATIC void
2093 unwind_handler_stack(pTHX_ void *p)
2094 {
2095     dTHR;
2096     U32 flags = *(U32*)p;
2097
2098     if (flags & 1)
2099         PL_savestack_ix -= 5; /* Unprotect save in progress. */
2100     /* cxstack_ix-- Not needed, die already unwound it. */
2101     if (flags & 64)
2102         SvREFCNT_dec(sig_sv);
2103 }
2104
2105 Signal_t
2106 Perl_sighandler(pTHX_ int sig)
2107 {
2108     dSP;
2109     GV *gv = Nullgv;
2110     HV *st;
2111     SV *sv, *tSv = PL_Sv;
2112     CV *cv = Nullcv;
2113     OP *myop = PL_op;
2114     U32 flags = 0;
2115     I32 o_save_i = PL_savestack_ix, type;
2116     XPV *tXpv = PL_Xpv;
2117     
2118     if (PL_savestack_ix + 15 <= PL_savestack_max)
2119         flags |= 1;
2120     if (PL_markstack_ptr < PL_markstack_max - 2)
2121         flags |= 4;
2122     if (PL_retstack_ix < PL_retstack_max - 2)
2123         flags |= 8;
2124     if (PL_scopestack_ix < PL_scopestack_max - 3)
2125         flags |= 16;
2126
2127     if (!PL_psig_ptr[sig])
2128         die("Signal SIG%s received, but no signal handler set.\n",
2129             PL_sig_name[sig]);
2130
2131     /* Max number of items pushed there is 3*n or 4. We cannot fix
2132        infinity, so we fix 4 (in fact 5): */
2133     if (flags & 1) {
2134         PL_savestack_ix += 5;           /* Protect save in progress. */
2135         o_save_i = PL_savestack_ix;
2136         SAVEDESTRUCTOR(unwind_handler_stack, (void*)&flags);
2137     }
2138     if (flags & 4) 
2139         PL_markstack_ptr++;             /* Protect mark. */
2140     if (flags & 8) {
2141         PL_retstack_ix++;
2142         PL_retstack[PL_retstack_ix] = NULL;
2143     }
2144     if (flags & 16)
2145         PL_scopestack_ix += 1;
2146     /* sv_2cv is too complicated, try a simpler variant first: */
2147     if (!SvROK(PL_psig_ptr[sig]) || !(cv = (CV*)SvRV(PL_psig_ptr[sig])) 
2148         || SvTYPE(cv) != SVt_PVCV)
2149         cv = sv_2cv(PL_psig_ptr[sig],&st,&gv,TRUE);
2150
2151     if (!cv || !CvROOT(cv)) {
2152         if (ckWARN(WARN_SIGNAL))
2153             warner(WARN_SIGNAL, "SIG%s handler \"%s\" not defined.\n",
2154                 PL_sig_name[sig], (gv ? GvENAME(gv)
2155                                 : ((cv && CvGV(cv))
2156                                    ? GvENAME(CvGV(cv))
2157                                    : "__ANON__")));
2158         goto cleanup;
2159     }
2160
2161     if(PL_psig_name[sig]) {
2162         sv = SvREFCNT_inc(PL_psig_name[sig]);
2163         flags |= 64;
2164         sig_sv = sv;
2165     } else {
2166         sv = sv_newmortal();
2167         sv_setpv(sv,PL_sig_name[sig]);
2168     }
2169
2170     PUSHSTACKi(PERLSI_SIGNAL);
2171     PUSHMARK(SP);
2172     PUSHs(sv);
2173     PUTBACK;
2174
2175     call_sv((SV*)cv, G_DISCARD);
2176
2177     POPSTACK;
2178 cleanup:
2179     if (flags & 1)
2180         PL_savestack_ix -= 8; /* Unprotect save in progress. */
2181     if (flags & 4) 
2182         PL_markstack_ptr--;
2183     if (flags & 8) 
2184         PL_retstack_ix--;
2185     if (flags & 16)
2186         PL_scopestack_ix -= 1;
2187     if (flags & 64)
2188         SvREFCNT_dec(sv);
2189     PL_op = myop;                       /* Apparently not needed... */
2190     
2191     PL_Sv = tSv;                        /* Restore global temporaries. */
2192     PL_Xpv = tXpv;
2193     return;
2194 }
2195
2196