Math::Complex update
[p5sagit/p5-mst-13.2.git] / mg.c
1 /*    mg.c
2  *
3  *    Copyright (c) 1991-1997, 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 #include "perl.h"
17
18 /* XXX If this causes problems, set i_unistd=undef in the hint file.  */
19 #ifdef I_UNISTD
20 # include <unistd.h>
21 #endif
22
23 #ifdef HAS_GETGROUPS
24 #  ifndef NGROUPS
25 #    define NGROUPS 32
26 #  endif
27 #endif
28
29 /*
30  * Use the "DESTRUCTOR" scope cleanup to reinstate magic.
31  */
32
33 struct magic_state {
34     SV* mgs_sv;
35     U32 mgs_flags;
36 };
37 typedef struct magic_state MGS;
38
39 static void restore_magic _((void *p));
40
41 static void
42 save_magic(mgs, sv)
43 MGS* mgs;
44 SV* sv;
45 {
46     assert(SvMAGICAL(sv));
47
48     mgs->mgs_sv = sv;
49     mgs->mgs_flags = SvMAGICAL(sv) | SvREADONLY(sv);
50     SAVEDESTRUCTOR(restore_magic, mgs);
51
52     SvMAGICAL_off(sv);
53     SvREADONLY_off(sv);
54     SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT;
55 }
56
57 static void
58 restore_magic(p)
59 void* p;
60 {
61     MGS* mgs = (MGS*)p;
62     SV* sv = mgs->mgs_sv;
63
64     if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv))
65     {
66         if (mgs->mgs_flags)
67             SvFLAGS(sv) |= mgs->mgs_flags;
68         else
69             mg_magical(sv);
70         if (SvGMAGICAL(sv))
71             SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK|SVf_POK);
72     }
73 }
74
75
76 void
77 mg_magical(sv)
78 SV* sv;
79 {
80     MAGIC* mg;
81     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
82         MGVTBL* vtbl = mg->mg_virtual;
83         if (vtbl) {
84             if (vtbl->svt_get && !(mg->mg_flags & MGf_GSKIP))
85                 SvGMAGICAL_on(sv);
86             if (vtbl->svt_set)
87                 SvSMAGICAL_on(sv);
88             if (!(SvFLAGS(sv) & (SVs_GMG|SVs_SMG)) || vtbl->svt_clear)
89                 SvRMAGICAL_on(sv);
90         }
91     }
92 }
93
94 int
95 mg_get(sv)
96 SV* sv;
97 {
98     MGS mgs;
99     MAGIC* mg;
100     MAGIC** mgp;
101     int mgp_valid = 0;
102
103     ENTER;
104     save_magic(&mgs, sv);
105
106     mgp = &SvMAGIC(sv);
107     while ((mg = *mgp) != 0) {
108         MGVTBL* vtbl = mg->mg_virtual;
109         if (!(mg->mg_flags & MGf_GSKIP) && vtbl && vtbl->svt_get) {
110             (*vtbl->svt_get)(sv, mg);
111             /* Ignore this magic if it's been deleted */
112             if ((mg == (mgp_valid ? *mgp : SvMAGIC(sv))) &&
113                   (mg->mg_flags & MGf_GSKIP))
114                 mgs.mgs_flags = 0;
115         }
116         /* Advance to next magic (complicated by possible deletion) */
117         if (mg == (mgp_valid ? *mgp : SvMAGIC(sv))) {
118             mgp = &mg->mg_moremagic;
119             mgp_valid = 1;
120         }
121         else
122             mgp = &SvMAGIC(sv); /* Re-establish pointer after sv_upgrade */
123     }
124
125     LEAVE;
126     return 0;
127 }
128
129 int
130 mg_set(sv)
131 SV* sv;
132 {
133     MGS mgs;
134     MAGIC* mg;
135     MAGIC* nextmg;
136
137     ENTER;
138     save_magic(&mgs, sv);
139
140     for (mg = SvMAGIC(sv); mg; mg = nextmg) {
141         MGVTBL* vtbl = mg->mg_virtual;
142         nextmg = mg->mg_moremagic;      /* it may delete itself */
143         if (mg->mg_flags & MGf_GSKIP) {
144             mg->mg_flags &= ~MGf_GSKIP; /* setting requires another read */
145             mgs.mgs_flags = 0;
146         }
147         if (vtbl && vtbl->svt_set)
148             (*vtbl->svt_set)(sv, mg);
149     }
150
151     LEAVE;
152     return 0;
153 }
154
155 U32
156 mg_len(sv)
157 SV* sv;
158 {
159     MAGIC* mg;
160     char *junk;
161     STRLEN len;
162
163     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
164         MGVTBL* vtbl = mg->mg_virtual;
165         if (vtbl && vtbl->svt_len) {
166             MGS mgs;
167
168             ENTER;
169             save_magic(&mgs, sv);
170             /* omit MGf_GSKIP -- not changed here */
171             len = (*vtbl->svt_len)(sv, mg);
172             LEAVE;
173             return len;
174         }
175     }
176
177     junk = SvPV(sv, len);
178     return len;
179 }
180
181 int
182 mg_clear(sv)
183 SV* sv;
184 {
185     MGS mgs;
186     MAGIC* mg;
187
188     ENTER;
189     save_magic(&mgs, sv);
190
191     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
192         MGVTBL* vtbl = mg->mg_virtual;
193         /* omit GSKIP -- never set here */
194         
195         if (vtbl && vtbl->svt_clear)
196             (*vtbl->svt_clear)(sv, mg);
197     }
198
199     LEAVE;
200     return 0;
201 }
202
203 MAGIC*
204 mg_find(sv, type)
205 SV* sv;
206 int type;
207 {
208     MAGIC* mg;
209     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
210         if (mg->mg_type == type)
211             return mg;
212     }
213     return 0;
214 }
215
216 int
217 mg_copy(sv, nsv, key, klen)
218 SV* sv;
219 SV* nsv;
220 char *key;
221 I32 klen;
222 {
223     int count = 0;
224     MAGIC* mg;
225     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
226         if (isUPPER(mg->mg_type)) {
227             sv_magic(nsv, mg->mg_obj, toLOWER(mg->mg_type), key, klen);
228             count++;
229         }
230     }
231     return count;
232 }
233
234 int
235 mg_free(sv)
236 SV* sv;
237 {
238     MAGIC* mg;
239     MAGIC* moremagic;
240     for (mg = SvMAGIC(sv); mg; mg = moremagic) {
241         MGVTBL* vtbl = mg->mg_virtual;
242         moremagic = mg->mg_moremagic;
243         if (vtbl && vtbl->svt_free)
244             (*vtbl->svt_free)(sv, mg);
245         if (mg->mg_ptr && mg->mg_type != 'g')
246             if (mg->mg_len >= 0)
247                 Safefree(mg->mg_ptr);
248             else if (mg->mg_len == HEf_SVKEY)
249                 SvREFCNT_dec((SV*)mg->mg_ptr);
250         if (mg->mg_flags & MGf_REFCOUNTED)
251             SvREFCNT_dec(mg->mg_obj);
252         Safefree(mg);
253     }
254     SvMAGIC(sv) = 0;
255     return 0;
256 }
257
258 #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
259 #include <signal.h>
260 #endif
261
262 U32
263 magic_len(sv, mg)
264 SV *sv;
265 MAGIC *mg;
266 {
267     register I32 paren;
268     register char *s;
269     register I32 i;
270     register REGEXP *rx;
271     char *t;
272
273     switch (*mg->mg_ptr) {
274     case '1': case '2': case '3': case '4':
275     case '5': case '6': case '7': case '8': case '9': case '&':
276         if (curpm && (rx = curpm->op_pmregexp)) {
277             paren = atoi(mg->mg_ptr);
278           getparen:
279             if (paren <= rx->nparens &&
280                 (s = rx->startp[paren]) &&
281                 (t = rx->endp[paren]))
282             {
283                 i = t - s;
284                 if (i >= 0)
285                     return i;
286             }
287         }
288         return 0;
289         break;
290     case '+':
291         if (curpm && (rx = curpm->op_pmregexp)) {
292             paren = rx->lastparen;
293             if (paren)
294                 goto getparen;
295         }
296         return 0;
297         break;
298     case '`':
299         if (curpm && (rx = curpm->op_pmregexp)) {
300             if ((s = rx->subbeg) && rx->startp[0]) {
301                 i = rx->startp[0] - s;
302                 if (i >= 0)
303                     return i;
304             }
305         }
306         return 0;
307     case '\'':
308         if (curpm && (rx = curpm->op_pmregexp)) {
309             if (rx->subend && (s = rx->endp[0])) {
310                 i = rx->subend - s;
311                 if (i >= 0)
312                     return 0;
313             }
314         }
315         return 0;
316     case ',':
317         return (STRLEN)ofslen;
318     case '\\':
319         return (STRLEN)orslen;
320     }
321     magic_get(sv,mg);
322     if (!SvPOK(sv) && SvNIOK(sv))
323         sv_2pv(sv, &na);
324     if (SvPOK(sv))
325         return SvCUR(sv);
326     return 0;
327 }
328
329 int
330 magic_get(sv, mg)
331 SV *sv;
332 MAGIC *mg;
333 {
334     register I32 paren;
335     register char *s;
336     register I32 i;
337     register REGEXP *rx;
338     char *t;
339
340     switch (*mg->mg_ptr) {
341     case '\001':                /* ^A */
342         sv_setsv(sv, bodytarget);
343         break;
344     case '\004':                /* ^D */
345         sv_setiv(sv, (IV)(debug & 32767));
346         break;
347     case '\005':  /* ^E */
348 #ifdef VMS
349         {
350 #           include <descrip.h>
351 #           include <starlet.h>
352             char msg[255];
353             $DESCRIPTOR(msgdsc,msg);
354             sv_setnv(sv,(double) vaxc$errno);
355             if (sys$getmsg(vaxc$errno,&msgdsc.dsc$w_length,&msgdsc,0,0) & 1)
356                 sv_setpvn(sv,msgdsc.dsc$a_pointer,msgdsc.dsc$w_length);
357             else
358                 sv_setpv(sv,"");
359         }
360 #else
361 #ifdef OS2
362         sv_setnv(sv, (double)Perl_rc);
363         sv_setpv(sv, os2error(Perl_rc));
364 #else
365         sv_setnv(sv, (double)errno);
366         sv_setpv(sv, errno ? Strerror(errno) : "");
367 #endif
368 #endif
369         SvNOK_on(sv);   /* what a wonderful hack! */
370         break;
371     case '\006':                /* ^F */
372         sv_setiv(sv, (IV)maxsysfd);
373         break;
374     case '\010':                /* ^H */
375         sv_setiv(sv, (IV)hints);
376         break;
377     case '\t':                  /* ^I */
378         if (inplace)
379             sv_setpv(sv, inplace);
380         else
381             sv_setsv(sv, &sv_undef);
382         break;
383     case '\017':                /* ^O */
384         sv_setpv(sv, osname);
385         break;
386     case '\020':                /* ^P */
387         sv_setiv(sv, (IV)perldb);
388         break;
389     case '\024':                /* ^T */
390 #ifdef BIG_TIME
391         sv_setnv(sv, basetime);
392 #else
393         sv_setiv(sv, (IV)basetime);
394 #endif
395         break;
396     case '\027':                /* ^W */
397         sv_setiv(sv, (IV)dowarn);
398         break;
399     case '1': case '2': case '3': case '4':
400     case '5': case '6': case '7': case '8': case '9': case '&':
401         if (curpm && (rx = curpm->op_pmregexp)) {
402             paren = atoi(GvENAME((GV*)mg->mg_obj));
403           getparen:
404             if (paren <= rx->nparens &&
405                 (s = rx->startp[paren]) &&
406                 (t = rx->endp[paren]))
407             {
408                 i = t - s;
409               getrx:
410                 if (i >= 0) {
411                     bool was_tainted;
412                     if (tainting) {
413                         was_tainted = tainted;
414                         tainted = FALSE;
415                     }
416                     sv_setpvn(sv,s,i);
417                     if (tainting)
418                         tainted = was_tainted || rx->exec_tainted;
419                     break;
420                 }
421             }
422         }
423         sv_setsv(sv,&sv_undef);
424         break;
425     case '+':
426         if (curpm && (rx = curpm->op_pmregexp)) {
427             paren = rx->lastparen;
428             if (paren)
429                 goto getparen;
430         }
431         sv_setsv(sv,&sv_undef);
432         break;
433     case '`':
434         if (curpm && (rx = curpm->op_pmregexp)) {
435             if ((s = rx->subbeg) && rx->startp[0]) {
436                 i = rx->startp[0] - s;
437                 goto getrx;
438             }
439         }
440         sv_setsv(sv,&sv_undef);
441         break;
442     case '\'':
443         if (curpm && (rx = curpm->op_pmregexp)) {
444             if (rx->subend && (s = rx->endp[0])) {
445                 i = rx->subend - s;
446                 goto getrx;
447             }
448         }
449         sv_setsv(sv,&sv_undef);
450         break;
451     case '.':
452 #ifndef lint
453         if (GvIO(last_in_gv)) {
454             sv_setiv(sv, (IV)IoLINES(GvIO(last_in_gv)));
455         }
456 #endif
457         break;
458     case '?':
459         sv_setiv(sv, (IV)STATUS_CURRENT);
460 #ifdef COMPLEX_STATUS
461         LvTARGOFF(sv) = statusvalue;
462         LvTARGLEN(sv) = statusvalue_vms;
463 #endif
464         break;
465     case '^':
466         s = IoTOP_NAME(GvIOp(defoutgv));
467         if (s)
468             sv_setpv(sv,s);
469         else {
470             sv_setpv(sv,GvENAME(defoutgv));
471             sv_catpv(sv,"_TOP");
472         }
473         break;
474     case '~':
475         s = IoFMT_NAME(GvIOp(defoutgv));
476         if (!s)
477             s = GvENAME(defoutgv);
478         sv_setpv(sv,s);
479         break;
480 #ifndef lint
481     case '=':
482         sv_setiv(sv, (IV)IoPAGE_LEN(GvIOp(defoutgv)));
483         break;
484     case '-':
485         sv_setiv(sv, (IV)IoLINES_LEFT(GvIOp(defoutgv)));
486         break;
487     case '%':
488         sv_setiv(sv, (IV)IoPAGE(GvIOp(defoutgv)));
489         break;
490 #endif
491     case ':':
492         break;
493     case '/':
494         break;
495     case '[':
496         sv_setiv(sv, (IV)curcop->cop_arybase);
497         break;
498     case '|':
499         sv_setiv(sv, (IV)(IoFLAGS(GvIOp(defoutgv)) & IOf_FLUSH) != 0 );
500         break;
501     case ',':
502         sv_setpvn(sv,ofs,ofslen);
503         break;
504     case '\\':
505         sv_setpvn(sv,ors,orslen);
506         break;
507     case '#':
508         sv_setpv(sv,ofmt);
509         break;
510     case '!':
511 #ifdef VMS
512         sv_setnv(sv, (double)((errno == EVMSERR) ? vaxc$errno : errno));
513         sv_setpv(sv, errno ? Strerror(errno) : "");
514 #else
515         {
516         int saveerrno = errno;
517         sv_setnv(sv, (double)errno);
518 #ifdef OS2
519         if (errno == errno_isOS2) sv_setpv(sv, os2error(Perl_rc));
520         else
521 #endif
522         sv_setpv(sv, errno ? Strerror(errno) : "");
523         errno = saveerrno;
524         }
525 #endif
526         SvNOK_on(sv);   /* what a wonderful hack! */
527         break;
528     case '<':
529         sv_setiv(sv, (IV)uid);
530         break;
531     case '>':
532         sv_setiv(sv, (IV)euid);
533         break;
534     case '(':
535         sv_setiv(sv, (IV)gid);
536         s = buf;
537         (void)sprintf(s,"%d",(int)gid);
538         goto add_groups;
539     case ')':
540         sv_setiv(sv, (IV)egid);
541         s = buf;
542         (void)sprintf(s,"%d",(int)egid);
543       add_groups:
544         while (*s) s++;
545 #ifdef HAS_GETGROUPS
546         {
547             Groups_t gary[NGROUPS];
548
549             i = getgroups(NGROUPS,gary);
550             while (--i >= 0) {
551                 (void)sprintf(s," %d", (int)gary[i]);
552                 while (*s) s++;
553             }
554         }
555 #endif
556         sv_setpv(sv,buf);
557         SvIOK_on(sv);   /* what a wonderful hack! */
558         break;
559     case '*':
560         break;
561     case '0':
562         break;
563     }
564     return 0;
565 }
566
567 int
568 magic_getuvar(sv, mg)
569 SV *sv;
570 MAGIC *mg;
571 {
572     struct ufuncs *uf = (struct ufuncs *)mg->mg_ptr;
573
574     if (uf && uf->uf_val)
575         (*uf->uf_val)(uf->uf_index, sv);
576     return 0;
577 }
578
579 int
580 magic_setenv(sv,mg)
581 SV* sv;
582 MAGIC* mg;
583 {
584     register char *s;
585     char *ptr;
586     STRLEN len;
587     I32 i;
588
589     s = SvPV(sv,len);
590     ptr = MgPV(mg);
591     my_setenv(ptr, s);
592
593 #ifdef DYNAMIC_ENV_FETCH
594      /* We just undefd an environment var.  Is a replacement */
595      /* waiting in the wings? */
596     if (!len) {
597         HE *envhe;
598         SV *keysv;
599         if (mg->mg_len == HEf_SVKEY)
600             keysv = (SV *)mg->mg_ptr;
601         else
602             keysv = newSVpv(mg->mg_ptr, mg->mg_len);
603         if ((envhe = hv_fetch_ent(GvHVn(envgv), keysv, FALSE, 0)))
604             s = SvPV(HeVAL(envhe), len);
605         if (mg->mg_len != HEf_SVKEY)
606             SvREFCNT_dec(keysv);
607     }
608 #endif
609
610 #if !defined(OS2) && !defined(AMIGAOS)
611                             /* And you'll never guess what the dog had */
612                             /*   in its mouth... */
613     if (tainting) {
614         MgTAINTEDDIR_off(mg);
615 #ifdef VMS
616         if (s && strnEQ(ptr, "DCL$PATH", 8)) {
617             char pathbuf[256], eltbuf[256], *cp, *elt = s;
618             struct stat sbuf;
619             int i = 0, j = 0;
620
621             do {          /* DCL$PATH may be a search list */
622                 while (1) {   /* as may dev portion of any element */
623                     if ( ((cp = strchr(elt,'[')) || (cp = strchr(elt,'<'))) ) {
624                         if ( *(cp+1) == '.' || *(cp+1) == '-' ||
625                              cando_by_name(S_IWUSR,0,elt) ) {
626                             MgTAINTEDDIR_on(mg);
627                             return 0;
628                         }
629                     }
630                     if ((cp = strchr(elt, ':')) != Nullch)
631                         *cp = '\0';
632                     if (my_trnlnm(elt, eltbuf, j++))
633                         elt = eltbuf;
634                     else
635                         break;
636                 }
637                 j = 0;
638             } while (my_trnlnm(s, pathbuf, i++) && (elt = pathbuf));
639         }
640 #endif /* VMS */
641         if (s && strEQ(ptr,"PATH")) {
642             char *strend = s + len;
643
644             while (s < strend) {
645                 struct stat st;
646                 s = cpytill(tokenbuf, s, strend, ':', &i);
647                 s++;
648                 if (*tokenbuf != '/'
649                       || (Stat(tokenbuf, &st) == 0 && (st.st_mode & 2)) ) {
650                     MgTAINTEDDIR_on(mg);
651                     return 0;
652                 }
653             }
654         }
655     }
656 #endif /* neither OS2 nor AMIGAOS */
657
658     return 0;
659 }
660
661 int
662 magic_clearenv(sv,mg)
663 SV* sv;
664 MAGIC* mg;
665 {
666     my_setenv(MgPV(mg),Nullch);
667     return 0;
668 }
669
670 int
671 magic_getsig(sv,mg)
672 SV* sv;
673 MAGIC* mg;
674 {
675     I32 i;
676     /* Are we fetching a signal entry? */
677     i = whichsig(MgPV(mg));
678     if (i) {
679         if(psig_ptr[i])
680             sv_setsv(sv,psig_ptr[i]);
681         else {
682             Sighandler_t sigstate = rsignal_state(i);
683
684             /* cache state so we don't fetch it again */
685             if(sigstate == SIG_IGN)
686                 sv_setpv(sv,"IGNORE");
687             else
688                 sv_setsv(sv,&sv_undef);
689             psig_ptr[i] = SvREFCNT_inc(sv);
690             SvTEMP_off(sv);
691         }
692     }
693     return 0;
694 }
695 int
696 magic_clearsig(sv,mg)
697 SV* sv;
698 MAGIC* mg;
699 {
700     I32 i;
701     /* Are we clearing a signal entry? */
702     i = whichsig(MgPV(mg));
703     if (i) {
704         if(psig_ptr[i]) {
705             SvREFCNT_dec(psig_ptr[i]);
706             psig_ptr[i]=0;
707         }
708         if(psig_name[i]) {
709             SvREFCNT_dec(psig_name[i]);
710             psig_name[i]=0;
711         }
712     }
713     return 0;
714 }
715
716 int
717 magic_setsig(sv,mg)
718 SV* sv;
719 MAGIC* mg;
720 {
721     register char *s;
722     I32 i;
723     SV** svp;
724
725     s = MgPV(mg);
726     if (*s == '_') {
727         if (strEQ(s,"__DIE__"))
728             svp = &diehook;
729         else if (strEQ(s,"__WARN__"))
730             svp = &warnhook;
731         else if (strEQ(s,"__PARSE__"))
732             svp = &parsehook;
733         else
734             croak("No such hook: %s", s);
735         i = 0;
736         if (*svp) {
737             SvREFCNT_dec(*svp);
738             *svp = 0;
739         }
740     }
741     else {
742         i = whichsig(s);        /* ...no, a brick */
743         if (!i) {
744             if (dowarn || strEQ(s,"ALARM"))
745                 warn("No such signal: SIG%s", s);
746             return 0;
747         }
748         SvREFCNT_dec(psig_name[i]);
749         SvREFCNT_dec(psig_ptr[i]);
750         psig_ptr[i] = SvREFCNT_inc(sv);
751         SvTEMP_off(sv); /* Make sure it doesn't go away on us */
752         psig_name[i] = newSVpv(s, strlen(s));
753         SvREADONLY_on(psig_name[i]);
754     }
755     if (SvTYPE(sv) == SVt_PVGV || SvROK(sv)) {
756         if (i)
757             (void)rsignal(i, sighandler);
758         else
759             *svp = SvREFCNT_inc(sv);
760         return 0;
761     }
762     s = SvPV_force(sv,na);
763     if (strEQ(s,"IGNORE")) {
764         if (i)
765             (void)rsignal(i, SIG_IGN);
766         else
767             *svp = 0;
768     }
769     else if (strEQ(s,"DEFAULT") || !*s) {
770         if (i)
771             (void)rsignal(i, SIG_DFL);
772         else
773             *svp = 0;
774     }
775     else {
776         if(hints & HINT_STRICT_REFS)
777                 die(no_symref,s,"a subroutine");
778         if (!strchr(s,':') && !strchr(s,'\'')) {
779             sprintf(tokenbuf, "main::%s",s);
780             sv_setpv(sv,tokenbuf);
781         }
782         if (i)
783             (void)rsignal(i, sighandler);
784         else
785             *svp = SvREFCNT_inc(sv);
786     }
787     return 0;
788 }
789
790 int
791 magic_setisa(sv,mg)
792 SV* sv;
793 MAGIC* mg;
794 {
795     sub_generation++;
796     return 0;
797 }
798
799 #ifdef OVERLOAD
800
801 int
802 magic_setamagic(sv,mg)
803 SV* sv;
804 MAGIC* mg;
805 {
806     /* HV_badAMAGIC_on(Sv_STASH(sv)); */
807     amagic_generation++;
808
809     return 0;
810 }
811 #endif /* OVERLOAD */
812
813 int
814 magic_setnkeys(sv,mg)
815 SV* sv;
816 MAGIC* mg;
817 {
818     if (LvTARG(sv)) {
819         hv_ksplit((HV*)LvTARG(sv), SvIV(sv));
820         LvTARG(sv) = Nullsv;    /* Don't allow a ref to reassign this. */
821     }
822     return 0;
823 }
824
825 static int
826 magic_methpack(sv,mg,meth)
827 SV* sv;
828 MAGIC* mg;
829 char *meth;
830 {
831     dSP;
832
833     ENTER;
834     SAVETMPS;
835     PUSHMARK(sp);
836     EXTEND(sp, 2);
837     PUSHs(mg->mg_obj);
838     if (mg->mg_ptr) {
839         if (mg->mg_len >= 0)
840             PUSHs(sv_2mortal(newSVpv(mg->mg_ptr, mg->mg_len)));
841         else if (mg->mg_len == HEf_SVKEY)
842             PUSHs((SV*)mg->mg_ptr);
843     }
844     else if (mg->mg_type == 'p')
845         PUSHs(sv_2mortal(newSViv(mg->mg_len)));
846     PUTBACK;
847
848     if (perl_call_method(meth, G_SCALAR))
849         sv_setsv(sv, *stack_sp--);
850
851     FREETMPS;
852     LEAVE;
853     return 0;
854 }
855
856 int
857 magic_getpack(sv,mg)
858 SV* sv;
859 MAGIC* mg;
860 {
861     magic_methpack(sv,mg,"FETCH");
862     if (mg->mg_ptr)
863         mg->mg_flags |= MGf_GSKIP;
864     return 0;
865 }
866
867 int
868 magic_setpack(sv,mg)
869 SV* sv;
870 MAGIC* mg;
871 {
872     dSP;
873
874     PUSHMARK(sp);
875     EXTEND(sp, 3);
876     PUSHs(mg->mg_obj);
877     if (mg->mg_ptr) {
878         if (mg->mg_len >= 0)
879             PUSHs(sv_2mortal(newSVpv(mg->mg_ptr, mg->mg_len)));
880         else if (mg->mg_len == HEf_SVKEY)
881             PUSHs((SV*)mg->mg_ptr);
882     }
883     else if (mg->mg_type == 'p')
884         PUSHs(sv_2mortal(newSViv(mg->mg_len)));
885     PUSHs(sv);
886     PUTBACK;
887
888     perl_call_method("STORE", G_SCALAR|G_DISCARD);
889
890     return 0;
891 }
892
893 int
894 magic_clearpack(sv,mg)
895 SV* sv;
896 MAGIC* mg;
897 {
898     return magic_methpack(sv,mg,"DELETE");
899 }
900
901 int magic_wipepack(sv,mg)
902 SV* sv;
903 MAGIC* mg;
904 {
905     dSP;
906
907     PUSHMARK(sp);
908     XPUSHs(mg->mg_obj);
909     PUTBACK;
910
911     perl_call_method("CLEAR", G_SCALAR|G_DISCARD);
912
913     return 0;
914 }
915
916 int
917 magic_nextpack(sv,mg,key)
918 SV* sv;
919 MAGIC* mg;
920 SV* key;
921 {
922     dSP;
923     char *meth = SvOK(key) ? "NEXTKEY" : "FIRSTKEY";
924
925     ENTER;
926     SAVETMPS;
927     PUSHMARK(sp);
928     EXTEND(sp, 2);
929     PUSHs(mg->mg_obj);
930     if (SvOK(key))
931         PUSHs(key);
932     PUTBACK;
933
934     if (perl_call_method(meth, G_SCALAR))
935         sv_setsv(key, *stack_sp--);
936
937     FREETMPS;
938     LEAVE;
939     return 0;
940 }
941
942 int
943 magic_existspack(sv,mg)
944 SV* sv;
945 MAGIC* mg;
946 {
947     return magic_methpack(sv,mg,"EXISTS");
948
949
950 int
951 magic_setdbline(sv,mg)
952 SV* sv;
953 MAGIC* mg;
954 {
955     OP *o;
956     I32 i;
957     GV* gv;
958     SV** svp;
959
960     gv = DBline;
961     i = SvTRUE(sv);
962     svp = av_fetch(GvAV(gv),
963                      atoi(MgPV(mg)), FALSE);
964     if (svp && SvIOKp(*svp) && (o = (OP*)SvSTASH(*svp)))
965         o->op_private = i;
966     else
967         warn("Can't break at that line\n");
968     return 0;
969 }
970
971 int
972 magic_getarylen(sv,mg)
973 SV* sv;
974 MAGIC* mg;
975 {
976     sv_setiv(sv, AvFILL((AV*)mg->mg_obj) + curcop->cop_arybase);
977     return 0;
978 }
979
980 int
981 magic_setarylen(sv,mg)
982 SV* sv;
983 MAGIC* mg;
984 {
985     av_fill((AV*)mg->mg_obj, SvIV(sv) - curcop->cop_arybase);
986     return 0;
987 }
988
989 int
990 magic_getpos(sv,mg)
991 SV* sv;
992 MAGIC* mg;
993 {
994     SV* lsv = LvTARG(sv);
995     
996     if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv)) {
997         mg = mg_find(lsv, 'g');
998         if (mg && mg->mg_len >= 0) {
999             sv_setiv(sv, mg->mg_len + curcop->cop_arybase);
1000             return 0;
1001         }
1002     }
1003     (void)SvOK_off(sv);
1004     return 0;
1005 }
1006
1007 int
1008 magic_setpos(sv,mg)
1009 SV* sv;
1010 MAGIC* mg;
1011 {
1012     SV* lsv = LvTARG(sv);
1013     SSize_t pos;
1014     STRLEN len;
1015
1016     mg = 0;
1017     
1018     if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv))
1019         mg = mg_find(lsv, 'g');
1020     if (!mg) {
1021         if (!SvOK(sv))
1022             return 0;
1023         sv_magic(lsv, (SV*)0, 'g', Nullch, 0);
1024         mg = mg_find(lsv, 'g');
1025     }
1026     else if (!SvOK(sv)) {
1027         mg->mg_len = -1;
1028         return 0;
1029     }
1030     len = SvPOK(lsv) ? SvCUR(lsv) : sv_len(lsv);
1031
1032     pos = SvIV(sv) - curcop->cop_arybase;
1033     if (pos < 0) {
1034         pos += len;
1035         if (pos < 0)
1036             pos = 0;
1037     }
1038     else if (pos > len)
1039         pos = len;
1040     mg->mg_len = pos;
1041     mg->mg_flags &= ~MGf_MINMATCH;
1042
1043     return 0;
1044 }
1045
1046 int
1047 magic_getglob(sv,mg)
1048 SV* sv;
1049 MAGIC* mg;
1050 {
1051     if (SvFAKE(sv)) {                   /* FAKE globs can get coerced */
1052         SvFAKE_off(sv);
1053         gv_efullname3(sv,((GV*)sv), "*");
1054         SvFAKE_on(sv);
1055     }
1056     else
1057         gv_efullname3(sv,((GV*)sv), "*");       /* a gv value, be nice */
1058     return 0;
1059 }
1060
1061 int
1062 magic_setglob(sv,mg)
1063 SV* sv;
1064 MAGIC* mg;
1065 {
1066     register char *s;
1067     GV* gv;
1068
1069     if (!SvOK(sv))
1070         return 0;
1071     s = SvPV(sv, na);
1072     if (*s == '*' && s[1])
1073         s++;
1074     gv = gv_fetchpv(s,TRUE, SVt_PVGV);
1075     if (sv == (SV*)gv)
1076         return 0;
1077     if (GvGP(sv))
1078         gp_free((GV*)sv);
1079     GvGP(sv) = gp_ref(GvGP(gv));
1080     return 0;
1081 }
1082
1083 int
1084 magic_setsubstr(sv,mg)
1085 SV* sv;
1086 MAGIC* mg;
1087 {
1088     STRLEN len;
1089     char *tmps = SvPV(sv,len);
1090     sv_insert(LvTARG(sv),LvTARGOFF(sv),LvTARGLEN(sv), tmps, len);
1091     return 0;
1092 }
1093
1094 int
1095 magic_gettaint(sv,mg)
1096 SV* sv;
1097 MAGIC* mg;
1098 {
1099     TAINT_IF((mg->mg_len & 1) ||
1100              (mg->mg_len & 2) && mg->mg_obj == sv);     /* kludge */
1101     return 0;
1102 }
1103
1104 int
1105 magic_settaint(sv,mg)
1106 SV* sv;
1107 MAGIC* mg;
1108 {
1109     if (localizing) {
1110         if (localizing == 1)
1111             mg->mg_len <<= 1;
1112         else
1113             mg->mg_len >>= 1;
1114     }
1115     else if (tainted)
1116         mg->mg_len |= 1;
1117     else
1118         mg->mg_len &= ~1;
1119     return 0;
1120 }
1121
1122 int
1123 magic_setvec(sv,mg)
1124 SV* sv;
1125 MAGIC* mg;
1126 {
1127     do_vecset(sv);      /* XXX slurp this routine */
1128     return 0;
1129 }
1130
1131 int
1132 magic_getitervar(sv,mg)
1133 SV* sv;
1134 MAGIC* mg;
1135 {
1136     SV *targ = Nullsv;
1137     if (LvTARGLEN(sv)) {
1138         AV* av = (AV*)LvTARG(sv);
1139         if (LvTARGOFF(sv) <= AvFILL(av))
1140             targ = AvARRAY(av)[LvTARGOFF(sv)];
1141     }
1142     else
1143         targ = LvTARG(sv);
1144     sv_setsv(sv, targ ? targ : &sv_undef);
1145     return 0;
1146 }
1147
1148 int
1149 magic_setitervar(sv,mg)
1150 SV* sv;
1151 MAGIC* mg;
1152 {
1153     if (LvTARGLEN(sv))
1154         vivify_itervar(sv);
1155     if (LvTARG(sv))
1156         sv_setsv(LvTARG(sv), sv);
1157     return 0;
1158 }
1159
1160 int
1161 magic_freeitervar(sv,mg)
1162 SV* sv;
1163 MAGIC* mg;
1164 {
1165     SvREFCNT_dec(LvTARG(sv));
1166     return 0;
1167 }
1168
1169 void
1170 vivify_itervar(sv)
1171 SV* sv;
1172 {
1173     AV* av;
1174
1175     if (!LvTARGLEN(sv))
1176         return;
1177     av = (AV*)LvTARG(sv);
1178     if (LvTARGOFF(sv) <= AvFILL(av)) {
1179         SV** svp = AvARRAY(av) + LvTARGOFF(sv);
1180         LvTARG(sv) = newSVsv(*svp);
1181         SvREFCNT_dec(*svp);
1182         *svp = SvREFCNT_inc(LvTARG(sv));
1183     }
1184     else
1185         LvTARG(sv) = Nullsv;
1186     SvREFCNT_dec(av);
1187     LvTARGLEN(sv) = 0;
1188 }
1189
1190 int
1191 magic_setmglob(sv,mg)
1192 SV* sv;
1193 MAGIC* mg;
1194 {
1195     mg->mg_len = -1;
1196     SvSCREAM_off(sv);
1197     return 0;
1198 }
1199
1200 int
1201 magic_setbm(sv,mg)
1202 SV* sv;
1203 MAGIC* mg;
1204 {
1205     sv_unmagic(sv, 'B');
1206     SvVALID_off(sv);
1207     return 0;
1208 }
1209
1210 int
1211 magic_setfm(sv,mg)
1212 SV* sv;
1213 MAGIC* mg;
1214 {
1215     sv_unmagic(sv, 'f');
1216     SvCOMPILED_off(sv);
1217     return 0;
1218 }
1219
1220 int
1221 magic_setuvar(sv,mg)
1222 SV* sv;
1223 MAGIC* mg;
1224 {
1225     struct ufuncs *uf = (struct ufuncs *)mg->mg_ptr;
1226
1227     if (uf && uf->uf_set)
1228         (*uf->uf_set)(uf->uf_index, sv);
1229     return 0;
1230 }
1231
1232 #ifdef USE_LOCALE_COLLATE
1233 int
1234 magic_setcollxfrm(sv,mg)
1235 SV* sv;
1236 MAGIC* mg;
1237 {
1238     /*
1239      * RenĂ© Descartes said "I think not."
1240      * and vanished with a faint plop.
1241      */
1242     if (mg->mg_ptr) {
1243         Safefree(mg->mg_ptr);
1244         mg->mg_ptr = NULL;
1245         mg->mg_len = -1;
1246     }
1247     return 0;
1248 }
1249 #endif /* USE_LOCALE_COLLATE */
1250
1251 int
1252 magic_set(sv,mg)
1253 SV* sv;
1254 MAGIC* mg;
1255 {
1256     register char *s;
1257     I32 i;
1258     STRLEN len;
1259     switch (*mg->mg_ptr) {
1260     case '\001':        /* ^A */
1261         sv_setsv(bodytarget, sv);
1262         break;
1263     case '\004':        /* ^D */
1264         debug = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) | 0x80000000;
1265         DEBUG_x(dump_all());
1266         break;
1267     case '\005':  /* ^E */
1268 #ifdef VMS
1269         set_vaxc_errno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1270 #else
1271         /* will anyone ever use this? */
1272         SETERRNO(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv), 4);
1273 #endif
1274         break;
1275     case '\006':        /* ^F */
1276         maxsysfd = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1277         break;
1278     case '\010':        /* ^H */
1279         hints = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1280         break;
1281     case '\t':  /* ^I */
1282         if (inplace)
1283             Safefree(inplace);
1284         if (SvOK(sv))
1285             inplace = savepv(SvPV(sv,na));
1286         else
1287             inplace = Nullch;
1288         break;
1289     case '\017':        /* ^O */
1290         if (osname)
1291             Safefree(osname);
1292         if (SvOK(sv))
1293             osname = savepv(SvPV(sv,na));
1294         else
1295             osname = Nullch;
1296         break;
1297     case '\020':        /* ^P */
1298         i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1299         if (i != perldb) {
1300             if (perldb)
1301                 oldlastpm = curpm;
1302             else
1303                 curpm = oldlastpm;
1304         }
1305         perldb = i;
1306         break;
1307     case '\024':        /* ^T */
1308 #ifdef BIG_TIME
1309         basetime = (Time_t)(SvNOK(sv) ? SvNVX(sv) : sv_2nv(sv));
1310 #else
1311         basetime = (Time_t)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1312 #endif
1313         break;
1314     case '\027':        /* ^W */
1315         dowarn = (bool)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1316         break;
1317     case '.':
1318         if (localizing) {
1319             if (localizing == 1)
1320                 save_sptr((SV**)&last_in_gv);
1321         }
1322         else if (SvOK(sv) && GvIO(last_in_gv))
1323             IoLINES(GvIOp(last_in_gv)) = (long)SvIV(sv);
1324         break;
1325     case '^':
1326         Safefree(IoTOP_NAME(GvIOp(defoutgv)));
1327         IoTOP_NAME(GvIOp(defoutgv)) = s = savepv(SvPV(sv,na));
1328         IoTOP_GV(GvIOp(defoutgv)) = gv_fetchpv(s,TRUE, SVt_PVIO);
1329         break;
1330     case '~':
1331         Safefree(IoFMT_NAME(GvIOp(defoutgv)));
1332         IoFMT_NAME(GvIOp(defoutgv)) = s = savepv(SvPV(sv,na));
1333         IoFMT_GV(GvIOp(defoutgv)) = gv_fetchpv(s,TRUE, SVt_PVIO);
1334         break;
1335     case '=':
1336         IoPAGE_LEN(GvIOp(defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1337         break;
1338     case '-':
1339         IoLINES_LEFT(GvIOp(defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1340         if (IoLINES_LEFT(GvIOp(defoutgv)) < 0L)
1341             IoLINES_LEFT(GvIOp(defoutgv)) = 0L;
1342         break;
1343     case '%':
1344         IoPAGE(GvIOp(defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1345         break;
1346     case '|':
1347         IoFLAGS(GvIOp(defoutgv)) &= ~IOf_FLUSH;
1348         if ((SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) != 0) {
1349             IoFLAGS(GvIOp(defoutgv)) |= IOf_FLUSH;
1350         }
1351         break;
1352     case '*':
1353         i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1354         multiline = (i != 0);
1355         break;
1356     case '/':
1357         SvREFCNT_dec(nrs);
1358         nrs = newSVsv(sv);
1359         SvREFCNT_dec(rs);
1360         rs = SvREFCNT_inc(nrs);
1361         break;
1362     case '\\':
1363         if (ors)
1364             Safefree(ors);
1365         if (SvOK(sv) || SvGMAGICAL(sv))
1366             ors = savepv(SvPV(sv,orslen));
1367         else {
1368             ors = Nullch;
1369             orslen = 0;
1370         }
1371         break;
1372     case ',':
1373         if (ofs)
1374             Safefree(ofs);
1375         ofs = savepv(SvPV(sv, ofslen));
1376         break;
1377     case '#':
1378         if (ofmt)
1379             Safefree(ofmt);
1380         ofmt = savepv(SvPV(sv,na));
1381         break;
1382     case '[':
1383         compiling.cop_arybase = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1384         break;
1385     case '?':
1386 #ifdef COMPLEX_STATUS
1387         if (localizing == 2) {
1388             statusvalue = LvTARGOFF(sv);
1389             statusvalue_vms = LvTARGLEN(sv);
1390         }
1391         else
1392 #endif
1393 #ifdef VMSISH_STATUS
1394         if (VMSISH_STATUS)
1395             STATUS_NATIVE_SET((U32)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)));
1396         else
1397 #endif
1398             STATUS_POSIX_SET(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1399         break;
1400     case '!':
1401         SETERRNO(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv),
1402                  (SvIV(sv) == EVMSERR) ? 4 : vaxc$errno);
1403         break;
1404     case '<':
1405         uid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1406         if (delaymagic) {
1407             delaymagic |= DM_RUID;
1408             break;                              /* don't do magic till later */
1409         }
1410 #ifdef HAS_SETRUID
1411         (void)setruid((Uid_t)uid);
1412 #else
1413 #ifdef HAS_SETREUID
1414         (void)setreuid((Uid_t)uid, (Uid_t)-1);
1415 #else
1416 #ifdef HAS_SETRESUID
1417       (void)setresuid((Uid_t)uid, (Uid_t)-1, (Uid_t)-1);
1418 #else
1419         if (uid == euid)                /* special case $< = $> */
1420             (void)setuid(uid);
1421         else {
1422             uid = (I32)getuid();
1423             croak("setruid() not implemented");
1424         }
1425 #endif
1426 #endif
1427 #endif
1428         uid = (I32)getuid();
1429         tainting |= (uid && (euid != uid || egid != gid));
1430         break;
1431     case '>':
1432         euid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1433         if (delaymagic) {
1434             delaymagic |= DM_EUID;
1435             break;                              /* don't do magic till later */
1436         }
1437 #ifdef HAS_SETEUID
1438         (void)seteuid((Uid_t)euid);
1439 #else
1440 #ifdef HAS_SETREUID
1441         (void)setreuid((Uid_t)-1, (Uid_t)euid);
1442 #else
1443 #ifdef HAS_SETRESUID
1444         (void)setresuid((Uid_t)-1, (Uid_t)euid, (Uid_t)-1);
1445 #else
1446         if (euid == uid)                /* special case $> = $< */
1447             setuid(euid);
1448         else {
1449             euid = (I32)geteuid();
1450             croak("seteuid() not implemented");
1451         }
1452 #endif
1453 #endif
1454 #endif
1455         euid = (I32)geteuid();
1456         tainting |= (uid && (euid != uid || egid != gid));
1457         break;
1458     case '(':
1459         gid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1460         if (delaymagic) {
1461             delaymagic |= DM_RGID;
1462             break;                              /* don't do magic till later */
1463         }
1464 #ifdef HAS_SETRGID
1465         (void)setrgid((Gid_t)gid);
1466 #else
1467 #ifdef HAS_SETREGID
1468         (void)setregid((Gid_t)gid, (Gid_t)-1);
1469 #else
1470 #ifdef HAS_SETRESGID
1471       (void)setresgid((Gid_t)gid, (Gid_t)-1, (Gid_t) 1);
1472 #else
1473         if (gid == egid)                        /* special case $( = $) */
1474             (void)setgid(gid);
1475         else {
1476             gid = (I32)getgid();
1477             croak("setrgid() not implemented");
1478         }
1479 #endif
1480 #endif
1481 #endif
1482         gid = (I32)getgid();
1483         tainting |= (uid && (euid != uid || egid != gid));
1484         break;
1485     case ')':
1486         egid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1487         if (delaymagic) {
1488             delaymagic |= DM_EGID;
1489             break;                              /* don't do magic till later */
1490         }
1491 #ifdef HAS_SETEGID
1492         (void)setegid((Gid_t)egid);
1493 #else
1494 #ifdef HAS_SETREGID
1495         (void)setregid((Gid_t)-1, (Gid_t)egid);
1496 #else
1497 #ifdef HAS_SETRESGID
1498         (void)setresgid((Gid_t)-1, (Gid_t)egid, (Gid_t)-1);
1499 #else
1500         if (egid == gid)                        /* special case $) = $( */
1501             (void)setgid(egid);
1502         else {
1503             egid = (I32)getegid();
1504             croak("setegid() not implemented");
1505         }
1506 #endif
1507 #endif
1508 #endif
1509         egid = (I32)getegid();
1510         tainting |= (uid && (euid != uid || egid != gid));
1511         break;
1512     case ':':
1513         chopset = SvPV_force(sv,na);
1514         break;
1515     case '0':
1516         if (!origalen) {
1517             s = origargv[0];
1518             s += strlen(s);
1519             /* See if all the arguments are contiguous in memory */
1520             for (i = 1; i < origargc; i++) {
1521                 if (origargv[i] == s + 1)
1522                     s += strlen(++s);   /* this one is ok too */
1523             }
1524             /* can grab env area too? */
1525             if (origenviron && origenviron[0] == s + 1) {
1526                 my_setenv("NoNeSuCh", Nullch);
1527                                             /* force copy of environment */
1528                 for (i = 0; origenviron[i]; i++)
1529                     if (origenviron[i] == s + 1)
1530                         s += strlen(++s);
1531             }
1532             origalen = s - origargv[0];
1533         }
1534         s = SvPV_force(sv,len);
1535         i = len;
1536         if (i >= origalen) {
1537             i = origalen;
1538             SvCUR_set(sv, i);
1539             *SvEND(sv) = '\0';
1540             Copy(s, origargv[0], i, char);
1541         }
1542         else {
1543             Copy(s, origargv[0], i, char);
1544             s = origargv[0]+i;
1545             *s++ = '\0';
1546             while (++i < origalen)
1547                 *s++ = ' ';
1548             s = origargv[0]+i;
1549             for (i = 1; i < origargc; i++)
1550                 origargv[i] = Nullch;
1551         }
1552         break;
1553     }
1554     return 0;
1555 }
1556
1557 I32
1558 whichsig(sig)
1559 char *sig;
1560 {
1561     register char **sigv;
1562
1563     for (sigv = sig_name+1; *sigv; sigv++)
1564         if (strEQ(sig,*sigv))
1565             return sig_num[sigv - sig_name];
1566 #ifdef SIGCLD
1567     if (strEQ(sig,"CHLD"))
1568         return SIGCLD;
1569 #endif
1570 #ifdef SIGCHLD
1571     if (strEQ(sig,"CLD"))
1572         return SIGCHLD;
1573 #endif
1574     return 0;
1575 }
1576
1577 Signal_t
1578 sighandler(sig)
1579 int sig;
1580 {
1581     dSP;
1582     GV *gv;
1583     HV *st;
1584     SV *sv;
1585     CV *cv;
1586     AV *oldstack;
1587
1588     if (!psig_ptr[sig])
1589         die("Signal SIG%s received, but no signal handler set.\n",
1590             sig_name[sig]);
1591
1592     cv = sv_2cv(psig_ptr[sig],&st,&gv,TRUE);
1593     if (!cv || !CvROOT(cv)) {
1594         if (dowarn)
1595             warn("SIG%s handler \"%s\" not defined.\n",
1596                 sig_name[sig], GvENAME(gv) );
1597         return;
1598     }
1599
1600     oldstack = curstack;
1601     if (curstack != signalstack)
1602         AvFILL(signalstack) = 0;
1603     SWITCHSTACK(curstack, signalstack);
1604
1605     if(psig_name[sig])
1606         sv = SvREFCNT_inc(psig_name[sig]);
1607     else {
1608         sv = sv_newmortal();
1609         sv_setpv(sv,sig_name[sig]);
1610     }
1611     PUSHMARK(sp);
1612     PUSHs(sv);
1613     PUTBACK;
1614
1615     perl_call_sv((SV*)cv, G_DISCARD);
1616
1617     SWITCHSTACK(signalstack, oldstack);
1618
1619     return;
1620 }