/* mg.c
*
- * Copyright (c) 1991-1997, Larry Wall
+ * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ * 2000, 2001, 2002, 2003, 2004, by Larry Wall and others
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
* come here, and I don't want to see no more magic,' he said, and fell silent."
*/
+/*
+=head1 Magical Functions
+*/
+
#include "EXTERN.h"
+#define PERL_IN_MG_C
#include "perl.h"
-/* XXX If this causes problems, set i_unistd=undef in the hint file. */
-#ifdef I_UNISTD
-# include <unistd.h>
-#endif
-
#if defined(HAS_GETGROUPS) || defined(HAS_SETGROUPS)
# ifndef NGROUPS
# define NGROUPS 32
# endif
+# ifdef I_GRP
+# include <grp.h>
+# endif
#endif
-#ifdef PERL_OBJECT
-# define VTBL this->*vtbl
-#else
-# define VTBL *vtbl
-static void restore_magic _((void *p));
+#ifdef __hpux
+# include <sys/pstat.h>
+#endif
+
+Signal_t Perl_csighandler(int sig);
+
+/* if you only have signal() and it resets on each signal, FAKE_PERSISTENT_SIGNAL_HANDLERS fixes */
+#if !defined(HAS_SIGACTION) && defined(VMS)
+# define FAKE_PERSISTENT_SIGNAL_HANDLERS
+#endif
+/* if we're doing kill() with sys$sigprc on VMS, FAKE_DEFAULT_SIGNAL_HANDLERS */
+#if defined(KILL_BY_SIGPRC)
+# define FAKE_DEFAULT_SIGNAL_HANDLERS
+#endif
+
+static void restore_magic(pTHX_ void *p);
+static void unwind_handler_stack(pTHX_ void *p);
+
+#ifdef __Lynx__
+/* Missing protos on LynxOS */
+void setruid(uid_t id);
+void seteuid(uid_t id);
+void setrgid(uid_t id);
+void setegid(uid_t id);
#endif
/*
/* MGS is typedef'ed to struct magic_state in perl.h */
STATIC void
-save_magic(I32 mgs_ix, SV *sv)
+S_save_magic(pTHX_ I32 mgs_ix, SV *sv)
{
MGS* mgs;
assert(SvMAGICAL(sv));
+#ifdef PERL_COPY_ON_WRITE
+ /* Turning READONLY off for a copy-on-write scalar is a bad idea. */
+ if (SvIsCOW(sv))
+ sv_force_normal(sv);
+#endif
- SAVEDESTRUCTOR(restore_magic, (void*)mgs_ix);
+ SAVEDESTRUCTOR_X(restore_magic, INT2PTR(void*, (IV)mgs_ix));
mgs = SSPTR(mgs_ix, MGS*);
mgs->mgs_sv = sv;
SvMAGICAL_off(sv);
SvREADONLY_off(sv);
- SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT;
+ SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_NOK|SVp_POK)) >> PRIVSHIFT;
}
-STATIC void
-restore_magic(void *p)
-{
- MGS* mgs = SSPTR((I32)p, MGS*);
- SV* sv = mgs->mgs_sv;
-
- if (!sv)
- return;
-
- if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv))
- {
- if (mgs->mgs_flags)
- SvFLAGS(sv) |= mgs->mgs_flags;
- else
- mg_magical(sv);
- if (SvGMAGICAL(sv))
- SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK|SVf_POK);
- }
-
- mgs->mgs_sv = NULL; /* mark the MGS structure as restored */
+/*
+=for apidoc mg_magical
- /* If we're still on top of the stack, pop us off. (That condition
- * will be satisfied if restore_magic was called explicitly, but *not*
- * if it's being called via leave_scope.)
- * The reason for doing this is that otherwise, things like sv_2cv()
- * may leave alloc gunk on the savestack, and some code
- * (e.g. sighandler) doesn't expect that...
- */
- if (PL_savestack_ix == mgs->mgs_ss_ix)
- {
- assert(SSPOPINT == SAVEt_DESTRUCTOR);
- PL_savestack_ix -= 2;
- assert(SSPOPINT == SAVEt_ALLOC);
- PL_savestack_ix -= SSPOPINT;
- }
+Turns on the magical status of an SV. See C<sv_magic>.
-}
+=cut
+*/
void
-mg_magical(SV *sv)
+Perl_mg_magical(pTHX_ SV *sv)
{
MAGIC* mg;
for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
MGVTBL* vtbl = mg->mg_virtual;
if (vtbl) {
- if ((vtbl->svt_get != NULL) && !(mg->mg_flags & MGf_GSKIP))
+ if (vtbl->svt_get && !(mg->mg_flags & MGf_GSKIP))
SvGMAGICAL_on(sv);
if (vtbl->svt_set)
SvSMAGICAL_on(sv);
- if (!(SvFLAGS(sv) & (SVs_GMG|SVs_SMG)) || (vtbl->svt_clear != NULL))
+ if (!(SvFLAGS(sv) & (SVs_GMG|SVs_SMG)) || vtbl->svt_clear)
SvRMAGICAL_on(sv);
}
}
}
+/*
+=for apidoc mg_get
+
+Do magic after a value is retrieved from the SV. See C<sv_magic>.
+
+=cut
+*/
+
int
-mg_get(SV *sv)
+Perl_mg_get(pTHX_ SV *sv)
{
- I32 mgs_ix;
- MAGIC* mg;
- MAGIC** mgp;
- int mgp_valid = 0;
+ int new = 0;
+ MAGIC *newmg, *head, *cur, *mg;
+ I32 mgs_ix = SSNEW(sizeof(MGS));
+ int was_temp = SvTEMP(sv);
+ /* guard against sv having being freed midway by holding a private
+ reference. */
+
+ /* sv_2mortal has this side effect of turning on the TEMP flag, which can
+ cause the SV's buffer to get stolen (and maybe other stuff).
+ So restore it.
+ */
+ sv_2mortal(SvREFCNT_inc(sv));
+ if (!was_temp) {
+ SvTEMP_off(sv);
+ }
- mgs_ix = SSNEW(sizeof(MGS));
save_magic(mgs_ix, sv);
- mgp = &SvMAGIC(sv);
- while ((mg = *mgp) != 0) {
- MGVTBL* vtbl = mg->mg_virtual;
- if (!(mg->mg_flags & MGf_GSKIP) && vtbl && (vtbl->svt_get != NULL)) {
- (VTBL->svt_get)(sv, mg);
- /* Ignore this magic if it's been deleted */
- if ((mg == (mgp_valid ? *mgp : SvMAGIC(sv))) &&
- (mg->mg_flags & MGf_GSKIP))
- (SSPTR(mgs_ix, MGS*))->mgs_flags = 0;
- }
- /* Advance to next magic (complicated by possible deletion) */
- if (mg == (mgp_valid ? *mgp : SvMAGIC(sv))) {
- mgp = &mg->mg_moremagic;
- mgp_valid = 1;
+ /* We must call svt_get(sv, mg) for each valid entry in the linked
+ list of magic. svt_get() may delete the current entry, add new
+ magic to the head of the list, or upgrade the SV. AMS 20010810 */
+
+ newmg = cur = head = mg = SvMAGIC(sv);
+ while (mg) {
+ MGVTBL *vtbl = mg->mg_virtual;
+
+ if (!(mg->mg_flags & MGf_GSKIP) && vtbl && vtbl->svt_get) {
+ CALL_FPTR(vtbl->svt_get)(aTHX_ sv, mg);
+
+ /* guard against magic having been deleted - eg FETCH calling
+ * untie */
+ if (!SvMAGIC(sv))
+ break;
+
+ /* Don't restore the flags for this entry if it was deleted. */
+ if (mg->mg_flags & MGf_GSKIP)
+ (SSPTR(mgs_ix, MGS *))->mgs_flags = 0;
+ }
+
+ mg = mg->mg_moremagic;
+
+ if (new) {
+ /* Have we finished with the new entries we saw? Start again
+ where we left off (unless there are more new entries). */
+ if (mg == head) {
+ new = 0;
+ mg = cur;
+ head = newmg;
+ }
+ }
+
+ /* Were any new entries added? */
+ if (!new && (newmg = SvMAGIC(sv)) != head) {
+ new = 1;
+ cur = mg;
+ mg = newmg;
}
- else
- mgp = &SvMAGIC(sv); /* Re-establish pointer after sv_upgrade */
}
- restore_magic((void*)mgs_ix);
+ restore_magic(aTHX_ INT2PTR(void *, (IV)mgs_ix));
+
+ if (SvREFCNT(sv) == 1) {
+ /* We hold the last reference to this SV, which implies that the
+ SV was deleted as a side effect of the routines we called. */
+ SvOK_off(sv);
+ }
return 0;
}
+/*
+=for apidoc mg_set
+
+Do magic after a value is assigned to the SV. See C<sv_magic>.
+
+=cut
+*/
+
int
-mg_set(SV *sv)
+Perl_mg_set(pTHX_ SV *sv)
{
I32 mgs_ix;
MAGIC* mg;
mg->mg_flags &= ~MGf_GSKIP; /* setting requires another read */
(SSPTR(mgs_ix, MGS*))->mgs_flags = 0;
}
- if (vtbl && (vtbl->svt_set != NULL))
- (VTBL->svt_set)(sv, mg);
+ if (vtbl && vtbl->svt_set)
+ CALL_FPTR(vtbl->svt_set)(aTHX_ sv, mg);
}
- restore_magic((void*)mgs_ix);
+ restore_magic(aTHX_ INT2PTR(void*, (IV)mgs_ix));
return 0;
}
+/*
+=for apidoc mg_length
+
+Report on the SV's length. See C<sv_magic>.
+
+=cut
+*/
+
U32
-mg_length(SV *sv)
+Perl_mg_length(pTHX_ SV *sv)
{
MAGIC* mg;
- char *junk;
STRLEN len;
for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
MGVTBL* vtbl = mg->mg_virtual;
- if (vtbl && (vtbl->svt_len != NULL)) {
+ if (vtbl && vtbl->svt_len) {
I32 mgs_ix;
mgs_ix = SSNEW(sizeof(MGS));
save_magic(mgs_ix, sv);
/* omit MGf_GSKIP -- not changed here */
- len = (VTBL->svt_len)(sv, mg);
- restore_magic((void*)mgs_ix);
+ len = CALL_FPTR(vtbl->svt_len)(aTHX_ sv, mg);
+ restore_magic(aTHX_ INT2PTR(void*, (IV)mgs_ix));
return len;
}
}
- junk = SvPV(sv, len);
+ if (DO_UTF8(sv))
+ {
+ U8 *s = (U8*)SvPV(sv, len);
+ len = Perl_utf8_length(aTHX_ s, s + len);
+ }
+ else
+ (void)SvPV(sv, len);
return len;
}
I32
-mg_size(SV *sv)
+Perl_mg_size(pTHX_ SV *sv)
{
MAGIC* mg;
I32 len;
-
+
for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
MGVTBL* vtbl = mg->mg_virtual;
- if (vtbl && (vtbl->svt_len != NULL)) {
+ if (vtbl && vtbl->svt_len) {
I32 mgs_ix;
mgs_ix = SSNEW(sizeof(MGS));
save_magic(mgs_ix, sv);
/* omit MGf_GSKIP -- not changed here */
- len = (VTBL->svt_len)(sv, mg);
- restore_magic((void*)mgs_ix);
+ len = CALL_FPTR(vtbl->svt_len)(aTHX_ sv, mg);
+ restore_magic(aTHX_ INT2PTR(void*, (IV)mgs_ix));
return len;
}
}
case SVt_PVHV:
/* FIXME */
default:
- croak("Size magic not implemented");
+ Perl_croak(aTHX_ "Size magic not implemented");
break;
}
return 0;
}
+/*
+=for apidoc mg_clear
+
+Clear something magical that the SV represents. See C<sv_magic>.
+
+=cut
+*/
+
int
-mg_clear(SV *sv)
+Perl_mg_clear(pTHX_ SV *sv)
{
I32 mgs_ix;
MAGIC* mg;
for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
MGVTBL* vtbl = mg->mg_virtual;
/* omit GSKIP -- never set here */
-
- if (vtbl && (vtbl->svt_clear != NULL))
- (VTBL->svt_clear)(sv, mg);
+
+ if (vtbl && vtbl->svt_clear)
+ CALL_FPTR(vtbl->svt_clear)(aTHX_ sv, mg);
}
- restore_magic((void*)mgs_ix);
+ restore_magic(aTHX_ INT2PTR(void*, (IV)mgs_ix));
return 0;
}
+/*
+=for apidoc mg_find
+
+Finds the magic pointer for type matching the SV. See C<sv_magic>.
+
+=cut
+*/
+
MAGIC*
-mg_find(SV *sv, int type)
+Perl_mg_find(pTHX_ SV *sv, int type)
{
MAGIC* mg;
+ if (!sv)
+ return 0;
for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
if (mg->mg_type == type)
return mg;
return 0;
}
+/*
+=for apidoc mg_copy
+
+Copies the magic from one SV to another. See C<sv_magic>.
+
+=cut
+*/
+
int
-mg_copy(SV *sv, SV *nsv, char *key, I32 klen)
+Perl_mg_copy(pTHX_ SV *sv, SV *nsv, const char *key, I32 klen)
{
int count = 0;
MAGIC* mg;
for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
- if (isUPPER(mg->mg_type)) {
- sv_magic(nsv, mg->mg_obj, toLOWER(mg->mg_type), key, klen);
+ MGVTBL* vtbl = mg->mg_virtual;
+ if ((mg->mg_flags & MGf_COPY) && vtbl->svt_copy){
+ count += CALL_FPTR(vtbl->svt_copy)(aTHX_ sv, mg, nsv, key, klen);
+ }
+ else if (isUPPER(mg->mg_type)) {
+ sv_magic(nsv,
+ mg->mg_type == PERL_MAGIC_tied ? SvTIED_obj(sv, mg) :
+ (mg->mg_type == PERL_MAGIC_regdata && mg->mg_obj)
+ ? sv : mg->mg_obj,
+ toLOWER(mg->mg_type), key, klen);
count++;
}
}
return count;
}
+/*
+=for apidoc mg_free
+
+Free any magic storage used by the SV. See C<sv_magic>.
+
+=cut
+*/
+
int
-mg_free(SV *sv)
+Perl_mg_free(pTHX_ SV *sv)
{
MAGIC* mg;
MAGIC* moremagic;
for (mg = SvMAGIC(sv); mg; mg = moremagic) {
MGVTBL* vtbl = mg->mg_virtual;
moremagic = mg->mg_moremagic;
- if (vtbl && (vtbl->svt_free != NULL))
- (VTBL->svt_free)(sv, mg);
- if (mg->mg_ptr && mg->mg_type != 'g')
- if (mg->mg_len >= 0)
+ if (vtbl && vtbl->svt_free)
+ CALL_FPTR(vtbl->svt_free)(aTHX_ sv, mg);
+ if (mg->mg_ptr && mg->mg_type != PERL_MAGIC_regex_global) {
+ if (mg->mg_len > 0 || mg->mg_type == PERL_MAGIC_utf8)
Safefree(mg->mg_ptr);
else if (mg->mg_len == HEf_SVKEY)
SvREFCNT_dec((SV*)mg->mg_ptr);
+ }
if (mg->mg_flags & MGf_REFCOUNTED)
SvREFCNT_dec(mg->mg_obj);
Safefree(mg);
return 0;
}
-#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
#include <signal.h>
-#endif
-int
-magic_regdata_cnt(SV *sv, MAGIC *mg)
+U32
+Perl_magic_regdata_cnt(pTHX_ SV *sv, MAGIC *mg)
{
- dTHR;
- register char *s;
- register I32 i;
register REGEXP *rx;
- char *t;
- if (PL_curpm && (rx = PL_curpm->op_pmregexp))
- return rx->lastparen;
- return -1;
+ if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
+ if (mg->mg_obj) /* @+ */
+ return rx->nparens;
+ else /* @- */
+ return rx->lastparen;
+ }
+
+ return (U32)-1;
}
int
-magic_regdatum_get(SV *sv, MAGIC *mg)
+Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg)
{
- dTHR;
register I32 paren;
- register char *s;
+ register I32 s;
register I32 i;
register REGEXP *rx;
- char *t;
+ I32 t;
- if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
+ if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
paren = mg->mg_len;
if (paren < 0)
return 0;
- if (paren <= rx->nparens &&
- (s = rx->startp[paren]) &&
- (t = rx->endp[paren]))
+ if (paren <= (I32)rx->nparens &&
+ (s = rx->startp[paren]) != -1 &&
+ (t = rx->endp[paren]) != -1)
{
if (mg->mg_obj) /* @+ */
- i = t - rx->subbase;
+ i = t;
else /* @- */
- i = s - rx->subbase;
- sv_setiv(sv,i);
+ i = s;
+
+ if (i > 0 && RX_MATCH_UTF8(rx)) {
+ char *b = rx->subbeg;
+ if (b)
+ i = Perl_utf8_length(aTHX_ (U8*)b, (U8*)(b+i));
+ }
+
+ sv_setiv(sv, i);
}
}
return 0;
}
+int
+Perl_magic_regdatum_set(pTHX_ SV *sv, MAGIC *mg)
+{
+ Perl_croak(aTHX_ PL_no_modify);
+ /* NOT REACHED */
+ return 0;
+}
+
U32
-magic_len(SV *sv, MAGIC *mg)
+Perl_magic_len(pTHX_ SV *sv, MAGIC *mg)
{
- dTHR;
register I32 paren;
- register char *s;
register I32 i;
register REGEXP *rx;
- char *t;
+ I32 s1, t1;
switch (*mg->mg_ptr) {
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': case '&':
- if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
- paren = atoi(mg->mg_ptr);
+ if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
+
+ paren = atoi(mg->mg_ptr); /* $& is in [0] */
getparen:
- if (paren <= rx->nparens &&
- (s = rx->startp[paren]) &&
- (t = rx->endp[paren]))
+ if (paren <= (I32)rx->nparens &&
+ (s1 = rx->startp[paren]) != -1 &&
+ (t1 = rx->endp[paren]) != -1)
{
- i = t - s;
- if (i >= 0)
- return i;
+ i = t1 - s1;
+ getlen:
+ if (i > 0 && RX_MATCH_UTF8(rx)) {
+ char *s = rx->subbeg + s1;
+ char *send = rx->subbeg + t1;
+
+ i = t1 - s1;
+ if (is_utf8_string((U8*)s, i))
+ i = Perl_utf8_length(aTHX_ (U8*)s, (U8*)send);
+ }
+ if (i < 0)
+ Perl_croak(aTHX_ "panic: magic_len: %"IVdf, (IV)i);
+ return i;
}
+ else {
+ if (ckWARN(WARN_UNINITIALIZED))
+ report_uninit(sv);
+ }
+ }
+ else {
+ if (ckWARN(WARN_UNINITIALIZED))
+ report_uninit(sv);
}
return 0;
case '+':
- if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
+ if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
paren = rx->lastparen;
if (paren)
goto getparen;
}
return 0;
+ case '\016': /* ^N */
+ if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
+ paren = rx->lastcloseparen;
+ if (paren)
+ goto getparen;
+ }
+ return 0;
case '`':
- if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
- if ((s = rx->subbeg) && rx->startp[0]) {
- i = rx->startp[0] - s;
- if (i >= 0)
- return i;
+ if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
+ if (rx->startp[0] != -1) {
+ i = rx->startp[0];
+ if (i > 0) {
+ s1 = 0;
+ t1 = i;
+ goto getlen;
+ }
}
}
return 0;
case '\'':
- if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
- if (rx->subend && (s = rx->endp[0])) {
- i = rx->subend - s;
- if (i >= 0)
- return i;
+ if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
+ if (rx->endp[0] != -1) {
+ i = rx->sublen - rx->endp[0];
+ if (i > 0) {
+ s1 = rx->endp[0];
+ t1 = rx->sublen;
+ goto getlen;
+ }
}
}
return 0;
- case ',':
- return (STRLEN)PL_ofslen;
- case '\\':
- return (STRLEN)PL_orslen;
}
magic_get(sv,mg);
- if (!SvPOK(sv) && SvNIOK(sv))
- sv_2pv(sv, &PL_na);
+ if (!SvPOK(sv) && SvNIOK(sv)) {
+ STRLEN n_a;
+ sv_2pv(sv, &n_a);
+ }
if (SvPOK(sv))
return SvCUR(sv);
return 0;
}
-#if 0
-static char *
-printW(sv)
-SV * sv ;
-{
-#if 1
- return "" ;
-
-#else
- int i ;
- static char buffer[50] ;
- char buf1[20] ;
- char * p ;
-
-
- sprintf(buffer, "Buffer %d, Length = %d - ", sv, SvCUR(sv)) ;
- p = SvPVX(sv) ;
- for (i = 0; i < SvCUR(sv) ; ++ i) {
- sprintf (buf1, " %x [%x]", (p+i), *(p+i)) ;
- strcat(buffer, buf1) ;
- }
-
- return buffer ;
-
-#endif
-}
-#endif
-
int
-magic_get(SV *sv, MAGIC *mg)
+Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
{
- dTHR;
register I32 paren;
- register char *s;
+ register char *s = NULL;
register I32 i;
register REGEXP *rx;
- char *t;
switch (*mg->mg_ptr) {
case '\001': /* ^A */
sv_setsv(sv, PL_bodytarget);
break;
- case '\002': /* ^B */
- /* printf("magic_get $^B: ") ; */
- if (curcop->cop_warnings == WARN_NONE)
- /* printf("WARN_NONE\n"), */
- sv_setpvn(sv, WARN_NONEstring, WARNsize) ;
- else if (curcop->cop_warnings == WARN_ALL)
- /* printf("WARN_ALL\n"), */
- sv_setpvn(sv, WARN_ALLstring, WARNsize) ;
- else
- /* printf("some %s\n", printW(curcop->cop_warnings)), */
- sv_setsv(sv, curcop->cop_warnings);
+ case '\003': /* ^C */
+ sv_setiv(sv, (IV)PL_minus_c);
break;
+
case '\004': /* ^D */
- sv_setiv(sv, (IV)(PL_debug & 32767));
+ sv_setiv(sv, (IV)(PL_debug & DEBUG_MASK));
break;
case '\005': /* ^E */
+ if (*(mg->mg_ptr+1) == '\0') {
+#ifdef MACOS_TRADITIONAL
+ {
+ char msg[256];
+
+ sv_setnv(sv,(double)gMacPerl_OSErr);
+ sv_setpv(sv, gMacPerl_OSErr ? GetSysErrText(gMacPerl_OSErr, msg) : "");
+ }
+#else
#ifdef VMS
- {
-# include <descrip.h>
-# include <starlet.h>
- char msg[255];
- $DESCRIPTOR(msgdsc,msg);
- sv_setnv(sv,(double) vaxc$errno);
- if (sys$getmsg(vaxc$errno,&msgdsc.dsc$w_length,&msgdsc,0,0) & 1)
- sv_setpvn(sv,msgdsc.dsc$a_pointer,msgdsc.dsc$w_length);
- else
- sv_setpv(sv,"");
- }
+ {
+# include <descrip.h>
+# include <starlet.h>
+ char msg[255];
+ $DESCRIPTOR(msgdsc,msg);
+ sv_setnv(sv,(NV) vaxc$errno);
+ if (sys$getmsg(vaxc$errno,&msgdsc.dsc$w_length,&msgdsc,0,0) & 1)
+ sv_setpvn(sv,msgdsc.dsc$a_pointer,msgdsc.dsc$w_length);
+ else
+ sv_setpv(sv,"");
+ }
#else
#ifdef OS2
- if (!(_emx_env & 0x200)) { /* Under DOS */
- sv_setnv(sv, (double)errno);
- sv_setpv(sv, errno ? Strerror(errno) : "");
- } else {
- if (errno != errno_isOS2)
- Perl_rc = _syserrno();
- sv_setnv(sv, (double)Perl_rc);
- sv_setpv(sv, os2error(Perl_rc));
- }
+ if (!(_emx_env & 0x200)) { /* Under DOS */
+ sv_setnv(sv, (NV)errno);
+ sv_setpv(sv, errno ? Strerror(errno) : "");
+ } else {
+ if (errno != errno_isOS2) {
+ int tmp = _syserrno();
+ if (tmp) /* 2nd call to _syserrno() makes it 0 */
+ Perl_rc = tmp;
+ }
+ sv_setnv(sv, (NV)Perl_rc);
+ sv_setpv(sv, os2error(Perl_rc));
+ }
#else
#ifdef WIN32
- {
- DWORD dwErr = GetLastError();
- sv_setnv(sv, (double)dwErr);
- if (dwErr)
- {
-#ifdef PERL_OBJECT
- char *sMsg;
- DWORD dwLen;
- PerlProc_GetSysMsg(sMsg, dwLen, dwErr);
- sv_setpvn(sv, sMsg, dwLen);
- PerlProc_FreeBuf(sMsg);
+ {
+ DWORD dwErr = GetLastError();
+ sv_setnv(sv, (NV)dwErr);
+ if (dwErr)
+ {
+ PerlProc_GetOSError(sv, dwErr);
+ }
+ else
+ sv_setpv(sv, "");
+ SetLastError(dwErr);
+ }
#else
- win32_str_os_error(sv, dwErr);
+ {
+ int saveerrno = errno;
+ sv_setnv(sv, (NV)errno);
+ sv_setpv(sv, errno ? Strerror(errno) : "");
+ errno = saveerrno;
+ }
#endif
- }
- else
- sv_setpv(sv, "");
- SetLastError(dwErr);
- }
-#else
- sv_setnv(sv, (double)errno);
- sv_setpv(sv, errno ? Strerror(errno) : "");
#endif
#endif
#endif
- SvNOK_on(sv); /* what a wonderful hack! */
- break;
+ SvNOK_on(sv); /* what a wonderful hack! */
+ }
+ else if (strEQ(mg->mg_ptr+1, "NCODING"))
+ sv_setsv(sv, PL_encoding);
+ break;
case '\006': /* ^F */
sv_setiv(sv, (IV)PL_maxsysfd);
break;
else
sv_setsv(sv, &PL_sv_undef);
break;
- case '\017': /* ^O */
- sv_setpv(sv, PL_osname);
+ case '\017': /* ^O & ^OPEN */
+ if (*(mg->mg_ptr+1) == '\0') {
+ sv_setpv(sv, PL_osname);
+ SvTAINTED_off(sv);
+ }
+ else if (strEQ(mg->mg_ptr, "\017PEN")) {
+ if (!PL_compiling.cop_io)
+ sv_setsv(sv, &PL_sv_undef);
+ else {
+ sv_setsv(sv, PL_compiling.cop_io);
+ }
+ }
break;
case '\020': /* ^P */
sv_setiv(sv, (IV)PL_perldb);
break;
case '\023': /* ^S */
- {
- dTHR;
+ if (*(mg->mg_ptr+1) == '\0') {
if (PL_lex_state != LEX_NOTPARSING)
- SvOK_off(sv);
+ (void)SvOK_off(sv);
else if (PL_in_eval)
- sv_setiv(sv, 1);
+ sv_setiv(sv, PL_in_eval & ~(EVAL_INREQUIRE));
else
sv_setiv(sv, 0);
}
break;
case '\024': /* ^T */
+ if (*(mg->mg_ptr+1) == '\0') {
#ifdef BIG_TIME
- sv_setnv(sv, PL_basetime);
+ sv_setnv(sv, PL_basetime);
#else
- sv_setiv(sv, (IV)PL_basetime);
+ sv_setiv(sv, (IV)PL_basetime);
#endif
- break;
- case '\027': /* ^W */
- sv_setiv(sv, (IV)((PL_dowarn & G_WARN_ON) == G_WARN_ON));
+ }
+ else if (strEQ(mg->mg_ptr, "\024AINT"))
+ sv_setiv(sv, PL_tainting
+ ? (PL_taint_warn || PL_unsafe ? -1 : 1)
+ : 0);
+ break;
+ case '\025': /* $^UNICODE */
+ if (strEQ(mg->mg_ptr, "\025NICODE"))
+ sv_setuv(sv, (UV) PL_unicode);
+ break;
+ case '\027': /* ^W & $^WARNING_BITS */
+ if (*(mg->mg_ptr+1) == '\0')
+ sv_setiv(sv, (IV)((PL_dowarn & G_WARN_ON) ? TRUE : FALSE));
+ else if (strEQ(mg->mg_ptr+1, "ARNING_BITS")) {
+ if (PL_compiling.cop_warnings == pWARN_NONE ||
+ PL_compiling.cop_warnings == pWARN_STD)
+ {
+ sv_setpvn(sv, WARN_NONEstring, WARNsize) ;
+ }
+ else if (PL_compiling.cop_warnings == pWARN_ALL) {
+ /* Get the bit mask for $warnings::Bits{all}, because
+ * it could have been extended by warnings::register */
+ SV **bits_all;
+ HV *bits=get_hv("warnings::Bits", FALSE);
+ if (bits && (bits_all=hv_fetch(bits, "all", 3, FALSE))) {
+ sv_setsv(sv, *bits_all);
+ }
+ else {
+ sv_setpvn(sv, WARN_ALLstring, WARNsize) ;
+ }
+ }
+ else {
+ sv_setsv(sv, PL_compiling.cop_warnings);
+ }
+ SvPOK_only(sv);
+ }
break;
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': case '&':
- if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
+ if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
+ I32 s1, t1;
+
/*
* Pre-threads, this was paren = atoi(GvENAME((GV*)mg->mg_obj));
* XXX Does the new way break anything?
*/
- paren = atoi(mg->mg_ptr);
+ paren = atoi(mg->mg_ptr); /* $& is in [0] */
getparen:
- if (paren <= rx->nparens &&
- (s = rx->startp[paren]) &&
- (t = rx->endp[paren]))
+ if (paren <= (I32)rx->nparens &&
+ (s1 = rx->startp[paren]) != -1 &&
+ (t1 = rx->endp[paren]) != -1)
{
- i = t - s;
+ i = t1 - s1;
+ s = rx->subbeg + s1;
+ if (!rx->subbeg)
+ break;
+
getrx:
if (i >= 0) {
- bool was_tainted;
+ sv_setpvn(sv, s, i);
+ if (RX_MATCH_UTF8(rx) && is_utf8_string((U8*)s, i))
+ SvUTF8_on(sv);
+ else
+ SvUTF8_off(sv);
if (PL_tainting) {
- was_tainted = PL_tainted;
- PL_tainted = FALSE;
+ if (RX_MATCH_TAINTED(rx)) {
+ MAGIC* mg = SvMAGIC(sv);
+ MAGIC* mgt;
+ PL_tainted = 1;
+ SvMAGIC(sv) = mg->mg_moremagic;
+ SvTAINT(sv);
+ if ((mgt = SvMAGIC(sv))) {
+ mg->mg_moremagic = mgt;
+ SvMAGIC(sv) = mg;
+ }
+ } else
+ SvTAINTED_off(sv);
}
- sv_setpvn(sv,s,i);
- if (PL_tainting)
- PL_tainted = (was_tainted || RX_MATCH_TAINTED(rx));
break;
}
}
sv_setsv(sv,&PL_sv_undef);
break;
case '+':
- if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
+ if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
paren = rx->lastparen;
if (paren)
goto getparen;
}
sv_setsv(sv,&PL_sv_undef);
break;
+ case '\016': /* ^N */
+ if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
+ paren = rx->lastcloseparen;
+ if (paren)
+ goto getparen;
+ }
+ sv_setsv(sv,&PL_sv_undef);
+ break;
case '`':
- if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
- if ((s = rx->subbeg) && rx->startp[0]) {
- i = rx->startp[0] - s;
+ if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
+ if ((s = rx->subbeg) && rx->startp[0] != -1) {
+ i = rx->startp[0];
goto getrx;
}
}
sv_setsv(sv,&PL_sv_undef);
break;
case '\'':
- if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
- if (rx->subend && (s = rx->endp[0])) {
- i = rx->subend - s;
+ if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
+ if (rx->subbeg && rx->endp[0] != -1) {
+ s = rx->subbeg + rx->endp[0];
+ i = rx->sublen - rx->endp[0];
goto getrx;
}
}
case '.':
#ifndef lint
if (GvIO(PL_last_in_gv)) {
- sv_setiv(sv, (IV)IoLINES(GvIO(PL_last_in_gv)));
+ sv_setiv(sv, (IV)IoLINES(GvIOp(PL_last_in_gv)));
}
#endif
break;
}
break;
case '^':
- s = IoTOP_NAME(GvIOp(PL_defoutgv));
+ if (GvIOp(PL_defoutgv))
+ s = IoTOP_NAME(GvIOp(PL_defoutgv));
if (s)
sv_setpv(sv,s);
else {
}
break;
case '~':
- s = IoFMT_NAME(GvIOp(PL_defoutgv));
+ if (GvIOp(PL_defoutgv))
+ s = IoFMT_NAME(GvIOp(PL_defoutgv));
if (!s)
s = GvENAME(PL_defoutgv);
sv_setpv(sv,s);
break;
#ifndef lint
case '=':
- sv_setiv(sv, (IV)IoPAGE_LEN(GvIOp(PL_defoutgv)));
+ if (GvIOp(PL_defoutgv))
+ sv_setiv(sv, (IV)IoPAGE_LEN(GvIOp(PL_defoutgv)));
break;
case '-':
- sv_setiv(sv, (IV)IoLINES_LEFT(GvIOp(PL_defoutgv)));
+ if (GvIOp(PL_defoutgv))
+ sv_setiv(sv, (IV)IoLINES_LEFT(GvIOp(PL_defoutgv)));
break;
case '%':
- sv_setiv(sv, (IV)IoPAGE(GvIOp(PL_defoutgv)));
+ if (GvIOp(PL_defoutgv))
+ sv_setiv(sv, (IV)IoPAGE(GvIOp(PL_defoutgv)));
break;
#endif
case ':':
WITH_THR(sv_setiv(sv, (IV)PL_curcop->cop_arybase));
break;
case '|':
- sv_setiv(sv, (IV)(IoFLAGS(GvIOp(PL_defoutgv)) & IOf_FLUSH) != 0 );
+ if (GvIOp(PL_defoutgv))
+ sv_setiv(sv, (IV)(IoFLAGS(GvIOp(PL_defoutgv)) & IOf_FLUSH) != 0 );
break;
case ',':
- sv_setpvn(sv,PL_ofs,PL_ofslen);
break;
case '\\':
- sv_setpvn(sv,PL_ors,PL_orslen);
+ if (PL_ors_sv)
+ sv_copypv(sv, PL_ors_sv);
break;
case '#':
sv_setpv(sv,PL_ofmt);
break;
case '!':
#ifdef VMS
- sv_setnv(sv, (double)((errno == EVMSERR) ? vaxc$errno : errno));
+ sv_setnv(sv, (NV)((errno == EVMSERR) ? vaxc$errno : errno));
sv_setpv(sv, errno ? Strerror(errno) : "");
#else
{
int saveerrno = errno;
- sv_setnv(sv, (double)errno);
+ sv_setnv(sv, (NV)errno);
#ifdef OS2
- if (errno == errno_isOS2) sv_setpv(sv, os2error(Perl_rc));
+ if (errno == errno_isOS2 || errno == errno_isOS2_set)
+ sv_setpv(sv, os2error(Perl_rc));
else
#endif
sv_setpv(sv, errno ? Strerror(errno) : "");
break;
case '(':
sv_setiv(sv, (IV)PL_gid);
- sv_setpvf(sv, "%Vd", (IV)PL_gid);
+#ifdef HAS_GETGROUPS
+ Perl_sv_setpvf(aTHX_ sv, "%"Gid_t_f, PL_gid);
+#endif
goto add_groups;
case ')':
sv_setiv(sv, (IV)PL_egid);
- sv_setpvf(sv, "%Vd", (IV)PL_egid);
+#ifdef HAS_GETGROUPS
+ Perl_sv_setpvf(aTHX_ sv, "%"Gid_t_f, PL_egid);
+#endif
add_groups:
#ifdef HAS_GETGROUPS
{
Groups_t gary[NGROUPS];
i = getgroups(NGROUPS,gary);
while (--i >= 0)
- sv_catpvf(sv, " %Vd", (IV)gary[i]);
+ Perl_sv_catpvf(aTHX_ sv, " %"Gid_t_f, gary[i]);
}
#endif
- SvIOK_on(sv); /* what a wonderful hack! */
- break;
- case '*':
+ (void)SvIOK_on(sv); /* what a wonderful hack! */
break;
+#ifndef MACOS_TRADITIONAL
case '0':
break;
-#ifdef USE_THREADS
- case '@':
- sv_setsv(sv, thr->errsv);
- break;
-#endif /* USE_THREADS */
+#endif
}
return 0;
}
int
-magic_getuvar(SV *sv, MAGIC *mg)
+Perl_magic_getuvar(pTHX_ SV *sv, MAGIC *mg)
{
struct ufuncs *uf = (struct ufuncs *)mg->mg_ptr;
if (uf && uf->uf_val)
- (*uf->uf_val)(uf->uf_index, sv);
+ (*uf->uf_val)(aTHX_ uf->uf_index, sv);
return 0;
}
int
-magic_setenv(SV *sv, MAGIC *mg)
+Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg)
{
register char *s;
char *ptr;
STRLEN len, klen;
- I32 i;
s = SvPV(sv,len);
ptr = MgPV(mg,klen);
#ifdef VMS
if (s && klen == 8 && strEQ(ptr, "DCL$PATH")) {
char pathbuf[256], eltbuf[256], *cp, *elt = s;
- struct stat sbuf;
+ Stat_t sbuf;
int i = 0, j = 0;
do { /* DCL$PATH may be a search list */
while (s < strend) {
char tmpbuf[256];
- struct stat st;
+ Stat_t st;
+ I32 i;
s = delimcpy(tmpbuf, tmpbuf + sizeof tmpbuf,
s, strend, ':', &i);
s++;
}
int
-magic_clearenv(SV *sv, MAGIC *mg)
+Perl_magic_clearenv(pTHX_ SV *sv, MAGIC *mg)
{
- my_setenv(MgPV(mg,PL_na),Nullch);
+ STRLEN n_a;
+ my_setenv(MgPV(mg,n_a),Nullch);
return 0;
}
int
-magic_set_all_env(SV *sv, MAGIC *mg)
+Perl_magic_set_all_env(pTHX_ SV *sv, MAGIC *mg)
{
#if defined(VMS)
- die("Can't make list assignment to %%ENV on this system");
+ Perl_die(aTHX_ "Can't make list assignment to %%ENV on this system");
#else
- dTHR;
if (PL_localizing) {
HE* entry;
+ STRLEN n_a;
magic_clear_all_env(sv,mg);
hv_iterinit((HV*)sv);
- while (entry = hv_iternext((HV*)sv)) {
+ while ((entry = hv_iternext((HV*)sv))) {
I32 keylen;
my_setenv(hv_iterkey(entry, &keylen),
- SvPV(hv_iterval((HV*)sv, entry), PL_na));
+ SvPV(hv_iterval((HV*)sv, entry), n_a));
}
}
#endif
}
int
-magic_clear_all_env(SV *sv, MAGIC *mg)
+Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg)
{
-#if defined(VMS)
- die("Can't make list assignment to %%ENV on this system");
-#else
-#ifdef WIN32
- char *envv = GetEnvironmentStrings();
- char *cur = envv;
- STRLEN len;
- while (*cur) {
- char *end = strchr(cur,'=');
- if (end && end != cur) {
- *end = '\0';
- my_setenv(cur,Nullch);
- *end = '=';
- cur += strlen(end+1)+1;
- }
- else if ((len = strlen(cur)))
- cur += len+1;
- }
- FreeEnvironmentStrings(envv);
+#ifndef PERL_MICRO
+#if defined(VMS) || defined(EPOC)
+ Perl_die(aTHX_ "Can't make list assignment to %%ENV on this system");
#else
+# if defined(PERL_IMPLICIT_SYS) || defined(WIN32)
+ PerlEnv_clearenv();
+# else
+# ifdef USE_ENVIRON_ARRAY
+# if defined(USE_ITHREADS)
+ /* only the parent thread can clobber the process environment */
+ if (PL_curinterp == aTHX)
+# endif
+ {
+# ifndef PERL_USE_SAFE_PUTENV
I32 i;
if (environ == PL_origenviron)
- New(901, environ, 1, char*);
+ environ = (char**)safesysmalloc(sizeof(char*));
else
for (i = 0; environ[i]; i++)
- Safefree(environ[i]);
+ safesysfree(environ[i]);
+# endif /* PERL_USE_SAFE_PUTENV */
+
environ[0] = Nullch;
+ }
+# endif /* USE_ENVIRON_ARRAY */
+# endif /* PERL_IMPLICIT_SYS || WIN32 */
+#endif /* VMS || EPOC */
+#endif /* !PERL_MICRO */
+ return 0;
+}
+#if defined(FAKE_PERSISTENT_SIGNAL_HANDLERS)||defined(FAKE_DEFAULT_SIGNAL_HANDLERS)
+static int sig_handlers_initted = 0;
#endif
+#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
+static int sig_ignoring[SIG_SIZE]; /* which signals we are ignoring */
+#endif
+#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
+static int sig_defaulting[SIG_SIZE];
#endif
- return 0;
-}
+#ifndef PERL_MICRO
+#ifdef HAS_SIGPROCMASK
+static void
+restore_sigmask(pTHX_ SV *save_sv)
+{
+ sigset_t *ossetp = (sigset_t *) SvPV_nolen( save_sv );
+ (void)sigprocmask(SIG_SETMASK, ossetp, (sigset_t *)0);
+}
+#endif
int
-magic_getsig(SV *sv, MAGIC *mg)
+Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg)
{
I32 i;
+ STRLEN n_a;
/* Are we fetching a signal entry? */
- i = whichsig(MgPV(mg,PL_na));
- if (i) {
- if(psig_ptr[i])
- sv_setsv(sv,psig_ptr[i]);
+ i = whichsig(MgPV(mg,n_a));
+ if (i > 0) {
+ if(PL_psig_ptr[i])
+ sv_setsv(sv,PL_psig_ptr[i]);
else {
- Sighandler_t sigstate = rsignal_state(i);
-
+ Sighandler_t sigstate;
+ sigstate = rsignal_state(i);
+#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
+ if (sig_handlers_initted && sig_ignoring[i]) sigstate = SIG_IGN;
+#endif
+#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
+ if (sig_handlers_initted && sig_defaulting[i]) sigstate = SIG_DFL;
+#endif
/* cache state so we don't fetch it again */
if(sigstate == SIG_IGN)
sv_setpv(sv,"IGNORE");
else
sv_setsv(sv,&PL_sv_undef);
- psig_ptr[i] = SvREFCNT_inc(sv);
+ PL_psig_ptr[i] = SvREFCNT_inc(sv);
SvTEMP_off(sv);
}
}
return 0;
}
int
-magic_clearsig(SV *sv, MAGIC *mg)
+Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg)
{
- I32 i;
- /* Are we clearing a signal entry? */
- i = whichsig(MgPV(mg,PL_na));
- if (i) {
- if(psig_ptr[i]) {
- SvREFCNT_dec(psig_ptr[i]);
- psig_ptr[i]=0;
- }
- if(psig_name[i]) {
- SvREFCNT_dec(psig_name[i]);
- psig_name[i]=0;
- }
+ /* XXX Some of this code was copied from Perl_magic_setsig. A little
+ * refactoring might be in order.
+ */
+ register char *s;
+ STRLEN n_a;
+ SV* to_dec;
+ s = MgPV(mg,n_a);
+ if (*s == '_') {
+ SV** svp;
+ if (strEQ(s,"__DIE__"))
+ svp = &PL_diehook;
+ else if (strEQ(s,"__WARN__"))
+ svp = &PL_warnhook;
+ else
+ Perl_croak(aTHX_ "No such hook: %s", s);
+ if (*svp) {
+ to_dec = *svp;
+ *svp = 0;
+ SvREFCNT_dec(to_dec);
+ }
+ }
+ else {
+ I32 i;
+ /* Are we clearing a signal entry? */
+ i = whichsig(s);
+ if (i > 0) {
+#ifdef HAS_SIGPROCMASK
+ sigset_t set, save;
+ SV* save_sv;
+ /* Avoid having the signal arrive at a bad time, if possible. */
+ sigemptyset(&set);
+ sigaddset(&set,i);
+ sigprocmask(SIG_BLOCK, &set, &save);
+ ENTER;
+ save_sv = newSVpv((char *)(&save), sizeof(sigset_t));
+ SAVEFREESV(save_sv);
+ SAVEDESTRUCTOR_X(restore_sigmask, save_sv);
+#endif
+ PERL_ASYNC_CHECK();
+#if defined(FAKE_PERSISTENT_SIGNAL_HANDLERS) || defined(FAKE_DEFAULT_SIGNAL_HANDLERS)
+ if (!sig_handlers_initted) Perl_csighandler_init();
+#endif
+#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
+ sig_defaulting[i] = 1;
+ (void)rsignal(i, PL_csighandlerp);
+#else
+ (void)rsignal(i, SIG_DFL);
+#endif
+ if(PL_psig_name[i]) {
+ SvREFCNT_dec(PL_psig_name[i]);
+ PL_psig_name[i]=0;
+ }
+ if(PL_psig_ptr[i]) {
+ to_dec=PL_psig_ptr[i];
+ PL_psig_ptr[i]=0;
+ LEAVE;
+ SvREFCNT_dec(to_dec);
+ }
+ else
+ LEAVE;
+ }
}
return 0;
}
+void
+Perl_raise_signal(pTHX_ int sig)
+{
+ /* Set a flag to say this signal is pending */
+ PL_psig_pend[sig]++;
+ /* And one to say _a_ signal is pending */
+ PL_sig_pending = 1;
+}
+
+Signal_t
+Perl_csighandler(int sig)
+{
+#ifdef PERL_GET_SIG_CONTEXT
+ dTHXa(PERL_GET_SIG_CONTEXT);
+#else
+ dTHX;
+#endif
+#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
+ (void) rsignal(sig, PL_csighandlerp);
+ if (sig_ignoring[sig]) return;
+#endif
+#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
+ if (sig_defaulting[sig])
+#ifdef KILL_BY_SIGPRC
+ exit((Perl_sig_to_vmscondition(sig)&STS$M_COND_ID)|STS$K_SEVERE|STS$M_INHIB_MSG);
+#else
+ exit(1);
+#endif
+#endif
+ if (PL_signals & PERL_SIGNALS_UNSAFE_FLAG)
+ /* Call the perl level handler now--
+ * with risk we may be in malloc() etc. */
+ (*PL_sighandlerp)(sig);
+ else
+ Perl_raise_signal(aTHX_ sig);
+}
+
+#if defined(FAKE_PERSISTENT_SIGNAL_HANDLERS) || defined(FAKE_DEFAULT_SIGNAL_HANDLERS)
+void
+Perl_csighandler_init(void)
+{
+ int sig;
+ if (sig_handlers_initted) return;
+
+ for (sig = 1; sig < SIG_SIZE; sig++) {
+#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
+ dTHX;
+ sig_defaulting[sig] = 1;
+ (void) rsignal(sig, PL_csighandlerp);
+#endif
+#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
+ sig_ignoring[sig] = 0;
+#endif
+ }
+ sig_handlers_initted = 1;
+}
+#endif
+
+void
+Perl_despatch_signals(pTHX)
+{
+ int sig;
+ PL_sig_pending = 0;
+ for (sig = 1; sig < SIG_SIZE; sig++) {
+ if (PL_psig_pend[sig]) {
+ PERL_BLOCKSIG_ADD(set, sig);
+ PL_psig_pend[sig] = 0;
+ PERL_BLOCKSIG_BLOCK(set);
+ (*PL_sighandlerp)(sig);
+ PERL_BLOCKSIG_UNBLOCK(set);
+ }
+ }
+}
+
int
-magic_setsig(SV *sv, MAGIC *mg)
+Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
{
- dTHR;
register char *s;
I32 i;
- SV** svp;
+ SV** svp = 0;
+ /* Need to be careful with SvREFCNT_dec(), because that can have side
+ * effects (due to closures). We must make sure that the new disposition
+ * is in place before it is called.
+ */
+ SV* to_dec = 0;
+ STRLEN len;
+#ifdef HAS_SIGPROCMASK
+ sigset_t set, save;
+ SV* save_sv;
+#endif
- s = MgPV(mg,PL_na);
+ s = MgPV(mg,len);
if (*s == '_') {
if (strEQ(s,"__DIE__"))
svp = &PL_diehook;
else if (strEQ(s,"__WARN__"))
svp = &PL_warnhook;
- else if (strEQ(s,"__PARSE__"))
- svp = &PL_parsehook;
else
- croak("No such hook: %s", s);
+ Perl_croak(aTHX_ "No such hook: %s", s);
i = 0;
if (*svp) {
- SvREFCNT_dec(*svp);
+ to_dec = *svp;
*svp = 0;
}
}
else {
i = whichsig(s); /* ...no, a brick */
- if (!i) {
- if (ckWARN(WARN_SIGNAL) || strEQ(s,"ALARM"))
- warner(WARN_SIGNAL, "No such signal: SIG%s", s);
+ if (i < 0) {
+ if (ckWARN(WARN_SIGNAL))
+ Perl_warner(aTHX_ packWARN(WARN_SIGNAL), "No such signal: SIG%s", s);
return 0;
}
- SvREFCNT_dec(psig_name[i]);
- SvREFCNT_dec(psig_ptr[i]);
- psig_ptr[i] = SvREFCNT_inc(sv);
+#ifdef HAS_SIGPROCMASK
+ /* Avoid having the signal arrive at a bad time, if possible. */
+ sigemptyset(&set);
+ sigaddset(&set,i);
+ sigprocmask(SIG_BLOCK, &set, &save);
+ ENTER;
+ save_sv = newSVpv((char *)(&save), sizeof(sigset_t));
+ SAVEFREESV(save_sv);
+ SAVEDESTRUCTOR_X(restore_sigmask, save_sv);
+#endif
+ PERL_ASYNC_CHECK();
+#if defined(FAKE_PERSISTENT_SIGNAL_HANDLERS) || defined(FAKE_DEFAULT_SIGNAL_HANDLERS)
+ if (!sig_handlers_initted) Perl_csighandler_init();
+#endif
+#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
+ sig_ignoring[i] = 0;
+#endif
+#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
+ sig_defaulting[i] = 0;
+#endif
+ SvREFCNT_dec(PL_psig_name[i]);
+ to_dec = PL_psig_ptr[i];
+ PL_psig_ptr[i] = SvREFCNT_inc(sv);
SvTEMP_off(sv); /* Make sure it doesn't go away on us */
- psig_name[i] = newSVpv(s, strlen(s));
- SvREADONLY_on(psig_name[i]);
+ PL_psig_name[i] = newSVpvn(s, len);
+ SvREADONLY_on(PL_psig_name[i]);
}
if (SvTYPE(sv) == SVt_PVGV || SvROK(sv)) {
- if (i)
- (void)rsignal(i, PL_sighandlerp);
+ if (i) {
+ (void)rsignal(i, PL_csighandlerp);
+#ifdef HAS_SIGPROCMASK
+ LEAVE;
+#endif
+ }
else
*svp = SvREFCNT_inc(sv);
+ if(to_dec)
+ SvREFCNT_dec(to_dec);
return 0;
}
- s = SvPV_force(sv,PL_na);
+ s = SvPV_force(sv,len);
if (strEQ(s,"IGNORE")) {
- if (i)
+ if (i) {
+#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
+ sig_ignoring[i] = 1;
+ (void)rsignal(i, PL_csighandlerp);
+#else
(void)rsignal(i, SIG_IGN);
- else
- *svp = 0;
+#endif
+ }
}
else if (strEQ(s,"DEFAULT") || !*s) {
if (i)
+#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
+ {
+ sig_defaulting[i] = 1;
+ (void)rsignal(i, PL_csighandlerp);
+ }
+#else
(void)rsignal(i, SIG_DFL);
- else
- *svp = 0;
+#endif
}
else {
/*
* tell whether HINT_STRICT_REFS is in force or not.
*/
if (!strchr(s,':') && !strchr(s,'\''))
- sv_setpv(sv, form("main::%s", s));
+ sv_insert(sv, 0, 0, "main::", 6);
if (i)
- (void)rsignal(i, PL_sighandlerp);
+ (void)rsignal(i, PL_csighandlerp);
else
*svp = SvREFCNT_inc(sv);
}
+#ifdef HAS_SIGPROCMASK
+ if(i)
+ LEAVE;
+#endif
+ if(to_dec)
+ SvREFCNT_dec(to_dec);
return 0;
}
+#endif /* !PERL_MICRO */
int
-magic_setisa(SV *sv, MAGIC *mg)
+Perl_magic_setisa(pTHX_ SV *sv, MAGIC *mg)
{
PL_sub_generation++;
return 0;
}
-#ifdef OVERLOAD
-
int
-magic_setamagic(SV *sv, MAGIC *mg)
+Perl_magic_setamagic(pTHX_ SV *sv, MAGIC *mg)
{
/* HV_badAMAGIC_on(Sv_STASH(sv)); */
PL_amagic_generation++;
return 0;
}
-#endif /* OVERLOAD */
int
-magic_getnkeys(SV *sv, MAGIC *mg)
+Perl_magic_getnkeys(pTHX_ SV *sv, MAGIC *mg)
{
HV *hv = (HV*)LvTARG(sv);
- HE *entry;
I32 i = 0;
if (hv) {
- (void) hv_iterinit(hv);
- if (!SvRMAGICAL(hv) || !mg_find((SV*)hv,'P'))
- i = HvKEYS(hv);
- else {
- /*SUPPRESS 560*/
- while (entry = hv_iternext(hv)) {
- i++;
- }
- }
+ (void) hv_iterinit(hv);
+ if (! SvTIED_mg((SV*)hv, PERL_MAGIC_tied))
+ i = HvKEYS(hv);
+ else {
+ while (hv_iternext(hv))
+ i++;
+ }
}
sv_setiv(sv, (IV)i);
}
int
-magic_setnkeys(SV *sv, MAGIC *mg)
+Perl_magic_setnkeys(pTHX_ SV *sv, MAGIC *mg)
{
if (LvTARG(sv)) {
hv_ksplit((HV*)LvTARG(sv), SvIV(sv));
}
return 0;
-}
+}
/* caller is responsible for stack switching/cleanup */
STATIC int
-magic_methcall(MAGIC *mg, char *meth, I32 flags, int n, SV *val)
+S_magic_methcall(pTHX_ SV *sv, MAGIC *mg, char *meth, I32 flags, int n, SV *val)
{
dSP;
PUSHMARK(SP);
EXTEND(SP, n);
- PUSHs(mg->mg_obj);
- if (n > 1) {
+ PUSHs(SvTIED_obj(sv, mg));
+ if (n > 1) {
if (mg->mg_ptr) {
if (mg->mg_len >= 0)
- PUSHs(sv_2mortal(newSVpv(mg->mg_ptr, mg->mg_len)));
+ PUSHs(sv_2mortal(newSVpvn(mg->mg_ptr, mg->mg_len)));
else if (mg->mg_len == HEf_SVKEY)
PUSHs((SV*)mg->mg_ptr);
}
- else if (mg->mg_type == 'p') {
+ else if (mg->mg_type == PERL_MAGIC_tiedelem) {
PUSHs(sv_2mortal(newSViv(mg->mg_len)));
}
}
}
PUTBACK;
- return perl_call_method(meth, flags);
+ return call_method(meth, flags);
}
STATIC int
-magic_methpack(SV *sv, MAGIC *mg, char *meth)
+S_magic_methpack(pTHX_ SV *sv, MAGIC *mg, char *meth)
{
dSP;
SAVETMPS;
PUSHSTACKi(PERLSI_MAGIC);
- if (magic_methcall(mg, meth, G_SCALAR, 2, NULL)) {
+ if (magic_methcall(sv, mg, meth, G_SCALAR, 2, NULL)) {
sv_setsv(sv, *PL_stack_sp--);
}
}
int
-magic_getpack(SV *sv, MAGIC *mg)
+Perl_magic_getpack(pTHX_ SV *sv, MAGIC *mg)
{
- magic_methpack(sv,mg,"FETCH");
if (mg->mg_ptr)
mg->mg_flags |= MGf_GSKIP;
+ magic_methpack(sv,mg,"FETCH");
return 0;
}
int
-magic_setpack(SV *sv, MAGIC *mg)
+Perl_magic_setpack(pTHX_ SV *sv, MAGIC *mg)
{
dSP;
ENTER;
PUSHSTACKi(PERLSI_MAGIC);
- magic_methcall(mg, "STORE", G_SCALAR|G_DISCARD, 3, sv);
+ magic_methcall(sv, mg, "STORE", G_SCALAR|G_DISCARD, 3, sv);
POPSTACK;
LEAVE;
return 0;
}
int
-magic_clearpack(SV *sv, MAGIC *mg)
+Perl_magic_clearpack(pTHX_ SV *sv, MAGIC *mg)
{
return magic_methpack(sv,mg,"DELETE");
}
U32
-magic_sizepack(SV *sv, MAGIC *mg)
-{
+Perl_magic_sizepack(pTHX_ SV *sv, MAGIC *mg)
+{
dSP;
U32 retval = 0;
ENTER;
SAVETMPS;
PUSHSTACKi(PERLSI_MAGIC);
- if (magic_methcall(mg, "FETCHSIZE", G_SCALAR, 2, NULL)) {
+ if (magic_methcall(sv, mg, "FETCHSIZE", G_SCALAR, 2, NULL)) {
sv = *PL_stack_sp--;
retval = (U32) SvIV(sv)-1;
}
return retval;
}
-int magic_wipepack(SV *sv, MAGIC *mg)
+int
+Perl_magic_wipepack(pTHX_ SV *sv, MAGIC *mg)
{
dSP;
ENTER;
PUSHSTACKi(PERLSI_MAGIC);
PUSHMARK(SP);
- XPUSHs(mg->mg_obj);
+ XPUSHs(SvTIED_obj(sv, mg));
PUTBACK;
- perl_call_method("CLEAR", G_SCALAR|G_DISCARD);
+ call_method("CLEAR", G_SCALAR|G_DISCARD);
POPSTACK;
LEAVE;
+
return 0;
}
int
-magic_nextpack(SV *sv, MAGIC *mg, SV *key)
+Perl_magic_nextpack(pTHX_ SV *sv, MAGIC *mg, SV *key)
{
dSP;
- char *meth = SvOK(key) ? "NEXTKEY" : "FIRSTKEY";
+ const char *meth = SvOK(key) ? "NEXTKEY" : "FIRSTKEY";
ENTER;
SAVETMPS;
PUSHSTACKi(PERLSI_MAGIC);
PUSHMARK(SP);
EXTEND(SP, 2);
- PUSHs(mg->mg_obj);
+ PUSHs(SvTIED_obj(sv, mg));
if (SvOK(key))
PUSHs(key);
PUTBACK;
- if (perl_call_method(meth, G_SCALAR))
+ if (call_method(meth, G_SCALAR))
sv_setsv(key, *PL_stack_sp--);
POPSTACK;
}
int
-magic_existspack(SV *sv, MAGIC *mg)
+Perl_magic_existspack(pTHX_ SV *sv, MAGIC *mg)
{
return magic_methpack(sv,mg,"EXISTS");
-}
+}
+
+SV *
+Perl_magic_scalarpack(pTHX_ HV *hv, MAGIC *mg)
+{
+ dSP;
+ SV *retval = &PL_sv_undef;
+ SV *tied = SvTIED_obj((SV*)hv, mg);
+ HV *pkg = SvSTASH((SV*)SvRV(tied));
+
+ if (!gv_fetchmethod_autoload(pkg, "SCALAR", FALSE)) {
+ SV *key;
+ if (HvEITER(hv))
+ /* we are in an iteration so the hash cannot be empty */
+ return &PL_sv_yes;
+ /* no xhv_eiter so now use FIRSTKEY */
+ key = sv_newmortal();
+ magic_nextpack((SV*)hv, mg, key);
+ HvEITER(hv) = NULL; /* need to reset iterator */
+ return SvOK(key) ? &PL_sv_yes : &PL_sv_no;
+ }
+
+ /* there is a SCALAR method that we can call */
+ ENTER;
+ PUSHSTACKi(PERLSI_MAGIC);
+ PUSHMARK(SP);
+ EXTEND(SP, 1);
+ PUSHs(tied);
+ PUTBACK;
+
+ if (call_method("SCALAR", G_SCALAR))
+ retval = *PL_stack_sp--;
+ POPSTACK;
+ LEAVE;
+ return retval;
+}
int
-magic_setdbline(SV *sv, MAGIC *mg)
+Perl_magic_setdbline(pTHX_ SV *sv, MAGIC *mg)
{
- dTHR;
OP *o;
I32 i;
GV* gv;
SV** svp;
+ STRLEN n_a;
gv = PL_DBline;
i = SvTRUE(sv);
svp = av_fetch(GvAV(gv),
- atoi(MgPV(mg,PL_na)), FALSE);
- if (svp && SvIOKp(*svp) && (o = (OP*)SvSTASH(*svp)))
- o->op_private = i;
- else
- warn("Can't break at that line\n");
+ atoi(MgPV(mg,n_a)), FALSE);
+ if (svp && SvIOKp(*svp) && (o = INT2PTR(OP*,SvIVX(*svp)))) {
+ /* set or clear breakpoint in the relevant control op */
+ if (i)
+ o->op_flags |= OPf_SPECIAL;
+ else
+ o->op_flags &= ~OPf_SPECIAL;
+ }
return 0;
}
int
-magic_getarylen(SV *sv, MAGIC *mg)
+Perl_magic_getarylen(pTHX_ SV *sv, MAGIC *mg)
{
- dTHR;
sv_setiv(sv, AvFILL((AV*)mg->mg_obj) + PL_curcop->cop_arybase);
return 0;
}
int
-magic_setarylen(SV *sv, MAGIC *mg)
+Perl_magic_setarylen(pTHX_ SV *sv, MAGIC *mg)
{
- dTHR;
av_fill((AV*)mg->mg_obj, SvIV(sv) - PL_curcop->cop_arybase);
return 0;
}
int
-magic_getpos(SV *sv, MAGIC *mg)
+Perl_magic_getpos(pTHX_ SV *sv, MAGIC *mg)
{
SV* lsv = LvTARG(sv);
-
+
if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv)) {
- mg = mg_find(lsv, 'g');
+ mg = mg_find(lsv, PERL_MAGIC_regex_global);
if (mg && mg->mg_len >= 0) {
- dTHR;
I32 i = mg->mg_len;
- if (IN_UTF8)
+ if (DO_UTF8(lsv))
sv_pos_b2u(lsv, &i);
sv_setiv(sv, i + PL_curcop->cop_arybase);
return 0;
}
int
-magic_setpos(SV *sv, MAGIC *mg)
+Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg)
{
SV* lsv = LvTARG(sv);
SSize_t pos;
STRLEN len;
- STRLEN ulen;
- dTHR;
+ STRLEN ulen = 0;
mg = 0;
-
+
if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv))
- mg = mg_find(lsv, 'g');
+ mg = mg_find(lsv, PERL_MAGIC_regex_global);
if (!mg) {
if (!SvOK(sv))
return 0;
- sv_magic(lsv, (SV*)0, 'g', Nullch, 0);
- mg = mg_find(lsv, 'g');
+ sv_magic(lsv, (SV*)0, PERL_MAGIC_regex_global, Nullch, 0);
+ mg = mg_find(lsv, PERL_MAGIC_regex_global);
}
else if (!SvOK(sv)) {
mg->mg_len = -1;
pos = SvIV(sv) - PL_curcop->cop_arybase;
- if (IN_UTF8) {
+ if (DO_UTF8(lsv)) {
ulen = sv_len_utf8(lsv);
if (ulen)
len = ulen;
- else
- ulen = 0;
}
if (pos < 0) {
if (pos < 0)
pos = 0;
}
- else if (pos > len)
+ else if (pos > (SSize_t)len)
pos = len;
if (ulen) {
sv_pos_u2b(lsv, &p, 0);
pos = p;
}
-
+
mg->mg_len = pos;
mg->mg_flags &= ~MGf_MINMATCH;
}
int
-magic_getglob(SV *sv, MAGIC *mg)
+Perl_magic_getglob(pTHX_ SV *sv, MAGIC *mg)
{
if (SvFAKE(sv)) { /* FAKE globs can get coerced */
SvFAKE_off(sv);
}
int
-magic_setglob(SV *sv, MAGIC *mg)
+Perl_magic_setglob(pTHX_ SV *sv, MAGIC *mg)
{
register char *s;
GV* gv;
+ STRLEN n_a;
if (!SvOK(sv))
return 0;
- s = SvPV(sv, PL_na);
+ s = SvPV(sv, n_a);
if (*s == '*' && s[1])
s++;
gv = gv_fetchpv(s,TRUE, SVt_PVGV);
}
int
-magic_getsubstr(SV *sv, MAGIC *mg)
+Perl_magic_getsubstr(pTHX_ SV *sv, MAGIC *mg)
{
STRLEN len;
SV *lsv = LvTARG(sv);
I32 offs = LvTARGOFF(sv);
I32 rem = LvTARGLEN(sv);
- if (offs > len)
+ if (SvUTF8(lsv))
+ sv_pos_u2b(lsv, &offs, &rem);
+ if (offs > (I32)len)
offs = len;
- if (rem + offs > len)
+ if (rem + offs > (I32)len)
rem = len - offs;
sv_setpvn(sv, tmps + offs, (STRLEN)rem);
+ if (SvUTF8(lsv))
+ SvUTF8_on(sv);
return 0;
}
int
-magic_setsubstr(SV *sv, MAGIC *mg)
+Perl_magic_setsubstr(pTHX_ SV *sv, MAGIC *mg)
{
STRLEN len;
- char *tmps = SvPV(sv,len);
- sv_insert(LvTARG(sv),LvTARGOFF(sv),LvTARGLEN(sv), tmps, len);
+ char *tmps = SvPV(sv, len);
+ SV *lsv = LvTARG(sv);
+ I32 lvoff = LvTARGOFF(sv);
+ I32 lvlen = LvTARGLEN(sv);
+
+ if (DO_UTF8(sv)) {
+ sv_utf8_upgrade(lsv);
+ sv_pos_u2b(lsv, &lvoff, &lvlen);
+ sv_insert(lsv, lvoff, lvlen, tmps, len);
+ LvTARGLEN(sv) = sv_len_utf8(sv);
+ SvUTF8_on(lsv);
+ }
+ else if (lsv && SvUTF8(lsv)) {
+ sv_pos_u2b(lsv, &lvoff, &lvlen);
+ LvTARGLEN(sv) = len;
+ tmps = (char*)bytes_to_utf8((U8*)tmps, &len);
+ sv_insert(lsv, lvoff, lvlen, tmps, len);
+ Safefree(tmps);
+ }
+ else {
+ sv_insert(lsv, lvoff, lvlen, tmps, len);
+ LvTARGLEN(sv) = len;
+ }
+
+
return 0;
}
int
-magic_gettaint(SV *sv, MAGIC *mg)
+Perl_magic_gettaint(pTHX_ SV *sv, MAGIC *mg)
{
- dTHR;
TAINT_IF((mg->mg_len & 1) ||
- (mg->mg_len & 2) && mg->mg_obj == sv); /* kludge */
+ ((mg->mg_len & 2) && mg->mg_obj == sv)); /* kludge */
return 0;
}
int
-magic_settaint(SV *sv, MAGIC *mg)
+Perl_magic_settaint(pTHX_ SV *sv, MAGIC *mg)
{
- dTHR;
if (PL_localizing) {
if (PL_localizing == 1)
mg->mg_len <<= 1;
}
int
-magic_getvec(SV *sv, MAGIC *mg)
+Perl_magic_getvec(pTHX_ SV *sv, MAGIC *mg)
{
SV *lsv = LvTARG(sv);
- unsigned char *s;
- unsigned long retnum;
- STRLEN lsvlen;
- I32 len;
- I32 offset;
- I32 size;
if (!lsv) {
- SvOK_off(sv);
+ (void)SvOK_off(sv);
return 0;
}
- s = (unsigned char *) SvPV(lsv, lsvlen);
- offset = LvTARGOFF(sv);
- size = LvTARGLEN(sv);
- len = (offset + size + 7) / 8;
- /* Copied from pp_vec() */
-
- if (len > lsvlen) {
- if (size <= 8)
- retnum = 0;
- else {
- offset >>= 3;
- if (size == 16) {
- if (offset >= lsvlen)
- retnum = 0;
- else
- retnum = (unsigned long) s[offset] << 8;
- }
- else if (size == 32) {
- if (offset >= lsvlen)
- retnum = 0;
- else if (offset + 1 >= lsvlen)
- retnum = (unsigned long) s[offset] << 24;
- else if (offset + 2 >= lsvlen)
- retnum = ((unsigned long) s[offset] << 24) +
- ((unsigned long) s[offset + 1] << 16);
- else
- retnum = ((unsigned long) s[offset] << 24) +
- ((unsigned long) s[offset + 1] << 16) +
- (s[offset + 2] << 8);
- }
- }
- }
- else if (size < 8)
- retnum = (s[offset >> 3] >> (offset & 7)) & ((1 << size) - 1);
- else {
- offset >>= 3;
- if (size == 8)
- retnum = s[offset];
- else if (size == 16)
- retnum = ((unsigned long) s[offset] << 8) + s[offset+1];
- else if (size == 32)
- retnum = ((unsigned long) s[offset] << 24) +
- ((unsigned long) s[offset + 1] << 16) +
- (s[offset + 2] << 8) + s[offset+3];
- }
-
- sv_setuv(sv, (UV)retnum);
+ sv_setuv(sv, do_vecget(lsv, LvTARGOFF(sv), LvTARGLEN(sv)));
return 0;
}
int
-magic_setvec(SV *sv, MAGIC *mg)
+Perl_magic_setvec(pTHX_ SV *sv, MAGIC *mg)
{
do_vecset(sv); /* XXX slurp this routine */
return 0;
}
int
-magic_getdefelem(SV *sv, MAGIC *mg)
+Perl_magic_getdefelem(pTHX_ SV *sv, MAGIC *mg)
{
SV *targ = Nullsv;
if (LvTARGLEN(sv)) {
if (mg->mg_obj) {
SV *ahv = LvTARG(sv);
- if (SvTYPE(ahv) == SVt_PVHV) {
- HE *he = hv_fetch_ent((HV*)ahv, mg->mg_obj, FALSE, 0);
- if (he)
- targ = HeVAL(he);
- }
- else {
- SV **svp = avhv_fetch_ent((AV*)ahv, mg->mg_obj, FALSE, 0);
- if (svp)
- targ = *svp;
- }
+ HE *he = hv_fetch_ent((HV*)ahv, mg->mg_obj, FALSE, 0);
+ if (he)
+ targ = HeVAL(he);
}
else {
AV* av = (AV*)LvTARG(sv);
targ = AvARRAY(av)[LvTARGOFF(sv)];
}
if (targ && targ != &PL_sv_undef) {
- dTHR; /* just for SvREFCNT_dec */
/* somebody else defined it for us */
SvREFCNT_dec(LvTARG(sv));
LvTARG(sv) = SvREFCNT_inc(targ);
}
int
-magic_setdefelem(SV *sv, MAGIC *mg)
+Perl_magic_setdefelem(pTHX_ SV *sv, MAGIC *mg)
{
if (LvTARGLEN(sv))
vivify_defelem(sv);
}
void
-vivify_defelem(SV *sv)
+Perl_vivify_defelem(pTHX_ SV *sv)
{
- dTHR; /* just for SvREFCNT_inc and SvREFCNT_dec*/
MAGIC *mg;
SV *value = Nullsv;
- if (!LvTARGLEN(sv) || !(mg = mg_find(sv, 'y')))
+ if (!LvTARGLEN(sv) || !(mg = mg_find(sv, PERL_MAGIC_defelem)))
return;
if (mg->mg_obj) {
SV *ahv = LvTARG(sv);
- if (SvTYPE(ahv) == SVt_PVHV) {
- HE *he = hv_fetch_ent((HV*)ahv, mg->mg_obj, TRUE, 0);
- if (he)
- value = HeVAL(he);
- }
- else {
- SV **svp = avhv_fetch_ent((AV*)ahv, mg->mg_obj, TRUE, 0);
- if (svp)
- value = *svp;
- }
+ STRLEN n_a;
+ HE *he = hv_fetch_ent((HV*)ahv, mg->mg_obj, TRUE, 0);
+ if (he)
+ value = HeVAL(he);
if (!value || value == &PL_sv_undef)
- croak(no_helem, SvPV(mg->mg_obj, PL_na));
+ Perl_croak(aTHX_ PL_no_helem, SvPV(mg->mg_obj, n_a));
}
else {
AV* av = (AV*)LvTARG(sv);
else {
SV** svp = av_fetch(av, LvTARGOFF(sv), TRUE);
if (!svp || (value = *svp) == &PL_sv_undef)
- croak(no_aelem, (I32)LvTARGOFF(sv));
+ Perl_croak(aTHX_ PL_no_aelem, (I32)LvTARGOFF(sv));
}
}
(void)SvREFCNT_inc(value);
}
int
-magic_setmglob(SV *sv, MAGIC *mg)
+Perl_magic_killbackrefs(pTHX_ SV *sv, MAGIC *mg)
+{
+ AV *av = (AV*)mg->mg_obj;
+ SV **svp = AvARRAY(av);
+ I32 i = AvFILLp(av);
+ while (i >= 0) {
+ if (svp[i]) {
+ if (!SvWEAKREF(svp[i]))
+ Perl_croak(aTHX_ "panic: magic_killbackrefs");
+ /* XXX Should we check that it hasn't changed? */
+ SvRV(svp[i]) = 0;
+ (void)SvOK_off(svp[i]);
+ SvWEAKREF_off(svp[i]);
+ svp[i] = Nullsv;
+ }
+ i--;
+ }
+ SvREFCNT_dec(av); /* remove extra count added by sv_add_backref() */
+ return 0;
+}
+
+int
+Perl_magic_setmglob(pTHX_ SV *sv, MAGIC *mg)
{
mg->mg_len = -1;
SvSCREAM_off(sv);
}
int
-magic_setbm(SV *sv, MAGIC *mg)
+Perl_magic_setbm(pTHX_ SV *sv, MAGIC *mg)
{
- sv_unmagic(sv, 'B');
+ sv_unmagic(sv, PERL_MAGIC_bm);
SvVALID_off(sv);
return 0;
}
int
-magic_setfm(SV *sv, MAGIC *mg)
+Perl_magic_setfm(pTHX_ SV *sv, MAGIC *mg)
{
- sv_unmagic(sv, 'f');
+ sv_unmagic(sv, PERL_MAGIC_fm);
SvCOMPILED_off(sv);
return 0;
}
int
-magic_setuvar(SV *sv, MAGIC *mg)
+Perl_magic_setuvar(pTHX_ SV *sv, MAGIC *mg)
{
struct ufuncs *uf = (struct ufuncs *)mg->mg_ptr;
if (uf && uf->uf_set)
- (*uf->uf_set)(uf->uf_index, sv);
+ (*uf->uf_set)(aTHX_ uf->uf_index, sv);
+ return 0;
+}
+
+int
+Perl_magic_setregexp(pTHX_ SV *sv, MAGIC *mg)
+{
+ sv_unmagic(sv, PERL_MAGIC_qr);
return 0;
}
int
-magic_freeregexp(SV *sv, MAGIC *mg)
+Perl_magic_freeregexp(pTHX_ SV *sv, MAGIC *mg)
{
regexp *re = (regexp *)mg->mg_obj;
ReREFCNT_dec(re);
#ifdef USE_LOCALE_COLLATE
int
-magic_setcollxfrm(SV *sv, MAGIC *mg)
+Perl_magic_setcollxfrm(pTHX_ SV *sv, MAGIC *mg)
{
/*
- * René Descartes said "I think not."
+ * RenE<eacute> Descartes said "I think not."
* and vanished with a faint plop.
*/
if (mg->mg_ptr) {
}
#endif /* USE_LOCALE_COLLATE */
+/* Just clear the UTF-8 cache data. */
+int
+Perl_magic_setutf8(pTHX_ SV *sv, MAGIC *mg)
+{
+ Safefree(mg->mg_ptr); /* The mg_ptr holds the pos cache. */
+ mg->mg_ptr = 0;
+ mg->mg_len = -1; /* The mg_len holds the len cache. */
+ return 0;
+}
+
int
-magic_set(SV *sv, MAGIC *mg)
+Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
{
- dTHR;
register char *s;
I32 i;
STRLEN len;
case '\001': /* ^A */
sv_setsv(PL_bodytarget, sv);
break;
- case '\002': /* ^B */
- if ( ! (PL_dowarn & G_WARN_ALL_MASK)) {
- if (memEQ(SvPVX(sv), WARN_ALLstring, WARNsize))
- compiling.cop_warnings = WARN_ALL;
- else if (memEQ(SvPVX(sv), WARN_NONEstring, WARNsize))
- compiling.cop_warnings = WARN_NONE;
- else {
- if (compiling.cop_warnings != WARN_NONE &&
- compiling.cop_warnings != WARN_ALL)
- sv_setsv(compiling.cop_warnings, sv);
- else
- compiling.cop_warnings = newSVsv(sv) ;
- }
- }
+ case '\003': /* ^C */
+ PL_minus_c = (bool)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
break;
+
case '\004': /* ^D */
- PL_debug = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) | 0x80000000;
+#ifdef DEBUGGING
+ s = SvPV_nolen(sv);
+ PL_debug = get_debug_opts(&s) | DEBUG_TOP_FLAG;
DEBUG_x(dump_all());
+#else
+ PL_debug = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) | DEBUG_TOP_FLAG;
+#endif
break;
case '\005': /* ^E */
-#ifdef VMS
- set_vaxc_errno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
-#else
-#ifdef WIN32
- SetLastError( SvIV(sv) );
+ if (*(mg->mg_ptr+1) == '\0') {
+#ifdef MACOS_TRADITIONAL
+ gMacPerl_OSErr = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
#else
- /* will anyone ever use this? */
- SETERRNO(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv), 4);
-#endif
+# ifdef VMS
+ set_vaxc_errno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
+# else
+# ifdef WIN32
+ SetLastError( SvIV(sv) );
+# else
+# ifdef OS2
+ os2_setsyserrno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
+# else
+ /* will anyone ever use this? */
+ SETERRNO(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv), 4);
+# endif
+# endif
+# endif
#endif
+ }
+ else if (strEQ(mg->mg_ptr+1, "NCODING")) {
+ if (PL_encoding)
+ SvREFCNT_dec(PL_encoding);
+ if (SvOK(sv) || SvGMAGICAL(sv)) {
+ PL_encoding = newSVsv(sv);
+ }
+ else {
+ PL_encoding = Nullsv;
+ }
+ }
break;
case '\006': /* ^F */
PL_maxsysfd = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
if (PL_inplace)
Safefree(PL_inplace);
if (SvOK(sv))
- PL_inplace = savepv(SvPV(sv,PL_na));
+ PL_inplace = savepv(SvPV(sv,len));
else
PL_inplace = Nullch;
break;
case '\017': /* ^O */
- if (PL_osname)
- Safefree(PL_osname);
- if (SvOK(sv))
- PL_osname = savepv(SvPV(sv,PL_na));
- else
- PL_osname = Nullch;
+ if (*(mg->mg_ptr+1) == '\0') {
+ if (PL_osname) {
+ Safefree(PL_osname);
+ PL_osname = Nullch;
+ }
+ if (SvOK(sv)) {
+ TAINT_PROPER("assigning to $^O");
+ PL_osname = savepv(SvPV(sv,len));
+ }
+ }
+ else if (strEQ(mg->mg_ptr, "\017PEN")) {
+ if (!PL_compiling.cop_io)
+ PL_compiling.cop_io = newSVsv(sv);
+ else
+ sv_setsv(PL_compiling.cop_io,sv);
+ }
break;
case '\020': /* ^P */
PL_perldb = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
+ if ((PERLDB_SUB || PERLDB_LINE || PERLDB_SUBLINE || PERLDB_ASSERTION)
+ && !PL_DBsingle)
+ init_debugger();
break;
case '\024': /* ^T */
#ifdef BIG_TIME
PL_basetime = (Time_t)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
#endif
break;
- case '\027': /* ^W */
- if ( ! (PL_dowarn & G_WARN_ALL_MASK)) {
- i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
- PL_dowarn = (i ? G_WARN_ON : G_WARN_OFF) ;
+ case '\027': /* ^W & $^WARNING_BITS */
+ if (*(mg->mg_ptr+1) == '\0') {
+ if ( ! (PL_dowarn & G_WARN_ALL_MASK)) {
+ i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
+ PL_dowarn = (PL_dowarn & ~G_WARN_ON)
+ | (i ? G_WARN_ON : G_WARN_OFF) ;
+ }
+ }
+ else if (strEQ(mg->mg_ptr+1, "ARNING_BITS")) {
+ if ( ! (PL_dowarn & G_WARN_ALL_MASK)) {
+ if (!SvPOK(sv) && PL_localizing) {
+ sv_setpvn(sv, WARN_NONEstring, WARNsize);
+ PL_compiling.cop_warnings = pWARN_NONE;
+ break;
+ }
+ {
+ STRLEN len, i;
+ int accumulate = 0 ;
+ int any_fatals = 0 ;
+ char * ptr = (char*)SvPV(sv, len) ;
+ for (i = 0 ; i < len ; ++i) {
+ accumulate |= ptr[i] ;
+ any_fatals |= (ptr[i] & 0xAA) ;
+ }
+ if (!accumulate)
+ PL_compiling.cop_warnings = pWARN_NONE;
+ else if (isWARN_on(sv, WARN_ALL) && !any_fatals) {
+ PL_compiling.cop_warnings = pWARN_ALL;
+ PL_dowarn |= G_WARN_ONCE ;
+ }
+ else {
+ if (specialWARN(PL_compiling.cop_warnings))
+ PL_compiling.cop_warnings = newSVsv(sv) ;
+ else
+ sv_setsv(PL_compiling.cop_warnings, sv);
+ if (isWARN_on(PL_compiling.cop_warnings, WARN_ONCE))
+ PL_dowarn |= G_WARN_ONCE ;
+ }
+
+ }
+ }
}
break;
case '.':
if (PL_localizing) {
if (PL_localizing == 1)
- save_sptr((SV**)&PL_last_in_gv);
+ SAVESPTR(PL_last_in_gv);
}
else if (SvOK(sv) && GvIO(PL_last_in_gv))
- IoLINES(GvIOp(PL_last_in_gv)) = (long)SvIV(sv);
+ IoLINES(GvIOp(PL_last_in_gv)) = SvIV(sv);
break;
case '^':
Safefree(IoTOP_NAME(GvIOp(PL_defoutgv)));
- IoTOP_NAME(GvIOp(PL_defoutgv)) = s = savepv(SvPV(sv,PL_na));
+ IoTOP_NAME(GvIOp(PL_defoutgv)) = s = savepv(SvPV(sv,len));
IoTOP_GV(GvIOp(PL_defoutgv)) = gv_fetchpv(s,TRUE, SVt_PVIO);
break;
case '~':
Safefree(IoFMT_NAME(GvIOp(PL_defoutgv)));
- IoFMT_NAME(GvIOp(PL_defoutgv)) = s = savepv(SvPV(sv,PL_na));
+ IoFMT_NAME(GvIOp(PL_defoutgv)) = s = savepv(SvPV(sv,len));
IoFMT_GV(GvIOp(PL_defoutgv)) = gv_fetchpv(s,TRUE, SVt_PVIO);
break;
case '=':
- IoPAGE_LEN(GvIOp(PL_defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
+ IoPAGE_LEN(GvIOp(PL_defoutgv)) = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
break;
case '-':
- IoLINES_LEFT(GvIOp(PL_defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
+ IoLINES_LEFT(GvIOp(PL_defoutgv)) = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
if (IoLINES_LEFT(GvIOp(PL_defoutgv)) < 0L)
IoLINES_LEFT(GvIOp(PL_defoutgv)) = 0L;
break;
case '%':
- IoPAGE(GvIOp(PL_defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
+ IoPAGE(GvIOp(PL_defoutgv)) = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
break;
case '|':
{
IO *io = GvIOp(PL_defoutgv);
+ if(!io)
+ break;
if ((SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) == 0)
IoFLAGS(io) &= ~IOf_FLUSH;
else {
}
}
break;
- case '*':
- i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
- PL_multiline = (i != 0);
- break;
case '/':
- SvREFCNT_dec(PL_nrs);
- PL_nrs = newSVsv(sv);
SvREFCNT_dec(PL_rs);
- PL_rs = SvREFCNT_inc(PL_nrs);
+ PL_rs = newSVsv(sv);
break;
case '\\':
- if (PL_ors)
- Safefree(PL_ors);
- if (SvOK(sv) || SvGMAGICAL(sv))
- PL_ors = savepv(SvPV(sv,PL_orslen));
+ if (PL_ors_sv)
+ SvREFCNT_dec(PL_ors_sv);
+ if (SvOK(sv) || SvGMAGICAL(sv)) {
+ PL_ors_sv = newSVsv(sv);
+ }
else {
- PL_ors = Nullch;
- PL_orslen = 0;
+ PL_ors_sv = Nullsv;
}
break;
case ',':
- if (PL_ofs)
- Safefree(PL_ofs);
- PL_ofs = savepv(SvPV(sv, PL_ofslen));
+ if (PL_ofs_sv)
+ SvREFCNT_dec(PL_ofs_sv);
+ if (SvOK(sv) || SvGMAGICAL(sv)) {
+ PL_ofs_sv = newSVsv(sv);
+ }
+ else {
+ PL_ofs_sv = Nullsv;
+ }
break;
case '#':
if (PL_ofmt)
Safefree(PL_ofmt);
- PL_ofmt = savepv(SvPV(sv,PL_na));
+ PL_ofmt = savepv(SvPV(sv,len));
break;
case '[':
PL_compiling.cop_arybase = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
STATUS_POSIX_SET(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
break;
case '!':
+ {
+#ifdef VMS
+# define PERL_VMS_BANG vaxc$errno
+#else
+# define PERL_VMS_BANG 0
+#endif
SETERRNO(SvIOK(sv) ? SvIVX(sv) : SvOK(sv) ? sv_2iv(sv) : 0,
- (SvIV(sv) == EVMSERR) ? 4 : vaxc$errno);
+ (SvIV(sv) == EVMSERR) ? 4 : PERL_VMS_BANG);
+ }
break;
case '<':
PL_uid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
#ifdef HAS_SETRESUID
(void)setresuid((Uid_t)PL_uid, (Uid_t)-1, (Uid_t)-1);
#else
- if (PL_uid == PL_euid) /* special case $< = $> */
+ if (PL_uid == PL_euid) { /* special case $< = $> */
+#ifdef PERL_DARWIN
+ /* workaround for Darwin's setuid peculiarity, cf [perl #24122] */
+ if (PL_uid != 0 && PerlProc_getuid() == 0)
+ (void)PerlProc_setuid(0);
+#endif
(void)PerlProc_setuid(PL_uid);
- else {
- PL_uid = (I32)PerlProc_getuid();
- croak("setruid() not implemented");
+ } else {
+ PL_uid = PerlProc_getuid();
+ Perl_croak(aTHX_ "setruid() not implemented");
}
#endif
#endif
#endif
- PL_uid = (I32)PerlProc_getuid();
+ PL_uid = PerlProc_getuid();
PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid));
break;
case '>':
if (PL_euid == PL_uid) /* special case $> = $< */
PerlProc_setuid(PL_euid);
else {
- PL_euid = (I32)PerlProc_geteuid();
- croak("seteuid() not implemented");
+ PL_euid = PerlProc_geteuid();
+ Perl_croak(aTHX_ "seteuid() not implemented");
}
#endif
#endif
#endif
- PL_euid = (I32)PerlProc_geteuid();
+ PL_euid = PerlProc_geteuid();
PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid));
break;
case '(':
if (PL_gid == PL_egid) /* special case $( = $) */
(void)PerlProc_setgid(PL_gid);
else {
- PL_gid = (I32)PerlProc_getgid();
- croak("setrgid() not implemented");
+ PL_gid = PerlProc_getgid();
+ Perl_croak(aTHX_ "setrgid() not implemented");
}
#endif
#endif
#endif
- PL_gid = (I32)PerlProc_getgid();
+ PL_gid = PerlProc_getgid();
PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid));
break;
case ')':
#ifdef HAS_SETGROUPS
{
- char *p = SvPV(sv, PL_na);
+ char *p = SvPV(sv, len);
Groups_t gary[NGROUPS];
- SET_NUMERIC_STANDARD();
while (isSPACE(*p))
++p;
- PL_egid = I_V(atof(p));
+ PL_egid = Atol(p);
for (i = 0; i < NGROUPS; ++i) {
while (*p && !isSPACE(*p))
++p;
++p;
if (!*p)
break;
- gary[i] = I_V(atof(p));
+ gary[i] = Atol(p);
}
if (i)
(void)setgroups(i, gary);
if (PL_egid == PL_gid) /* special case $) = $( */
(void)PerlProc_setgid(PL_egid);
else {
- PL_egid = (I32)PerlProc_getegid();
- croak("setegid() not implemented");
+ PL_egid = PerlProc_getegid();
+ Perl_croak(aTHX_ "setegid() not implemented");
}
#endif
#endif
#endif
- PL_egid = (I32)PerlProc_getegid();
+ PL_egid = PerlProc_getegid();
PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid));
break;
case ':':
- PL_chopset = SvPV_force(sv,PL_na);
+ PL_chopset = SvPV_force(sv,len);
break;
+#ifndef MACOS_TRADITIONAL
case '0':
- if (!PL_origalen) {
- s = PL_origargv[0];
- s += strlen(s);
- /* See if all the arguments are contiguous in memory */
- for (i = 1; i < PL_origargc; i++) {
- if (PL_origargv[i] == s + 1
-#ifdef OS2
- || PL_origargv[i] == s + 2
-#endif
- )
- s += strlen(++s); /* this one is ok too */
- else
- break;
- }
- /* can grab env area too? */
- if (PL_origenviron && (PL_origenviron[0] == s + 1
-#ifdef OS2
- || (PL_origenviron[0] == s + 9 && (s += 8))
-#endif
- )) {
- my_setenv("NoNe SuCh", Nullch);
- /* force copy of environment */
- for (i = 0; PL_origenviron[i]; i++)
- if (PL_origenviron[i] == s + 1)
- s += strlen(++s);
- else
- break;
- }
- PL_origalen = s - PL_origargv[0];
+ LOCK_DOLLARZERO_MUTEX;
+#ifdef HAS_SETPROCTITLE
+ /* The BSDs don't show the argv[] in ps(1) output, they
+ * show a string from the process struct and provide
+ * the setproctitle() routine to manipulate that. */
+ {
+ s = SvPV(sv, len);
+# if __FreeBSD_version > 410001
+ /* The leading "-" removes the "perl: " prefix,
+ * but not the "(perl) suffix from the ps(1)
+ * output, because that's what ps(1) shows if the
+ * argv[] is modified. */
+ setproctitle("-%s", s);
+# else /* old FreeBSDs, NetBSD, OpenBSD, anyBSD */
+ /* This doesn't really work if you assume that
+ * $0 = 'foobar'; will wipe out 'perl' from the $0
+ * because in ps(1) output the result will be like
+ * sprintf("perl: %s (perl)", s)
+ * I guess this is a security feature:
+ * one (a user process) cannot get rid of the original name.
+ * --jhi */
+ setproctitle("%s", s);
+# endif
}
+#endif
+#if defined(__hpux) && defined(PSTAT_SETCMD)
+ {
+ union pstun un;
+ s = SvPV(sv, len);
+ un.pst_command = s;
+ pstat(PSTAT_SETCMD, un, len, 0, 0);
+ }
+#endif
+ /* PL_origalen is set in perl_parse(). */
s = SvPV_force(sv,len);
- i = len;
- if (i >= PL_origalen) {
- i = PL_origalen;
- /* don't allow system to limit $0 seen by script */
- /* SvCUR_set(sv, i); *SvEND(sv) = '\0'; */
- Copy(s, PL_origargv[0], i, char);
- s = PL_origargv[0]+i;
- *s = '\0';
+ if (len >= (STRLEN)PL_origalen-1) {
+ /* Longer than original, will be truncated. We assume that
+ * PL_origalen bytes are available. */
+ Copy(s, PL_origargv[0], PL_origalen-1, char);
}
else {
- Copy(s, PL_origargv[0], i, char);
- s = PL_origargv[0]+i;
- *s++ = '\0';
- while (++i < PL_origalen)
- *s++ = ' ';
- s = PL_origargv[0]+i;
- for (i = 1; i < PL_origargc; i++)
- PL_origargv[i] = Nullch;
+ /* Shorter than original, will be padded. */
+ Copy(s, PL_origargv[0], len, char);
+ PL_origargv[0][len] = 0;
+ memset(PL_origargv[0] + len + 1,
+ /* Is the space counterintuitive? Yes.
+ * (You were expecting \0?)
+ * Does it work? Seems to. (In Linux 2.4.20 at least.)
+ * --jhi */
+ (int)' ',
+ PL_origalen - len - 1);
}
+ PL_origargv[0][PL_origalen-1] = 0;
+ for (i = 1; i < PL_origargc; i++)
+ PL_origargv[i] = 0;
+ UNLOCK_DOLLARZERO_MUTEX;
break;
-#ifdef USE_THREADS
- case '@':
- sv_setsv(thr->errsv, sv);
- break;
-#endif /* USE_THREADS */
+#endif
}
return 0;
}
-#ifdef USE_THREADS
-int
-magic_mutexfree(SV *sv, MAGIC *mg)
-{
- dTHR;
- DEBUG_S(PerlIO_printf(PerlIO_stderr(), "0x%lx: magic_mutexfree 0x%lx\n",
- (unsigned long)thr, (unsigned long)sv);)
- if (MgOWNER(mg))
- croak("panic: magic_mutexfree");
- MUTEX_DESTROY(MgMUTEXP(mg));
- COND_DESTROY(MgCONDP(mg));
- SvREFCNT_dec(sv);
- return 0;
-}
-#endif /* USE_THREADS */
-
I32
-whichsig(char *sig)
+Perl_whichsig(pTHX_ char *sig)
{
register char **sigv;
- for (sigv = sig_name+1; *sigv; sigv++)
+ for (sigv = PL_sig_name; *sigv; sigv++)
if (strEQ(sig,*sigv))
- return sig_num[sigv - sig_name];
+ return PL_sig_num[sigv - PL_sig_name];
#ifdef SIGCLD
if (strEQ(sig,"CHLD"))
return SIGCLD;
if (strEQ(sig,"CLD"))
return SIGCHLD;
#endif
- return 0;
+ return -1;
}
+#if !defined(PERL_IMPLICIT_CONTEXT)
static SV* sig_sv;
-
-STATIC void
-unwind_handler_stack(void *p)
-{
- dTHR;
- U32 flags = *(U32*)p;
-
- if (flags & 1)
- PL_savestack_ix -= 5; /* Unprotect save in progress. */
- /* cxstack_ix-- Not needed, die already unwound it. */
- if (flags & 64)
- SvREFCNT_dec(sig_sv);
-}
+#endif
Signal_t
-sighandler(int sig)
+Perl_sighandler(int sig)
{
+#ifdef PERL_GET_SIG_CONTEXT
+ dTHXa(PERL_GET_SIG_CONTEXT);
+#else
+ dTHX;
+#endif
dSP;
GV *gv = Nullgv;
HV *st;
- SV *sv, *tSv = PL_Sv;
+ SV *sv = Nullsv, *tSv = PL_Sv;
CV *cv = Nullcv;
OP *myop = PL_op;
U32 flags = 0;
- I32 o_save_i = PL_savestack_ix, type;
XPV *tXpv = PL_Xpv;
-
+
if (PL_savestack_ix + 15 <= PL_savestack_max)
flags |= 1;
if (PL_markstack_ptr < PL_markstack_max - 2)
if (PL_scopestack_ix < PL_scopestack_max - 3)
flags |= 16;
- if (!psig_ptr[sig])
- die("Signal SIG%s received, but no signal handler set.\n",
- sig_name[sig]);
+ if (!PL_psig_ptr[sig]) {
+ PerlIO_printf(Perl_error_log, "Signal SIG%s received, but no signal handler set.\n",
+ PL_sig_name[sig]);
+ exit(sig);
+ }
/* Max number of items pushed there is 3*n or 4. We cannot fix
infinity, so we fix 4 (in fact 5): */
if (flags & 1) {
PL_savestack_ix += 5; /* Protect save in progress. */
- o_save_i = PL_savestack_ix;
- SAVEDESTRUCTOR(unwind_handler_stack, (void*)&flags);
+ SAVEDESTRUCTOR_X(unwind_handler_stack, (void*)&flags);
}
- if (flags & 4)
+ if (flags & 4)
PL_markstack_ptr++; /* Protect mark. */
if (flags & 8) {
PL_retstack_ix++;
if (flags & 16)
PL_scopestack_ix += 1;
/* sv_2cv is too complicated, try a simpler variant first: */
- if (!SvROK(psig_ptr[sig]) || !(cv = (CV*)SvRV(psig_ptr[sig]))
+ if (!SvROK(PL_psig_ptr[sig]) || !(cv = (CV*)SvRV(PL_psig_ptr[sig]))
|| SvTYPE(cv) != SVt_PVCV)
- cv = sv_2cv(psig_ptr[sig],&st,&gv,TRUE);
+ cv = sv_2cv(PL_psig_ptr[sig],&st,&gv,TRUE);
if (!cv || !CvROOT(cv)) {
if (ckWARN(WARN_SIGNAL))
- warner(WARN_SIGNAL, "SIG%s handler \"%s\" not defined.\n",
- sig_name[sig], (gv ? GvENAME(gv)
+ Perl_warner(aTHX_ packWARN(WARN_SIGNAL), "SIG%s handler \"%s\" not defined.\n",
+ PL_sig_name[sig], (gv ? GvENAME(gv)
: ((cv && CvGV(cv))
? GvENAME(CvGV(cv))
: "__ANON__")));
goto cleanup;
}
- if(psig_name[sig]) {
- sv = SvREFCNT_inc(psig_name[sig]);
+ if(PL_psig_name[sig]) {
+ sv = SvREFCNT_inc(PL_psig_name[sig]);
flags |= 64;
+#if !defined(PERL_IMPLICIT_CONTEXT)
sig_sv = sv;
+#endif
} else {
sv = sv_newmortal();
- sv_setpv(sv,sig_name[sig]);
+ sv_setpv(sv,PL_sig_name[sig]);
}
PUSHSTACKi(PERLSI_SIGNAL);
PUSHs(sv);
PUTBACK;
- perl_call_sv((SV*)cv, G_DISCARD);
+ call_sv((SV*)cv, G_DISCARD|G_EVAL);
POPSTACK;
+ if (SvTRUE(ERRSV)) {
+#ifndef PERL_MICRO
+#ifdef HAS_SIGPROCMASK
+ /* Handler "died", for example to get out of a restart-able read().
+ * Before we re-do that on its behalf re-enable the signal which was
+ * blocked by the system when we entered.
+ */
+ sigset_t set;
+ sigemptyset(&set);
+ sigaddset(&set,sig);
+ sigprocmask(SIG_UNBLOCK, &set, NULL);
+#else
+ /* Not clear if this will work */
+ (void)rsignal(sig, SIG_IGN);
+ (void)rsignal(sig, PL_csighandlerp);
+#endif
+#endif /* !PERL_MICRO */
+ Perl_die(aTHX_ Nullformat);
+ }
cleanup:
if (flags & 1)
PL_savestack_ix -= 8; /* Unprotect save in progress. */
- if (flags & 4)
+ if (flags & 4)
PL_markstack_ptr--;
- if (flags & 8)
+ if (flags & 8)
PL_retstack_ix--;
if (flags & 16)
PL_scopestack_ix -= 1;
if (flags & 64)
SvREFCNT_dec(sv);
PL_op = myop; /* Apparently not needed... */
-
+
PL_Sv = tSv; /* Restore global temporaries. */
PL_Xpv = tXpv;
return;
}
+static void
+restore_magic(pTHX_ void *p)
+{
+ MGS* mgs = SSPTR(PTR2IV(p), MGS*);
+ SV* sv = mgs->mgs_sv;
+
+ if (!sv)
+ return;
+
+ if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv))
+ {
+#ifdef PERL_COPY_ON_WRITE
+ /* While magic was saved (and off) sv_setsv may well have seen
+ this SV as a prime candidate for COW. */
+ if (SvIsCOW(sv))
+ sv_force_normal(sv);
+#endif
+
+ if (mgs->mgs_flags)
+ SvFLAGS(sv) |= mgs->mgs_flags;
+ else
+ mg_magical(sv);
+ if (SvGMAGICAL(sv))
+ SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK|SVf_POK);
+ }
+
+ mgs->mgs_sv = NULL; /* mark the MGS structure as restored */
+
+ /* If we're still on top of the stack, pop us off. (That condition
+ * will be satisfied if restore_magic was called explicitly, but *not*
+ * if it's being called via leave_scope.)
+ * The reason for doing this is that otherwise, things like sv_2cv()
+ * may leave alloc gunk on the savestack, and some code
+ * (e.g. sighandler) doesn't expect that...
+ */
+ if (PL_savestack_ix == mgs->mgs_ss_ix)
+ {
+ I32 popval = SSPOPINT;
+ assert(popval == SAVEt_DESTRUCTOR_X);
+ PL_savestack_ix -= 2;
+ popval = SSPOPINT;
+ assert(popval == SAVEt_ALLOC);
+ popval = SSPOPINT;
+ PL_savestack_ix -= popval;
+ }
+
+}
+
+static void
+unwind_handler_stack(pTHX_ void *p)
+{
+ U32 flags = *(U32*)p;
+
+ if (flags & 1)
+ PL_savestack_ix -= 5; /* Unprotect save in progress. */
+ /* cxstack_ix-- Not needed, die already unwound it. */
+#if !defined(PERL_IMPLICIT_CONTEXT)
+ if (flags & 64)
+ SvREFCNT_dec(sig_sv);
+#endif
+}
+
+