Put back the cygwin32 Configure fix of 3582 undone by 3597.
[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 #    ifndef OS2
1711         /* will anyone ever use this? */
1712         SETERRNO(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv), 4);
1713 #    endif
1714 #  endif
1715 #endif
1716         break;
1717     case '\006':        /* ^F */
1718         PL_maxsysfd = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1719         break;
1720     case '\010':        /* ^H */
1721         PL_hints = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1722         break;
1723     case '\011':        /* ^I */ /* NOT \t in EBCDIC */
1724         if (PL_inplace)
1725             Safefree(PL_inplace);
1726         if (SvOK(sv))
1727             PL_inplace = savepv(SvPV(sv,len));
1728         else
1729             PL_inplace = Nullch;
1730         break;
1731     case '\017':        /* ^O */
1732         if (PL_osname)
1733             Safefree(PL_osname);
1734         if (SvOK(sv))
1735             PL_osname = savepv(SvPV(sv,len));
1736         else
1737             PL_osname = Nullch;
1738         break;
1739     case '\020':        /* ^P */
1740         PL_perldb = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1741         break;
1742     case '\024':        /* ^T */
1743 #ifdef BIG_TIME
1744         PL_basetime = (Time_t)(SvNOK(sv) ? SvNVX(sv) : sv_2nv(sv));
1745 #else
1746         PL_basetime = (Time_t)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1747 #endif
1748         break;
1749     case '\027':        /* ^W */
1750         if ( ! (PL_dowarn & G_WARN_ALL_MASK)) {
1751             i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1752             PL_dowarn = (i ? G_WARN_ON : G_WARN_OFF) ;
1753         }
1754         break;
1755     case '.':
1756         if (PL_localizing) {
1757             if (PL_localizing == 1)
1758                 save_sptr((SV**)&PL_last_in_gv);
1759         }
1760         else if (SvOK(sv) && GvIO(PL_last_in_gv))
1761             IoLINES(GvIOp(PL_last_in_gv)) = (long)SvIV(sv);
1762         break;
1763     case '^':
1764         Safefree(IoTOP_NAME(GvIOp(PL_defoutgv)));
1765         IoTOP_NAME(GvIOp(PL_defoutgv)) = s = savepv(SvPV(sv,len));
1766         IoTOP_GV(GvIOp(PL_defoutgv)) = gv_fetchpv(s,TRUE, SVt_PVIO);
1767         break;
1768     case '~':
1769         Safefree(IoFMT_NAME(GvIOp(PL_defoutgv)));
1770         IoFMT_NAME(GvIOp(PL_defoutgv)) = s = savepv(SvPV(sv,len));
1771         IoFMT_GV(GvIOp(PL_defoutgv)) = gv_fetchpv(s,TRUE, SVt_PVIO);
1772         break;
1773     case '=':
1774         IoPAGE_LEN(GvIOp(PL_defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1775         break;
1776     case '-':
1777         IoLINES_LEFT(GvIOp(PL_defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1778         if (IoLINES_LEFT(GvIOp(PL_defoutgv)) < 0L)
1779             IoLINES_LEFT(GvIOp(PL_defoutgv)) = 0L;
1780         break;
1781     case '%':
1782         IoPAGE(GvIOp(PL_defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1783         break;
1784     case '|':
1785         {
1786             IO *io = GvIOp(PL_defoutgv);
1787             if ((SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) == 0)
1788                 IoFLAGS(io) &= ~IOf_FLUSH;
1789             else {
1790                 if (!(IoFLAGS(io) & IOf_FLUSH)) {
1791                     PerlIO *ofp = IoOFP(io);
1792                     if (ofp)
1793                         (void)PerlIO_flush(ofp);
1794                     IoFLAGS(io) |= IOf_FLUSH;
1795                 }
1796             }
1797         }
1798         break;
1799     case '*':
1800         i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1801         PL_multiline = (i != 0);
1802         break;
1803     case '/':
1804         SvREFCNT_dec(PL_nrs);
1805         PL_nrs = newSVsv(sv);
1806         SvREFCNT_dec(PL_rs);
1807         PL_rs = SvREFCNT_inc(PL_nrs);
1808         break;
1809     case '\\':
1810         if (PL_ors)
1811             Safefree(PL_ors);
1812         if (SvOK(sv) || SvGMAGICAL(sv))
1813             PL_ors = savepv(SvPV(sv,PL_orslen));
1814         else {
1815             PL_ors = Nullch;
1816             PL_orslen = 0;
1817         }
1818         break;
1819     case ',':
1820         if (PL_ofs)
1821             Safefree(PL_ofs);
1822         PL_ofs = savepv(SvPV(sv, PL_ofslen));
1823         break;
1824     case '#':
1825         if (PL_ofmt)
1826             Safefree(PL_ofmt);
1827         PL_ofmt = savepv(SvPV(sv,len));
1828         break;
1829     case '[':
1830         PL_compiling.cop_arybase = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1831         break;
1832     case '?':
1833 #ifdef COMPLEX_STATUS
1834         if (PL_localizing == 2) {
1835             PL_statusvalue = LvTARGOFF(sv);
1836             PL_statusvalue_vms = LvTARGLEN(sv);
1837         }
1838         else
1839 #endif
1840 #ifdef VMSISH_STATUS
1841         if (VMSISH_STATUS)
1842             STATUS_NATIVE_SET((U32)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)));
1843         else
1844 #endif
1845             STATUS_POSIX_SET(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1846         break;
1847     case '!':
1848         SETERRNO(SvIOK(sv) ? SvIVX(sv) : SvOK(sv) ? sv_2iv(sv) : 0,
1849                  (SvIV(sv) == EVMSERR) ? 4 : vaxc$errno);
1850         break;
1851     case '<':
1852         PL_uid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1853         if (PL_delaymagic) {
1854             PL_delaymagic |= DM_RUID;
1855             break;                              /* don't do magic till later */
1856         }
1857 #ifdef HAS_SETRUID
1858         (void)setruid((Uid_t)PL_uid);
1859 #else
1860 #ifdef HAS_SETREUID
1861         (void)setreuid((Uid_t)PL_uid, (Uid_t)-1);
1862 #else
1863 #ifdef HAS_SETRESUID
1864       (void)setresuid((Uid_t)PL_uid, (Uid_t)-1, (Uid_t)-1);
1865 #else
1866         if (PL_uid == PL_euid)          /* special case $< = $> */
1867             (void)PerlProc_setuid(PL_uid);
1868         else {
1869             PL_uid = (I32)PerlProc_getuid();
1870             Perl_croak(aTHX_ "setruid() not implemented");
1871         }
1872 #endif
1873 #endif
1874 #endif
1875         PL_uid = (I32)PerlProc_getuid();
1876         PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid));
1877         break;
1878     case '>':
1879         PL_euid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1880         if (PL_delaymagic) {
1881             PL_delaymagic |= DM_EUID;
1882             break;                              /* don't do magic till later */
1883         }
1884 #ifdef HAS_SETEUID
1885         (void)seteuid((Uid_t)PL_euid);
1886 #else
1887 #ifdef HAS_SETREUID
1888         (void)setreuid((Uid_t)-1, (Uid_t)PL_euid);
1889 #else
1890 #ifdef HAS_SETRESUID
1891         (void)setresuid((Uid_t)-1, (Uid_t)PL_euid, (Uid_t)-1);
1892 #else
1893         if (PL_euid == PL_uid)          /* special case $> = $< */
1894             PerlProc_setuid(PL_euid);
1895         else {
1896             PL_euid = (I32)PerlProc_geteuid();
1897             Perl_croak(aTHX_ "seteuid() not implemented");
1898         }
1899 #endif
1900 #endif
1901 #endif
1902         PL_euid = (I32)PerlProc_geteuid();
1903         PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid));
1904         break;
1905     case '(':
1906         PL_gid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1907         if (PL_delaymagic) {
1908             PL_delaymagic |= DM_RGID;
1909             break;                              /* don't do magic till later */
1910         }
1911 #ifdef HAS_SETRGID
1912         (void)setrgid((Gid_t)PL_gid);
1913 #else
1914 #ifdef HAS_SETREGID
1915         (void)setregid((Gid_t)PL_gid, (Gid_t)-1);
1916 #else
1917 #ifdef HAS_SETRESGID
1918       (void)setresgid((Gid_t)PL_gid, (Gid_t)-1, (Gid_t) 1);
1919 #else
1920         if (PL_gid == PL_egid)                  /* special case $( = $) */
1921             (void)PerlProc_setgid(PL_gid);
1922         else {
1923             PL_gid = (I32)PerlProc_getgid();
1924             Perl_croak(aTHX_ "setrgid() not implemented");
1925         }
1926 #endif
1927 #endif
1928 #endif
1929         PL_gid = (I32)PerlProc_getgid();
1930         PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid));
1931         break;
1932     case ')':
1933 #ifdef HAS_SETGROUPS
1934         {
1935             char *p = SvPV(sv, len);
1936             Groups_t gary[NGROUPS];
1937
1938             while (isSPACE(*p))
1939                 ++p;
1940             PL_egid = I_V(atol(p));
1941             for (i = 0; i < NGROUPS; ++i) {
1942                 while (*p && !isSPACE(*p))
1943                     ++p;
1944                 while (isSPACE(*p))
1945                     ++p;
1946                 if (!*p)
1947                     break;
1948                 gary[i] = I_V(atol(p));
1949             }
1950             if (i)
1951                 (void)setgroups(i, gary);
1952         }
1953 #else  /* HAS_SETGROUPS */
1954         PL_egid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1955 #endif /* HAS_SETGROUPS */
1956         if (PL_delaymagic) {
1957             PL_delaymagic |= DM_EGID;
1958             break;                              /* don't do magic till later */
1959         }
1960 #ifdef HAS_SETEGID
1961         (void)setegid((Gid_t)PL_egid);
1962 #else
1963 #ifdef HAS_SETREGID
1964         (void)setregid((Gid_t)-1, (Gid_t)PL_egid);
1965 #else
1966 #ifdef HAS_SETRESGID
1967         (void)setresgid((Gid_t)-1, (Gid_t)PL_egid, (Gid_t)-1);
1968 #else
1969         if (PL_egid == PL_gid)                  /* special case $) = $( */
1970             (void)PerlProc_setgid(PL_egid);
1971         else {
1972             PL_egid = (I32)PerlProc_getegid();
1973             Perl_croak(aTHX_ "setegid() not implemented");
1974         }
1975 #endif
1976 #endif
1977 #endif
1978         PL_egid = (I32)PerlProc_getegid();
1979         PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid));
1980         break;
1981     case ':':
1982         PL_chopset = SvPV_force(sv,len);
1983         break;
1984     case '0':
1985         if (!PL_origalen) {
1986             s = PL_origargv[0];
1987             s += strlen(s);
1988             /* See if all the arguments are contiguous in memory */
1989             for (i = 1; i < PL_origargc; i++) {
1990                 if (PL_origargv[i] == s + 1
1991 #ifdef OS2
1992                     || PL_origargv[i] == s + 2
1993 #endif 
1994                    )
1995                 {
1996                     ++s;
1997                     s += strlen(s);     /* this one is ok too */
1998                 }
1999                 else
2000                     break;
2001             }
2002             /* can grab env area too? */
2003             if (PL_origenviron && (PL_origenviron[0] == s + 1
2004 #ifdef OS2
2005                                 || (PL_origenviron[0] == s + 9 && (s += 8))
2006 #endif 
2007                )) {
2008                 my_setenv("NoNe  SuCh", Nullch);
2009                                             /* force copy of environment */
2010                 for (i = 0; PL_origenviron[i]; i++)
2011                     if (PL_origenviron[i] == s + 1) {
2012                         ++s;
2013                         s += strlen(s);
2014                     }
2015                     else
2016                         break;
2017             }
2018             PL_origalen = s - PL_origargv[0];
2019         }
2020         s = SvPV_force(sv,len);
2021         i = len;
2022         if (i >= PL_origalen) {
2023             i = PL_origalen;
2024             /* don't allow system to limit $0 seen by script */
2025             /* SvCUR_set(sv, i); *SvEND(sv) = '\0'; */
2026             Copy(s, PL_origargv[0], i, char);
2027             s = PL_origargv[0]+i;
2028             *s = '\0';
2029         }
2030         else {
2031             Copy(s, PL_origargv[0], i, char);
2032             s = PL_origargv[0]+i;
2033             *s++ = '\0';
2034             while (++i < PL_origalen)
2035                 *s++ = ' ';
2036             s = PL_origargv[0]+i;
2037             for (i = 1; i < PL_origargc; i++)
2038                 PL_origargv[i] = Nullch;
2039         }
2040         break;
2041 #ifdef USE_THREADS
2042     case '@':
2043         sv_setsv(thr->errsv, sv);
2044         break;
2045 #endif /* USE_THREADS */
2046     }
2047     return 0;
2048 }
2049
2050 #ifdef USE_THREADS
2051 int
2052 Perl_magic_mutexfree(pTHX_ SV *sv, MAGIC *mg)
2053 {
2054     dTHR;
2055     DEBUG_S(PerlIO_printf(PerlIO_stderr(), "0x%lx: magic_mutexfree 0x%lx\n",
2056                           (unsigned long)thr, (unsigned long)sv);)
2057     if (MgOWNER(mg))
2058         Perl_croak(aTHX_ "panic: magic_mutexfree");
2059     MUTEX_DESTROY(MgMUTEXP(mg));
2060     COND_DESTROY(MgCONDP(mg));
2061     return 0;
2062 }
2063 #endif /* USE_THREADS */
2064
2065 I32
2066 Perl_whichsig(pTHX_ char *sig)
2067 {
2068     register char **sigv;
2069
2070     for (sigv = PL_sig_name+1; *sigv; sigv++)
2071         if (strEQ(sig,*sigv))
2072             return PL_sig_num[sigv - PL_sig_name];
2073 #ifdef SIGCLD
2074     if (strEQ(sig,"CHLD"))
2075         return SIGCLD;
2076 #endif
2077 #ifdef SIGCHLD
2078     if (strEQ(sig,"CLD"))
2079         return SIGCHLD;
2080 #endif
2081     return 0;
2082 }
2083
2084 static SV* sig_sv;
2085
2086 STATIC void
2087 S_unwind_handler_stack(pTHX_ void *p)
2088 {
2089     dTHR;
2090     U32 flags = *(U32*)p;
2091
2092     if (flags & 1)
2093         PL_savestack_ix -= 5; /* Unprotect save in progress. */
2094     /* cxstack_ix-- Not needed, die already unwound it. */
2095     if (flags & 64)
2096         SvREFCNT_dec(sig_sv);
2097 }
2098
2099 Signal_t
2100 Perl_sighandler(int sig)
2101 {
2102     dTHX;
2103     dSP;
2104     GV *gv = Nullgv;
2105     HV *st;
2106     SV *sv, *tSv = PL_Sv;
2107     CV *cv = Nullcv;
2108     OP *myop = PL_op;
2109     U32 flags = 0;
2110     I32 o_save_i = PL_savestack_ix, type;
2111     XPV *tXpv = PL_Xpv;
2112     
2113     if (PL_savestack_ix + 15 <= PL_savestack_max)
2114         flags |= 1;
2115     if (PL_markstack_ptr < PL_markstack_max - 2)
2116         flags |= 4;
2117     if (PL_retstack_ix < PL_retstack_max - 2)
2118         flags |= 8;
2119     if (PL_scopestack_ix < PL_scopestack_max - 3)
2120         flags |= 16;
2121
2122     if (!PL_psig_ptr[sig])
2123         Perl_die(aTHX_ "Signal SIG%s received, but no signal handler set.\n",
2124             PL_sig_name[sig]);
2125
2126     /* Max number of items pushed there is 3*n or 4. We cannot fix
2127        infinity, so we fix 4 (in fact 5): */
2128     if (flags & 1) {
2129         PL_savestack_ix += 5;           /* Protect save in progress. */
2130         o_save_i = PL_savestack_ix;
2131         SAVEDESTRUCTOR(S_unwind_handler_stack, (void*)&flags);
2132     }
2133     if (flags & 4) 
2134         PL_markstack_ptr++;             /* Protect mark. */
2135     if (flags & 8) {
2136         PL_retstack_ix++;
2137         PL_retstack[PL_retstack_ix] = NULL;
2138     }
2139     if (flags & 16)
2140         PL_scopestack_ix += 1;
2141     /* sv_2cv is too complicated, try a simpler variant first: */
2142     if (!SvROK(PL_psig_ptr[sig]) || !(cv = (CV*)SvRV(PL_psig_ptr[sig])) 
2143         || SvTYPE(cv) != SVt_PVCV)
2144         cv = sv_2cv(PL_psig_ptr[sig],&st,&gv,TRUE);
2145
2146     if (!cv || !CvROOT(cv)) {
2147         if (ckWARN(WARN_SIGNAL))
2148             Perl_warner(aTHX_ WARN_SIGNAL, "SIG%s handler \"%s\" not defined.\n",
2149                 PL_sig_name[sig], (gv ? GvENAME(gv)
2150                                 : ((cv && CvGV(cv))
2151                                    ? GvENAME(CvGV(cv))
2152                                    : "__ANON__")));
2153         goto cleanup;
2154     }
2155
2156     if(PL_psig_name[sig]) {
2157         sv = SvREFCNT_inc(PL_psig_name[sig]);
2158         flags |= 64;
2159         sig_sv = sv;
2160     } else {
2161         sv = sv_newmortal();
2162         sv_setpv(sv,PL_sig_name[sig]);
2163     }
2164
2165     PUSHSTACKi(PERLSI_SIGNAL);
2166     PUSHMARK(SP);
2167     PUSHs(sv);
2168     PUTBACK;
2169
2170     call_sv((SV*)cv, G_DISCARD);
2171
2172     POPSTACK;
2173 cleanup:
2174     if (flags & 1)
2175         PL_savestack_ix -= 8; /* Unprotect save in progress. */
2176     if (flags & 4) 
2177         PL_markstack_ptr--;
2178     if (flags & 8) 
2179         PL_retstack_ix--;
2180     if (flags & 16)
2181         PL_scopestack_ix -= 1;
2182     if (flags & 64)
2183         SvREFCNT_dec(sv);
2184     PL_op = myop;                       /* Apparently not needed... */
2185     
2186     PL_Sv = tSv;                        /* Restore global temporaries. */
2187     PL_Xpv = tXpv;
2188     return;
2189 }
2190
2191