summaryrefslogtreecommitdiff
path: root/pp.c
diff options
context:
space:
mode:
Diffstat (limited to 'pp.c')
-rw-r--r--pp.c9464
1 files changed, 1115 insertions, 8349 deletions
diff --git a/pp.c b/pp.c
index b8b2bbd5bc..5c51bc5b3b 100644
--- a/pp.c
+++ b/pp.c
@@ -1,111 +1,23 @@
-/***********************************************************
+/* pp.c
*
- * $Header: /usr/src/local/lwall/perl5/RCS/pp.c, v 4.1 92/08/07 18:26:21 lwall Exp Locker: lwall $
+ * Copyright (c) 1991-1994, Larry Wall
*
- * Description:
- * Push/Pop code.
+ * You may distribute under the terms of either the GNU General Public
+ * License or the Artistic License, as specified in the README file.
*
- * Standards:
- *
- * Created:
- * Mon Jun 15 16:45:59 1992
- *
- * Author:
- * Larry Wall <lwall@netlabs.com>
- *
- * $Log: pp.c, v $
- * Revision 4.1 92/08/07 18:26:21 lwall
- *
- *
- **********************************************************/
+ */
+
+/*
+ * "It's a big house this, and very peculiar. Always a bit more to discover,
+ * and no knowing what you'll find around a corner. And Elves, sir!" --Samwise
+ */
#include "EXTERN.h"
#include "perl.h"
-#ifdef HAS_SOCKET
-# include <sys/socket.h>
-# include <netdb.h>
-# ifndef ENOTSOCK
-# ifdef I_NET_ERRNO
-# include <net/errno.h>
-# endif
-# endif
-#endif
-
-#ifdef HAS_SELECT
-#ifdef I_SYS_SELECT
-#ifndef I_SYS_TIME
-#include <sys/select.h>
-#endif
-#endif
-#endif
-
-#ifdef HOST_NOT_FOUND
-extern int h_errno;
-#endif
-
-#ifdef HAS_PASSWD
-# ifdef I_PWD
-# include <pwd.h>
-# else
- struct passwd *getpwnam P((char *));
- struct passwd *getpwuid P((Uid_t));
-# endif
- struct passwd *getpwent();
-#endif
-
-#ifdef HAS_GROUP
-# ifdef I_GRP
-# include <grp.h>
-# else
- struct group *getgrnam P((char *));
- struct group *getgrgid P((Gid_t));
-# endif
- struct group *getgrent();
-#endif
-
-#ifdef I_UTIME
-#include <utime.h>
-#endif
-#ifdef I_FCNTL
-#include <fcntl.h>
-#endif
-#ifdef I_SYS_FILE
-#include <sys/file.h>
-#endif
-
-#ifdef HAS_GETPGRP2
-# define getpgrp getpgrp2
-#endif
-
-#ifdef HAS_SETPGRP2
-# define setpgrp setpgrp2
-#endif
-
-#ifdef HAS_GETPGRP2
-# define getpgrp getpgrp2
-#endif
-
-#ifdef HAS_SETPGRP2
-# define setpgrp setpgrp2
-#endif
-
-#ifdef HAS_GETPGRP2
-# define getpgrp getpgrp2
-#endif
-
-#ifdef HAS_SETPGRP2
-# define setpgrp setpgrp2
-#endif
+static void doencodes _((SV *sv, char *s, I32 len));
-static I32 dopoptosub P((I32 startingblock));
-
-/* Nothing. */
-
-PP(pp_null)
-{
- return NORMAL;
-}
+/* variations on pp_null */
PP(pp_stub)
{
@@ -123,106 +35,13 @@ PP(pp_scalar)
/* Pushy stuff. */
-PP(pp_pushmark)
-{
- if (++markstack_ptr == markstack_max) {
- I32 oldmax = markstack_max - markstack;
- I32 newmax = oldmax * 3 / 2;
-
- Renew(markstack, newmax, I32);
- markstack_ptr = markstack + oldmax;
- markstack_max = markstack + newmax;
- }
- *markstack_ptr = stack_sp - stack_base;
- return NORMAL;
-}
-
-PP(pp_wantarray)
-{
- dSP;
- I32 cxix;
- EXTEND(SP, 1);
-
- cxix = dopoptosub(cxstack_ix);
- if (cxix < 0)
- RETPUSHUNDEF;
-
- if (cxstack[cxix].blk_gimme == G_ARRAY)
- RETPUSHYES;
- else
- RETPUSHNO;
-}
-
-PP(pp_const)
-{
- dSP;
- XPUSHs(cSVOP->op_sv);
- RETURN;
-}
-
-static void
-ucase(s,send)
-register char *s;
-register char *send;
-{
- while (s < send) {
- if (isLOWER(*s))
- *s = toupper(*s);
- s++;
- }
-}
-
-static void
-lcase(s,send)
-register char *s;
-register char *send;
-{
- while (s < send) {
- if (isUPPER(*s))
- *s = tolower(*s);
- s++;
- }
-}
-
-PP(pp_interp)
-{
- DIE("panic: pp_interp");
-}
-
-PP(pp_gvsv)
-{
- dSP;
- EXTEND(sp,1);
- if (op->op_flags & OPf_INTRO)
- PUSHs(save_scalar(cGVOP->op_gv));
- else
- PUSHs(GvSV(cGVOP->op_gv));
- RETURN;
-}
-
-PP(pp_gv)
-{
- dSP;
- XPUSHs((SV*)cGVOP->op_gv);
- RETURN;
-}
-
-PP(pp_padsv)
-{
- dSP; dTARGET;
- XPUSHs(TARG);
- if (op->op_flags & OPf_INTRO)
- SAVECLEARSV(curpad[op->op_targ]);
- RETURN;
-}
-
PP(pp_padav)
{
dSP; dTARGET;
- if (op->op_flags & OPf_INTRO)
+ if (op->op_private & OPpLVAL_INTRO)
SAVECLEARSV(curpad[op->op_targ]);
EXTEND(SP, 1);
- if (op->op_flags & OPf_LVAL) {
+ if (op->op_flags & OPf_REF) {
PUSHs(TARG);
RETURN;
}
@@ -245,12 +64,12 @@ PP(pp_padhv)
{
dSP; dTARGET;
XPUSHs(TARG);
- if (op->op_flags & OPf_INTRO)
+ if (op->op_private & OPpLVAL_INTRO)
SAVECLEARSV(curpad[op->op_targ]);
- if (op->op_flags & OPf_LVAL)
+ if (op->op_flags & OPf_REF)
RETURN;
if (GIMME == G_ARRAY) { /* array wanted */
- return do_kv(ARGS);
+ RETURNOP(do_kv(ARGS));
}
else {
SV* sv = sv_newmortal();
@@ -270,33 +89,37 @@ PP(pp_padany)
DIE("NOT IMPL LINE %d",__LINE__);
}
-PP(pp_pushre)
-{
- dSP;
- XPUSHs((SV*)op);
- RETURN;
-}
-
/* Translations. */
PP(pp_rv2gv)
{
dSP; dTOPss;
+
if (SvROK(sv)) {
+ wasref:
sv = SvRV(sv);
if (SvTYPE(sv) != SVt_PVGV)
- DIE("Not a symbol reference");
+ DIE("Not a GLOB reference");
}
else {
if (SvTYPE(sv) != SVt_PVGV) {
- if (!SvOK(sv))
- DIE(no_usym, "a symbol");
+ if (SvGMAGICAL(sv)) {
+ mg_get(sv);
+ if (SvROK(sv))
+ goto wasref;
+ }
+ if (!SvOK(sv)) {
+ if (op->op_flags & OPf_REF ||
+ op->op_private & HINT_STRICT_REFS)
+ DIE(no_usym, "a symbol");
+ RETSETUNDEF;
+ }
if (op->op_private & HINT_STRICT_REFS)
- DIE(no_hardref, "a symbol");
+ DIE(no_symref, "a symbol");
sv = (SV*)gv_fetchpv(SvPV(sv, na), TRUE, SVt_PVGV);
}
}
- if (op->op_flags & OPf_INTRO) {
+ if (op->op_private & OPpLVAL_INTRO) {
GP *ogp = GvGP(sv);
SSCHECK(3);
@@ -304,8 +127,10 @@ PP(pp_rv2gv)
SSPUSHPTR(ogp);
SSPUSHINT(SAVEt_GP);
- if (op->op_flags & OPf_SPECIAL)
+ if (op->op_flags & OPf_SPECIAL) {
GvGP(sv)->gp_refcnt++; /* will soon be assigned */
+ GvFLAGS(sv) |= GVf_INTRO;
+ }
else {
GP *gp;
Newz(602,gp, 1, GP);
@@ -333,55 +158,51 @@ PP(pp_rv2sv)
dSP; dTOPss;
if (SvROK(sv)) {
+ wasref:
sv = SvRV(sv);
switch (SvTYPE(sv)) {
case SVt_PVAV:
case SVt_PVHV:
case SVt_PVCV:
- DIE("Not a scalar reference");
+ DIE("Not a SCALAR reference");
}
}
else {
GV *gv = sv;
if (SvTYPE(gv) != SVt_PVGV) {
- if (!SvOK(sv))
- DIE(no_usym, "a scalar");
+ if (SvGMAGICAL(sv)) {
+ mg_get(sv);
+ if (SvROK(sv))
+ goto wasref;
+ }
+ if (!SvOK(sv)) {
+ if (op->op_flags & OPf_REF ||
+ op->op_private & HINT_STRICT_REFS)
+ DIE(no_usym, "a SCALAR");
+ RETSETUNDEF;
+ }
if (op->op_private & HINT_STRICT_REFS)
- DIE(no_hardref, "a scalar");
+ DIE(no_symref, "a SCALAR");
gv = (SV*)gv_fetchpv(SvPV(sv, na), TRUE, SVt_PV);
}
sv = GvSV(gv);
- if (op->op_private & (OPpDEREF_AV|OPpDEREF_HV)) {
- if (op->op_private & OPpDEREF_HV &&
- (!SvROK(sv) || SvTYPE(SvRV(sv)) != SVt_PVHV)) {
- if (op->op_private & HINT_STRICT_REFS && !SvROK(sv) && SvOK(sv))
- DIE(no_hardref, "a hash");
- SvREFCNT_dec(sv);
- sv = NEWSV(0,0);
- sv_upgrade(sv, SVt_RV);
- SvRV(sv) = SvREFCNT_inc(newHV());
- SvROK_on(sv);
- ++sv_rvcount;
- GvSV(gv) = sv;
- }
- else if (op->op_private & OPpDEREF_AV &&
- (!SvROK(sv) || SvTYPE(SvRV(sv)) != SVt_PVAV)) {
- if (op->op_private & HINT_STRICT_REFS && !SvROK(sv) && SvOK(sv))
- DIE(no_hardref, "an array");
- SvREFCNT_dec(sv);
- sv = NEWSV(0,0);
- sv_upgrade(sv, SVt_RV);
- SvRV(sv) = SvREFCNT_inc(newAV());
+ }
+ if (op->op_flags & OPf_MOD) {
+ if (op->op_private & OPpLVAL_INTRO)
+ sv = save_scalar((GV*)TOPs);
+ else if (op->op_private & (OPpDEREF_HV|OPpDEREF_AV)) {
+ if (SvGMAGICAL(sv))
+ mg_get(sv);
+ if (!SvOK(sv)) {
+ (void)SvUPGRADE(sv, SVt_RV);
+ SvRV(sv) = (op->op_private & OPpDEREF_HV ?
+ (SV*)newHV() : (SV*)newAV());
SvROK_on(sv);
- ++sv_rvcount;
- GvSV(gv) = sv;
+ SvSETMAGIC(sv);
}
}
}
- if (op->op_flags & OPf_INTRO)
- SETs(save_scalar((GV*)TOPs));
- else
- SETs(sv);
+ SETs(sv);
RETURN;
}
@@ -399,10 +220,33 @@ PP(pp_av2arylen)
RETURN;
}
+PP(pp_pos)
+{
+ dSP; dTARGET; dPOPss;
+
+ if (op->op_flags & OPf_MOD) {
+ LvTYPE(TARG) = '<';
+ LvTARG(TARG) = sv;
+ PUSHs(TARG); /* no SvSETMAGIC */
+ RETURN;
+ }
+ else {
+ MAGIC* mg;
+
+ if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) {
+ mg = mg_find(sv, 'g');
+ if (mg && mg->mg_len >= 0) {
+ PUSHi(mg->mg_len + curcop->cop_arybase);
+ RETURN;
+ }
+ }
+ RETPUSHUNDEF;
+ }
+}
+
PP(pp_rv2cv)
{
dSP;
- SV *sv;
GV *gv;
HV *stash;
@@ -413,19 +257,55 @@ PP(pp_rv2cv)
RETURN;
}
-PP(pp_refgen)
+PP(pp_anoncode)
+{
+ dSP;
+ XPUSHs(cSVOP->op_sv);
+ RETURN;
+}
+
+PP(pp_srefgen)
{
dSP; dTOPss;
SV* rv;
- if (!sv)
- RETSETUNDEF;
rv = sv_newmortal();
sv_upgrade(rv, SVt_RV);
- SvRV(rv) = SvREFCNT_inc(sv);
+ if (SvPADTMP(sv))
+ sv = newSVsv(sv);
+ else {
+ SvTEMP_off(sv);
+ (void)SvREFCNT_inc(sv);
+ }
+ SvRV(rv) = sv;
SvROK_on(rv);
- ++sv_rvcount;
SETs(rv);
RETURN;
+}
+
+PP(pp_refgen)
+{
+ dSP; dMARK;
+ SV* sv;
+ SV* rv;
+ if (GIMME != G_ARRAY) {
+ MARK[1] = *SP;
+ SP = MARK + 1;
+ }
+ while (MARK < SP) {
+ sv = *++MARK;
+ rv = sv_newmortal();
+ sv_upgrade(rv, SVt_RV);
+ if (SvPADTMP(sv))
+ sv = newSVsv(sv);
+ else {
+ SvTEMP_off(sv);
+ (void)SvREFCNT_inc(sv);
+ }
+ SvRV(rv) = sv;
+ SvROK_on(rv);
+ *MARK = rv;
+ }
+ RETURN;
}
PP(pp_ref)
@@ -434,43 +314,12 @@ PP(pp_ref)
SV *sv;
char *pv;
- if (MAXARG < 1) {
- sv = GvSV(defgv);
- EXTEND(SP, 1);
- }
- else
- sv = POPs;
- if (!SvROK(sv))
+ sv = POPs;
+ if (!sv || !SvROK(sv))
RETPUSHUNDEF;
sv = SvRV(sv);
- if (SvOBJECT(sv))
- pv = HvNAME(SvSTASH(sv));
- else {
- switch (SvTYPE(sv)) {
- case SVt_NULL:
- case SVt_IV:
- case SVt_NV:
- case SVt_RV:
- case SVt_PV:
- case SVt_PVIV:
- case SVt_PVNV:
- case SVt_PVMG:
- case SVt_PVBM:
- if (SvROK(sv))
- pv = "REF";
- else
- pv = "SCALAR";
- break;
- case SVt_PVLV: pv = "LVALUE"; break;
- case SVt_PVAV: pv = "ARRAY"; break;
- case SVt_PVHV: pv = "HASH"; break;
- case SVt_PVCV: pv = "CODE"; break;
- case SVt_PVGV: pv = "GLOB"; break;
- case SVt_PVFM: pv = "FORMLINE"; break;
- default: pv = "UNKNOWN"; break;
- }
- }
+ pv = sv_reftype(sv,TRUE);
PUSHp(pv, strlen(pv));
RETURN;
}
@@ -478,763 +327,84 @@ PP(pp_ref)
PP(pp_bless)
{
dSP;
- register SV* ref;
- SV *sv;
HV *stash;
if (MAXARG == 1)
stash = curcop->cop_stash;
else
- stash = fetch_stash(POPs, TRUE);
-
- sv = TOPs;
- if (!SvROK(sv))
- DIE("Can't bless non-reference value");
- ref = SvRV(sv);
- SvOBJECT_on(ref);
- SvUPGRADE(ref, SVt_PVMG);
- SvSTASH(ref) = (HV*)SvREFCNT_inc(stash);
- RETURN;
-}
-
-/* Pushy I/O. */
-
-PP(pp_backtick)
-{
- dSP; dTARGET;
- FILE *fp;
- char *tmps = POPp;
- TAINT_PROPER("``");
- fp = my_popen(tmps, "r");
- if (fp) {
- sv_setpv(TARG, ""); /* note that this preserves previous buffer */
- if (GIMME == G_SCALAR) {
- while (sv_gets(TARG, fp, SvCUR(TARG)) != Nullch)
- /*SUPPRESS 530*/
- ;
- XPUSHs(TARG);
- }
- else {
- SV *sv;
-
- for (;;) {
- sv = NEWSV(56, 80);
- if (sv_gets(sv, fp, 0) == Nullch) {
- SvREFCNT_dec(sv);
- break;
- }
- XPUSHs(sv_2mortal(sv));
- if (SvLEN(sv) - SvCUR(sv) > 20) {
- SvLEN_set(sv, SvCUR(sv)+1);
- Renew(SvPVX(sv), SvLEN(sv), char);
- }
- }
- }
- statusvalue = my_pclose(fp);
- }
- else {
- statusvalue = -1;
- if (GIMME == G_SCALAR)
- RETPUSHUNDEF;
- }
+ stash = gv_stashsv(POPs, TRUE);
+ (void)sv_bless(TOPs, stash);
RETURN;
}
-OP *
-do_readline()
-{
- dSP; dTARGETSTACKED;
- register SV *sv;
- STRLEN tmplen;
- STRLEN offset;
- FILE *fp;
- register IO *io = GvIO(last_in_gv);
- register I32 type = op->op_type;
-
- fp = Nullfp;
- if (io) {
- fp = IoIFP(io);
- if (!fp) {
- if (IoFLAGS(io) & IOf_ARGV) {
- if (IoFLAGS(io) & IOf_START) {
- IoFLAGS(io) &= ~IOf_START;
- IoLINES(io) = 0;
- if (av_len(GvAVn(last_in_gv)) < 0) {
- SV *tmpstr = newSVpv("-", 1); /* assume stdin */
- (void)av_push(GvAVn(last_in_gv), tmpstr);
- }
- }
- fp = nextargv(last_in_gv);
- if (!fp) { /* Note: fp != IoIFP(io) */
- (void)do_close(last_in_gv, FALSE); /* now it does*/
- IoFLAGS(io) |= IOf_START;
- }
- }
- else if (type == OP_GLOB) {
- SV *tmpcmd = NEWSV(55, 0);
- SV *tmpglob = POPs;
- ENTER;
- SAVEFREESV(tmpcmd);
-#ifdef DOSISH
- sv_setpv(tmpcmd, "perlglob ");
- sv_catsv(tmpcmd, tmpglob);
- sv_catpv(tmpcmd, " |");
-#else
-#ifdef CSH
- sv_setpvn(tmpcmd, cshname, cshlen);
- sv_catpv(tmpcmd, " -cf 'set nonomatch; glob ");
- sv_catsv(tmpcmd, tmpglob);
- sv_catpv(tmpcmd, "'|");
-#else
- sv_setpv(tmpcmd, "echo ");
- sv_catsv(tmpcmd, tmpglob);
- sv_catpv(tmpcmd, "|tr -s ' \t\f\r' '\\012\\012\\012\\012'|");
-#endif /* !CSH */
-#endif /* !MSDOS */
- (void)do_open(last_in_gv, SvPVX(tmpcmd), SvCUR(tmpcmd));
- fp = IoIFP(io);
- LEAVE;
- }
- }
- else if (type == OP_GLOB)
- SP--;
- }
- if (!fp) {
- if (dowarn)
- warn("Read on closed filehandle <%s>", GvENAME(last_in_gv));
- if (GIMME == G_SCALAR)
- RETPUSHUNDEF;
- RETURN;
- }
- if (GIMME == G_ARRAY) {
- sv = sv_2mortal(NEWSV(57, 80));
- offset = 0;
- }
- else {
- sv = TARG;
- SvUPGRADE(sv, SVt_PV);
- tmplen = SvLEN(sv); /* remember if already alloced */
- if (!tmplen)
- Sv_Grow(sv, 80); /* try short-buffering it */
- if (type == OP_RCATLINE)
- offset = SvCUR(sv);
- else
- offset = 0;
- }
- for (;;) {
- if (!sv_gets(sv, fp, offset)) {
- clearerr(fp);
- if (IoFLAGS(io) & IOf_ARGV) {
- fp = nextargv(last_in_gv);
- if (fp)
- continue;
- (void)do_close(last_in_gv, FALSE);
- IoFLAGS(io) |= IOf_START;
- }
- else if (type == OP_GLOB) {
- (void)do_close(last_in_gv, FALSE);
- }
- if (GIMME == G_SCALAR)
- RETPUSHUNDEF;
- RETURN;
- }
- IoLINES(io)++;
- XPUSHs(sv);
- if (tainting) {
- tainted = TRUE;
- SvTAINT(sv); /* Anything from the outside world...*/
- }
- if (type == OP_GLOB) {
- char *tmps;
-
- if (SvCUR(sv) > 0)
- SvCUR(sv)--;
- if (*SvEND(sv) == rschar)
- *SvEND(sv) = '\0';
- else
- SvCUR(sv)++;
- for (tmps = SvPVX(sv); *tmps; tmps++)
- if (!isALPHA(*tmps) && !isDIGIT(*tmps) &&
- strchr("$&*(){}[]'\";\\|?<>~`", *tmps))
- break;
- if (*tmps && stat(SvPVX(sv), &statbuf) < 0) {
- POPs; /* Unmatched wildcard? Chuck it... */
- continue;
- }
- }
- if (GIMME == G_ARRAY) {
- if (SvLEN(sv) - SvCUR(sv) > 20) {
- SvLEN_set(sv, SvCUR(sv)+1);
- Renew(SvPVX(sv), SvLEN(sv), char);
- }
- sv = sv_2mortal(NEWSV(58, 80));
- continue;
- }
- else if (!tmplen && SvLEN(sv) - SvCUR(sv) > 80) {
- /* try to reclaim a bit of scalar space (only on 1st alloc) */
- if (SvCUR(sv) < 60)
- SvLEN_set(sv, 80);
- else
- SvLEN_set(sv, SvCUR(sv)+40); /* allow some slop */
- Renew(SvPVX(sv), SvLEN(sv), char);
- }
- RETURN;
- }
-}
-
-PP(pp_glob)
-{
- OP *result;
- ENTER;
- SAVEINT(rschar);
- SAVEINT(rslen);
-
- SAVESPTR(last_in_gv); /* We don't want this to be permanent. */
- last_in_gv = (GV*)*stack_sp--;
-
- rslen = 1;
-#ifdef DOSISH
- rschar = 0;
-#else
-#ifdef CSH
- rschar = 0;
-#else
- rschar = '\n';
-#endif /* !CSH */
-#endif /* !MSDOS */
- result = do_readline();
- LEAVE;
- return result;
-}
-
-PP(pp_readline)
-{
- last_in_gv = (GV*)(*stack_sp--);
- return do_readline();
-}
-
-PP(pp_indread)
-{
- last_in_gv = gv_fetchpv(SvPVx(GvSV((GV*)(*stack_sp--)), na), TRUE,SVt_PVIO);
- return do_readline();
-}
-
-PP(pp_rcatline)
-{
- last_in_gv = cGVOP->op_gv;
- return do_readline();
-}
-
-PP(pp_regcmaybe)
-{
- return NORMAL;
-}
-
-PP(pp_regcomp) {
- dSP;
- register PMOP *pm = (PMOP*)cLOGOP->op_other;
- register char *t;
- SV *tmpstr;
- STRLEN len;
-
- tmpstr = POPs;
- t = SvPV(tmpstr, len);
-
- if (pm->op_pmregexp) {
- regfree(pm->op_pmregexp);
- pm->op_pmregexp = Null(REGEXP*); /* crucial if regcomp aborts */
- }
-
- pm->op_pmregexp = regcomp(t, t + len, pm->op_pmflags & PMf_FOLD);
-
- if (!pm->op_pmregexp->prelen && curpm)
- pm = curpm;
- else if (strEQ("\\s+", pm->op_pmregexp->precomp))
- pm->op_pmflags |= PMf_WHITE;
-
- if (pm->op_pmflags & PMf_KEEP) {
- if (!(pm->op_pmflags & PMf_FOLD))
- scan_prefix(pm, pm->op_pmregexp->precomp,
- pm->op_pmregexp->prelen);
- pm->op_pmflags &= ~PMf_RUNTIME; /* no point compiling again */
- hoistmust(pm);
- cLOGOP->op_first->op_next = op->op_next;
- /* XXX delete push code? */
- }
- RETURN;
-}
+/* Pattern matching */
-PP(pp_match)
+PP(pp_study)
{
- dSP; dTARG;
- register PMOP *pm = cPMOP;
- register char *t;
- register char *s;
- char *strend;
- SV *tmpstr;
- I32 global;
- I32 safebase;
- char *truebase;
- register REGEXP *rx = pm->op_pmregexp;
- I32 gimme = GIMME;
+ dSP; dTARGET;
+ register unsigned char *s;
+ register I32 pos;
+ register I32 ch;
+ register I32 *sfirst;
+ register I32 *snext;
+ I32 retval;
STRLEN len;
- if (op->op_flags & OPf_STACKED)
- TARG = POPs;
- else {
- TARG = GvSV(defgv);
- EXTEND(SP,1);
- }
- s = SvPV(TARG, len);
- strend = s + len;
- if (!s)
- DIE("panic: do_match");
-
- if (pm->op_pmflags & PMf_USED) {
- if (gimme == G_ARRAY)
- RETURN;
- RETPUSHNO;
- }
-
- if (!rx->prelen && curpm) {
- pm = curpm;
- rx = pm->op_pmregexp;
- }
- truebase = t = s;
- if (global = pm->op_pmflags & PMf_GLOBAL) {
- rx->startp[0] = 0;
- if (SvTYPE(TARG) >= SVt_PVMG && SvMAGIC(TARG)) {
- MAGIC* mg = mg_find(TARG, 'g');
- if (mg && mg->mg_ptr) {
- rx->startp[0] = mg->mg_ptr;
- rx->endp[0] = mg->mg_ptr + mg->mg_len;
- }
- }
- }
- safebase = (gimme == G_ARRAY) || global;
-
-play_it_again:
- if (global && rx->startp[0]) {
- t = s = rx->endp[0];
- if (s == rx->startp[0])
- s++, t++;
- if (s > strend)
- goto nope;
- }
- if (pm->op_pmshort) {
- if (pm->op_pmflags & PMf_SCANFIRST) {
- if (SvSCREAM(TARG)) {
- if (screamfirst[BmRARE(pm->op_pmshort)] < 0)
- goto nope;
- else if (!(s = screaminstr(TARG, pm->op_pmshort)))
- goto nope;
- else if (pm->op_pmflags & PMf_ALL)
- goto yup;
- }
- else if (!(s = fbm_instr((unsigned char*)s,
- (unsigned char*)strend, pm->op_pmshort)))
- goto nope;
- else if (pm->op_pmflags & PMf_ALL)
- goto yup;
- if (s && rx->regback >= 0) {
- ++BmUSEFUL(pm->op_pmshort);
- s -= rx->regback;
- if (s < t)
- s = t;
- }
- else
- s = t;
- }
- else if (!multiline) {
- if (*SvPVX(pm->op_pmshort) != *s ||
- bcmp(SvPVX(pm->op_pmshort), s, pm->op_pmslen) ) {
- if (pm->op_pmflags & PMf_FOLD) {
- if (ibcmp(SvPVX(pm->op_pmshort), s, pm->op_pmslen) )
- goto nope;
- }
- else
- goto nope;
- }
- }
- if (--BmUSEFUL(pm->op_pmshort) < 0) {
- SvREFCNT_dec(pm->op_pmshort);
- pm->op_pmshort = Nullsv; /* opt is being useless */
- }
- }
- if (!rx->nparens && !global) {
- gimme = G_SCALAR; /* accidental array context? */
- safebase = FALSE;
- }
- if (regexec(rx, s, strend, truebase, 0,
- SvSCREAM(TARG) ? TARG : Nullsv,
- safebase)) {
- curpm = pm;
- if (pm->op_pmflags & PMf_ONCE)
- pm->op_pmflags |= PMf_USED;
- goto gotcha;
+ s = (unsigned char*)(SvPV(TARG, len));
+ pos = len;
+ if (lastscream)
+ SvSCREAM_off(lastscream);
+ lastscream = TARG;
+ if (pos <= 0) {
+ retval = 0;
+ goto ret;
}
- else
- goto ret_no;
- /*NOTREACHED*/
-
- gotcha:
- if (gimme == G_ARRAY) {
- I32 iters, i, len;
-
- iters = rx->nparens;
- if (global && !iters)
- i = 1;
- else
- i = 0;
- EXTEND(SP, iters + i);
- for (i = !i; i <= iters; i++) {
- PUSHs(sv_newmortal());
- /*SUPPRESS 560*/
- if (s = rx->startp[i]) {
- len = rx->endp[i] - s;
- if (len > 0)
- sv_setpvn(*SP, s, len);
- }
- }
- if (global) {
- truebase = rx->subbeg;
- goto play_it_again;
+ if (pos > maxscream) {
+ if (maxscream < 0) {
+ maxscream = pos + 80;
+ New(301, screamfirst, 256, I32);
+ New(302, screamnext, maxscream, I32);
}
- RETURN;
- }
- else {
- if (global) {
- MAGIC* mg = 0;
- if (SvTYPE(TARG) >= SVt_PVMG && SvMAGIC(TARG))
- mg = mg_find(TARG, 'g');
- if (!mg) {
- sv_magic(TARG, (SV*)0, 'g', Nullch, 0);
- mg = mg_find(TARG, 'g');
- }
- mg->mg_ptr = rx->startp[0];
- mg->mg_len = rx->endp[0] - rx->startp[0];
+ else {
+ maxscream = pos + pos / 4;
+ Renew(screamnext, maxscream, I32);
}
- RETPUSHYES;
- }
-
-yup:
- ++BmUSEFUL(pm->op_pmshort);
- curpm = pm;
- if (pm->op_pmflags & PMf_ONCE)
- pm->op_pmflags |= PMf_USED;
- if (global) {
- rx->subbeg = truebase;
- rx->subend = strend;
- rx->startp[0] = s;
- rx->endp[0] = s + SvCUR(pm->op_pmshort);
- goto gotcha;
}
- if (sawampersand) {
- char *tmps;
-
- if (rx->subbase)
- Safefree(rx->subbase);
- tmps = rx->subbase = nsavestr(t, strend-t);
- rx->subbeg = tmps;
- rx->subend = tmps + (strend-t);
- tmps = rx->startp[0] = tmps + (s - t);
- rx->endp[0] = tmps + SvCUR(pm->op_pmshort);
- }
- RETPUSHYES;
-nope:
- if (pm->op_pmshort)
- ++BmUSEFUL(pm->op_pmshort);
-
-ret_no:
- if (global) {
- if (SvTYPE(TARG) >= SVt_PVMG && SvMAGIC(TARG)) {
- MAGIC* mg = mg_find(TARG, 'g');
- if (mg) {
- mg->mg_ptr = 0;
- mg->mg_len = 0;
- }
- }
- }
- if (gimme == G_ARRAY)
- RETURN;
- RETPUSHNO;
-}
+ sfirst = screamfirst;
+ snext = screamnext;
-PP(pp_subst)
-{
- dSP; dTARG;
- register PMOP *pm = cPMOP;
- PMOP *rpm = pm;
- register SV *dstr;
- register char *s;
- char *strend;
- register char *m;
- char *c;
- register char *d;
- STRLEN clen;
- I32 iters = 0;
- I32 maxiters;
- register I32 i;
- bool once;
- char *orig;
- I32 safebase;
- register REGEXP *rx = pm->op_pmregexp;
- STRLEN len;
+ if (!sfirst || !snext)
+ DIE("do_study: out of memory");
- if (pm->op_pmflags & PMf_CONST) /* known replacement string? */
- dstr = POPs;
- if (op->op_flags & OPf_STACKED)
- TARG = POPs;
- else {
- TARG = GvSV(defgv);
- EXTEND(SP,1);
- }
- s = SvPV(TARG, len);
- if (!pm || !s)
- DIE("panic: do_subst");
+ for (ch = 256; ch; --ch)
+ *sfirst++ = -1;
+ sfirst -= 256;
- strend = s + len;
- maxiters = (strend - s) + 10;
+ while (--pos >= 0) {
+ ch = s[pos];
+ if (sfirst[ch] >= 0)
+ snext[pos] = sfirst[ch] - pos;
+ else
+ snext[pos] = -pos;
+ sfirst[ch] = pos;
- if (!rx->prelen && curpm) {
- pm = curpm;
- rx = pm->op_pmregexp;
- }
- safebase = ((!rx || !rx->nparens) && !sawampersand);
- orig = m = s;
- if (pm->op_pmshort) {
- if (pm->op_pmflags & PMf_SCANFIRST) {
- if (SvSCREAM(TARG)) {
- if (screamfirst[BmRARE(pm->op_pmshort)] < 0)
- goto nope;
- else if (!(s = screaminstr(TARG, pm->op_pmshort)))
- goto nope;
- }
- else if (!(s = fbm_instr((unsigned char*)s, (unsigned char*)strend,
- pm->op_pmshort)))
- goto nope;
- if (s && rx->regback >= 0) {
- ++BmUSEFUL(pm->op_pmshort);
- s -= rx->regback;
- if (s < m)
- s = m;
- }
- else
- s = m;
- }
- else if (!multiline) {
- if (*SvPVX(pm->op_pmshort) != *s ||
- bcmp(SvPVX(pm->op_pmshort), s, pm->op_pmslen) ) {
- if (pm->op_pmflags & PMf_FOLD) {
- if (ibcmp(SvPVX(pm->op_pmshort), s, pm->op_pmslen) )
- goto nope;
- }
- else
- goto nope;
- }
- }
- if (--BmUSEFUL(pm->op_pmshort) < 0) {
- SvREFCNT_dec(pm->op_pmshort);
- pm->op_pmshort = Nullsv; /* opt is being useless */
- }
- }
- once = !(rpm->op_pmflags & PMf_GLOBAL);
- if (rpm->op_pmflags & PMf_CONST) { /* known replacement string? */
- c = SvPV(dstr, clen);
- if (clen <= rx->minlen) {
- /* can do inplace substitution */
- if (regexec(rx, s, strend, orig, 0,
- SvSCREAM(TARG) ? TARG : Nullsv, safebase)) {
- if (rx->subbase) /* oops, no we can't */
- goto long_way;
- d = s;
- curpm = pm;
- SvSCREAM_off(TARG); /* disable possible screamer */
- if (once) {
- m = rx->startp[0];
- d = rx->endp[0];
- s = orig;
- if (m - s > strend - d) { /* faster to shorten from end */
- if (clen) {
- Copy(c, m, clen, char);
- m += clen;
- }
- i = strend - d;
- if (i > 0) {
- Move(d, m, i, char);
- m += i;
- }
- *m = '\0';
- SvCUR_set(TARG, m - s);
- SvPOK_only(TARG);
- SvSETMAGIC(TARG);
- PUSHs(&sv_yes);
- RETURN;
- }
- /*SUPPRESS 560*/
- else if (i = m - s) { /* faster from front */
- d -= clen;
- m = d;
- sv_chop(TARG, d-i);
- s += i;
- while (i--)
- *--d = *--s;
- if (clen)
- Copy(c, m, clen, char);
- SvPOK_only(TARG);
- SvSETMAGIC(TARG);
- PUSHs(&sv_yes);
- RETURN;
- }
- else if (clen) {
- d -= clen;
- sv_chop(TARG, d);
- Copy(c, d, clen, char);
- SvPOK_only(TARG);
- SvSETMAGIC(TARG);
- PUSHs(&sv_yes);
- RETURN;
- }
- else {
- sv_chop(TARG, d);
- SvPOK_only(TARG);
- SvSETMAGIC(TARG);
- PUSHs(&sv_yes);
- RETURN;
- }
- /* NOTREACHED */
- }
- do {
- if (iters++ > maxiters)
- DIE("Substitution loop");
- m = rx->startp[0];
- /*SUPPRESS 560*/
- if (i = m - s) {
- if (s != d)
- Move(s, d, i, char);
- d += i;
- }
- if (clen) {
- Copy(c, d, clen, char);
- d += clen;
- }
- s = rx->endp[0];
- } while (regexec(rx, s, strend, orig, s == m,
- Nullsv, TRUE)); /* (don't match same null twice) */
- if (s != d) {
- i = strend - s;
- SvCUR_set(TARG, d - SvPVX(TARG) + i);
- Move(s, d, i+1, char); /* include the Null */
- }
- SvPOK_only(TARG);
- SvSETMAGIC(TARG);
- PUSHs(sv_2mortal(newSViv((I32)iters)));
- RETURN;
- }
- PUSHs(&sv_no);
- RETURN;
- }
- }
- else
- c = Nullch;
- if (regexec(rx, s, strend, orig, 0,
- SvSCREAM(TARG) ? TARG : Nullsv, safebase)) {
- long_way:
- dstr = NEWSV(25, sv_len(TARG));
- sv_setpvn(dstr, m, s-m);
- curpm = pm;
- if (!c) {
- register CONTEXT *cx;
- PUSHSUBST(cx);
- RETURNOP(cPMOP->op_pmreplroot);
- }
- do {
- if (iters++ > maxiters)
- DIE("Substitution loop");
- if (rx->subbase && rx->subbase != orig) {
- m = s;
- s = orig;
- orig = rx->subbase;
- s = orig + (m - s);
- strend = s + (strend - m);
- }
- m = rx->startp[0];
- sv_catpvn(dstr, s, m-s);
- s = rx->endp[0];
- if (clen)
- sv_catpvn(dstr, c, clen);
- if (once)
- break;
- } while (regexec(rx, s, strend, orig, s == m, Nullsv,
- safebase));
- sv_catpvn(dstr, s, strend - s);
- sv_replace(TARG, dstr);
- SvPOK_only(TARG);
- SvSETMAGIC(TARG);
- PUSHs(sv_2mortal(newSViv((I32)iters)));
- RETURN;
+ /* If there were any case insensitive searches, we must assume they
+ * all are. This speeds up insensitive searches much more than
+ * it slows down sensitive ones.
+ */
+ if (sawi)
+ sfirst[fold[ch]] = pos;
}
- PUSHs(&sv_no);
- RETURN;
-nope:
- ++BmUSEFUL(pm->op_pmshort);
- PUSHs(&sv_no);
+ SvSCREAM_on(TARG);
+ retval = 1;
+ ret:
+ XPUSHs(sv_2mortal(newSViv((I32)retval)));
RETURN;
}
-PP(pp_substcont)
-{
- dSP;
- register PMOP *pm = (PMOP*) cLOGOP->op_other;
- register CONTEXT *cx = &cxstack[cxstack_ix];
- register SV *dstr = cx->sb_dstr;
- register char *s = cx->sb_s;
- register char *m = cx->sb_m;
- char *orig = cx->sb_orig;
- register REGEXP *rx = pm->op_pmregexp;
-
- if (cx->sb_iters++) {
- if (cx->sb_iters > cx->sb_maxiters)
- DIE("Substitution loop");
-
- sv_catsv(dstr, POPs);
- if (rx->subbase)
- Safefree(rx->subbase);
- rx->subbase = cx->sb_subbase;
-
- /* Are we done */
- if (cx->sb_once || !regexec(rx, s, cx->sb_strend, orig,
- s == m, Nullsv, cx->sb_safebase))
- {
- SV *targ = cx->sb_targ;
- sv_catpvn(dstr, s, cx->sb_strend - s);
- sv_replace(targ, dstr);
- SvPOK_only(targ);
- SvSETMAGIC(targ);
- PUSHs(sv_2mortal(newSViv((I32)cx->sb_iters - 1)));
- POPSUBST(cx);
- RETURNOP(pm->op_next);
- }
- }
- if (rx->subbase && rx->subbase != orig) {
- m = s;
- s = orig;
- cx->sb_orig = orig = rx->subbase;
- s = orig + (m - s);
- cx->sb_strend = s + (cx->sb_strend - m);
- }
- cx->sb_m = m = rx->startp[0];
- sv_catpvn(dstr, s, m-s);
- cx->sb_s = rx->endp[0];
- cx->sb_subbase = rx->subbase;
-
- rx->subbase = Nullch; /* so recursion works */
- RETURNOP(pm->op_pmreplstart);
-}
-
PP(pp_trans)
{
dSP; dTARG;
@@ -1253,221 +423,38 @@ PP(pp_trans)
/* Lvalue operators. */
-PP(pp_sassign)
+PP(pp_schop)
{
- dSP; dPOPTOPssrl;
- if (tainting && tainted && (!SvRMAGICAL(lstr) || !mg_find(lstr, 't'))) {
- TAINT_NOT;
- }
- SvSetSV(rstr, lstr);
- SvSETMAGIC(rstr);
- SETs(rstr);
+ dSP; dTARGET;
+ do_chop(TARG, TOPs);
+ SETTARG;
RETURN;
}
-PP(pp_aassign)
+PP(pp_chop)
{
- dSP;
- SV **lastlelem = stack_sp;
- SV **lastrelem = stack_base + POPMARK;
- SV **firstrelem = stack_base + POPMARK + 1;
- SV **firstlelem = lastrelem + 1;
-
- register SV **relem;
- register SV **lelem;
-
- register SV *sv;
- register AV *ary;
-
- HV *hash;
- I32 i;
- int magic;
-
- delaymagic = DM_DELAY; /* catch simultaneous items */
-
- /* If there's a common identifier on both sides we have to take
- * special care that assigning the identifier on the left doesn't
- * clobber a value on the right that's used later in the list.
- */
- if (op->op_private & OPpASSIGN_COMMON) {
- for (relem = firstrelem; relem <= lastrelem; relem++) {
- /*SUPPRESS 560*/
- if (sv = *relem)
- *relem = sv_mortalcopy(sv);
- }
- }
-
- relem = firstrelem;
- lelem = firstlelem;
- ary = Null(AV*);
- hash = Null(HV*);
- while (lelem <= lastlelem) {
- sv = *lelem++;
- switch (SvTYPE(sv)) {
- case SVt_PVAV:
- ary = (AV*)sv;
- magic = SvSMAGICAL(ary) != 0;
- AvREAL_on(ary);
- AvFILL(ary) = -1;
- i = 0;
- while (relem <= lastrelem) { /* gobble up all the rest */
- sv = NEWSV(28,0);
- if (*relem)
- sv_setsv(sv,*relem);
- *(relem++) = sv;
- (void)av_store(ary,i++,sv);
- if (magic)
- mg_set(sv);
- }
- break;
- case SVt_PVHV: {
- char *tmps;
- SV *tmpstr;
-
- hash = (HV*)sv;
- magic = SvSMAGICAL(hash) != 0;
- hv_clear(hash);
-
- while (relem < lastrelem) { /* gobble up all the rest */
- STRLEN len;
- if (*relem)
- sv = *(relem++);
- else
- sv = &sv_no, relem++;
- tmps = SvPV(sv, len);
- tmpstr = NEWSV(29,0);
- if (*relem)
- sv_setsv(tmpstr,*relem); /* value */
- *(relem++) = tmpstr;
- (void)hv_store(hash,tmps,len,tmpstr,0);
- if (magic)
- mg_set(tmpstr);
- }
- }
- break;
- default:
- if (SvTHINKFIRST(sv)) {
- if (SvREADONLY(sv) && curcop != &compiling) {
- if (sv != &sv_undef && sv != &sv_yes && sv != &sv_no)
- DIE(no_modify);
- if (relem <= lastrelem)
- relem++;
- break;
- }
- if (SvROK(sv))
- sv_unref(sv);
- }
- if (relem <= lastrelem) {
- sv_setsv(sv, *relem);
- *(relem++) = sv;
- }
- else
- sv_setsv(sv, &sv_undef);
- SvSETMAGIC(sv);
- break;
- }
- }
- if (delaymagic & ~DM_DELAY) {
- if (delaymagic & DM_UID) {
-#ifdef HAS_SETRESUID
- (void)setresuid(uid,euid,(Uid_t)-1);
-#else /* not HAS_SETRESUID */
-#ifdef HAS_SETREUID
- (void)setreuid(uid,euid);
-#else /* not HAS_SETREUID */
-#ifdef HAS_SETRUID
- if ((delaymagic & DM_UID) == DM_RUID) {
- (void)setruid(uid);
- delaymagic =~ DM_RUID;
- }
-#endif /* HAS_SETRUID */
-#endif /* HAS_SETRESUID */
-#ifdef HAS_SETEUID
- if ((delaymagic & DM_UID) == DM_EUID) {
- (void)seteuid(uid);
- delaymagic =~ DM_EUID;
- }
-#endif /* HAS_SETEUID */
- if (delaymagic & DM_UID) {
- if (uid != euid)
- DIE("No setreuid available");
- (void)setuid(uid);
- }
-#endif /* not HAS_SETREUID */
- uid = (int)getuid();
- euid = (int)geteuid();
- }
- if (delaymagic & DM_GID) {
-#ifdef HAS_SETRESGID
- (void)setresgid(gid,egid,(Gid_t)-1);
-#else /* not HAS_SETREGID */
-#ifdef HAS_SETREGID
- (void)setregid(gid,egid);
-#else /* not HAS_SETREGID */
-#endif /* not HAS_SETRESGID */
-#ifdef HAS_SETRGID
- if ((delaymagic & DM_GID) == DM_RGID) {
- (void)setrgid(gid);
- delaymagic =~ DM_RGID;
- }
-#endif /* HAS_SETRGID */
-#ifdef HAS_SETRESGID
- (void)setresgid(gid,egid,(Gid_t)-1);
-#else /* not HAS_SETREGID */
-#ifdef HAS_SETEGID
- if ((delaymagic & DM_GID) == DM_EGID) {
- (void)setegid(gid);
- delaymagic =~ DM_EGID;
- }
-#endif /* HAS_SETEGID */
- if (delaymagic & DM_GID) {
- if (gid != egid)
- DIE("No setregid available");
- (void)setgid(gid);
- }
-#endif /* not HAS_SETRESGID */
-#endif /* not HAS_SETREGID */
- gid = (int)getgid();
- egid = (int)getegid();
- }
- tainting |= (euid != uid || egid != gid);
- }
- delaymagic = 0;
- if (GIMME == G_ARRAY) {
- if (ary || hash)
- SP = lastrelem;
- else
- SP = firstrelem + (lastlelem - firstlelem);
- RETURN;
- }
- else {
- dTARGET;
- SP = firstrelem;
- SETi(lastrelem - firstrelem + 1);
- RETURN;
- }
+ dSP; dMARK; dTARGET;
+ while (SP > MARK)
+ do_chop(TARG, POPs);
+ PUSHTARG;
+ RETURN;
}
-PP(pp_schop)
+PP(pp_schomp)
{
dSP; dTARGET;
- SV *sv;
-
- if (MAXARG < 1)
- sv = GvSV(defgv);
- else
- sv = POPs;
- do_chop(TARG, sv);
- PUSHTARG;
+ SETi(do_chomp(TOPs));
RETURN;
}
-PP(pp_chop)
+PP(pp_chomp)
{
dSP; dMARK; dTARGET;
+ register I32 count = 0;
+
while (SP > MARK)
- do_chop(TARG, POPs);
- PUSHTARG;
+ count += do_chomp(POPs);
+ PUSHi(count);
RETURN;
}
@@ -1476,12 +463,7 @@ PP(pp_defined)
dSP;
register SV* sv;
- if (MAXARG < 1) {
- sv = GvSV(defgv);
- EXTEND(SP, 1);
- }
- else
- sv = POPs;
+ sv = POPs;
if (!sv || !SvANY(sv))
RETPUSHNO;
switch (SvTYPE(sv)) {
@@ -1494,10 +476,12 @@ PP(pp_defined)
RETPUSHYES;
break;
case SVt_PVCV:
- if (CvROOT(sv))
+ if (CvROOT(sv) || CvXSUB(sv))
RETPUSHYES;
break;
default:
+ if (SvGMAGICAL(sv))
+ mg_get(sv);
if (SvOK(sv))
RETPUSHYES;
}
@@ -1533,18 +517,18 @@ PP(pp_undef)
hv_undef((HV*)sv);
break;
case SVt_PVCV:
- sub_generation++;
cv_undef((CV*)sv);
+ sub_generation++;
break;
default:
if (sv != GvSV(defgv)) {
if (SvPOK(sv) && SvLEN(sv)) {
- SvOOK_off(sv);
+ (void)SvOOK_off(sv);
Safefree(SvPVX(sv));
SvPV_set(sv, Nullch);
SvLEN_set(sv, 0);
}
- SvOK_off(sv);
+ (void)SvOK_off(sv);
SvSETMAGIC(sv);
}
}
@@ -1552,79 +536,6 @@ PP(pp_undef)
RETPUSHUNDEF;
}
-PP(pp_study)
-{
- dSP; dTARGET;
- register unsigned char *s;
- register I32 pos;
- register I32 ch;
- register I32 *sfirst;
- register I32 *snext;
- I32 retval;
- STRLEN len;
-
- s = (unsigned char*)(SvPV(TARG, len));
- pos = len;
- if (lastscream)
- SvSCREAM_off(lastscream);
- lastscream = TARG;
- if (pos <= 0) {
- retval = 0;
- goto ret;
- }
- if (pos > maxscream) {
- if (maxscream < 0) {
- maxscream = pos + 80;
- New(301, screamfirst, 256, I32);
- New(302, screamnext, maxscream, I32);
- }
- else {
- maxscream = pos + pos / 4;
- Renew(screamnext, maxscream, I32);
- }
- }
-
- sfirst = screamfirst;
- snext = screamnext;
-
- if (!sfirst || !snext)
- DIE("do_study: out of memory");
-
- for (ch = 256; ch; --ch)
- *sfirst++ = -1;
- sfirst -= 256;
-
- while (--pos >= 0) {
- ch = s[pos];
- if (sfirst[ch] >= 0)
- snext[pos] = sfirst[ch] - pos;
- else
- snext[pos] = -pos;
- sfirst[ch] = pos;
-
- /* If there were any case insensitive searches, we must assume they
- * all are. This speeds up insensitive searches much more than
- * it slows down sensitive ones.
- */
- if (sawi)
- sfirst[fold[ch]] = pos;
- }
-
- SvSCREAM_on(TARG);
- retval = 1;
- ret:
- XPUSHs(sv_2mortal(newSViv((I32)retval)));
- RETURN;
-}
-
-PP(pp_preinc)
-{
- dSP;
- sv_inc(TOPs);
- SvSETMAGIC(TOPs);
- return NORMAL;
-}
-
PP(pp_predec)
{
dSP;
@@ -1659,63 +570,74 @@ PP(pp_postdec)
PP(pp_pow)
{
- dSP; dATARGET; dPOPTOPnnrl;
- SETn( pow( left, right) );
- RETURN;
+ dSP; dATARGET; tryAMAGICbin(pow,opASSIGN);
+ {
+ dPOPTOPnnrl;
+ SETn( pow( left, right) );
+ RETURN;
+ }
}
PP(pp_multiply)
{
- dSP; dATARGET; dPOPTOPnnrl;
- SETn( left * right );
- RETURN;
+ dSP; dATARGET; tryAMAGICbin(mult,opASSIGN);
+ {
+ dPOPTOPnnrl;
+ SETn( left * right );
+ RETURN;
+ }
}
PP(pp_divide)
{
- dSP; dATARGET; dPOPnv;
- if (value == 0.0)
+ dSP; dATARGET; tryAMAGICbin(div,opASSIGN);
+ {
+ dPOPnv;
+ if (value == 0.0)
DIE("Illegal division by zero");
#ifdef SLOPPYDIVIDE
- /* insure that 20./5. == 4. */
- {
+ /* insure that 20./5. == 4. */
+ {
double x;
I32 k;
x = POPn;
- if ((double)(I32)x == x &&
- (double)(I32)value == value &&
- (k = (I32)x/(I32)value)*(I32)value == (I32)x) {
+ if ((double)I_32(x) == x &&
+ (double)I_32(value) == value &&
+ (k = I_32(x)/I_32(value))*I_32(value) == I_32(x)) {
value = k;
} else {
value = x/value;
}
- }
+ }
#else
- value = POPn / value;
+ value = POPn / value;
#endif
- PUSHn( value );
- RETURN;
+ PUSHn( value );
+ RETURN;
+ }
}
PP(pp_modulo)
{
- dSP; dATARGET;
- register unsigned long tmpulong;
- register long tmplong;
- I32 value;
+ dSP; dATARGET; tryAMAGICbin(mod,opASSIGN);
+ {
+ register unsigned long tmpulong;
+ register long tmplong;
+ I32 value;
- tmpulong = (unsigned long) POPn;
- if (tmpulong == 0L)
+ tmpulong = (unsigned long) POPn;
+ if (tmpulong == 0L)
DIE("Illegal modulus zero");
- value = TOPn;
- if (value >= 0.0)
+ value = TOPn;
+ if (value >= 0.0)
value = (I32)(((unsigned long)value) % tmpulong);
- else {
+ else {
tmplong = (long)value;
value = (I32)(tmpulong - ((-tmplong - 1) % tmpulong)) - 1;
+ }
+ SETi(value);
+ RETURN;
}
- SETi(value);
- RETURN;
}
PP(pp_repeat)
@@ -1738,12 +660,14 @@ PP(pp_repeat)
MARK++;
repeatcpy((char*)(MARK + items), (char*)MARK,
items * sizeof(SV*), count - 1);
+ SP += max;
}
- SP += max;
+ else if (count <= 0)
+ SP -= items;
}
else { /* Note: mark already snarfed by pp_list */
SV *tmpstr;
- char *tmps;
+ STRLEN len;
tmpstr = POPs;
if (TARG == tmpstr && SvTHINKFIRST(tmpstr)) {
@@ -1753,19 +677,14 @@ PP(pp_repeat)
sv_unref(tmpstr);
}
SvSetSV(TARG, tmpstr);
+ SvPV_force(TARG, len);
if (count >= 1) {
- STRLEN len;
- STRLEN tlen;
- tmpstr = NEWSV(50, 0);
- tmps = SvPV(TARG, len);
- sv_setpvn(tmpstr, tmps, len);
- tmps = SvPV(tmpstr, tlen); /* force to be string */
SvGROW(TARG, (count * len) + 1);
- repeatcpy((char*)SvPVX(TARG), tmps, tlen, count);
+ if (count > 1)
+ repeatcpy(SvPVX(TARG) + len, SvPVX(TARG), len, count - 1);
SvCUR(TARG) *= count;
*SvEND(TARG) = '\0';
- SvPOK_only(TARG);
- SvREFCNT_dec(tmpstr);
+ (void)SvPOK_only(TARG);
}
else
sv_setsv(TARG, &sv_no);
@@ -1774,228 +693,269 @@ PP(pp_repeat)
RETURN;
}
-PP(pp_add)
-{
- dSP; dATARGET; dPOPTOPnnrl;
- SETn( left + right );
- RETURN;
-}
-
PP(pp_subtract)
{
- dSP; dATARGET; dPOPTOPnnrl;
- SETn( left - right );
- RETURN;
-}
-
-PP(pp_concat)
-{
- dSP; dATARGET; dPOPTOPssrl;
- STRLEN len;
- char *s;
- if (TARG != lstr) {
- s = SvPV(lstr,len);
- sv_setpvn(TARG,s,len);
+ dSP; dATARGET; tryAMAGICbin(subtr,opASSIGN);
+ {
+ dPOPTOPnnrl;
+ SETn( left - right );
+ RETURN;
}
- s = SvPV(rstr,len);
- sv_catpvn(TARG,s,len);
- SETTARG;
- RETURN;
}
PP(pp_left_shift)
{
- dSP; dATARGET; dPOPTOPiirl;
- SETi( left << right );
- RETURN;
+ dSP; dATARGET; tryAMAGICbin(lshift,opASSIGN);
+ {
+ dPOPTOPiirl;
+ SETi( left << right );
+ RETURN;
+ }
}
PP(pp_right_shift)
{
- dSP; dATARGET; dPOPTOPiirl;
- SETi( left >> right );
- RETURN;
+ dSP; dATARGET; tryAMAGICbin(rshift,opASSIGN);
+ {
+ dPOPTOPiirl;
+ SETi( left >> right );
+ RETURN;
+ }
}
PP(pp_lt)
{
- dSP; dPOPnv;
- SETs((TOPn < value) ? &sv_yes : &sv_no);
- RETURN;
+ dSP; tryAMAGICbinSET(lt,0);
+ {
+ dPOPnv;
+ SETs((TOPn < value) ? &sv_yes : &sv_no);
+ RETURN;
+ }
}
PP(pp_gt)
{
- dSP; dPOPnv;
- SETs((TOPn > value) ? &sv_yes : &sv_no);
- RETURN;
+ dSP; tryAMAGICbinSET(gt,0);
+ {
+ dPOPnv;
+ SETs((TOPn > value) ? &sv_yes : &sv_no);
+ RETURN;
+ }
}
PP(pp_le)
{
- dSP; dPOPnv;
- SETs((TOPn <= value) ? &sv_yes : &sv_no);
- RETURN;
+ dSP; tryAMAGICbinSET(le,0);
+ {
+ dPOPnv;
+ SETs((TOPn <= value) ? &sv_yes : &sv_no);
+ RETURN;
+ }
}
PP(pp_ge)
{
- dSP; dPOPnv;
- SETs((TOPn >= value) ? &sv_yes : &sv_no);
- RETURN;
-}
-
-PP(pp_eq)
-{
- dSP; dPOPnv;
- SETs((TOPn == value) ? &sv_yes : &sv_no);
- RETURN;
+ dSP; tryAMAGICbinSET(ge,0);
+ {
+ dPOPnv;
+ SETs((TOPn >= value) ? &sv_yes : &sv_no);
+ RETURN;
+ }
}
PP(pp_ne)
{
- dSP; dPOPnv;
- SETs((TOPn != value) ? &sv_yes : &sv_no);
- RETURN;
+ dSP; tryAMAGICbinSET(ne,0);
+ {
+ dPOPnv;
+ SETs((TOPn != value) ? &sv_yes : &sv_no);
+ RETURN;
+ }
}
PP(pp_ncmp)
{
- dSP; dTARGET; dPOPTOPnnrl;
- I32 value;
+ dSP; dTARGET; tryAMAGICbin(ncmp,0);
+ {
+ dPOPTOPnnrl;
+ I32 value;
- if (left > right)
+ if (left > right)
value = 1;
- else if (left < right)
+ else if (left < right)
value = -1;
- else
+ else
value = 0;
- SETi(value);
- RETURN;
+ SETi(value);
+ RETURN;
+ }
}
PP(pp_slt)
{
- dSP; dPOPTOPssrl;
- SETs( sv_cmp(lstr, rstr) < 0 ? &sv_yes : &sv_no );
- RETURN;
+ dSP; tryAMAGICbinSET(slt,0);
+ {
+ dPOPTOPssrl;
+ SETs( sv_cmp(left, right) < 0 ? &sv_yes : &sv_no );
+ RETURN;
+ }
}
PP(pp_sgt)
{
- dSP; dPOPTOPssrl;
- SETs( sv_cmp(lstr, rstr) > 0 ? &sv_yes : &sv_no );
- RETURN;
+ dSP; tryAMAGICbinSET(sgt,0);
+ {
+ dPOPTOPssrl;
+ SETs( sv_cmp(left, right) > 0 ? &sv_yes : &sv_no );
+ RETURN;
+ }
}
PP(pp_sle)
{
- dSP; dPOPTOPssrl;
- SETs( sv_cmp(lstr, rstr) <= 0 ? &sv_yes : &sv_no );
- RETURN;
+ dSP; tryAMAGICbinSET(sle,0);
+ {
+ dPOPTOPssrl;
+ SETs( sv_cmp(left, right) <= 0 ? &sv_yes : &sv_no );
+ RETURN;
+ }
}
PP(pp_sge)
{
- dSP; dPOPTOPssrl;
- SETs( sv_cmp(lstr, rstr) >= 0 ? &sv_yes : &sv_no );
- RETURN;
-}
-
-PP(pp_seq)
-{
- dSP; dPOPTOPssrl;
- SETs( sv_eq(lstr, rstr) ? &sv_yes : &sv_no );
- RETURN;
+ dSP; tryAMAGICbinSET(sge,0);
+ {
+ dPOPTOPssrl;
+ SETs( sv_cmp(left, right) >= 0 ? &sv_yes : &sv_no );
+ RETURN;
+ }
}
PP(pp_sne)
{
- dSP; dPOPTOPssrl;
- SETs( !sv_eq(lstr, rstr) ? &sv_yes : &sv_no );
- RETURN;
+ dSP; tryAMAGICbinSET(sne,0);
+ {
+ dPOPTOPssrl;
+ SETs( !sv_eq(left, right) ? &sv_yes : &sv_no );
+ RETURN;
+ }
}
PP(pp_scmp)
{
- dSP; dTARGET;
- dPOPTOPssrl;
- SETi( sv_cmp(lstr, rstr) );
- RETURN;
+ dSP; dTARGET; tryAMAGICbin(scmp,0);
+ {
+ dPOPTOPssrl;
+ SETi( sv_cmp(left, right) );
+ RETURN;
+ }
}
PP(pp_bit_and) {
- dSP; dATARGET; dPOPTOPssrl;
- if (SvNIOK(lstr) || SvNIOK(rstr)) {
- unsigned long value = U_L(SvNV(lstr));
- value = value & U_L(SvNV(rstr));
+ dSP; dATARGET; tryAMAGICbin(band,opASSIGN);
+ {
+ dPOPTOPssrl;
+ if (SvNIOK(left) || SvNIOK(right)) {
+ unsigned long value = U_L(SvNV(left));
+ value = value & U_L(SvNV(right));
SETn((double)value);
- }
- else {
- do_vop(op->op_type, TARG, lstr, rstr);
+ }
+ else {
+ do_vop(op->op_type, TARG, left, right);
SETTARG;
+ }
+ RETURN;
}
- RETURN;
}
-PP(pp_xor)
+PP(pp_bit_xor)
{
- dSP; dATARGET; dPOPTOPssrl;
- if (SvNIOK(lstr) || SvNIOK(rstr)) {
- unsigned long value = U_L(SvNV(lstr));
- value = value ^ U_L(SvNV(rstr));
+ dSP; dATARGET; tryAMAGICbin(bxor,opASSIGN);
+ {
+ dPOPTOPssrl;
+ if (SvNIOK(left) || SvNIOK(right)) {
+ unsigned long value = U_L(SvNV(left));
+ value = value ^ U_L(SvNV(right));
SETn((double)value);
- }
- else {
- do_vop(op->op_type, TARG, lstr, rstr);
+ }
+ else {
+ do_vop(op->op_type, TARG, left, right);
SETTARG;
+ }
+ RETURN;
}
- RETURN;
}
PP(pp_bit_or)
{
- dSP; dATARGET; dPOPTOPssrl;
- if (SvNIOK(lstr) || SvNIOK(rstr)) {
- unsigned long value = U_L(SvNV(lstr));
- value = value | U_L(SvNV(rstr));
+ dSP; dATARGET; tryAMAGICbin(bor,opASSIGN);
+ {
+ dPOPTOPssrl;
+ if (SvNIOK(left) || SvNIOK(right)) {
+ unsigned long value = U_L(SvNV(left));
+ value = value | U_L(SvNV(right));
SETn((double)value);
- }
- else {
- do_vop(op->op_type, TARG, lstr, rstr);
+ }
+ else {
+ do_vop(op->op_type, TARG, left, right);
SETTARG;
+ }
+ RETURN;
}
- RETURN;
}
PP(pp_negate)
{
- dSP; dTARGET;
- SETn(-TOPn);
+ dSP; dTARGET; tryAMAGICun(neg);
+ {
+ dTOPss;
+ if (SvNIOK(sv))
+ SETn(-SvNV(sv));
+ else if (SvPOK(sv)) {
+ STRLEN len;
+ char *s = SvPV(sv, len);
+ if (isALPHA(*s) || *s == '_') {
+ sv_setpvn(TARG, "-", 1);
+ sv_catsv(TARG, sv);
+ }
+ else if (*s == '+' || *s == '-') {
+ sv_setsv(TARG, sv);
+ *SvPV_force(TARG, len) = *s == '-' ? '+' : '-';
+ }
+ else
+ sv_setnv(TARG, -SvNV(sv));
+ SETTARG;
+ }
+ }
RETURN;
}
PP(pp_not)
{
+#ifdef OVERLOAD
+ dSP; tryAMAGICunSET(not);
+#endif /* OVERLOAD */
*stack_sp = SvTRUE(*stack_sp) ? &sv_no : &sv_yes;
return NORMAL;
}
PP(pp_complement)
{
- dSP; dTARGET; dTOPss;
- register I32 anum;
+ dSP; dTARGET; tryAMAGICun(compl);
+ {
+ dTOPss;
+ register I32 anum;
- if (SvNIOK(sv)) {
+ if (SvNIOK(sv)) {
SETi( ~SvIV(sv) );
- }
- else {
+ }
+ else {
register char *tmps;
register long *tmpl;
STRLEN len;
SvSetSV(TARG, sv);
- tmps = SvPV(TARG, len);
+ tmps = SvPV_force(TARG, len);
anum = len;
#ifdef LIBERAL
for ( ; anum && (unsigned long)tmps % sizeof(long); anum--, tmps++)
@@ -2009,25 +969,48 @@ PP(pp_complement)
*tmps = ~*tmps;
SETs(TARG);
+ }
+ RETURN;
}
- RETURN;
}
/* integer versions of some of the above */
PP(pp_i_preinc)
{
+#ifndef OVERLOAD
dSP; dTOPiv;
sv_setiv(TOPs, value + 1);
SvSETMAGIC(TOPs);
+#else
+ dSP;
+ if (SvAMAGIC(TOPs) ) {
+ sv_inc(TOPs);
+ } else {
+ dTOPiv;
+ sv_setiv(TOPs, value + 1);
+ SvSETMAGIC(TOPs);
+ }
+#endif /* OVERLOAD */
return NORMAL;
}
PP(pp_i_predec)
{
+#ifndef OVERLOAD
dSP; dTOPiv;
sv_setiv(TOPs, value - 1);
SvSETMAGIC(TOPs);
+#else
+ dSP;
+ if (SvAMAGIC(TOPs)) {
+ sv_dec(TOPs);
+ } else {
+ dTOPiv;
+ sv_setiv(TOPs, value - 1);
+ SvSETMAGIC(TOPs);
+ }
+#endif /* OVERLOAD */
return NORMAL;
}
@@ -2035,8 +1018,17 @@ PP(pp_i_postinc)
{
dSP; dTARGET;
sv_setsv(TARG, TOPs);
+#ifndef OVERLOAD
sv_setiv(TOPs, SvIV(TOPs) + 1);
SvSETMAGIC(TOPs);
+#else
+ if (SvAMAGIC(TOPs) ) {
+ sv_inc(TOPs);
+ } else {
+ sv_setiv(TOPs, SvIV(TOPs) + 1);
+ SvSETMAGIC(TOPs);
+ }
+#endif /* OVERLOAD */
if (!SvOK(TARG))
sv_setiv(TARG, 0);
SETs(TARG);
@@ -2047,110 +1039,155 @@ PP(pp_i_postdec)
{
dSP; dTARGET;
sv_setsv(TARG, TOPs);
+#ifndef OVERLOAD
sv_setiv(TOPs, SvIV(TOPs) - 1);
SvSETMAGIC(TOPs);
+#else
+ if (SvAMAGIC(TOPs) ) {
+ sv_dec(TOPs);
+ } else {
+ sv_setiv(TOPs, SvIV(TOPs) - 1);
+ SvSETMAGIC(TOPs);
+ }
+#endif /* OVERLOAD */
SETs(TARG);
return NORMAL;
}
PP(pp_i_multiply)
{
- dSP; dATARGET; dPOPTOPiirl;
- SETi( left * right );
- RETURN;
+ dSP; dATARGET; tryAMAGICbin(mult,opASSIGN);
+ {
+ dPOPTOPiirl;
+ SETi( left * right );
+ RETURN;
+ }
}
PP(pp_i_divide)
{
- dSP; dATARGET; dPOPiv;
- if (value == 0)
+ dSP; dATARGET; tryAMAGICbin(div,opASSIGN);
+ {
+ dPOPiv;
+ if (value == 0)
DIE("Illegal division by zero");
- value = POPi / value;
- PUSHi( value );
- RETURN;
+ value = POPi / value;
+ PUSHi( value );
+ RETURN;
+ }
}
PP(pp_i_modulo)
{
- dSP; dATARGET; dPOPTOPiirl;
- SETi( left % right );
- RETURN;
+ dSP; dATARGET; tryAMAGICbin(mod,opASSIGN);
+ {
+ dPOPTOPiirl;
+ SETi( left % right );
+ RETURN;
+ }
}
PP(pp_i_add)
{
- dSP; dATARGET; dPOPTOPiirl;
- SETi( left + right );
- RETURN;
+ dSP; dATARGET; tryAMAGICbin(add,opASSIGN);
+ {
+ dPOPTOPiirl;
+ SETi( left + right );
+ RETURN;
+ }
}
PP(pp_i_subtract)
{
- dSP; dATARGET; dPOPTOPiirl;
- SETi( left - right );
- RETURN;
+ dSP; dATARGET; tryAMAGICbin(subtr,opASSIGN);
+ {
+ dPOPTOPiirl;
+ SETi( left - right );
+ RETURN;
+ }
}
PP(pp_i_lt)
{
- dSP; dPOPTOPiirl;
- SETs((left < right) ? &sv_yes : &sv_no);
- RETURN;
+ dSP; tryAMAGICbinSET(lt,0);
+ {
+ dPOPTOPiirl;
+ SETs((left < right) ? &sv_yes : &sv_no);
+ RETURN;
+ }
}
PP(pp_i_gt)
{
- dSP; dPOPTOPiirl;
- SETs((left > right) ? &sv_yes : &sv_no);
- RETURN;
+ dSP; tryAMAGICbinSET(gt,0);
+ {
+ dPOPTOPiirl;
+ SETs((left > right) ? &sv_yes : &sv_no);
+ RETURN;
+ }
}
PP(pp_i_le)
{
- dSP; dPOPTOPiirl;
- SETs((left <= right) ? &sv_yes : &sv_no);
- RETURN;
+ dSP; tryAMAGICbinSET(le,0);
+ {
+ dPOPTOPiirl;
+ SETs((left <= right) ? &sv_yes : &sv_no);
+ RETURN;
+ }
}
PP(pp_i_ge)
{
- dSP; dPOPTOPiirl;
- SETs((left >= right) ? &sv_yes : &sv_no);
- RETURN;
+ dSP; tryAMAGICbinSET(ge,0);
+ {
+ dPOPTOPiirl;
+ SETs((left >= right) ? &sv_yes : &sv_no);
+ RETURN;
+ }
}
PP(pp_i_eq)
{
- dSP; dPOPTOPiirl;
- SETs((left == right) ? &sv_yes : &sv_no);
- RETURN;
+ dSP; tryAMAGICbinSET(eq,0);
+ {
+ dPOPTOPiirl;
+ SETs((left == right) ? &sv_yes : &sv_no);
+ RETURN;
+ }
}
PP(pp_i_ne)
{
- dSP; dPOPTOPiirl;
- SETs((left != right) ? &sv_yes : &sv_no);
- RETURN;
+ dSP; tryAMAGICbinSET(ne,0);
+ {
+ dPOPTOPiirl;
+ SETs((left != right) ? &sv_yes : &sv_no);
+ RETURN;
+ }
}
PP(pp_i_ncmp)
{
- dSP; dTARGET; dPOPTOPiirl;
- I32 value;
+ dSP; dTARGET; tryAMAGICbin(ncmp,0);
+ {
+ dPOPTOPiirl;
+ I32 value;
- if (left > right)
+ if (left > right)
value = 1;
- else if (left < right)
+ else if (left < right)
value = -1;
- else
+ else
value = 0;
- SETi(value);
- RETURN;
+ SETi(value);
+ RETURN;
+ }
}
PP(pp_i_negate)
{
- dSP; dTARGET;
+ dSP; dTARGET; tryAMAGICun(neg);
SETi(-TOPi);
RETURN;
}
@@ -2159,35 +1196,36 @@ PP(pp_i_negate)
PP(pp_atan2)
{
- dSP; dTARGET; dPOPTOPnnrl;
- SETn(atan2(left, right));
- RETURN;
+ dSP; dTARGET; tryAMAGICbin(atan2,0);
+ {
+ dPOPTOPnnrl;
+ SETn(atan2(left, right));
+ RETURN;
+ }
}
PP(pp_sin)
{
- dSP; dTARGET;
- double value;
- if (MAXARG < 1)
- value = SvNVx(GvSV(defgv));
- else
- value = POPn;
- value = sin(value);
- XPUSHn(value);
- RETURN;
+ dSP; dTARGET; tryAMAGICun(sin);
+ {
+ double value;
+ value = POPn;
+ value = sin(value);
+ XPUSHn(value);
+ RETURN;
+ }
}
PP(pp_cos)
{
- dSP; dTARGET;
- double value;
- if (MAXARG < 1)
- value = SvNVx(GvSV(defgv));
- else
- value = POPn;
- value = cos(value);
- XPUSHn(value);
- RETURN;
+ dSP; dTARGET; tryAMAGICun(cos);
+ {
+ double value;
+ value = POPn;
+ value = cos(value);
+ XPUSHn(value);
+ RETURN;
+ }
}
PP(pp_rand)
@@ -2236,55 +1274,49 @@ PP(pp_srand)
PP(pp_exp)
{
- dSP; dTARGET;
- double value;
- if (MAXARG < 1)
- value = SvNVx(GvSV(defgv));
- else
- value = POPn;
- value = exp(value);
- XPUSHn(value);
- RETURN;
+ dSP; dTARGET; tryAMAGICun(exp);
+ {
+ double value;
+ value = POPn;
+ value = exp(value);
+ XPUSHn(value);
+ RETURN;
+ }
}
PP(pp_log)
{
- dSP; dTARGET;
- double value;
- if (MAXARG < 1)
- value = SvNVx(GvSV(defgv));
- else
- value = POPn;
- if (value <= 0.0)
+ dSP; dTARGET; tryAMAGICun(log);
+ {
+ double value;
+ value = POPn;
+ if (value <= 0.0)
DIE("Can't take log of %g", value);
- value = log(value);
- XPUSHn(value);
- RETURN;
+ value = log(value);
+ XPUSHn(value);
+ RETURN;
+ }
}
PP(pp_sqrt)
{
- dSP; dTARGET;
- double value;
- if (MAXARG < 1)
- value = SvNVx(GvSV(defgv));
- else
- value = POPn;
- if (value < 0.0)
+ dSP; dTARGET; tryAMAGICun(sqrt);
+ {
+ double value;
+ value = POPn;
+ if (value < 0.0)
DIE("Can't take sqrt of %g", value);
- value = sqrt(value);
- XPUSHn(value);
- RETURN;
+ value = sqrt(value);
+ XPUSHn(value);
+ RETURN;
+ }
}
PP(pp_int)
{
dSP; dTARGET;
double value;
- if (MAXARG < 1)
- value = SvNVx(GvSV(defgv));
- else
- value = POPn;
+ value = POPn;
if (value >= 0.0)
(void)modf(value, &value);
else {
@@ -2297,18 +1329,17 @@ PP(pp_int)
PP(pp_abs)
{
- dSP; dTARGET;
- double value;
- if (MAXARG < 1)
- value = SvNVx(GvSV(defgv));
- else
- value = POPn;
+ dSP; dTARGET; tryAMAGICun(abs);
+ {
+ double value;
+ value = POPn;
- if (value < 0.0)
+ if (value < 0.0)
value = -value;
- XPUSHn(value);
- RETURN;
+ XPUSHn(value);
+ RETURN;
+ }
}
PP(pp_hex)
@@ -2317,10 +1348,7 @@ PP(pp_hex)
char *tmps;
I32 argtype;
- if (MAXARG < 1)
- tmps = SvPVx(GvSV(defgv), na);
- else
- tmps = POPp;
+ tmps = POPp;
XPUSHi( scan_hex(tmps, 99, &argtype) );
RETURN;
}
@@ -2332,10 +1360,7 @@ PP(pp_oct)
I32 argtype;
char *tmps;
- if (MAXARG < 1)
- tmps = SvPVx(GvSV(defgv), na);
- else
- tmps = POPp;
+ tmps = POPp;
while (*tmps && (isSPACE(*tmps) || *tmps == '0'))
tmps++;
if (*tmps == 'x')
@@ -2351,11 +1376,7 @@ PP(pp_oct)
PP(pp_length)
{
dSP; dTARGET;
- if (MAXARG < 1) {
- XPUSHi( sv_len(GvSV(defgv)) );
- }
- else
- SETi( sv_len(TOPs) );
+ SETi( sv_len(TOPs) );
RETURN;
}
@@ -2367,41 +1388,44 @@ PP(pp_substr)
STRLEN curlen;
I32 pos;
I32 rem;
- I32 lvalue = op->op_flags & OPf_LVAL;
+ I32 lvalue = op->op_flags & OPf_MOD;
char *tmps;
+ I32 arybase = curcop->cop_arybase;
if (MAXARG > 2)
len = POPi;
pos = POPi - arybase;
sv = POPs;
- tmps = SvPV(sv, curlen); /* force conversion to string */
+ tmps = SvPV(sv, curlen);
if (pos < 0)
pos += curlen + arybase;
if (pos < 0 || pos > curlen) {
- if (dowarn)
+ if (dowarn || lvalue)
warn("substr outside of string");
RETPUSHUNDEF;
}
else {
if (MAXARG < 3)
len = curlen;
- if (len < 0)
- len = 0;
+ else if (len < 0) {
+ len += curlen;
+ if (len < 0)
+ len = 0;
+ }
tmps += pos;
rem = curlen - pos; /* rem=how many bytes left*/
if (rem > len)
rem = len;
sv_setpvn(TARG, tmps, rem);
if (lvalue) { /* it's an lvalue! */
- if (SvTHINKFIRST(sv)) {
- if (SvREADONLY(sv) && curcop != &compiling)
- DIE(no_modify);
- if (SvROK(sv))
- DIE("Can't modify substr of a reference");
+ if (SvTYPE(TARG) < SVt_PVLV) {
+ sv_upgrade(TARG, SVt_PVLV);
+ sv_magic(TARG, Nullsv, 'x', Nullch, 0);
}
+
LvTYPE(TARG) = 's';
LvTARG(TARG) = sv;
- LvTARGOFF(TARG) = tmps - SvPV(sv, na);
+ LvTARGOFF(TARG) = pos;
LvTARGLEN(TARG) = rem;
}
}
@@ -2415,7 +1439,7 @@ PP(pp_vec)
register I32 size = POPi;
register I32 offset = POPi;
register SV *src = POPs;
- I32 lvalue = op->op_flags & OPf_LVAL;
+ I32 lvalue = op->op_flags & OPf_MOD;
STRLEN srclen;
unsigned char *s = (unsigned char*)SvPV(src, srclen);
unsigned long retnum;
@@ -2425,16 +1449,41 @@ PP(pp_vec)
len = (offset + size + 7) / 8;
if (offset < 0 || size < 1)
retnum = 0;
- else if (!lvalue && len > srclen)
- retnum = 0;
else {
+ if (lvalue) { /* it's an lvalue! */
+ if (SvTYPE(TARG) < SVt_PVLV) {
+ sv_upgrade(TARG, SVt_PVLV);
+ sv_magic(TARG, Nullsv, 'v', Nullch, 0);
+ }
+
+ LvTYPE(TARG) = 'v';
+ LvTARG(TARG) = src;
+ LvTARGOFF(TARG) = offset;
+ LvTARGLEN(TARG) = size;
+ }
if (len > srclen) {
- SvGROW(src, len);
- (void)memzero(SvPVX(src) + srclen, len - srclen);
- SvCUR_set(src, len);
+ if (size <= 8)
+ retnum = 0;
+ else {
+ offset >>= 3;
+ if (size == 16)
+ retnum = (unsigned long) s[offset] << 8;
+ else if (size == 32) {
+ if (offset < len) {
+ if (offset + 1 < len)
+ retnum = ((unsigned long) s[offset] << 24) +
+ ((unsigned long) s[offset + 1] << 16) +
+ (s[offset + 2] << 8);
+ else
+ retnum = ((unsigned long) s[offset] << 24) +
+ ((unsigned long) s[offset + 1] << 16);
+ }
+ else
+ retnum = (unsigned long) s[offset] << 24;
+ }
+ }
}
- s = (unsigned char*)SvPV(src, na);
- if (size < 8)
+ else if (size < 8)
retnum = (s[offset >> 3] >> (offset & 7)) & ((1 << size) - 1);
else {
offset >>= 3;
@@ -2447,19 +1496,6 @@ PP(pp_vec)
((unsigned long) s[offset + 1] << 16) +
(s[offset + 2] << 8) + s[offset+3];
}
-
- if (lvalue) { /* it's an lvalue! */
- if (SvTHINKFIRST(src)) {
- if (SvREADONLY(src) && curcop != &compiling)
- DIE(no_modify);
- if (SvROK(src))
- DIE("Can't modify vec of a reference");
- }
- LvTYPE(TARG) = 'v';
- LvTARG(TARG) = src;
- LvTARGOFF(TARG) = offset;
- LvTARGLEN(TARG) = size;
- }
}
sv_setiv(TARG, (I32)retnum);
@@ -2477,6 +1513,7 @@ PP(pp_index)
char *tmps;
char *tmps2;
STRLEN biglen;
+ I32 arybase = curcop->cop_arybase;
if (MAXARG < 3)
offset = 0;
@@ -2510,8 +1547,9 @@ PP(pp_rindex)
I32 retval;
char *tmps;
char *tmps2;
+ I32 arybase = curcop->cop_arybase;
- if (MAXARG == 3)
+ if (MAXARG >= 3)
offstr = POPs;
little = POPs;
big = POPs;
@@ -2543,485 +1581,18 @@ PP(pp_sprintf)
RETURN;
}
-static void
-doparseform(sv)
-SV *sv;
-{
- STRLEN len;
- register char *s = SvPV(sv, len);
- register char *send = s + len;
- register char *base;
- register I32 skipspaces = 0;
- bool noblank;
- bool repeat;
- bool postspace = FALSE;
- U16 *fops;
- register U16 *fpc;
- U16 *linepc;
- register I32 arg;
- bool ischop;
-
- New(804, fops, send - s, U16); /* Almost certainly too long... */
- fpc = fops;
-
- if (s < send) {
- linepc = fpc;
- *fpc++ = FF_LINEMARK;
- noblank = repeat = FALSE;
- base = s;
- }
-
- while (s <= send) {
- switch (*s++) {
- default:
- skipspaces = 0;
- continue;
-
- case '~':
- if (*s == '~') {
- repeat = TRUE;
- *s = ' ';
- }
- noblank = TRUE;
- s[-1] = ' ';
- /* FALL THROUGH */
- case ' ': case '\t':
- skipspaces++;
- continue;
-
- case '\n': case 0:
- arg = s - base;
- skipspaces++;
- arg -= skipspaces;
- if (arg) {
- if (postspace) {
- *fpc++ = FF_SPACE;
- postspace = FALSE;
- }
- *fpc++ = FF_LITERAL;
- *fpc++ = arg;
- }
- if (s <= send)
- skipspaces--;
- if (skipspaces) {
- *fpc++ = FF_SKIP;
- *fpc++ = skipspaces;
- }
- skipspaces = 0;
- if (s <= send)
- *fpc++ = FF_NEWLINE;
- if (noblank) {
- *fpc++ = FF_BLANK;
- if (repeat)
- arg = fpc - linepc + 1;
- else
- arg = 0;
- *fpc++ = arg;
- }
- if (s < send) {
- linepc = fpc;
- *fpc++ = FF_LINEMARK;
- noblank = repeat = FALSE;
- base = s;
- }
- else
- s++;
- continue;
-
- case '@':
- case '^':
- ischop = s[-1] == '^';
-
- if (postspace) {
- *fpc++ = FF_SPACE;
- postspace = FALSE;
- }
- arg = (s - base) - 1;
- if (arg) {
- *fpc++ = FF_LITERAL;
- *fpc++ = arg;
- }
-
- base = s - 1;
- *fpc++ = FF_FETCH;
- if (*s == '*') {
- s++;
- *fpc++ = 0;
- *fpc++ = FF_LINEGLOB;
- }
- else if (*s == '#' || (*s == '.' && s[1] == '#')) {
- arg = ischop ? 512 : 0;
- base = s - 1;
- while (*s == '#')
- s++;
- if (*s == '.') {
- char *f;
- s++;
- f = s;
- while (*s == '#')
- s++;
- arg |= 256 + (s - f);
- }
- *fpc++ = s - base; /* fieldsize for FETCH */
- *fpc++ = FF_DECIMAL;
- *fpc++ = arg;
- }
- else {
- I32 prespace = 0;
- bool ismore = FALSE;
-
- if (*s == '>') {
- while (*++s == '>') ;
- prespace = FF_SPACE;
- }
- else if (*s == '|') {
- while (*++s == '|') ;
- prespace = FF_HALFSPACE;
- postspace = TRUE;
- }
- else {
- if (*s == '<')
- while (*++s == '<') ;
- postspace = TRUE;
- }
- if (*s == '.' && s[1] == '.' && s[2] == '.') {
- s += 3;
- ismore = TRUE;
- }
- *fpc++ = s - base; /* fieldsize for FETCH */
-
- *fpc++ = ischop ? FF_CHECKCHOP : FF_CHECKNL;
-
- if (prespace)
- *fpc++ = prespace;
- *fpc++ = FF_ITEM;
- if (ismore)
- *fpc++ = FF_MORE;
- if (ischop)
- *fpc++ = FF_CHOP;
- }
- base = s;
- skipspaces = 0;
- continue;
- }
- }
- *fpc++ = FF_END;
-
- arg = fpc - fops;
- SvGROW(sv, SvCUR(sv) + arg * sizeof(U16) + 4);
-
- s = SvPVX(sv) + SvCUR(sv);
- s += 2 + (SvCUR(sv) & 1);
-
- Copy(fops, s, arg, U16);
- Safefree(fops);
-}
-
-PP(pp_formline)
-{
- dSP; dMARK; dORIGMARK;
- register SV *form = *++MARK;
- register U16 *fpc;
- register char *t;
- register char *f;
- register char *s;
- register char *send;
- register I32 arg;
- register SV *sv;
- char *item;
- I32 itemsize;
- I32 fieldsize;
- I32 lines = 0;
- bool chopspace = (strchr(chopset, ' ') != Nullch);
- char *chophere;
- char *linemark;
- char *formmark;
- SV **markmark;
- double value;
- bool gotsome;
- STRLEN len;
-
- if (!SvCOMPILED(form)) {
- SvREADONLY_off(form);
- doparseform(form);
- }
-
- SvUPGRADE(formtarget, SVt_PV);
- SvGROW(formtarget, SvCUR(formtarget) + SvCUR(form) + 1);
- t = SvPV(formtarget, len);
- t += len;
- f = SvPV(form, len);
-
- s = f + len;
- s += 2 + (len & 1);
-
- fpc = (U16*)s;
-
- for (;;) {
- DEBUG_f( {
- char *name = "???";
- arg = -1;
- switch (*fpc) {
- case FF_LITERAL: arg = fpc[1]; name = "LITERAL"; break;
- case FF_BLANK: arg = fpc[1]; name = "BLANK"; break;
- case FF_SKIP: arg = fpc[1]; name = "SKIP"; break;
- case FF_FETCH: arg = fpc[1]; name = "FETCH"; break;
- case FF_DECIMAL: arg = fpc[1]; name = "DECIMAL"; break;
-
- case FF_CHECKNL: name = "CHECKNL"; break;
- case FF_CHECKCHOP: name = "CHECKCHOP"; break;
- case FF_SPACE: name = "SPACE"; break;
- case FF_HALFSPACE: name = "HALFSPACE"; break;
- case FF_ITEM: name = "ITEM"; break;
- case FF_CHOP: name = "CHOP"; break;
- case FF_LINEGLOB: name = "LINEGLOB"; break;
- case FF_NEWLINE: name = "NEWLINE"; break;
- case FF_MORE: name = "MORE"; break;
- case FF_LINEMARK: name = "LINEMARK"; break;
- case FF_END: name = "END"; break;
- }
- if (arg >= 0)
- fprintf(stderr, "%-16s%d\n", name, arg);
- else
- fprintf(stderr, "%-16s\n", name);
- } )
- switch (*fpc++) {
- case FF_LINEMARK:
- linemark = t;
- formmark = f;
- markmark = MARK;
- lines++;
- gotsome = FALSE;
- break;
-
- case FF_LITERAL:
- arg = *fpc++;
- while (arg--)
- *t++ = *f++;
- break;
-
- case FF_SKIP:
- f += *fpc++;
- break;
-
- case FF_FETCH:
- arg = *fpc++;
- f += arg;
- fieldsize = arg;
-
- if (MARK < SP)
- sv = *++MARK;
- else {
- sv = &sv_no;
- if (dowarn)
- warn("Not enough format arguments");
- }
- break;
-
- case FF_CHECKNL:
- item = s = SvPV(sv, len);
- itemsize = len;
- if (itemsize > fieldsize)
- itemsize = fieldsize;
- send = chophere = s + itemsize;
- while (s < send) {
- if (*s & ~31)
- gotsome = TRUE;
- else if (*s == '\n')
- break;
- s++;
- }
- itemsize = s - item;
- break;
-
- case FF_CHECKCHOP:
- item = s = SvPV(sv, len);
- itemsize = len;
- if (itemsize <= fieldsize) {
- send = chophere = s + itemsize;
- while (s < send) {
- if (*s == '\r') {
- itemsize = s - item;
- break;
- }
- if (*s++ & ~31)
- gotsome = TRUE;
- }
- }
- else {
- itemsize = fieldsize;
- send = chophere = s + itemsize;
- while (s < send || (s == send && isSPACE(*s))) {
- if (isSPACE(*s)) {
- if (chopspace)
- chophere = s;
- if (*s == '\r')
- break;
- }
- else {
- if (*s & ~31)
- gotsome = TRUE;
- if (strchr(chopset, *s))
- chophere = s + 1;
- }
- s++;
- }
- itemsize = chophere - item;
- }
- break;
-
- case FF_SPACE:
- arg = fieldsize - itemsize;
- if (arg) {
- fieldsize -= arg;
- while (arg-- > 0)
- *t++ = ' ';
- }
- break;
-
- case FF_HALFSPACE:
- arg = fieldsize - itemsize;
- if (arg) {
- arg /= 2;
- fieldsize -= arg;
- while (arg-- > 0)
- *t++ = ' ';
- }
- break;
-
- case FF_ITEM:
- arg = itemsize;
- s = item;
- while (arg--) {
- if ((*t++ = *s++) < ' ')
- t[-1] = ' ';
- }
- break;
-
- case FF_CHOP:
- s = chophere;
- if (chopspace) {
- while (*s && isSPACE(*s))
- s++;
- }
- sv_chop(sv,s);
- break;
-
- case FF_LINEGLOB:
- item = s = SvPV(sv, len);
- itemsize = len;
- if (itemsize) {
- gotsome = TRUE;
- send = s + itemsize;
- while (s < send) {
- if (*s++ == '\n') {
- if (s == send)
- itemsize--;
- else
- lines++;
- }
- }
- SvCUR_set(formtarget, t - SvPVX(formtarget));
- sv_catpvn(formtarget, item, itemsize);
- SvGROW(formtarget, SvCUR(formtarget) + SvCUR(form) + 1);
- t = SvPVX(formtarget) + SvCUR(formtarget);
- }
- break;
-
- case FF_DECIMAL:
- /* If the field is marked with ^ and the value is undefined,
- blank it out. */
- arg = *fpc++;
- if ((arg & 512) && !SvOK(sv)) {
- arg = fieldsize;
- while (arg--)
- *t++ = ' ';
- break;
- }
- gotsome = TRUE;
- value = SvNV(sv);
- if (arg & 256) {
- sprintf(t, "%#*.*f", fieldsize, arg & 255, value);
- } else {
- sprintf(t, "%*.0f", fieldsize, value);
- }
- t += fieldsize;
- break;
-
- case FF_NEWLINE:
- f++;
- while (t-- > linemark && *t == ' ') ;
- t++;
- *t++ = '\n';
- break;
-
- case FF_BLANK:
- arg = *fpc++;
- if (gotsome) {
- if (arg) { /* repeat until fields exhausted? */
- fpc -= arg;
- f = formmark;
- MARK = markmark;
- if (lines == 200) {
- arg = t - linemark;
- if (strnEQ(linemark, linemark - arg, arg))
- DIE("Runaway format");
- }
- arg = t - SvPVX(formtarget);
- SvGROW(formtarget,
- (t - SvPVX(formtarget)) + (f - formmark) + 1);
- t = SvPVX(formtarget) + arg;
- }
- }
- else {
- t = linemark;
- lines--;
- }
- break;
-
- case FF_MORE:
- if (itemsize) {
- arg = fieldsize - itemsize;
- if (arg) {
- fieldsize -= arg;
- while (arg-- > 0)
- *t++ = ' ';
- }
- s = t - 3;
- if (strnEQ(s," ",3)) {
- while (s > SvPVX(formtarget) && isSPACE(s[-1]))
- s--;
- }
- *s++ = '.';
- *s++ = '.';
- *s++ = '.';
- }
- break;
-
- case FF_END:
- *t = '\0';
- SvCUR_set(formtarget, t - SvPVX(formtarget));
- FmLINES(formtarget) += lines;
- SP = ORIGMARK;
- RETPUSHYES;
- }
- }
-}
-
PP(pp_ord)
{
dSP; dTARGET;
I32 value;
char *tmps;
- I32 anum;
- if (MAXARG < 1)
- tmps = SvPVx(GvSV(defgv), na);
- else
- tmps = POPp;
#ifndef I286
+ tmps = POPp;
value = (I32) (*tmps & 255);
#else
+ I32 anum;
+ tmps = POPp;
anum = (I32) *tmps;
value = (I32) (anum & 255);
#endif
@@ -3034,17 +1605,14 @@ PP(pp_chr)
dSP; dTARGET;
char *tmps;
- if (SvTYPE(TARG) == SVt_NULL) {
- sv_upgrade(TARG,SVt_PV);
+ if (!SvPOK(TARG)) {
+ (void)SvUPGRADE(TARG,SVt_PV);
SvGROW(TARG,1);
}
SvCUR_set(TARG, 1);
tmps = SvPVX(TARG);
- if (MAXARG < 1)
- *tmps = SvIVx(GvSV(defgv));
- else
- *tmps = POPi;
- SvPOK_only(TARG);
+ *tmps = POPi;
+ (void)SvPOK_only(TARG);
XPUSHs(TARG);
RETURN;
}
@@ -3053,11 +1621,11 @@ PP(pp_crypt)
{
dSP; dTARGET; dPOPTOPssrl;
#ifdef HAS_CRYPT
- char *tmps = SvPV(lstr, na);
+ char *tmps = SvPV(left, na);
#ifdef FCRYPT
- sv_setpv(TARG, fcrypt(tmps, SvPV(rstr, na)));
+ sv_setpv(TARG, fcrypt(tmps, SvPV(right, na)));
#else
- sv_setpv(TARG, crypt(tmps, SvPV(rstr, na)));
+ sv_setpv(TARG, crypt(tmps, SvPV(right, na)));
#endif
#else
DIE(
@@ -3079,9 +1647,9 @@ PP(pp_ucfirst)
sv = TARG;
SETs(sv);
}
- s = SvPV(sv, na);
- if (isascii(*s) && islower(*s))
- *s = toupper(*s);
+ s = SvPV_force(sv, na);
+ if (isLOWER(*s))
+ *s = toUPPER(*s);
RETURN;
}
@@ -3098,9 +1666,9 @@ PP(pp_lcfirst)
sv = TARG;
SETs(sv);
}
- s = SvPV(sv, na);
- if (isascii(*s) && isupper(*s))
- *s = tolower(*s);
+ s = SvPV_force(sv, na);
+ if (isUPPER(*s))
+ *s = toLOWER(*s);
SETs(sv);
RETURN;
@@ -3120,11 +1688,11 @@ PP(pp_uc)
sv = TARG;
SETs(sv);
}
- s = SvPV(sv, len);
+ s = SvPV_force(sv, len);
send = s + len;
while (s < send) {
- if (isascii(*s) && islower(*s))
- *s = toupper(*s);
+ if (isLOWER(*s))
+ *s = toUPPER(*s);
s++;
}
RETURN;
@@ -3144,149 +1712,71 @@ PP(pp_lc)
sv = TARG;
SETs(sv);
}
- s = SvPV(sv, len);
+ s = SvPV_force(sv, len);
send = s + len;
while (s < send) {
- if (isascii(*s) && isupper(*s))
- *s = tolower(*s);
+ if (isUPPER(*s))
+ *s = toLOWER(*s);
s++;
}
RETURN;
}
-/* Arrays. */
-
-PP(pp_rv2av)
-{
- dSP; dPOPss;
-
- AV *av;
-
- if (SvROK(sv)) {
- av = (AV*)SvRV(sv);
- if (SvTYPE(av) != SVt_PVAV)
- DIE("Not an array reference");
- if (op->op_flags & OPf_LVAL) {
- if (op->op_flags & OPf_INTRO)
- av = (AV*)save_svref((SV**)sv);
- PUSHs((SV*)av);
- RETURN;
- }
- }
- else {
- if (SvTYPE(sv) == SVt_PVAV) {
- av = (AV*)sv;
- if (op->op_flags & OPf_LVAL) {
- PUSHs((SV*)av);
- RETURN;
- }
- }
- else {
- if (SvTYPE(sv) != SVt_PVGV) {
- if (!SvOK(sv))
- DIE(no_usym, "an array");
- if (op->op_private & HINT_STRICT_REFS)
- DIE(no_hardref, "an array");
- sv = (SV*)gv_fetchpv(SvPV(sv, na), TRUE, SVt_PVAV);
- }
- av = GvAVn(sv);
- if (op->op_flags & OPf_LVAL) {
- if (op->op_flags & OPf_INTRO)
- av = save_ary(sv);
- PUSHs((SV*)av);
- RETURN;
- }
- }
- }
-
- if (GIMME == G_ARRAY) {
- I32 maxarg = AvFILL(av) + 1;
- EXTEND(SP, maxarg);
- Copy(AvARRAY(av), SP+1, maxarg, SV*);
- SP += maxarg;
- }
- else {
- dTARGET;
- I32 maxarg = AvFILL(av) + 1;
- PUSHi(maxarg);
- }
- RETURN;
-}
-
-PP(pp_aelemfast)
+PP(pp_quotemeta)
{
- dSP;
- AV *av = GvAV((GV*)cSVOP->op_sv);
- SV** svp = av_fetch(av, op->op_private - arybase, op->op_flags & OPf_LVAL);
- PUSHs(svp ? *svp : &sv_undef);
- RETURN;
-}
-
-PP(pp_aelem)
-{
- dSP;
- SV** svp;
- I32 elem = POPi - arybase;
- AV *av = (AV*)POPs;
+ dSP; dTARGET;
+ SV *sv = TOPs;
+ STRLEN len;
+ register char *s = SvPV(sv,len);
+ register char *d;
- if (op->op_flags & OPf_LVAL) {
- svp = av_fetch(av, elem, TRUE);
- if (!svp || *svp == &sv_undef)
- DIE(no_aelem, elem);
- if (op->op_flags & OPf_INTRO)
- save_svref(svp);
- else if (!SvOK(*svp)) {
- if (op->op_private & OPpDEREF_HV) {
- SvREFCNT_dec(*svp);
- *svp = NEWSV(0,0);
- sv_upgrade(*svp, SVt_RV);
- SvRV(*svp) = SvREFCNT_inc(newHV());
- SvROK_on(*svp);
- ++sv_rvcount;
- }
- else if (op->op_private & OPpDEREF_AV) {
- SvREFCNT_dec(*svp);
- *svp = NEWSV(0,0);
- sv_upgrade(*svp, SVt_RV);
- SvRV(*svp) = SvREFCNT_inc(newAV());
- SvROK_on(*svp);
- ++sv_rvcount;
- }
+ if (len) {
+ (void)SvUPGRADE(TARG, SVt_PV);
+ SvGROW(TARG, len * 2);
+ d = SvPVX(TARG);
+ while (len--) {
+ if (!isALNUM(*s))
+ *d++ = '\\';
+ *d++ = *s++;
}
+ *d = '\0';
+ SvCUR_set(TARG, d - SvPVX(TARG));
+ (void)SvPOK_only(TARG);
}
else
- svp = av_fetch(av, elem, FALSE);
- PUSHs(svp ? *svp : &sv_undef);
+ sv_setpvn(TARG, s, len);
+ SETs(TARG);
RETURN;
}
+/* Arrays. */
+
PP(pp_aslice)
{
dSP; dMARK; dORIGMARK;
register SV** svp;
register AV* av = (AV*)POPs;
- register I32 lval = op->op_flags & OPf_LVAL;
- I32 is_something_there = lval;
-
- while (++MARK <= SP) {
- I32 elem = SvIVx(*MARK);
-
- if (lval) {
- svp = av_fetch(av, elem, TRUE);
- if (!svp || *svp == &sv_undef)
- DIE(no_aelem, elem);
- if (op->op_flags & OPf_INTRO)
- save_svref(svp);
- }
- else {
- svp = av_fetch(av, elem, FALSE);
- if (!is_something_there && svp && SvOK(*svp))
- is_something_there = TRUE;
+ register I32 lval = op->op_flags & OPf_MOD;
+
+ if (SvTYPE(av) == SVt_PVAV) {
+ while (++MARK <= SP) {
+ I32 elem = SvIVx(*MARK);
+
+ svp = av_fetch(av, elem, lval);
+ if (lval) {
+ if (!svp || *svp == &sv_undef)
+ DIE(no_aelem, elem);
+ if (op->op_private & OPpLVAL_INTRO)
+ save_svref(svp);
+ }
+ *MARK = svp ? *svp : &sv_undef;
}
- *MARK = svp ? *svp : &sv_undef;
}
- if (!is_something_there)
- SP = ORIGMARK;
+ else if (GIMME != G_ARRAY) {
+ MARK = ORIGMARK;
+ *++MARK = *SP;
+ SP = MARK;
+ }
RETURN;
}
@@ -3335,8 +1825,8 @@ PP(pp_delete)
HV *hv = (HV*)POPs;
char *tmps;
STRLEN len;
- if (!hv) {
- DIE("Not an associative array reference");
+ if (SvTYPE(hv) != SVt_PVHV) {
+ DIE("Not a HASH reference");
}
tmps = SvPV(tmpsv, len);
sv = hv_delete(hv, tmps, len);
@@ -3346,135 +1836,425 @@ PP(pp_delete)
RETURN;
}
-PP(pp_rv2hv)
+PP(pp_exists)
{
+ dSP;
+ SV *tmpsv = POPs;
+ HV *hv = (HV*)POPs;
+ char *tmps;
+ STRLEN len;
+ if (SvTYPE(hv) != SVt_PVHV) {
+ DIE("Not a HASH reference");
+ }
+ tmps = SvPV(tmpsv, len);
+ if (hv_exists(hv, tmps, len))
+ RETPUSHYES;
+ RETPUSHNO;
+}
- dSP; dTOPss;
+PP(pp_hslice)
+{
+ dSP; dMARK; dORIGMARK;
+ register SV **svp;
+ register HV *hv = (HV*)POPs;
+ register I32 lval = op->op_flags & OPf_MOD;
- HV *hv;
+ if (SvTYPE(hv) == SVt_PVHV) {
+ while (++MARK <= SP) {
+ STRLEN keylen;
+ char *key = SvPV(*MARK, keylen);
- if (SvROK(sv)) {
- hv = (HV*)SvRV(sv);
- if (SvTYPE(hv) != SVt_PVHV)
- DIE("Not an associative array reference");
- if (op->op_flags & OPf_LVAL) {
- if (op->op_flags & OPf_INTRO)
- hv = (HV*)save_svref((SV**)sv);
- SETs((SV*)hv);
- RETURN;
+ svp = hv_fetch(hv, key, keylen, lval);
+ if (lval) {
+ if (!svp || *svp == &sv_undef)
+ DIE(no_helem, key);
+ if (op->op_private & OPpLVAL_INTRO)
+ save_svref(svp);
+ }
+ *MARK = svp ? *svp : &sv_undef;
+ }
+ }
+ if (GIMME != G_ARRAY) {
+ MARK = ORIGMARK;
+ *++MARK = *SP;
+ SP = MARK;
+ }
+ RETURN;
+}
+
+/* List operators. */
+
+PP(pp_list)
+{
+ dSP; dMARK;
+ if (GIMME != G_ARRAY) {
+ if (++MARK <= SP)
+ *MARK = *SP; /* unwanted list, return last item */
+ else
+ *MARK = &sv_undef;
+ SP = MARK;
+ }
+ RETURN;
+}
+
+PP(pp_lslice)
+{
+ dSP;
+ SV **lastrelem = stack_sp;
+ SV **lastlelem = stack_base + POPMARK;
+ SV **firstlelem = stack_base + POPMARK + 1;
+ register SV **firstrelem = lastlelem + 1;
+ I32 arybase = curcop->cop_arybase;
+
+ register I32 max = lastrelem - lastlelem;
+ register SV **lelem;
+ register I32 ix;
+
+ if (GIMME != G_ARRAY) {
+ ix = SvIVx(*lastlelem) - arybase;
+ if (ix < 0 || ix >= max)
+ *firstlelem = &sv_undef;
+ else
+ *firstlelem = firstrelem[ix];
+ SP = firstlelem;
+ RETURN;
+ }
+
+ if (max == 0) {
+ SP = firstlelem - 1;
+ RETURN;
+ }
+
+ for (lelem = firstlelem; lelem <= lastlelem; lelem++) {
+ ix = SvIVx(*lelem) - arybase;
+ if (ix < 0) {
+ ix += max;
+ if (ix < 0)
+ *lelem = &sv_undef;
+ else if (!(*lelem = firstrelem[ix]))
+ *lelem = &sv_undef;
+ }
+ else if (ix >= max || !(*lelem = firstrelem[ix]))
+ *lelem = &sv_undef;
+ }
+ SP = lastlelem;
+ RETURN;
+}
+
+PP(pp_anonlist)
+{
+ dSP; dMARK;
+ I32 items = SP - MARK;
+ SP = MARK;
+ XPUSHs((SV*)sv_2mortal((SV*)av_make(items, MARK+1)));
+ RETURN;
+}
+
+PP(pp_anonhash)
+{
+ dSP; dMARK; dORIGMARK;
+ STRLEN len;
+ HV* hv = (HV*)sv_2mortal((SV*)newHV());
+
+ while (MARK < SP) {
+ SV* key = *++MARK;
+ char *tmps;
+ SV *val = NEWSV(46, 0);
+ if (MARK < SP)
+ sv_setsv(val, *++MARK);
+ else
+ warn("Odd number of elements in hash list");
+ tmps = SvPV(key,len);
+ (void)hv_store(hv,tmps,len,val,0);
+ }
+ SP = ORIGMARK;
+ XPUSHs((SV*)hv);
+ RETURN;
+}
+
+PP(pp_splice)
+{
+ dSP; dMARK; dORIGMARK;
+ register AV *ary = (AV*)*++MARK;
+ register SV **src;
+ register SV **dst;
+ register I32 i;
+ register I32 offset;
+ register I32 length;
+ I32 newlen;
+ I32 after;
+ I32 diff;
+ SV **tmparyval = 0;
+
+ SP++;
+
+ if (++MARK < SP) {
+ offset = SvIVx(*MARK);
+ if (offset < 0)
+ offset += AvFILL(ary) + 1;
+ else
+ offset -= curcop->cop_arybase;
+ if (++MARK < SP) {
+ length = SvIVx(*MARK++);
+ if (length < 0)
+ length = 0;
}
+ else
+ length = AvMAX(ary) + 1; /* close enough to infinity */
}
else {
- if (SvTYPE(sv) == SVt_PVHV) {
- hv = (HV*)sv;
- if (op->op_flags & OPf_LVAL) {
- SETs((SV*)hv);
- RETURN;
+ offset = 0;
+ length = AvMAX(ary) + 1;
+ }
+ if (offset < 0) {
+ length += offset;
+ offset = 0;
+ if (length < 0)
+ length = 0;
+ }
+ if (offset > AvFILL(ary) + 1)
+ offset = AvFILL(ary) + 1;
+ after = AvFILL(ary) + 1 - (offset + length);
+ if (after < 0) { /* not that much array */
+ length += after; /* offset+length now in array */
+ after = 0;
+ if (!AvALLOC(ary))
+ av_extend(ary, 0);
+ }
+
+ /* At this point, MARK .. SP-1 is our new LIST */
+
+ newlen = SP - MARK;
+ diff = newlen - length;
+
+ if (diff < 0) { /* shrinking the area */
+ if (newlen) {
+ New(451, tmparyval, newlen, SV*); /* so remember insertion */
+ Copy(MARK, tmparyval, newlen, SV*);
+ }
+
+ MARK = ORIGMARK + 1;
+ if (GIMME == G_ARRAY) { /* copy return vals to stack */
+ MEXTEND(MARK, length);
+ Copy(AvARRAY(ary)+offset, MARK, length, SV*);
+ if (AvREAL(ary)) {
+ for (i = length, dst = MARK; i; i--)
+ sv_2mortal(*dst++); /* free them eventualy */
}
+ MARK += length - 1;
}
else {
- if (SvTYPE(sv) != SVt_PVGV) {
- if (!SvOK(sv))
- DIE(no_usym, "a hash");
- if (op->op_private & HINT_STRICT_REFS)
- DIE(no_hardref, "a hash");
- sv = (SV*)gv_fetchpv(SvPV(sv, na), TRUE, SVt_PVHV);
+ *MARK = AvARRAY(ary)[offset+length-1];
+ if (AvREAL(ary)) {
+ sv_2mortal(*MARK);
+ for (i = length - 1, dst = &AvARRAY(ary)[offset]; i > 0; i--)
+ SvREFCNT_dec(*dst++); /* free them now */
}
- hv = GvHVn(sv);
- if (op->op_flags & OPf_LVAL) {
- if (op->op_flags & OPf_INTRO)
- hv = save_hash(sv);
- SETs((SV*)hv);
- RETURN;
+ }
+ AvFILL(ary) += diff;
+
+ /* pull up or down? */
+
+ if (offset < after) { /* easier to pull up */
+ if (offset) { /* esp. if nothing to pull */
+ src = &AvARRAY(ary)[offset-1];
+ dst = src - diff; /* diff is negative */
+ for (i = offset; i > 0; i--) /* can't trust Copy */
+ *dst-- = *src--;
+ }
+ dst = AvARRAY(ary);
+ SvPVX(ary) = (char*)(AvARRAY(ary) - diff); /* diff is negative */
+ AvMAX(ary) += diff;
+ }
+ else {
+ if (after) { /* anything to pull down? */
+ src = AvARRAY(ary) + offset + length;
+ dst = src + diff; /* diff is negative */
+ Move(src, dst, after, SV*);
}
+ dst = &AvARRAY(ary)[AvFILL(ary)+1];
+ /* avoid later double free */
+ }
+ i = -diff;
+ while (i)
+ dst[--i] = &sv_undef;
+
+ if (newlen) {
+ for (src = tmparyval, dst = AvARRAY(ary) + offset;
+ newlen; newlen--) {
+ *dst = NEWSV(46, 0);
+ sv_setsv(*dst++, *src++);
+ }
+ Safefree(tmparyval);
}
}
+ else { /* no, expanding (or same) */
+ if (length) {
+ New(452, tmparyval, length, SV*); /* so remember deletion */
+ Copy(AvARRAY(ary)+offset, tmparyval, length, SV*);
+ }
- if (GIMME == G_ARRAY) { /* array wanted */
- *stack_sp = (SV*)hv;
- return do_kv(ARGS);
- }
- else {
- dTARGET;
- if (HvFILL(hv)) {
- sprintf(buf, "%d/%d", HvFILL(hv), HvMAX(hv)+1);
- sv_setpv(TARG, buf);
+ if (diff > 0) { /* expanding */
+
+ /* push up or down? */
+
+ if (offset < after && diff <= AvARRAY(ary) - AvALLOC(ary)) {
+ if (offset) {
+ src = AvARRAY(ary);
+ dst = src - diff;
+ Move(src, dst, offset, SV*);
+ }
+ SvPVX(ary) = (char*)(AvARRAY(ary) - diff);/* diff is positive */
+ AvMAX(ary) += diff;
+ AvFILL(ary) += diff;
+ }
+ else {
+ if (AvFILL(ary) + diff >= AvMAX(ary)) /* oh, well */
+ av_extend(ary, AvFILL(ary) + diff);
+ AvFILL(ary) += diff;
+
+ if (after) {
+ dst = AvARRAY(ary) + AvFILL(ary);
+ src = dst - diff;
+ for (i = after; i; i--) {
+ *dst-- = *src--;
+ }
+ }
+ }
+ }
+
+ for (src = MARK, dst = AvARRAY(ary) + offset; newlen; newlen--) {
+ *dst = NEWSV(46, 0);
+ sv_setsv(*dst++, *src++);
+ }
+ MARK = ORIGMARK + 1;
+ if (GIMME == G_ARRAY) { /* copy return vals to stack */
+ if (length) {
+ Copy(tmparyval, MARK, length, SV*);
+ if (AvREAL(ary)) {
+ for (i = length, dst = MARK; i; i--)
+ sv_2mortal(*dst++); /* free them eventualy */
+ }
+ Safefree(tmparyval);
+ }
+ MARK += length - 1;
+ }
+ else if (length--) {
+ *MARK = tmparyval[length];
+ if (AvREAL(ary)) {
+ sv_2mortal(*MARK);
+ while (length-- > 0)
+ SvREFCNT_dec(tmparyval[length]);
+ }
+ Safefree(tmparyval);
}
else
- sv_setiv(TARG, 0);
- SETTARG;
- RETURN;
+ *MARK = &sv_undef;
}
+ SP = MARK;
+ RETURN;
}
-PP(pp_helem)
+PP(pp_push)
+{
+ dSP; dMARK; dORIGMARK; dTARGET;
+ register AV *ary = (AV*)*++MARK;
+ register SV *sv = &sv_undef;
+
+ for (++MARK; MARK <= SP; MARK++) {
+ sv = NEWSV(51, 0);
+ if (*MARK)
+ sv_setsv(sv, *MARK);
+ av_push(ary, sv);
+ }
+ SP = ORIGMARK;
+ PUSHi( AvFILL(ary) + 1 );
+ RETURN;
+}
+
+PP(pp_pop)
{
dSP;
- SV** svp;
- SV *keysv = POPs;
- STRLEN keylen;
- char *key = SvPV(keysv, keylen);
- HV *hv = (HV*)POPs;
+ AV *av = (AV*)POPs;
+ SV *sv = av_pop(av);
+ if (sv != &sv_undef && AvREAL(av))
+ (void)sv_2mortal(sv);
+ PUSHs(sv);
+ RETURN;
+}
- if (op->op_flags & OPf_LVAL) {
- svp = hv_fetch(hv, key, keylen, TRUE);
- if (!svp || *svp == &sv_undef)
- DIE(no_helem, key);
- if (op->op_flags & OPf_INTRO)
- save_svref(svp);
- else if (!SvOK(*svp)) {
- if (op->op_private & OPpDEREF_HV) {
- SvREFCNT_dec(*svp);
- *svp = NEWSV(0,0);
- sv_upgrade(*svp, SVt_RV);
- SvRV(*svp) = SvREFCNT_inc(newHV());
- SvROK_on(*svp);
- ++sv_rvcount;
- }
- else if (op->op_private & OPpDEREF_AV) {
- SvREFCNT_dec(*svp);
- *svp = NEWSV(0,0);
- sv_upgrade(*svp, SVt_RV);
- SvRV(*svp) = SvREFCNT_inc(newAV());
- SvROK_on(*svp);
- ++sv_rvcount;
- }
- }
+PP(pp_shift)
+{
+ dSP;
+ AV *av = (AV*)POPs;
+ SV *sv = av_shift(av);
+ EXTEND(SP, 1);
+ if (!sv)
+ RETPUSHUNDEF;
+ if (sv != &sv_undef && AvREAL(av))
+ (void)sv_2mortal(sv);
+ PUSHs(sv);
+ RETURN;
+}
+
+PP(pp_unshift)
+{
+ dSP; dMARK; dORIGMARK; dTARGET;
+ register AV *ary = (AV*)*++MARK;
+ register SV *sv;
+ register I32 i = 0;
+
+ av_unshift(ary, SP - MARK);
+ while (MARK < SP) {
+ sv = NEWSV(27, 0);
+ sv_setsv(sv, *++MARK);
+ (void)av_store(ary, i++, sv);
}
- else
- svp = hv_fetch(hv, key, keylen, FALSE);
- PUSHs(svp ? *svp : &sv_undef);
+
+ SP = ORIGMARK;
+ PUSHi( AvFILL(ary) + 1 );
RETURN;
}
-PP(pp_hslice)
+PP(pp_reverse)
{
- dSP; dMARK; dORIGMARK;
- register SV **svp;
- register HV *hv = (HV*)POPs;
- register I32 lval = op->op_flags & OPf_LVAL;
- I32 is_something_there = lval;
-
- while (++MARK <= SP) {
- STRLEN keylen;
- char *key = SvPV(*MARK, keylen);
-
- if (lval) {
- svp = hv_fetch(hv, key, keylen, TRUE);
- if (!svp || *svp == &sv_undef)
- DIE(no_helem, key);
- if (op->op_flags & OPf_INTRO)
- save_svref(svp);
+ dSP; dMARK;
+ register SV *tmp;
+ SV **oldsp = SP;
+
+ if (GIMME == G_ARRAY) {
+ MARK++;
+ while (MARK < SP) {
+ tmp = *MARK;
+ *MARK++ = *SP;
+ *SP-- = tmp;
}
- else {
- svp = hv_fetch(hv, key, keylen, FALSE);
- if (!is_something_there && svp && SvOK(*svp))
- is_something_there = TRUE;
+ SP = oldsp;
+ }
+ else {
+ register char *up;
+ register char *down;
+ register I32 tmp;
+ dTARGET;
+ STRLEN len;
+
+ if (SP - MARK > 1)
+ do_join(TARG, &sv_no, MARK, SP);
+ else
+ sv_setsv(TARG, *SP);
+ up = SvPV_force(TARG, len);
+ if (len > 1) {
+ down = SvPVX(TARG) + len - 1;
+ while (down > up) {
+ tmp = *up;
+ *up++ = *down;
+ *down-- = tmp;
+ }
+ (void)SvPOK_only(TARG);
}
- *MARK = svp ? *svp : &sv_undef;
+ SP = MARK + 1;
+ SETTARG;
}
- if (!is_something_there)
- SP = ORIGMARK;
RETURN;
}
@@ -3487,8 +2267,8 @@ PP(pp_unpack)
SV *sv;
STRLEN llen;
STRLEN rlen;
- register char *pat = SvPV(lstr, llen);
- register char *s = SvPV(rstr, rlen);
+ register char *pat = SvPV(left, llen);
+ register char *s = SvPV(right, rlen);
char *strend = s + rlen;
char *strbeg = s;
register char *patend = pat + llen;
@@ -3957,7 +2737,7 @@ PP(pp_unpack)
s += sizeof(quad);
}
sv = NEWSV(42, 0);
- sv_setnv(sv, (double)aquad);
+ sv_setiv(sv, (IV)aquad);
PUSHs(sv_2mortal(sv));
}
break;
@@ -3971,7 +2751,7 @@ PP(pp_unpack)
s += sizeof(unsigned quad);
}
sv = NEWSV(43, 0);
- sv_setnv(sv, (double)auquad);
+ sv_setiv(sv, (IV)auquad);
PUSHs(sv_2mortal(sv));
}
break;
@@ -4067,7 +2847,6 @@ PP(pp_unpack)
sv = NEWSV(42, 0);
if (strchr("fFdD", datumtype) ||
(checksum > 32 && strchr("iIlLN", datumtype)) ) {
- double modf();
double trouble;
adouble = 1.0;
@@ -4452,14 +3231,14 @@ PP(pp_pack)
case 'Q':
while (len-- > 0) {
fromstr = NEXTFROM;
- auquad = (unsigned quad)SvNV(fromstr);
+ auquad = (unsigned quad)SvIV(fromstr);
sv_catpvn(cat, (char*)&auquad, sizeof(unsigned quad));
}
break;
case 'q':
while (len-- > 0) {
fromstr = NEXTFROM;
- aquad = (quad)SvNV(fromstr);
+ aquad = (quad)SvIV(fromstr);
sv_catpvn(cat, (char*)&aquad, sizeof(quad));
}
break;
@@ -4470,7 +3249,7 @@ PP(pp_pack)
case 'p':
while (len-- > 0) {
fromstr = NEXTFROM;
- aptr = SvPV(fromstr, na);
+ aptr = SvPV_force(fromstr, na); /* XXX Error if TEMP? */
sv_catpvn(cat, (char*)&aptr, sizeof(char*));
}
break;
@@ -4522,7 +3301,7 @@ PP(pp_split)
I32 origlimit = limit;
I32 realarray = 0;
I32 base;
- AV *oldstack;
+ AV *oldstack = stack;
register REGEXP *rx = pm->op_pmregexp;
I32 gimme = GIMME;
@@ -4539,12 +3318,11 @@ PP(pp_split)
if (!AvREAL(ary)) {
AvREAL_on(ary);
for (i = AvFILL(ary); i >= 0; i--)
- AvARRAY(ary)[i] = Nullsv; /* don't free mere refs */
+ AvARRAY(ary)[i] = &sv_undef; /* don't free mere refs */
}
- av_fill(ary,0); /* force allocation */
- av_fill(ary,-1);
+ av_extend(ary,0);
+ av_clear(ary);
/* temporarily switch stacks */
- oldstack = stack;
SWITCHSTACK(stack, ary);
}
base = SP - stack_base;
@@ -4591,12 +3369,12 @@ PP(pp_split)
I32 fold = (pm->op_pmflags & PMf_FOLD);
i = *SvPVX(pm->op_pmshort);
if (fold && isUPPER(i))
- i = tolower(i);
+ i = toLOWER(i);
while (--limit) {
if (fold) {
for ( m = s;
m < strend && *m != i &&
- (!isUPPER(*m) || tolower(*m) != i);
+ (!isUPPER(*m) || toLOWER(*m) != i);
m++) /*SUPPRESS 530*/
;
}
@@ -4663,7 +3441,9 @@ PP(pp_split)
iters = (SP - stack_base) - base;
if (iters > maxiters)
DIE("Split loop");
- if (s < strend || origlimit) { /* keep field after final delim? */
+
+ /* keep field after final delim? */
+ if (s < strend || (iters && origlimit)) {
dstr = NEWSV(34, strend-s);
sv_setpvn(dstr, s, strend-s);
if (!realarray)
@@ -4671,7 +3451,7 @@ PP(pp_split)
XPUSHs(dstr);
iters++;
}
- else {
+ else if (!origlimit) {
while (iters > 0 && SvCUR(TOPs) == 0)
iters--, SP--;
}
@@ -4688,6025 +3468,11 @@ PP(pp_split)
if (gimme == G_ARRAY)
RETURN;
}
- GETTARGET;
- PUSHi(iters);
- RETURN;
-}
-
-PP(pp_join)
-{
- dSP; dMARK; dTARGET;
- MARK++;
- do_join(TARG, *MARK, MARK, SP);
- SP = MARK;
- SETs(TARG);
- RETURN;
-}
-
-/* List operators. */
-
-PP(pp_list)
-{
- dSP; dMARK;
- if (GIMME != G_ARRAY) {
- if (++MARK <= SP)
- *MARK = *SP; /* unwanted list, return last item */
- else
- *MARK = &sv_undef;
- SP = MARK;
- }
- RETURN;
-}
-
-PP(pp_lslice)
-{
- dSP;
- SV **lastrelem = stack_sp;
- SV **lastlelem = stack_base + POPMARK;
- SV **firstlelem = stack_base + POPMARK + 1;
- register SV **firstrelem = lastlelem + 1;
- I32 lval = op->op_flags & OPf_LVAL;
- I32 is_something_there = lval;
-
- register I32 max = lastrelem - lastlelem;
- register SV **lelem;
- register I32 ix;
-
- if (GIMME != G_ARRAY) {
- ix = SvIVx(*lastlelem) - arybase;
- if (ix < 0 || ix >= max)
- *firstlelem = &sv_undef;
- else
- *firstlelem = firstrelem[ix];
- SP = firstlelem;
- RETURN;
- }
-
- if (max == 0) {
- SP = firstlelem - 1;
- RETURN;
- }
-
- for (lelem = firstlelem; lelem <= lastlelem; lelem++) {
- ix = SvIVx(*lelem) - arybase;
- if (ix < 0) {
- ix += max;
- if (ix < 0)
- *lelem = &sv_undef;
- else if (!(*lelem = firstrelem[ix]))
- *lelem = &sv_undef;
- }
- else if (ix >= max || !(*lelem = firstrelem[ix]))
- *lelem = &sv_undef;
- if (!is_something_there && SvOK(*lelem))
- is_something_there = TRUE;
- }
- if (is_something_there)
- SP = lastlelem;
- else
- SP = firstlelem - 1;
- RETURN;
-}
-
-PP(pp_anonlist)
-{
- dSP; dMARK;
- I32 items = SP - MARK;
- SP = MARK;
- XPUSHs((SV*)av_make(items, MARK+1));
- RETURN;
-}
-
-PP(pp_anonhash)
-{
- dSP; dMARK; dORIGMARK;
- STRLEN len;
- HV* hv = newHV();
-
- SvREFCNT(hv) = 0;
- while (MARK < SP) {
- SV* key = *++MARK;
- char *tmps;
- SV *val = NEWSV(46, 0);
- if (MARK < SP)
- sv_setsv(val, *++MARK);
- tmps = SvPV(key,len);
- (void)hv_store(hv,tmps,len,val,0);
- }
- SP = ORIGMARK;
- SvOK_on(hv);
- XPUSHs((SV*)hv);
- RETURN;
-}
-
-PP(pp_splice)
-{
- dSP; dMARK; dORIGMARK;
- register AV *ary = (AV*)*++MARK;
- register SV **src;
- register SV **dst;
- register I32 i;
- register I32 offset;
- register I32 length;
- I32 newlen;
- I32 after;
- I32 diff;
- SV **tmparyval;
-
- SP++;
-
- if (++MARK < SP) {
- offset = SvIVx(*MARK);
- if (offset < 0)
- offset += AvFILL(ary) + 1;
- else
- offset -= arybase;
- if (++MARK < SP) {
- length = SvIVx(*MARK++);
- if (length < 0)
- length = 0;
- }
- else
- length = AvMAX(ary) + 1; /* close enough to infinity */
- }
- else {
- offset = 0;
- length = AvMAX(ary) + 1;
- }
- if (offset < 0) {
- length += offset;
- offset = 0;
- if (length < 0)
- length = 0;
- }
- if (offset > AvFILL(ary) + 1)
- offset = AvFILL(ary) + 1;
- after = AvFILL(ary) + 1 - (offset + length);
- if (after < 0) { /* not that much array */
- length += after; /* offset+length now in array */
- after = 0;
- if (!AvALLOC(ary)) {
- av_fill(ary, 0);
- av_fill(ary, -1);
- }
- }
-
- /* At this point, MARK .. SP-1 is our new LIST */
-
- newlen = SP - MARK;
- diff = newlen - length;
-
- if (diff < 0) { /* shrinking the area */
- if (newlen) {
- New(451, tmparyval, newlen, SV*); /* so remember insertion */
- Copy(MARK, tmparyval, newlen, SV*);
- }
-
- MARK = ORIGMARK + 1;
- if (GIMME == G_ARRAY) { /* copy return vals to stack */
- MEXTEND(MARK, length);
- Copy(AvARRAY(ary)+offset, MARK, length, SV*);
- if (AvREAL(ary)) {
- for (i = length, dst = MARK; i; i--)
- sv_2mortal(*dst++); /* free them eventualy */
- }
- MARK += length - 1;
- }
- else {
- *MARK = AvARRAY(ary)[offset+length-1];
- if (AvREAL(ary)) {
- sv_2mortal(*MARK);
- for (i = length - 1, dst = &AvARRAY(ary)[offset]; i > 0; i--)
- SvREFCNT_dec(*dst++); /* free them now */
- }
- }
- AvFILL(ary) += diff;
-
- /* pull up or down? */
-
- if (offset < after) { /* easier to pull up */
- if (offset) { /* esp. if nothing to pull */
- src = &AvARRAY(ary)[offset-1];
- dst = src - diff; /* diff is negative */
- for (i = offset; i > 0; i--) /* can't trust Copy */
- *dst-- = *src--;
- }
- Zero(AvARRAY(ary), -diff, SV*);
- SvPVX(ary) = (char*)(AvARRAY(ary) - diff); /* diff is negative */
- AvMAX(ary) += diff;
- }
- else {
- if (after) { /* anything to pull down? */
- src = AvARRAY(ary) + offset + length;
- dst = src + diff; /* diff is negative */
- Move(src, dst, after, SV*);
- }
- Zero(&AvARRAY(ary)[AvFILL(ary)+1], -diff, SV*);
- /* avoid later double free */
- }
- if (newlen) {
- for (src = tmparyval, dst = AvARRAY(ary) + offset;
- newlen; newlen--) {
- *dst = NEWSV(46, 0);
- sv_setsv(*dst++, *src++);
- }
- Safefree(tmparyval);
- }
- }
- else { /* no, expanding (or same) */
- if (length) {
- New(452, tmparyval, length, SV*); /* so remember deletion */
- Copy(AvARRAY(ary)+offset, tmparyval, length, SV*);
- }
-
- if (diff > 0) { /* expanding */
-
- /* push up or down? */
-
- if (offset < after && diff <= AvARRAY(ary) - AvALLOC(ary)) {
- if (offset) {
- src = AvARRAY(ary);
- dst = src - diff;
- Move(src, dst, offset, SV*);
- }
- SvPVX(ary) = (char*)(AvARRAY(ary) - diff);/* diff is positive */
- AvMAX(ary) += diff;
- AvFILL(ary) += diff;
- }
- else {
- if (AvFILL(ary) + diff >= AvMAX(ary)) /* oh, well */
- av_store(ary, AvFILL(ary) + diff, Nullsv);
- else
- AvFILL(ary) += diff;
- dst = AvARRAY(ary) + AvFILL(ary);
- for (i = diff; i > 0; i--) {
- if (*dst) /* stuff was hanging around */
- SvREFCNT_dec(*dst); /* after $#foo */
- dst--;
- }
- if (after) {
- dst = AvARRAY(ary) + AvFILL(ary);
- src = dst - diff;
- for (i = after; i; i--) {
- *dst-- = *src--;
- }
- }
- }
- }
-
- for (src = MARK, dst = AvARRAY(ary) + offset; newlen; newlen--) {
- *dst = NEWSV(46, 0);
- sv_setsv(*dst++, *src++);
- }
- MARK = ORIGMARK + 1;
- if (GIMME == G_ARRAY) { /* copy return vals to stack */
- if (length) {
- Copy(tmparyval, MARK, length, SV*);
- if (AvREAL(ary)) {
- for (i = length, dst = MARK; i; i--)
- sv_2mortal(*dst++); /* free them eventualy */
- }
- Safefree(tmparyval);
- }
- MARK += length - 1;
- }
- else if (length--) {
- *MARK = tmparyval[length];
- if (AvREAL(ary)) {
- sv_2mortal(*MARK);
- while (length-- > 0)
- SvREFCNT_dec(tmparyval[length]);
- }
- Safefree(tmparyval);
- }
- else
- *MARK = &sv_undef;
- }
- SP = MARK;
- RETURN;
-}
-
-PP(pp_push)
-{
- dSP; dMARK; dORIGMARK; dTARGET;
- register AV *ary = (AV*)*++MARK;
- register SV *sv = &sv_undef;
-
- for (++MARK; MARK <= SP; MARK++) {
- sv = NEWSV(51, 0);
- if (*MARK)
- sv_setsv(sv, *MARK);
- (void)av_push(ary, sv);
- }
- SP = ORIGMARK;
- PUSHi( AvFILL(ary) + 1 );
- RETURN;
-}
-
-PP(pp_pop)
-{
- dSP;
- AV *av = (AV*)POPs;
- SV *sv = av_pop(av);
- if (!sv)
- RETPUSHUNDEF;
- if (AvREAL(av))
- (void)sv_2mortal(sv);
- PUSHs(sv);
- RETURN;
-}
-
-PP(pp_shift)
-{
- dSP;
- AV *av = (AV*)POPs;
- SV *sv = av_shift(av);
- EXTEND(SP, 1);
- if (!sv)
- RETPUSHUNDEF;
- if (AvREAL(av))
- (void)sv_2mortal(sv);
- PUSHs(sv);
- RETURN;
-}
-
-PP(pp_unshift)
-{
- dSP; dMARK; dORIGMARK; dTARGET;
- register AV *ary = (AV*)*++MARK;
- register SV *sv;
- register I32 i = 0;
-
- av_unshift(ary, SP - MARK);
- while (MARK < SP) {
- sv = NEWSV(27, 0);
- sv_setsv(sv, *++MARK);
- (void)av_store(ary, i++, sv);
- }
-
- SP = ORIGMARK;
- PUSHi( AvFILL(ary) + 1 );
- RETURN;
-}
-
-PP(pp_grepstart)
-{
- dSP;
- SV *src;
-
- if (stack_base + *markstack_ptr == sp) {
- POPMARK;
- RETURNOP(op->op_next->op_next);
- }
- stack_sp = stack_base + *markstack_ptr + 1;
- pp_pushmark(); /* push dst */
- pp_pushmark(); /* push src */
- ENTER; /* enter outer scope */
-
- SAVETMPS;
- SAVESPTR(GvSV(defgv));
-
- ENTER; /* enter inner scope */
- SAVESPTR(curpm);
-
- if (src = stack_base[*markstack_ptr]) {
- SvTEMP_off(src);
- GvSV(defgv) = src;
- }
- else
- GvSV(defgv) = sv_newmortal();
-
- RETURNOP(((LOGOP*)op->op_next)->op_other);
-}
-
-PP(pp_grepwhile)
-{
- dSP;
-
- if (SvTRUEx(POPs))
- stack_base[markstack_ptr[-1]++] = stack_base[*markstack_ptr];
- ++*markstack_ptr;
- LEAVE; /* exit inner scope */
-
- /* All done yet? */
- if (stack_base + *markstack_ptr > sp) {
- I32 items;
-
- LEAVE; /* exit outer scope */
- POPMARK; /* pop src */
- items = --*markstack_ptr - markstack_ptr[-1];
- POPMARK; /* pop dst */
- SP = stack_base + POPMARK; /* pop original mark */
- if (GIMME != G_ARRAY) {
- dTARGET;
- XPUSHi(items);
- RETURN;
- }
- SP += items;
- RETURN;
- }
- else {
- SV *src;
-
- ENTER; /* enter inner scope */
- SAVESPTR(curpm);
-
- if (src = stack_base[*markstack_ptr]) {
- SvTEMP_off(src);
- GvSV(defgv) = src;
- }
- else
- GvSV(defgv) = sv_newmortal();
-
- RETURNOP(cLOGOP->op_other);
- }
-}
-
-static int sortcmp();
-static int sortcv();
-
-PP(pp_sort)
-{
- dSP; dMARK; dORIGMARK;
- register SV **up;
- SV **myorigmark = ORIGMARK;
- register I32 max;
- register I32 i;
- HV *stash;
- SV *sortcvvar;
- GV *gv;
- CV *cv;
-
- if (GIMME != G_ARRAY) {
- SP = MARK;
- RETPUSHUNDEF;
- }
-
- if (op->op_flags & OPf_STACKED) {
- ENTER;
- if (op->op_flags & OPf_SPECIAL) {
- OP *kid = cLISTOP->op_first->op_sibling; /* pass pushmark */
- kid = kUNOP->op_first; /* pass rv2gv */
- kid = kUNOP->op_first; /* pass leave */
- sortcop = kid->op_next;
- stash = curcop->cop_stash;
- }
- else {
- cv = sv_2cv(*++MARK, &stash, &gv, 0);
- if (!(cv && CvROOT(cv))) {
- if (gv) {
- SV *tmpstr = sv_newmortal();
- gv_efullname(tmpstr, gv);
- if (CvUSERSUB(cv))
- DIE("Usersub \"%s\" called in sort", SvPVX(tmpstr));
- DIE("Undefined sort subroutine \"%s\" called",
- SvPVX(tmpstr));
- }
- if (cv) {
- if (CvUSERSUB(cv))
- DIE("Usersub called in sort");
- DIE("Undefined subroutine in sort");
- }
- DIE("Not a subroutine reference in sort");
- }
- sortcop = CvSTART(cv);
- SAVESPTR(CvROOT(cv)->op_ppaddr);
- CvROOT(cv)->op_ppaddr = ppaddr[OP_NULL];
-
- SAVESPTR(curpad);
- curpad = AvARRAY((AV*)AvARRAY(CvPADLIST(cv))[1]);
- }
- }
- else {
- sortcop = Nullop;
- stash = curcop->cop_stash;
- }
-
- up = myorigmark + 1;
- while (MARK < SP) { /* This may or may not shift down one here. */
- /*SUPPRESS 560*/
- if (*up = *++MARK) { /* Weed out nulls. */
- if (!SvPOK(*up))
- (void)sv_2pv(*up, &na);
- else
- SvTEMP_off(*up);
- up++;
- }
- }
- max = --up - myorigmark;
- if (max > 1) {
- if (sortcop) {
- AV *oldstack;
-
- SAVETMPS;
- SAVESPTR(op);
-
- oldstack = stack;
- if (!sortstack) {
- sortstack = newAV();
- av_store(sortstack, 32, Nullsv);
- av_clear(sortstack);
- AvREAL_off(sortstack);
- }
- SWITCHSTACK(stack, sortstack);
- if (sortstash != stash) {
- firstgv = gv_fetchpv("a", TRUE, SVt_PV);
- secondgv = gv_fetchpv("b", TRUE, SVt_PV);
- sortstash = stash;
- }
-
- SAVESPTR(GvSV(firstgv));
- SAVESPTR(GvSV(secondgv));
-
- qsort((char*)(myorigmark+1), max, sizeof(SV*), sortcv);
-
- SWITCHSTACK(sortstack, oldstack);
-
- LEAVE;
- }
- else {
- MEXTEND(SP, 20); /* Can't afford stack realloc on signal. */
- qsort((char*)(ORIGMARK+1), max, sizeof(SV*), sortcmp);
- }
- }
- SP = ORIGMARK + max;
- RETURN;
-}
-
-PP(pp_reverse)
-{
- dSP; dMARK;
- register SV *tmp;
- SV **oldsp = SP;
-
- if (GIMME == G_ARRAY) {
- MARK++;
- while (MARK < SP) {
- tmp = *MARK;
- *MARK++ = *SP;
- *SP-- = tmp;
- }
- SP = oldsp;
- }
- else {
- register char *up;
- register char *down;
- register I32 tmp;
- dTARGET;
- STRLEN len;
-
- if (SP - MARK > 1)
- do_join(TARG, &sv_no, MARK, SP);
- else
- sv_setsv(TARG, *SP);
- up = SvPV(TARG, len);
- if (len > 1) {
- down = SvPVX(TARG) + len - 1;
- while (down > up) {
- tmp = *up;
- *up++ = *down;
- *down-- = tmp;
- }
- SvPOK_only(TARG);
- }
- SP = MARK + 1;
- SETTARG;
- }
- RETURN;
-}
-
-/* Range stuff. */
-
-PP(pp_range)
-{
- if (GIMME == G_ARRAY)
- return cCONDOP->op_true;
- return SvTRUEx(PAD_SV(op->op_targ)) ? cCONDOP->op_false : cCONDOP->op_true;
-}
-
-PP(pp_flip)
-{
- dSP;
-
- if (GIMME == G_ARRAY) {
- RETURNOP(((CONDOP*)cUNOP->op_first)->op_false);
- }
- else {
- dTOPss;
- SV *targ = PAD_SV(op->op_targ);
-
- if ((op->op_private & OPpFLIP_LINENUM)
- ? last_in_gv && SvIV(sv) == IoLINES(GvIO(last_in_gv))
- : SvTRUE(sv) ) {
- sv_setiv(PAD_SV(cUNOP->op_first->op_targ), 1);
- if (op->op_flags & OPf_SPECIAL) {
- sv_setiv(targ, 1);
- RETURN;
- }
- else {
- sv_setiv(targ, 0);
- sp--;
- RETURNOP(((CONDOP*)cUNOP->op_first)->op_false);
- }
- }
- sv_setpv(TARG, "");
- SETs(targ);
+ if (iters || !pm->op_pmreplroot) {
+ GETTARGET;
+ PUSHi(iters);
RETURN;
}
-}
-
-PP(pp_flop)
-{
- dSP;
-
- if (GIMME == G_ARRAY) {
- dPOPPOPssrl;
- register I32 i;
- register SV *sv;
- I32 max;
-
- if (SvNIOK(lstr) || !SvPOK(lstr) ||
- (looks_like_number(lstr) && *SvPVX(lstr) != '0') ) {
- i = SvIV(lstr);
- max = SvIV(rstr);
- if (max > i)
- EXTEND(SP, max - i + 1);
- while (i <= max) {
- sv = sv_mortalcopy(&sv_no);
- sv_setiv(sv,i++);
- PUSHs(sv);
- }
- }
- else {
- SV *final = sv_mortalcopy(rstr);
- STRLEN len;
- char *tmps = SvPV(final, len);
-
- sv = sv_mortalcopy(lstr);
- while (!SvNIOK(sv) && SvCUR(sv) <= len &&
- strNE(SvPVX(sv),tmps) ) {
- XPUSHs(sv);
- sv = sv_2mortal(newSVsv(sv));
- sv_inc(sv);
- }
- if (strEQ(SvPVX(sv),tmps))
- XPUSHs(sv);
- }
- }
- else {
- dTOPss;
- SV *targ = PAD_SV(cUNOP->op_first->op_targ);
- sv_inc(targ);
- if ((op->op_private & OPpFLIP_LINENUM)
- ? last_in_gv && SvIV(sv) == IoLINES(GvIO(last_in_gv))
- : SvTRUE(sv) ) {
- sv_setiv(PAD_SV(((UNOP*)cUNOP->op_first)->op_first->op_targ), 0);
- sv_catpv(targ, "E0");
- }
- SETs(targ);
- }
-
- RETURN;
-}
-
-/* Control. */
-
-static I32
-dopoptolabel(label)
-char *label;
-{
- register I32 i;
- register CONTEXT *cx;
-
- for (i = cxstack_ix; i >= 0; i--) {
- cx = &cxstack[i];
- switch (cx->cx_type) {
- case CXt_SUBST:
- if (dowarn)
- warn("Exiting substitution via %s", op_name[op->op_type]);
- break;
- case CXt_SUB:
- if (dowarn)
- warn("Exiting subroutine via %s", op_name[op->op_type]);
- break;
- case CXt_EVAL:
- if (dowarn)
- warn("Exiting eval via %s", op_name[op->op_type]);
- break;
- case CXt_LOOP:
- if (!cx->blk_loop.label ||
- strNE(label, cx->blk_loop.label) ) {
- DEBUG_l(deb("(Skipping label #%d %s)\n",
- i, cx->blk_loop.label));
- continue;
- }
- DEBUG_l( deb("(Found label #%d %s)\n", i, label));
- return i;
- }
- }
-}
-
-static I32
-dopoptosub(startingblock)
-I32 startingblock;
-{
- I32 i;
- register CONTEXT *cx;
- for (i = startingblock; i >= 0; i--) {
- cx = &cxstack[i];
- switch (cx->cx_type) {
- default:
- continue;
- case CXt_EVAL:
- case CXt_SUB:
- DEBUG_l( deb("(Found sub #%d)\n", i));
- return i;
- }
- }
- return i;
-}
-
-I32
-dopoptoeval(startingblock)
-I32 startingblock;
-{
- I32 i;
- register CONTEXT *cx;
- for (i = startingblock; i >= 0; i--) {
- cx = &cxstack[i];
- switch (cx->cx_type) {
- default:
- continue;
- case CXt_EVAL:
- DEBUG_l( deb("(Found eval #%d)\n", i));
- return i;
- }
- }
- return i;
-}
-
-static I32
-dopoptoloop(startingblock)
-I32 startingblock;
-{
- I32 i;
- register CONTEXT *cx;
- for (i = startingblock; i >= 0; i--) {
- cx = &cxstack[i];
- switch (cx->cx_type) {
- case CXt_SUBST:
- if (dowarn)
- warn("Exiting substitition via %s", op_name[op->op_type]);
- break;
- case CXt_SUB:
- if (dowarn)
- warn("Exiting subroutine via %s", op_name[op->op_type]);
- break;
- case CXt_EVAL:
- if (dowarn)
- warn("Exiting eval via %s", op_name[op->op_type]);
- break;
- case CXt_LOOP:
- DEBUG_l( deb("(Found loop #%d)\n", i));
- return i;
- }
- }
- return i;
-}
-
-static void
-dounwind(cxix)
-I32 cxix;
-{
- register CONTEXT *cx;
- SV **newsp;
- I32 optype;
-
- while (cxstack_ix > cxix) {
- cx = &cxstack[cxstack_ix--];
- DEBUG_l(fprintf(stderr, "Unwinding block %d, type %s\n", cxstack_ix+1,
- block_type[cx->cx_type]));
- /* Note: we don't need to restore the base context info till the end. */
- switch (cx->cx_type) {
- case CXt_SUB:
- POPSUB(cx);
- break;
- case CXt_EVAL:
- POPEVAL(cx);
- break;
- case CXt_LOOP:
- POPLOOP(cx);
- break;
- case CXt_SUBST:
- break;
- }
- }
-}
-
-#ifdef STANDARD_C
-OP *
-die(char* pat, ...)
-#else
-/*VARARGS0*/
-OP *
-die(pat, va_alist)
- char *pat;
- va_dcl
-#endif
-{
- va_list args;
- char *tmps;
- char *message;
- OP *retop;
-
-#ifdef STANDARD_C
- va_start(args, pat);
-#else
- va_start(args);
-#endif
- message = mess(pat, &args);
- va_end(args);
- restartop = die_where(message);
- if (stack != mainstack)
- longjmp(top_env, 3);
- return restartop;
-}
-
-OP *
-die_where(message)
-char *message;
-{
- if (in_eval) {
- I32 cxix;
- register CONTEXT *cx;
- I32 gimme;
- SV **newsp;
-
- sv_setpv(GvSV(gv_fetchpv("@",TRUE, SVt_PV)),message);
- cxix = dopoptoeval(cxstack_ix);
- if (cxix >= 0) {
- I32 optype;
-
- if (cxix < cxstack_ix)
- dounwind(cxix);
-
- POPBLOCK(cx);
- if (cx->cx_type != CXt_EVAL) {
- fprintf(stderr, "panic: die %s", message);
- my_exit(1);
- }
- POPEVAL(cx);
-
- if (gimme == G_SCALAR)
- *++newsp = &sv_undef;
- stack_sp = newsp;
-
- LEAVE;
- if (optype == OP_REQUIRE)
- DIE("%s", SvPVx(GvSV(gv_fetchpv("@",TRUE, SVt_PV)), na));
- return pop_return();
- }
- }
- fputs(message, stderr);
- (void)fflush(stderr);
- if (e_fp)
- (void)UNLINK(e_tmpname);
- statusvalue >>= 8;
- my_exit((I32)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
- return 0;
-}
-
-PP(pp_and)
-{
- dSP;
- if (!SvTRUE(TOPs))
- RETURN;
- else {
- --SP;
- RETURNOP(cLOGOP->op_other);
- }
-}
-
-PP(pp_or)
-{
- dSP;
- if (SvTRUE(TOPs))
- RETURN;
- else {
- --SP;
- RETURNOP(cLOGOP->op_other);
- }
-}
-
-PP(pp_cond_expr)
-{
- dSP;
- if (SvTRUEx(POPs))
- RETURNOP(cCONDOP->op_true);
- else
- RETURNOP(cCONDOP->op_false);
-}
-
-PP(pp_andassign)
-{
- dSP;
- if (!SvTRUE(TOPs))
- RETURN;
- else
- RETURNOP(cLOGOP->op_other);
-}
-
-PP(pp_orassign)
-{
- dSP;
- if (SvTRUE(TOPs))
- RETURN;
- else
- RETURNOP(cLOGOP->op_other);
-}
-
-PP(pp_method)
-{
- dSP; dPOPss;
- SV* ob;
- GV* gv;
-
- EXTEND(sp,2);
-
- gv = 0;
- if (SvROK(sv))
- ob = SvRV(sv);
- else {
- GV* iogv;
- IO* io;
-
- if (!SvOK(sv) ||
- !(iogv = gv_fetchpv(SvPVX(sv), FALSE, SVt_PVIO)) ||
- !(ob=(SV*)GvIO(iogv)))
- {
- char *name = SvPVX(((SVOP*)cLOGOP->op_other)->op_sv);
- char tmpbuf[256];
- char* packname = SvPV(sv, na);
- HV *stash;
- if (!isALPHA(*packname))
-DIE("Can't call method \"%s\" without a package or object reference", name);
- if (!(stash = fetch_stash(sv, FALSE)))
- DIE("Can't call method \"%s\" in empty package \"%s\"",
- name, packname);
- gv = gv_fetchmethod(stash,name);
- if (!gv)
- DIE("Can't locate object method \"%s\" via package \"%s\"",
- name, packname);
- PUSHs(gv);
- PUSHs(sv);
- RETURN;
- }
- }
-
- if (!ob || !SvOBJECT(ob)) {
- char *name = SvPVX(((SVOP*)cLOGOP->op_other)->op_sv);
- DIE("Can't call method \"%s\" on unblessed reference", name);
- }
-
- if (!gv) { /* nothing cached */
- char *name = SvPVX(((SVOP*)cLOGOP->op_other)->op_sv);
- gv = gv_fetchmethod(SvSTASH(ob),name);
- if (!gv)
- DIE("Can't locate object method \"%s\" via package \"%s\"",
- name, HvNAME(SvSTASH(ob)));
- }
-
- PUSHs(gv);
- PUSHs(sv);
- RETURN;
-}
-
-PP(pp_entersubr)
-{
- dSP; dMARK;
- SV *sv = *++MARK;
- GV *gv;
- HV *stash;
- register CV *cv;
- register I32 items = SP - MARK;
- I32 hasargs = (op->op_flags & OPf_STACKED) != 0;
- register CONTEXT *cx;
-
- if (!sv)
- DIE("Not a subroutine reference");
- switch (SvTYPE(sv)) {
- default:
- if (!SvROK(sv)) {
- if (!SvOK(sv))
- DIE(no_usym, "a subroutine");
- if (op->op_private & HINT_STRICT_REFS)
- DIE(no_hardref, "a subroutine");
- gv = gv_fetchpv(SvPV(sv, na), FALSE, SVt_PVCV);
- if (!gv)
- cv = 0;
- else
- cv = GvCV(gv);
- break;
- }
- /* FALL THROUGH */
- case SVt_RV:
- cv = (CV*)SvRV(sv);
- if (SvTYPE(cv) == SVt_PVCV)
- break;
- /* FALL THROUGH */
- case SVt_PVHV:
- case SVt_PVAV:
- DIE("Not a subroutine reference");
- case SVt_PVCV:
- cv = (CV*)sv;
- break;
- case SVt_PVGV:
- if (!(cv = GvCV((GV*)sv)))
- cv = sv_2cv(sv, &stash, &gv, TRUE);
- break;
- }
-
- ENTER;
- SAVETMPS;
-
- retry:
- if (!cv)
- DIE("Not a subroutine reference");
-
- if (!CvROOT(cv) && !CvUSERSUB(cv)) {
- if (gv = CvGV(cv)) {
- SV *tmpstr = sv_newmortal();
- GV *ngv;
- gv_efullname(tmpstr, gv);
- ngv = gv_fetchmethod(GvESTASH(gv), "AUTOLOAD");
- if (ngv && ngv != gv && (cv = GvCV(ngv))) { /* One more chance... */
- gv = ngv;
- sv_setsv(GvSV(gv), tmpstr);
- goto retry;
- }
- else
- DIE("Undefined subroutine &%s called",SvPVX(tmpstr));
- }
- DIE("Undefined subroutine called");
- }
-
- if ((op->op_private & OPpDEREF_DB) && !CvUSERSUB(cv)) {
- sv = GvSV(DBsub);
- save_item(sv);
- gv = CvGV(cv);
- gv_efullname(sv,gv);
- cv = GvCV(DBsub);
- if (!cv)
- DIE("No DBsub routine");
- }
-
- if (CvUSERSUB(cv)) {
- items = (*CvUSERSUB(cv))(CvUSERINDEX(cv), MARK - stack_base, items);
- sp = stack_base + items;
- LEAVE;
- RETURN;
- }
- else {
- I32 gimme = GIMME;
- AV* padlist = CvPADLIST(cv);
- SV** svp = AvARRAY(padlist);
- push_return(op->op_next);
- PUSHBLOCK(cx, CXt_SUB, MARK - 1);
- PUSHSUB(cx);
- CvDEPTH(cv)++;
- if (CvDEPTH(cv) >= 2) { /* save temporaries on recursion? */
- if (CvDEPTH(cv) == 100 && dowarn)
- warn("Deep recursion on subroutine \"%s\"",GvENAME(CvGV(cv)));
- if (CvDEPTH(cv) > AvFILL(padlist)) {
- AV *newpad = newAV();
- I32 ix = AvFILL((AV*)svp[1]);
- svp = AvARRAY(svp[0]);
- while (ix > 0) {
- if (svp[ix]) {
- char *name = SvPVX(svp[ix]); /* XXX */
- if (*name == '@')
- av_store(newpad, ix--, (SV*)newAV());
- else if (*name == '%')
- av_store(newpad, ix--, (SV*)newHV());
- else
- av_store(newpad, ix--, NEWSV(0,0));
- }
- else
- av_store(newpad, ix--, NEWSV(0,0));
- }
- if (hasargs) {
- AV* av = newAV();
- av_store(av, 0, Nullsv);
- av_store(newpad, 0, (SV*)av);
- SvOK_on(av);
- AvREAL_off(av);
- }
- av_store(padlist, CvDEPTH(cv), (SV*)newpad);
- AvFILL(padlist) = CvDEPTH(cv);
- svp = AvARRAY(padlist);
- }
- }
- SAVESPTR(curpad);
- curpad = AvARRAY((AV*)svp[CvDEPTH(cv)]);
- if (hasargs) {
- AV* av = (AV*)curpad[0];
- SV** ary;
-
- cx->blk_sub.savearray = GvAV(defgv);
- cx->blk_sub.argarray = av;
- GvAV(defgv) = cx->blk_sub.argarray;
- ++MARK;
-
- if (items >= AvMAX(av)) {
- ary = AvALLOC(av);
- if (AvARRAY(av) != ary) {
- AvMAX(av) += AvARRAY(av) - AvALLOC(av);
- SvPVX(av) = (char*)ary;
- }
- if (items >= AvMAX(av)) {
- AvMAX(av) = items - 1;
- Renew(ary,items+1,SV*);
- AvALLOC(av) = ary;
- SvPVX(av) = (char*)ary;
- }
- }
- Copy(MARK,AvARRAY(av),items,SV*);
- AvFILL(av) = items - 1;
- while (items--) {
- if (*MARK)
- SvTEMP_off(*MARK);
- MARK++;
- }
- }
- RETURNOP(CvSTART(cv));
- }
-}
-
-PP(pp_leavesubr)
-{
- dSP;
- SV **mark;
- SV **newsp;
- I32 gimme;
- register CONTEXT *cx;
-
- POPBLOCK(cx);
- POPSUB(cx);
-
- if (gimme == G_SCALAR) {
- MARK = newsp + 1;
- if (MARK <= SP)
- if (SvFLAGS(TOPs) & (SVs_PADTMP|SVs_TEMP))
- *MARK = TOPs;
- else
- *MARK = sv_mortalcopy(TOPs);
- else {
- MEXTEND(mark,0);
- *MARK = &sv_undef;
- }
- SP = MARK;
- }
- else {
- for (mark = newsp + 1; mark <= SP; mark++)
- if (!(SvFLAGS(*mark) & (SVs_PADTMP|SVs_TEMP)))
- *mark = sv_mortalcopy(*mark);
- /* in case LEAVE wipes old return values */
- }
-
- LEAVE;
- PUTBACK;
- return pop_return();
-}
-
-PP(pp_done)
-{
- return pop_return();
-}
-
-PP(pp_caller)
-{
- dSP;
- register I32 cxix = dopoptosub(cxstack_ix);
- I32 nextcxix;
- register CONTEXT *cx;
- SV *sv;
- I32 count = 0;
-
- if (MAXARG)
- count = POPi;
- EXTEND(SP, 6);
- for (;;) {
- if (cxix < 0) {
- if (GIMME != G_ARRAY)
- RETPUSHUNDEF;
- RETURN;
- }
- nextcxix = dopoptosub(cxix - 1);
- if (DBsub && nextcxix >= 0 &&
- cxstack[nextcxix].blk_sub.cv == GvCV(DBsub))
- count++;
- if (!count--)
- break;
- cxix = nextcxix;
- }
- cx = &cxstack[cxix];
- if (GIMME != G_ARRAY) {
- dTARGET;
-
- sv_setpv(TARG, HvNAME(cx->blk_oldcop->cop_stash));
- PUSHs(TARG);
- RETURN;
- }
-
- PUSHs(sv_2mortal(newSVpv(HvNAME(cx->blk_oldcop->cop_stash), 0)));
- PUSHs(sv_2mortal(newSVpv(SvPVX(GvSV(cx->blk_oldcop->cop_filegv)), 0)));
- PUSHs(sv_2mortal(newSViv((I32)cx->blk_oldcop->cop_line)));
- if (!MAXARG)
- RETURN;
- if (cx->cx_type == CXt_SUB) {
- sv = NEWSV(49, 0);
- gv_efullname(sv, CvGV(cx->blk_sub.cv));
- PUSHs(sv_2mortal(sv));
- PUSHs(sv_2mortal(newSViv((I32)cx->blk_sub.hasargs)));
- }
- else {
- PUSHs(sv_2mortal(newSVpv("(eval)",0)));
- PUSHs(sv_2mortal(newSViv(0)));
- }
- PUSHs(sv_2mortal(newSViv((I32)cx->blk_gimme)));
- if (cx->blk_sub.hasargs && curstash == debstash) {
- AV *ary = cx->blk_sub.argarray;
-
- if (!dbargs) {
- GV* tmpgv;
- dbargs = GvAV(gv_AVadd(tmpgv = gv_fetchpv("DB::args", TRUE,
- SVt_PVAV)));
- SvMULTI_on(tmpgv);
- AvREAL_off(dbargs);
- }
- if (AvMAX(dbargs) < AvFILL(ary))
- av_store(dbargs, AvFILL(ary), Nullsv);
- Copy(AvARRAY(ary), AvARRAY(dbargs), AvFILL(ary)+1, SV*);
- AvFILL(dbargs) = AvFILL(ary);
- }
- RETURN;
-}
-
-static I32
-sortcv(str1, str2)
-SV **str1;
-SV **str2;
-{
- I32 oldscopeix = scopestack_ix;
- I32 result;
- GvSV(firstgv) = *str1;
- GvSV(secondgv) = *str2;
- stack_sp = stack_base;
- op = sortcop;
- run();
- result = SvIVx(AvARRAY(stack)[1]);
- while (scopestack_ix > oldscopeix) {
- LEAVE;
- }
- return result;
-}
-
-static I32
-sortcmp(strp1, strp2)
-SV **strp1;
-SV **strp2;
-{
- register SV *str1 = *strp1;
- register SV *str2 = *strp2;
- I32 retval;
-
- if (SvCUR(str1) < SvCUR(str2)) {
- /*SUPPRESS 560*/
- if (retval = memcmp(SvPVX(str1), SvPVX(str2), SvCUR(str1)))
- return retval;
- else
- return -1;
- }
- /*SUPPRESS 560*/
- else if (retval = memcmp(SvPVX(str1), SvPVX(str2), SvCUR(str2)))
- return retval;
- else if (SvCUR(str1) == SvCUR(str2))
- return 0;
- else
- return 1;
-}
-
-PP(pp_warn)
-{
- dSP; dMARK;
- char *tmps;
- if (SP - MARK != 1) {
- dTARGET;
- do_join(TARG, &sv_no, MARK, SP);
- tmps = SvPV(TARG, na);
- SP = MARK + 1;
- }
- else {
- tmps = SvPV(TOPs, na);
- }
- if (!tmps || !*tmps) {
- SV *error = GvSV(gv_fetchpv("@", TRUE, SVt_PV));
- SvUPGRADE(error, SVt_PV);
- if (SvPOK(error) && SvCUR(error))
- sv_catpv(error, "\t...caught");
- tmps = SvPV(error, na);
- }
- if (!tmps || !*tmps)
- tmps = "Warning: something's wrong";
- warn("%s", tmps);
- RETSETYES;
-}
-
-PP(pp_die)
-{
- dSP; dMARK;
- char *tmps;
- if (SP - MARK != 1) {
- dTARGET;
- do_join(TARG, &sv_no, MARK, SP);
- tmps = SvPV(TARG, na);
- SP = MARK + 1;
- }
- else {
- tmps = SvPV(TOPs, na);
- }
- if (!tmps || !*tmps) {
- SV *error = GvSV(gv_fetchpv("@", TRUE, SVt_PV));
- SvUPGRADE(error, SVt_PV);
- if (SvPOK(error) && SvCUR(error))
- sv_catpv(error, "\t...propagated");
- tmps = SvPV(error, na);
- }
- if (!tmps || !*tmps)
- tmps = "Died";
- DIE("%s", tmps);
-}
-
-PP(pp_reset)
-{
- dSP;
- double value;
- char *tmps;
-
- if (MAXARG < 1)
- tmps = "";
- else
- tmps = POPp;
- sv_reset(tmps, curcop->cop_stash);
- PUSHs(&sv_yes);
- RETURN;
-}
-
-PP(pp_lineseq)
-{
- return NORMAL;
-}
-
-PP(pp_nextstate)
-{
- curcop = (COP*)op;
- TAINT_NOT; /* Each statement is presumed innocent */
- stack_sp = stack_base + cxstack[cxstack_ix].blk_oldsp;
- FREE_TMPS();
- return NORMAL;
-}
-
-PP(pp_dbstate)
-{
- curcop = (COP*)op;
- TAINT_NOT; /* Each statement is presumed innocent */
- stack_sp = stack_base + cxstack[cxstack_ix].blk_oldsp;
- FREE_TMPS();
-
- if (op->op_private || SvIV(DBsingle) || SvIV(DBsignal) || SvIV(DBtrace))
- {
- SV **sp;
- register CV *cv;
- register CONTEXT *cx;
- I32 gimme = GIMME;
- I32 hasargs;
- GV *gv;
-
- ENTER;
- SAVETMPS;
-
- SAVEI32(debug);
- debug = 0;
- hasargs = 0;
- gv = DBgv;
- cv = GvCV(gv);
- sp = stack_sp;
- *++sp = Nullsv;
-
- if (!cv)
- DIE("No DB::DB routine defined");
-
- if (CvDEPTH(cv) >= 1) /* don't do recursive DB::DB call */
- return NORMAL;
- push_return(op->op_next);
- PUSHBLOCK(cx, CXt_SUB, sp - 1);
- PUSHSUB(cx);
- CvDEPTH(cv)++;
- SAVESPTR(curpad);
- curpad = AvARRAY((AV*)*av_fetch(CvPADLIST(cv),1,FALSE));
- RETURNOP(CvSTART(cv));
- }
- else
- return NORMAL;
-}
-
-PP(pp_unstack)
-{
- I32 oldsave;
- TAINT_NOT; /* Each statement is presumed innocent */
- stack_sp = stack_base + cxstack[cxstack_ix].blk_oldsp;
- FREE_TMPS();
- oldsave = scopestack[scopestack_ix - 1];
- LEAVE_SCOPE(oldsave);
- return NORMAL;
-}
-
-PP(pp_enter)
-{
- dSP;
- register CONTEXT *cx;
- I32 gimme;
-
- /*
- * We don't just use the GIMME macro here because it assumes there's
- * already a context, which ain't necessarily so at initial startup.
- */
-
- if (op->op_flags & OPf_KNOW)
- gimme = op->op_flags & OPf_LIST;
- else if (cxstack_ix >= 0)
- gimme = cxstack[cxstack_ix].blk_gimme;
- else
- gimme = G_SCALAR;
-
- ENTER;
-
- SAVETMPS;
- PUSHBLOCK(cx, CXt_BLOCK, sp);
-
- RETURN;
-}
-
-PP(pp_leave)
-{
- dSP;
- register CONTEXT *cx;
- register SV **mark;
- SV **newsp;
- I32 gimme;
-
- POPBLOCK(cx);
-
- if (op->op_flags & OPf_KNOW)
- gimme = op->op_flags & OPf_LIST;
- else if (cxstack_ix >= 0)
- gimme = cxstack[cxstack_ix].blk_gimme;
- else
- gimme = G_SCALAR;
-
- if (gimme == G_SCALAR) {
- MARK = newsp + 1;
- if (MARK <= SP)
- if (SvFLAGS(TOPs) & (SVs_PADTMP|SVs_TEMP))
- *MARK = TOPs;
- else
- *MARK = sv_mortalcopy(TOPs);
- else {
- MEXTEND(mark,0);
- *MARK = &sv_undef;
- }
- SP = MARK;
- }
- else {
- for (mark = newsp + 1; mark <= SP; mark++)
- if (!(SvFLAGS(*mark) & (SVs_PADTMP|SVs_TEMP)))
- *mark = sv_mortalcopy(*mark);
- /* in case LEAVE wipes old return values */
- }
-
- LEAVE;
-
- RETURN;
-}
-
-PP(pp_scope)
-{
- return NORMAL;
-}
-
-PP(pp_enteriter)
-{
- dSP; dMARK;
- register CONTEXT *cx;
- I32 gimme = GIMME;
- SV **svp;
-
- if (op->op_targ)
- svp = &curpad[op->op_targ]; /* "my" variable */
- else
- svp = &GvSV((GV*)POPs); /* symbol table variable */
-
- ENTER;
- SAVETMPS;
- ENTER;
-
- PUSHBLOCK(cx, CXt_LOOP, SP);
- PUSHLOOP(cx, svp, MARK);
- cx->blk_loop.iterary = stack;
- cx->blk_loop.iterix = MARK - stack_base;
-
- RETURN;
-}
-
-PP(pp_iter)
-{
- dSP;
- register CONTEXT *cx;
- SV *sv;
-
- EXTEND(sp, 1);
- cx = &cxstack[cxstack_ix];
- if (cx->cx_type != CXt_LOOP)
- DIE("panic: pp_iter");
-
- if (cx->blk_loop.iterix >= cx->blk_oldsp)
- RETPUSHNO;
-
- if (sv = AvARRAY(cx->blk_loop.iterary)[++cx->blk_loop.iterix]) {
- SvTEMP_off(sv);
- *cx->blk_loop.itervar = sv;
- }
- else
- *cx->blk_loop.itervar = &sv_undef;
-
- RETPUSHYES;
-}
-
-PP(pp_enterloop)
-{
- dSP;
- register CONTEXT *cx;
- I32 gimme = GIMME;
-
- ENTER;
- SAVETMPS;
- ENTER;
-
- PUSHBLOCK(cx, CXt_LOOP, SP);
- PUSHLOOP(cx, 0, SP);
-
- RETURN;
-}
-
-PP(pp_leaveloop)
-{
- dSP;
- register CONTEXT *cx;
- I32 gimme;
- SV **newsp;
- SV **mark;
-
- POPBLOCK(cx);
- mark = newsp;
- POPLOOP(cx);
- if (gimme == G_SCALAR) {
- if (mark < SP)
- *++newsp = sv_mortalcopy(*SP);
- else
- *++newsp = &sv_undef;
- }
- else {
- while (mark < SP)
- *++newsp = sv_mortalcopy(*++mark);
- }
- sp = newsp;
- LEAVE;
- LEAVE;
-
- RETURN;
-}
-
-PP(pp_return)
-{
- dSP; dMARK;
- I32 cxix;
- register CONTEXT *cx;
- I32 gimme;
- SV **newsp;
- I32 optype = 0;
-
- if (stack == sortstack) {
- AvARRAY(stack)[1] = *SP;
- return 0;
- }
-
- cxix = dopoptosub(cxstack_ix);
- if (cxix < 0)
- DIE("Can't return outside a subroutine");
- if (cxix < cxstack_ix)
- dounwind(cxix);
-
- POPBLOCK(cx);
- switch (cx->cx_type) {
- case CXt_SUB:
- POPSUB(cx);
- break;
- case CXt_EVAL:
- POPEVAL(cx);
- break;
- default:
- DIE("panic: return");
- break;
- }
-
- if (gimme == G_SCALAR) {
- if (MARK < SP)
- *++newsp = sv_mortalcopy(*SP);
- else
- *++newsp = &sv_undef;
- if (optype == OP_REQUIRE && !SvTRUE(*newsp))
- DIE("%s", SvPVx(GvSV(gv_fetchpv("@",TRUE, SVt_PV)), na));
- }
- else {
- if (optype == OP_REQUIRE && MARK == SP)
- DIE("%s", SvPVx(GvSV(gv_fetchpv("@",TRUE, SVt_PV)), na));
- while (MARK < SP)
- *++newsp = sv_mortalcopy(*++MARK);
- }
- stack_sp = newsp;
-
- LEAVE;
- return pop_return();
-}
-
-PP(pp_last)
-{
- dSP;
- I32 cxix;
- register CONTEXT *cx;
- I32 gimme;
- I32 optype;
- OP *nextop;
- SV **newsp;
- SV **mark = stack_base + cxstack[cxstack_ix].blk_oldsp;
- /* XXX The sp is probably not right yet... */
-
- if (op->op_flags & OPf_SPECIAL) {
- cxix = dopoptoloop(cxstack_ix);
- if (cxix < 0)
- DIE("Can't \"last\" outside a block");
- }
- else {
- cxix = dopoptolabel(cPVOP->op_pv);
- if (cxix < 0)
- DIE("Label not found for \"last %s\"", cPVOP->op_pv);
- }
- if (cxix < cxstack_ix)
- dounwind(cxix);
-
- POPBLOCK(cx);
- switch (cx->cx_type) {
- case CXt_LOOP:
- POPLOOP(cx);
- nextop = cx->blk_loop.last_op->op_next;
- LEAVE;
- break;
- case CXt_EVAL:
- POPEVAL(cx);
- nextop = pop_return();
- break;
- case CXt_SUB:
- POPSUB(cx);
- nextop = pop_return();
- break;
- default:
- DIE("panic: last");
- break;
- }
-
- if (gimme == G_SCALAR) {
- if (mark < SP)
- *++newsp = sv_mortalcopy(*SP);
- else
- *++newsp = &sv_undef;
- }
- else {
- while (mark < SP)
- *++newsp = sv_mortalcopy(*++mark);
- }
- sp = newsp;
-
- LEAVE;
- RETURNOP(nextop);
-}
-
-PP(pp_next)
-{
- dSP;
- I32 cxix;
- register CONTEXT *cx;
- I32 oldsave;
-
- if (op->op_flags & OPf_SPECIAL) {
- cxix = dopoptoloop(cxstack_ix);
- if (cxix < 0)
- DIE("Can't \"next\" outside a block");
- }
- else {
- cxix = dopoptolabel(cPVOP->op_pv);
- if (cxix < 0)
- DIE("Label not found for \"next %s\"", cPVOP->op_pv);
- }
- if (cxix < cxstack_ix)
- dounwind(cxix);
-
- TOPBLOCK(cx);
- oldsave = scopestack[scopestack_ix - 1];
- LEAVE_SCOPE(oldsave);
- return cx->blk_loop.next_op;
-}
-
-PP(pp_redo)
-{
- dSP;
- I32 cxix;
- register CONTEXT *cx;
- I32 oldsave;
-
- if (op->op_flags & OPf_SPECIAL) {
- cxix = dopoptoloop(cxstack_ix);
- if (cxix < 0)
- DIE("Can't \"redo\" outside a block");
- }
- else {
- cxix = dopoptolabel(cPVOP->op_pv);
- if (cxix < 0)
- DIE("Label not found for \"redo %s\"", cPVOP->op_pv);
- }
- if (cxix < cxstack_ix)
- dounwind(cxix);
-
- TOPBLOCK(cx);
- oldsave = scopestack[scopestack_ix - 1];
- LEAVE_SCOPE(oldsave);
- return cx->blk_loop.redo_op;
-}
-
-static OP* lastgotoprobe;
-
-OP *
-dofindlabel(op,label,opstack)
-OP *op;
-char *label;
-OP **opstack;
-{
- OP *kid;
- OP **ops = opstack;
-
- if (op->op_type == OP_LEAVE ||
- op->op_type == OP_SCOPE ||
- op->op_type == OP_LEAVELOOP ||
- op->op_type == OP_LEAVETRY)
- *ops++ = cUNOP->op_first;
- *ops = 0;
- if (op->op_flags & OPf_KIDS) {
- /* First try all the kids at this level, since that's likeliest. */
- for (kid = cUNOP->op_first; kid; kid = kid->op_sibling) {
- if ((kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE) &&
- kCOP->cop_label && strEQ(kCOP->cop_label, label))
- return kid;
- }
- for (kid = cUNOP->op_first; kid; kid = kid->op_sibling) {
- if (kid == lastgotoprobe)
- continue;
- if (kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE) {
- if (ops > opstack &&
- (ops[-1]->op_type == OP_NEXTSTATE ||
- ops[-1]->op_type == OP_DBSTATE))
- *ops = kid;
- else
- *ops++ = kid;
- }
- if (op = dofindlabel(kid,label,ops))
- return op;
- }
- }
- *ops = 0;
- return 0;
-}
-
-PP(pp_dump)
-{
- return pp_goto(ARGS);
- /*NOTREACHED*/
-}
-
-PP(pp_goto)
-{
- dSP;
- OP *retop = 0;
- I32 ix;
- register CONTEXT *cx;
- I32 entering = 0;
- OP *enterops[64];
- char *label;
-
- label = 0;
- if (op->op_flags & OPf_STACKED) {
- SV *sv = POPs;
-
- /* This egregious kludge implements goto &subroutine */
- if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVCV) {
- I32 cxix;
- register CONTEXT *cx;
- CV* cv = (CV*)SvRV(sv);
- SV** mark;
- I32 items = 0;
- I32 oldsave;
-
- /* First do some returnish stuff. */
- cxix = dopoptosub(cxstack_ix);
- if (cxix < 0)
- DIE("Can't goto subroutine outside a subroutine");
- if (cxix < cxstack_ix)
- dounwind(cxix);
- TOPBLOCK(cx);
- mark = ++stack_sp;
- *stack_sp = (SV*)cv;
- if (cx->blk_sub.hasargs) { /* put @_ back onto stack */
- items = AvFILL(cx->blk_sub.argarray) + 1;
- Copy(AvARRAY(cx->blk_sub.argarray), ++stack_sp, items, SV*);
- stack_sp += items;
- GvAV(defgv) = cx->blk_sub.savearray;
- }
- if (!(CvDEPTH(cx->blk_sub.cv) = cx->blk_sub.olddepth)) {
- if (CvDELETED(cx->blk_sub.cv))
- SvREFCNT_dec(cx->blk_sub.cv);
- }
- oldsave = scopestack[scopestack_ix - 1];
- LEAVE_SCOPE(oldsave);
-
- /* Now do some callish stuff. */
- if (CvUSERSUB(cv)) {
- items = (*CvUSERSUB(cv))(CvUSERINDEX(cv),
- mark - stack_base, items);
- sp = stack_base + items;
- LEAVE;
- return pop_return();
- }
- else {
- AV* padlist = CvPADLIST(cv);
- SV** svp = AvARRAY(padlist);
- cx->blk_sub.cv = cv;
- cx->blk_sub.olddepth = CvDEPTH(cv);
- CvDEPTH(cv)++;
- if (CvDEPTH(cv) >= 2) { /* save temporaries on recursion? */
- if (CvDEPTH(cv) == 100 && dowarn)
- warn("Deep recursion on subroutine \"%s\"",
- GvENAME(CvGV(cv)));
- if (CvDEPTH(cv) > AvFILL(padlist)) {
- AV *newpad = newAV();
- I32 ix = AvFILL((AV*)svp[1]);
- svp = AvARRAY(svp[0]);
- while (ix > 0) {
- if (svp[ix]) {
- char *name = SvPVX(svp[ix]); /* XXX */
- if (*name == '@')
- av_store(newpad, ix--, (SV*)newAV());
- else if (*name == '%')
- av_store(newpad, ix--, (SV*)newHV());
- else
- av_store(newpad, ix--, NEWSV(0,0));
- }
- else
- av_store(newpad, ix--, NEWSV(0,0));
- }
- if (cx->blk_sub.hasargs) {
- AV* av = newAV();
- av_store(av, 0, Nullsv);
- av_store(newpad, 0, (SV*)av);
- SvOK_on(av);
- AvREAL_off(av);
- }
- av_store(padlist, CvDEPTH(cv), (SV*)newpad);
- AvFILL(padlist) = CvDEPTH(cv);
- svp = AvARRAY(padlist);
- }
- }
- SAVESPTR(curpad);
- curpad = AvARRAY((AV*)svp[CvDEPTH(cv)]);
- if (cx->blk_sub.hasargs) {
- AV* av = (AV*)curpad[0];
- SV** ary;
-
- cx->blk_sub.savearray = GvAV(defgv);
- cx->blk_sub.argarray = av;
- GvAV(defgv) = cx->blk_sub.argarray;
- ++mark;
-
- if (items >= AvMAX(av)) {
- ary = AvALLOC(av);
- if (AvARRAY(av) != ary) {
- AvMAX(av) += AvARRAY(av) - AvALLOC(av);
- SvPVX(av) = (char*)ary;
- }
- if (items >= AvMAX(av)) {
- AvMAX(av) = items - 1;
- Renew(ary,items+1,SV*);
- AvALLOC(av) = ary;
- SvPVX(av) = (char*)ary;
- }
- }
- Copy(mark,AvARRAY(av),items,SV*);
- AvFILL(av) = items - 1;
- while (items--) {
- if (*mark)
- SvTEMP_off(*mark);
- mark++;
- }
- }
- RETURNOP(CvSTART(cv));
- }
- }
- else
- label = SvPV(sv,na);
- }
- else if (op->op_flags & OPf_SPECIAL) {
- if (op->op_type != OP_DUMP)
- DIE("goto must have label");
- }
- else
- label = cPVOP->op_pv;
-
- if (label && *label) {
- OP *gotoprobe;
-
- /* find label */
-
- lastgotoprobe = 0;
- *enterops = 0;
- for (ix = cxstack_ix; ix >= 0; ix--) {
- cx = &cxstack[ix];
- switch (cx->cx_type) {
- case CXt_SUB:
- gotoprobe = CvROOT(cx->blk_sub.cv);
- break;
- case CXt_EVAL:
- gotoprobe = eval_root; /* XXX not good for nested eval */
- break;
- case CXt_LOOP:
- gotoprobe = cx->blk_oldcop->op_sibling;
- break;
- case CXt_SUBST:
- continue;
- case CXt_BLOCK:
- if (ix)
- gotoprobe = cx->blk_oldcop->op_sibling;
- else
- gotoprobe = main_root;
- break;
- default:
- if (ix)
- DIE("panic: goto");
- else
- gotoprobe = main_root;
- break;
- }
- retop = dofindlabel(gotoprobe, label, enterops);
- if (retop)
- break;
- lastgotoprobe = gotoprobe;
- }
- if (!retop)
- DIE("Can't find label %s", label);
-
- /* pop unwanted frames */
-
- if (ix < cxstack_ix) {
- I32 oldsave;
-
- if (ix < 0)
- ix = 0;
- dounwind(ix);
- TOPBLOCK(cx);
- oldsave = scopestack[scopestack_ix - 1];
- LEAVE_SCOPE(oldsave);
- }
-
- /* push wanted frames */
-
- if (*enterops) {
- OP *oldop = op;
- for (ix = 0 + (gotoprobe == main_root); enterops[ix]; ix++) {
- op = enterops[ix];
- (*op->op_ppaddr)();
- }
- op = oldop;
- }
- }
-
- if (op->op_type == OP_DUMP) {
- restartop = retop;
- do_undump = TRUE;
-
- my_unexec();
-
- restartop = 0; /* hmm, must be GNU unexec().. */
- do_undump = FALSE;
- }
-
- RETURNOP(retop);
-}
-
-PP(pp_exit)
-{
- dSP;
- I32 anum;
-
- if (MAXARG < 1)
- anum = 0;
- else
- anum = SvIVx(POPs);
- my_exit(anum);
- PUSHs(&sv_undef);
- RETURN;
-}
-
-PP(pp_nswitch)
-{
- dSP;
- double value = SvNVx(GvSV(cCOP->cop_gv));
- register I32 match = (I32)value;
-
- if (value < 0.0) {
- if (((double)match) > value)
- --match; /* was fractional--truncate other way */
- }
- match -= cCOP->uop.scop.scop_offset;
- if (match < 0)
- match = 0;
- else if (match > cCOP->uop.scop.scop_max)
- match = cCOP->uop.scop.scop_max;
- op = cCOP->uop.scop.scop_next[match];
- RETURNOP(op);
-}
-
-PP(pp_cswitch)
-{
- dSP;
- register I32 match;
-
- if (multiline)
- op = op->op_next; /* can't assume anything */
- else {
- match = *(SvPVx(GvSV(cCOP->cop_gv), na)) & 255;
- match -= cCOP->uop.scop.scop_offset;
- if (match < 0)
- match = 0;
- else if (match > cCOP->uop.scop.scop_max)
- match = cCOP->uop.scop.scop_max;
- op = cCOP->uop.scop.scop_next[match];
- }
- RETURNOP(op);
-}
-
-/* I/O. */
-
-PP(pp_open)
-{
- dSP; dTARGET;
- GV *gv;
- SV *sv;
- char *tmps;
- STRLEN len;
-
- if (MAXARG > 1)
- sv = POPs;
- else
- sv = GvSV(TOPs);
- gv = (GV*)POPs;
- tmps = SvPV(sv, len);
- if (do_open(gv, tmps, len)) {
- IoLINES(GvIO(gv)) = 0;
- PUSHi( (I32)forkprocess );
- }
- else if (forkprocess == 0) /* we are a new child */
- PUSHi(0);
- else
- RETPUSHUNDEF;
- RETURN;
-}
-
-PP(pp_close)
-{
- dSP;
- GV *gv;
-
- if (MAXARG == 0)
- gv = defoutgv;
- else
- gv = (GV*)POPs;
- EXTEND(SP, 1);
- PUSHs( do_close(gv, TRUE) ? &sv_yes : &sv_no );
- RETURN;
-}
-
-PP(pp_pipe_op)
-{
- dSP;
-#ifdef HAS_PIPE
- GV *rgv;
- GV *wgv;
- register IO *rstio;
- register IO *wstio;
- int fd[2];
-
- wgv = (GV*)POPs;
- rgv = (GV*)POPs;
-
- if (!rgv || !wgv)
- goto badexit;
-
- rstio = GvIOn(rgv);
- wstio = GvIOn(wgv);
-
- if (IoIFP(rstio))
- do_close(rgv, FALSE);
- if (IoIFP(wstio))
- do_close(wgv, FALSE);
-
- if (pipe(fd) < 0)
- goto badexit;
-
- IoIFP(rstio) = fdopen(fd[0], "r");
- IoOFP(wstio) = fdopen(fd[1], "w");
- IoIFP(wstio) = IoOFP(wstio);
- IoTYPE(rstio) = '<';
- IoTYPE(wstio) = '>';
-
- if (!IoIFP(rstio) || !IoOFP(wstio)) {
- if (IoIFP(rstio)) fclose(IoIFP(rstio));
- else close(fd[0]);
- if (IoOFP(wstio)) fclose(IoOFP(wstio));
- else close(fd[1]);
- goto badexit;
- }
-
- RETPUSHYES;
-
-badexit:
- RETPUSHUNDEF;
-#else
- DIE(no_func, "pipe");
-#endif
-}
-
-PP(pp_fileno)
-{
- dSP; dTARGET;
- GV *gv;
- IO *io;
- FILE *fp;
- if (MAXARG < 1)
- RETPUSHUNDEF;
- gv = (GV*)POPs;
- if (!gv || !(io = GvIO(gv)) || !(fp = IoIFP(io)))
- RETPUSHUNDEF;
- PUSHi(fileno(fp));
- RETURN;
-}
-
-PP(pp_umask)
-{
- dSP; dTARGET;
- int anum;
-
-#ifdef HAS_UMASK
- if (MAXARG < 1) {
- anum = umask(0);
- (void)umask(anum);
- }
- else
- anum = umask(POPi);
- TAINT_PROPER("umask");
- XPUSHi(anum);
-#else
- DIE(no_func, "Unsupported function umask");
-#endif
- RETURN;
-}
-
-PP(pp_binmode)
-{
- dSP;
- GV *gv;
- IO *io;
- FILE *fp;
-
- if (MAXARG < 1)
- RETPUSHUNDEF;
-
- gv = (GV*)POPs;
-
- EXTEND(SP, 1);
- if (!gv || !(io = GvIO(gv)) || !(fp = IoIFP(io)))
- RETSETUNDEF;
-
-#ifdef DOSISH
-#ifdef atarist
- if (!fflush(fp) && (fp->_flag |= _IOBIN))
- RETPUSHYES;
- else
- RETPUSHUNDEF;
-#else
- if (setmode(fileno(fp), OP_BINARY) != -1)
- RETPUSHYES;
- else
- RETPUSHUNDEF;
-#endif
-#else
- RETPUSHYES;
-#endif
-}
-
-PP(pp_tie)
-{
- dSP;
- SV *varsv;
- HV* stash;
- GV *gv;
- BINOP myop;
- SV *sv;
- SV **mark = stack_base + *markstack_ptr + 1; /* reuse in entersubr */
-
- varsv = mark[0];
-
- stash = fetch_stash(mark[1], FALSE);
- if (!stash || !(gv = gv_fetchmethod(stash, "new")) || !GvCV(gv))
- DIE("Can't tie to package %s", SvPV(mark[1],na));
-
- Zero(&myop, 1, BINOP);
- myop.op_last = (OP *) &myop;
- myop.op_next = Nullop;
- myop.op_flags = OPf_STACKED;
-
- ENTER;
- SAVESPTR(op);
- op = (OP *) &myop;
-
- mark[0] = gv;
- PUTBACK;
-
- if (op = pp_entersubr())
- run();
- SPAGAIN;
-
- if (!sv_isobject(TOPs))
- DIE("new didn't return an object");
- sv = TOPs;
- if (SvTYPE(varsv) == SVt_PVHV || SvTYPE(varsv) == SVt_PVAV)
- sv_magic(varsv, sv, 'P', 0, 0);
- else
- sv_magic(varsv, sv, 'p', 0, -1);
- LEAVE;
- SPAGAIN;
- RETURN;
-}
-
-PP(pp_untie)
-{
- dSP;
- if (SvTYPE(TOPs) == SVt_PVHV || SvTYPE(TOPs) == SVt_PVAV)
- sv_unmagic(TOPs, 'P');
- else
- sv_unmagic(TOPs, 'p');
- RETSETYES;
-}
-
-PP(pp_dbmopen)
-{
- dSP;
- HV *hv;
- dPOPPOPssrl;
- HV* stash;
- GV *gv;
- BINOP myop;
- SV *sv;
-
- hv = (HV*)POPs;
-
- sv = sv_mortalcopy(&sv_no);
- sv_setpv(sv, "Any_DBM_File");
- stash = fetch_stash(sv, FALSE);
- if (!stash || !(gv = gv_fetchmethod(stash, "new")) || !GvCV(gv))
- DIE("No dbm on this machine");
-
- Zero(&myop, 1, BINOP);
- myop.op_last = (OP *) &myop;
- myop.op_next = Nullop;
- myop.op_flags = OPf_STACKED;
-
- ENTER;
- SAVESPTR(op);
- op = (OP *) &myop;
- PUTBACK;
- pp_pushmark();
-
- EXTEND(sp, 5);
- PUSHs(gv);
- PUSHs(sv);
- PUSHs(lstr);
- if (SvIV(rstr))
- PUSHs(sv_2mortal(newSViv(O_RDWR|O_CREAT)));
- else
- PUSHs(sv_2mortal(newSViv(O_RDWR)));
- PUSHs(rstr);
- PUTBACK;
-
- if (op = pp_entersubr())
- run();
- LEAVE;
- SPAGAIN;
-
- sv = TOPs;
- sv_magic((SV*)hv, sv, 'P', 0, 0);
- RETURN;
-}
-
-PP(pp_dbmclose)
-{
- return pp_untie(ARGS);
-}
-
-PP(pp_sselect)
-{
- dSP; dTARGET;
-#ifdef HAS_SELECT
- register I32 i;
- register I32 j;
- register char *s;
- register SV *sv;
- double value;
- I32 maxlen = 0;
- I32 nfound;
- struct timeval timebuf;
- struct timeval *tbuf = &timebuf;
- I32 growsize;
- char *fd_sets[4];
-#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
- I32 masksize;
- I32 offset;
- I32 k;
-
-# if BYTEORDER & 0xf0000
-# define ORDERBYTE (0x88888888 - BYTEORDER)
-# else
-# define ORDERBYTE (0x4444 - BYTEORDER)
-# endif
-
-#endif
-
- SP -= 4;
- for (i = 1; i <= 3; i++) {
- if (!SvPOK(SP[i]))
- continue;
- j = SvCUR(SP[i]);
- if (maxlen < j)
- maxlen = j;
- }
-
-#if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
- growsize = maxlen; /* little endians can use vecs directly */
-#else
-#ifdef NFDBITS
-
-#ifndef NBBY
-#define NBBY 8
-#endif
-
- masksize = NFDBITS / NBBY;
-#else
- masksize = sizeof(long); /* documented int, everyone seems to use long */
-#endif
- growsize = maxlen + (masksize - (maxlen % masksize));
- Zero(&fd_sets[0], 4, char*);
-#endif
-
- sv = SP[4];
- if (SvOK(sv)) {
- value = SvNV(sv);
- if (value < 0.0)
- value = 0.0;
- timebuf.tv_sec = (long)value;
- value -= (double)timebuf.tv_sec;
- timebuf.tv_usec = (long)(value * 1000000.0);
- }
- else
- tbuf = Null(struct timeval*);
-
- for (i = 1; i <= 3; i++) {
- sv = SP[i];
- if (!SvPOK(sv)) {
- fd_sets[i] = 0;
- continue;
- }
- j = SvLEN(sv);
- if (j < growsize) {
- Sv_Grow(sv, growsize);
- s = SvPV(sv, na) + j;
- while (++j <= growsize) {
- *s++ = '\0';
- }
- }
-#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
- s = SvPVX(sv);
- New(403, fd_sets[i], growsize, char);
- for (offset = 0; offset < growsize; offset += masksize) {
- for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
- fd_sets[i][j+offset] = s[(k % masksize) + offset];
- }
-#else
- fd_sets[i] = SvPVX(sv);
-#endif
- }
-
- nfound = select(
- maxlen * 8,
- fd_sets[1],
- fd_sets[2],
- fd_sets[3],
- tbuf);
-#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
- for (i = 1; i <= 3; i++) {
- if (fd_sets[i]) {
- sv = SP[i];
- s = SvPVX(sv);
- for (offset = 0; offset < growsize; offset += masksize) {
- for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
- s[(k % masksize) + offset] = fd_sets[i][j+offset];
- }
- Safefree(fd_sets[i]);
- }
- }
-#endif
-
- PUSHi(nfound);
- if (GIMME == G_ARRAY && tbuf) {
- value = (double)(timebuf.tv_sec) +
- (double)(timebuf.tv_usec) / 1000000.0;
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setnv(sv, value);
- }
- RETURN;
-#else
- DIE("select not implemented");
-#endif
-}
-
-PP(pp_select)
-{
- dSP; dTARGET;
- GV *oldgv = defoutgv;
- if (op->op_private > 0) {
- defoutgv = (GV*)POPs;
- if (!GvIO(defoutgv))
- GvIO(defoutgv) = newIO();
- curoutgv = defoutgv;
- }
- gv_efullname(TARG, oldgv);
- XPUSHTARG;
- RETURN;
-}
-
-PP(pp_getc)
-{
- dSP; dTARGET;
- GV *gv;
-
- if (MAXARG <= 0)
- gv = stdingv;
- else
- gv = (GV*)POPs;
- if (!gv)
- gv = argvgv;
- if (!gv || do_eof(gv)) /* make sure we have fp with something */
- RETPUSHUNDEF;
- TAINT_IF(1);
- sv_setpv(TARG, " ");
- *SvPVX(TARG) = getc(IoIFP(GvIO(gv))); /* should never be EOF */
- PUSHTARG;
- RETURN;
-}
-
-PP(pp_read)
-{
- return pp_sysread(ARGS);
-}
-
-static OP *
-doform(cv,gv,retop)
-CV *cv;
-GV *gv;
-OP *retop;
-{
- register CONTEXT *cx;
- I32 gimme = GIMME;
- ENTER;
- SAVETMPS;
-
- push_return(retop);
- PUSHBLOCK(cx, CXt_SUB, stack_sp);
- PUSHFORMAT(cx);
- defoutgv = gv; /* locally select filehandle so $% et al work */
- return CvSTART(cv);
-}
-
-PP(pp_enterwrite)
-{
- dSP;
- register GV *gv;
- register IO *io;
- GV *fgv;
- FILE *fp;
- CV *cv;
-
- if (MAXARG == 0)
- gv = defoutgv;
- else {
- gv = (GV*)POPs;
- if (!gv)
- gv = defoutgv;
- }
- EXTEND(SP, 1);
- io = GvIO(gv);
- if (!io) {
- RETPUSHNO;
- }
- curoutgv = gv;
- if (IoFMT_GV(io))
- fgv = IoFMT_GV(io);
- else
- fgv = gv;
-
- cv = GvFORM(fgv);
-
- if (!cv) {
- if (fgv) {
- SV *tmpstr = sv_newmortal();
- gv_efullname(tmpstr, gv);
- DIE("Undefined format \"%s\" called",SvPVX(tmpstr));
- }
- DIE("Not a format reference");
- }
-
- return doform(cv,gv,op->op_next);
-}
-
-PP(pp_leavewrite)
-{
- dSP;
- GV *gv = cxstack[cxstack_ix].blk_sub.gv;
- register IO *io = GvIO(gv);
- FILE *ofp = IoOFP(io);
- FILE *fp;
- SV **mark;
- SV **newsp;
- I32 gimme;
- register CONTEXT *cx;
-
- DEBUG_f(fprintf(stderr,"left=%ld, todo=%ld\n",
- (long)IoLINES_LEFT(io), (long)FmLINES(formtarget)));
- if (IoLINES_LEFT(io) < FmLINES(formtarget) &&
- formtarget != toptarget)
- {
- if (!IoTOP_GV(io)) {
- GV *topgv;
- char tmpbuf[256];
-
- if (!IoTOP_NAME(io)) {
- if (!IoFMT_NAME(io))
- IoFMT_NAME(io) = savestr(GvNAME(gv));
- sprintf(tmpbuf, "%s_TOP", IoFMT_NAME(io));
- topgv = gv_fetchpv(tmpbuf,FALSE, SVt_PVFM);
- if (topgv && GvFORM(topgv))
- IoTOP_NAME(io) = savestr(tmpbuf);
- else
- IoTOP_NAME(io) = savestr("top");
- }
- topgv = gv_fetchpv(IoTOP_NAME(io),FALSE, SVt_PVFM);
- if (!topgv || !GvFORM(topgv)) {
- IoLINES_LEFT(io) = 100000000;
- goto forget_top;
- }
- IoTOP_GV(io) = topgv;
- }
- if (IoLINES_LEFT(io) >= 0 && IoPAGE(io) > 0)
- fwrite(SvPVX(formfeed), SvCUR(formfeed), 1, ofp);
- IoLINES_LEFT(io) = IoPAGE_LEN(io);
- IoPAGE(io)++;
- formtarget = toptarget;
- return doform(GvFORM(IoTOP_GV(io)),gv,op);
- }
-
- forget_top:
- POPBLOCK(cx);
- POPFORMAT(cx);
- LEAVE;
-
- fp = IoOFP(io);
- if (!fp) {
- if (dowarn) {
- if (IoIFP(io))
- warn("Filehandle only opened for input");
- else
- warn("Write on closed filehandle");
- }
- PUSHs(&sv_no);
- }
- else {
- if ((IoLINES_LEFT(io) -= FmLINES(formtarget)) < 0) {
- if (dowarn)
- warn("page overflow");
- }
- if (!fwrite(SvPVX(formtarget), 1, SvCUR(formtarget), ofp) ||
- ferror(fp))
- PUSHs(&sv_no);
- else {
- FmLINES(formtarget) = 0;
- SvCUR_set(formtarget, 0);
- if (IoFLAGS(io) & IOf_FLUSH)
- (void)fflush(fp);
- PUSHs(&sv_yes);
- }
- }
- formtarget = bodytarget;
- PUTBACK;
- return pop_return();
-}
-
-PP(pp_prtf)
-{
- dSP; dMARK; dORIGMARK;
- GV *gv;
- IO *io;
- FILE *fp;
- SV *sv = NEWSV(0,0);
-
- if (op->op_flags & OPf_STACKED)
- gv = (GV*)*++MARK;
- else
- gv = defoutgv;
- if (!(io = GvIO(gv))) {
- if (dowarn)
- warn("Filehandle %s never opened", GvNAME(gv));
- errno = EBADF;
- goto just_say_no;
- }
- else if (!(fp = IoOFP(io))) {
- if (dowarn) {
- if (IoIFP(io))
- warn("Filehandle %s opened only for input", GvNAME(gv));
- else
- warn("printf on closed filehandle %s", GvNAME(gv));
- }
- errno = EBADF;
- goto just_say_no;
- }
- else {
- do_sprintf(sv, SP - MARK, MARK + 1);
- if (!do_print(sv, fp))
- goto just_say_no;
-
- if (IoFLAGS(io) & IOf_FLUSH)
- if (fflush(fp) == EOF)
- goto just_say_no;
- }
- SvREFCNT_dec(sv);
- SP = ORIGMARK;
- PUSHs(&sv_yes);
- RETURN;
-
- just_say_no:
- SvREFCNT_dec(sv);
- SP = ORIGMARK;
- PUSHs(&sv_undef);
- RETURN;
-}
-
-PP(pp_print)
-{
- dSP; dMARK; dORIGMARK;
- GV *gv;
- IO *io;
- register FILE *fp;
-
- if (op->op_flags & OPf_STACKED)
- gv = (GV*)*++MARK;
- else
- gv = defoutgv;
- if (!(io = GvIO(gv))) {
- if (dowarn)
- warn("Filehandle %s never opened", GvNAME(gv));
- errno = EBADF;
- goto just_say_no;
- }
- else if (!(fp = IoOFP(io))) {
- if (dowarn) {
- if (IoIFP(io))
- warn("Filehandle %s opened only for input", GvNAME(gv));
- else
- warn("print on closed filehandle %s", GvNAME(gv));
- }
- errno = EBADF;
- goto just_say_no;
- }
- else {
- MARK++;
- if (ofslen) {
- while (MARK <= SP) {
- if (!do_print(*MARK, fp))
- break;
- MARK++;
- if (MARK <= SP) {
- if (fwrite(ofs, 1, ofslen, fp) == 0 || ferror(fp)) {
- MARK--;
- break;
- }
- }
- }
- }
- else {
- while (MARK <= SP) {
- if (!do_print(*MARK, fp))
- break;
- MARK++;
- }
- }
- if (MARK <= SP)
- goto just_say_no;
- else {
- if (orslen)
- if (fwrite(ors, 1, orslen, fp) == 0 || ferror(fp))
- goto just_say_no;
-
- if (IoFLAGS(io) & IOf_FLUSH)
- if (fflush(fp) == EOF)
- goto just_say_no;
- }
- }
- SP = ORIGMARK;
- PUSHs(&sv_yes);
- RETURN;
-
- just_say_no:
- SP = ORIGMARK;
- PUSHs(&sv_undef);
- RETURN;
-}
-
-PP(pp_sysread)
-{
- dSP; dMARK; dORIGMARK; dTARGET;
- int offset;
- GV *gv;
- IO *io;
- char *buffer;
- int length;
- int bufsize;
- SV *bufstr;
- STRLEN blen;
-
- gv = (GV*)*++MARK;
- if (!gv)
- goto say_undef;
- bufstr = *++MARK;
- buffer = SvPV(bufstr, blen);
- length = SvIVx(*++MARK);
- if (SvTHINKFIRST(bufstr)) {
- if (SvREADONLY(bufstr) && curcop != &compiling)
- DIE(no_modify);
- if (SvROK(bufstr))
- sv_unref(bufstr);
- }
- errno = 0;
- if (MARK < SP)
- offset = SvIVx(*++MARK);
- else
- offset = 0;
- if (MARK < SP)
- warn("Too many args on read");
- io = GvIO(gv);
- if (!io || !IoIFP(io))
- goto say_undef;
-#ifdef HAS_SOCKET
- if (op->op_type == OP_RECV) {
- bufsize = sizeof buf;
- SvGROW(bufstr, length+1), (buffer = SvPV(bufstr, blen)); /* sneaky */
- length = recvfrom(fileno(IoIFP(io)), buffer, length, offset,
- (struct sockaddr *)buf, &bufsize);
- if (length < 0)
- RETPUSHUNDEF;
- SvCUR_set(bufstr, length);
- *SvEND(bufstr) = '\0';
- SvPOK_only(bufstr);
- if (tainting)
- sv_magic(bufstr, 0, 't', 0, 0);
- SP = ORIGMARK;
- sv_setpvn(TARG, buf, bufsize);
- PUSHs(TARG);
- RETURN;
- }
-#else
- if (op->op_type == OP_RECV)
- DIE(no_sock_func, "recv");
-#endif
- SvGROW(bufstr, length+offset+1), (buffer = SvPV(bufstr, blen)); /* sneaky */
- if (op->op_type == OP_SYSREAD) {
- length = read(fileno(IoIFP(io)), buffer+offset, length);
- }
- else
-#ifdef HAS_SOCKET
- if (IoTYPE(io) == 's') {
- bufsize = sizeof buf;
- length = recvfrom(fileno(IoIFP(io)), buffer+offset, length, 0,
- (struct sockaddr *)buf, &bufsize);
- }
- else
-#endif
- length = fread(buffer+offset, 1, length, IoIFP(io));
- if (length < 0)
- goto say_undef;
- SvCUR_set(bufstr, length+offset);
- *SvEND(bufstr) = '\0';
- SvPOK_only(bufstr);
- if (tainting)
- sv_magic(bufstr, 0, 't', 0, 0);
- SP = ORIGMARK;
- PUSHi(length);
- RETURN;
-
- say_undef:
- SP = ORIGMARK;
- RETPUSHUNDEF;
-}
-
-PP(pp_syswrite)
-{
- return pp_send(ARGS);
-}
-
-PP(pp_send)
-{
- dSP; dMARK; dORIGMARK; dTARGET;
- GV *gv;
- IO *io;
- int offset;
- SV *bufstr;
- char *buffer;
- int length;
- STRLEN blen;
-
- gv = (GV*)*++MARK;
- if (!gv)
- goto say_undef;
- bufstr = *++MARK;
- buffer = SvPV(bufstr, blen);
- length = SvIVx(*++MARK);
- errno = 0;
- io = GvIO(gv);
- if (!io || !IoIFP(io)) {
- length = -1;
- if (dowarn) {
- if (op->op_type == OP_SYSWRITE)
- warn("Syswrite on closed filehandle");
- else
- warn("Send on closed socket");
- }
- }
- else if (op->op_type == OP_SYSWRITE) {
- if (MARK < SP)
- offset = SvIVx(*++MARK);
- else
- offset = 0;
- if (MARK < SP)
- warn("Too many args on syswrite");
- length = write(fileno(IoIFP(io)), buffer+offset, length);
- }
-#ifdef HAS_SOCKET
- else if (SP >= MARK) {
- STRLEN mlen;
- if (SP > MARK)
- warn("Too many args on send");
- buffer = SvPVx(*++MARK, mlen);
- length = sendto(fileno(IoIFP(io)), buffer, blen, length,
- (struct sockaddr *)buffer, mlen);
- }
- else
- length = send(fileno(IoIFP(io)), buffer, blen, length);
-#else
- else
- DIE(no_sock_func, "send");
-#endif
- if (length < 0)
- goto say_undef;
- SP = ORIGMARK;
- PUSHi(length);
- RETURN;
-
- say_undef:
- SP = ORIGMARK;
- RETPUSHUNDEF;
-}
-
-PP(pp_recv)
-{
- return pp_sysread(ARGS);
-}
-
-PP(pp_eof)
-{
- dSP;
- GV *gv;
-
- if (MAXARG <= 0)
- gv = last_in_gv;
- else
- gv = last_in_gv = (GV*)POPs;
- PUSHs(!gv || do_eof(gv) ? &sv_yes : &sv_no);
- RETURN;
-}
-
-PP(pp_tell)
-{
- dSP; dTARGET;
- GV *gv;
-
- if (MAXARG <= 0)
- gv = last_in_gv;
- else
- gv = last_in_gv = (GV*)POPs;
- PUSHi( do_tell(gv) );
- RETURN;
-}
-
-PP(pp_seek)
-{
- dSP;
- GV *gv;
- int whence = POPi;
- long offset = POPl;
-
- gv = last_in_gv = (GV*)POPs;
- PUSHs( do_seek(gv, offset, whence) ? &sv_yes : &sv_no );
- RETURN;
-}
-
-PP(pp_truncate)
-{
- dSP;
- Off_t len = (Off_t)POPn;
- int result = 1;
- GV *tmpgv;
-
- errno = 0;
-#if defined(HAS_TRUNCATE) || defined(HAS_CHSIZE)
-#ifdef HAS_TRUNCATE
- if (op->op_flags & OPf_SPECIAL) {
- tmpgv = gv_fetchpv(POPp,FALSE, SVt_PVIO);
- if (!tmpgv || !GvIO(tmpgv) || !IoIFP(GvIO(tmpgv)) ||
- ftruncate(fileno(IoIFP(GvIO(tmpgv))), len) < 0)
- result = 0;
- }
- else if (truncate(POPp, len) < 0)
- result = 0;
-#else
- if (op->op_flags & OPf_SPECIAL) {
- tmpgv = gv_fetchpv(POPp,FALSE, SVt_PVIO);
- if (!tmpgv || !GvIO(tmpgv) || !IoIFP(GvIO(tmpgv)) ||
- chsize(fileno(IoIFP(GvIO(tmpgv))), len) < 0)
- result = 0;
- }
- else {
- int tmpfd;
-
- if ((tmpfd = open(POPp, 0)) < 0)
- result = 0;
- else {
- if (chsize(tmpfd, len) < 0)
- result = 0;
- close(tmpfd);
- }
- }
-#endif
-
- if (result)
- RETPUSHYES;
- if (!errno)
- errno = EBADF;
- RETPUSHUNDEF;
-#else
- DIE("truncate not implemented");
-#endif
-}
-
-PP(pp_fcntl)
-{
- return pp_ioctl(ARGS);
-}
-
-PP(pp_ioctl)
-{
- dSP; dTARGET;
- SV *argstr = POPs;
- unsigned int func = U_I(POPn);
- int optype = op->op_type;
- char *s;
- int retval;
- GV *gv = (GV*)POPs;
- IO *io = GvIOn(gv);
-
- if (!io || !argstr || !IoIFP(io)) {
- errno = EBADF; /* well, sort of... */
- RETPUSHUNDEF;
- }
-
- if (SvPOK(argstr) || !SvNIOK(argstr)) {
- STRLEN len = 0;
- if (!SvPOK(argstr))
- s = SvPV(argstr, len);
- retval = IOCPARM_LEN(func);
- if (len < retval) {
- Sv_Grow(argstr, retval+1);
- SvCUR_set(argstr, retval);
- }
-
- s = SvPVX(argstr);
- s[SvCUR(argstr)] = 17; /* a little sanity check here */
- }
- else {
- retval = SvIV(argstr);
-#ifdef DOSISH
- s = (char*)(long)retval; /* ouch */
-#else
- s = (char*)retval; /* ouch */
-#endif
- }
-
- TAINT_PROPER(optype == OP_IOCTL ? "ioctl" : "fcntl");
-
- if (optype == OP_IOCTL)
- retval = ioctl(fileno(IoIFP(io)), func, s);
- else
-#ifdef DOSISH
- DIE("fcntl is not implemented");
-#else
-# ifdef HAS_FCNTL
- retval = fcntl(fileno(IoIFP(io)), func, s);
-# else
- DIE("fcntl is not implemented");
-# endif
-#endif
-
- if (SvPOK(argstr)) {
- if (s[SvCUR(argstr)] != 17)
- DIE("Possible memory corruption: %s overflowed 3rd argument",
- op_name[optype]);
- s[SvCUR(argstr)] = 0; /* put our null back */
- }
-
- if (retval == -1)
- RETPUSHUNDEF;
- if (retval != 0) {
- PUSHi(retval);
- }
- else {
- PUSHp("0 but true", 10);
- }
- RETURN;
-}
-
-PP(pp_flock)
-{
- dSP; dTARGET;
- I32 value;
- int argtype;
- GV *gv;
- FILE *fp;
-#ifdef HAS_FLOCK
- argtype = POPi;
- if (MAXARG <= 0)
- gv = last_in_gv;
- else
- gv = (GV*)POPs;
- if (gv && GvIO(gv))
- fp = IoIFP(GvIO(gv));
- else
- fp = Nullfp;
- if (fp) {
- value = (I32)(flock(fileno(fp), argtype) >= 0);
- }
- else
- value = 0;
- PUSHi(value);
- RETURN;
-#else
- DIE(no_func, "flock()");
-#endif
-}
-
-/* Sockets. */
-
-PP(pp_socket)
-{
- dSP;
-#ifdef HAS_SOCKET
- GV *gv;
- register IO *io;
- int protocol = POPi;
- int type = POPi;
- int domain = POPi;
- int fd;
-
- gv = (GV*)POPs;
-
- if (!gv) {
- errno = EBADF;
- RETPUSHUNDEF;
- }
-
- io = GvIOn(gv);
- if (IoIFP(io))
- do_close(gv, FALSE);
-
- TAINT_PROPER("socket");
- fd = socket(domain, type, protocol);
- if (fd < 0)
- RETPUSHUNDEF;
- IoIFP(io) = fdopen(fd, "r"); /* stdio gets confused about sockets */
- IoOFP(io) = fdopen(fd, "w");
- IoTYPE(io) = 's';
- if (!IoIFP(io) || !IoOFP(io)) {
- if (IoIFP(io)) fclose(IoIFP(io));
- if (IoOFP(io)) fclose(IoOFP(io));
- if (!IoIFP(io) && !IoOFP(io)) close(fd);
- RETPUSHUNDEF;
- }
-
- RETPUSHYES;
-#else
- DIE(no_sock_func, "socket");
-#endif
-}
-
-PP(pp_sockpair)
-{
- dSP;
-#ifdef HAS_SOCKETPAIR
- GV *gv1;
- GV *gv2;
- register IO *io1;
- register IO *io2;
- int protocol = POPi;
- int type = POPi;
- int domain = POPi;
- int fd[2];
-
- gv2 = (GV*)POPs;
- gv1 = (GV*)POPs;
- if (!gv1 || !gv2)
- RETPUSHUNDEF;
-
- io1 = GvIOn(gv1);
- io2 = GvIOn(gv2);
- if (IoIFP(io1))
- do_close(gv1, FALSE);
- if (IoIFP(io2))
- do_close(gv2, FALSE);
-
- TAINT_PROPER("socketpair");
- if (socketpair(domain, type, protocol, fd) < 0)
- RETPUSHUNDEF;
- IoIFP(io1) = fdopen(fd[0], "r");
- IoOFP(io1) = fdopen(fd[0], "w");
- IoTYPE(io1) = 's';
- IoIFP(io2) = fdopen(fd[1], "r");
- IoOFP(io2) = fdopen(fd[1], "w");
- IoTYPE(io2) = 's';
- if (!IoIFP(io1) || !IoOFP(io1) || !IoIFP(io2) || !IoOFP(io2)) {
- if (IoIFP(io1)) fclose(IoIFP(io1));
- if (IoOFP(io1)) fclose(IoOFP(io1));
- if (!IoIFP(io1) && !IoOFP(io1)) close(fd[0]);
- if (IoIFP(io2)) fclose(IoIFP(io2));
- if (IoOFP(io2)) fclose(IoOFP(io2));
- if (!IoIFP(io2) && !IoOFP(io2)) close(fd[1]);
- RETPUSHUNDEF;
- }
-
- RETPUSHYES;
-#else
- DIE(no_sock_func, "socketpair");
-#endif
-}
-
-PP(pp_bind)
-{
- dSP;
-#ifdef HAS_SOCKET
- SV *addrstr = POPs;
- char *addr;
- GV *gv = (GV*)POPs;
- register IO *io = GvIOn(gv);
- STRLEN len;
-
- if (!io || !IoIFP(io))
- goto nuts;
-
- addr = SvPV(addrstr, len);
- TAINT_PROPER("bind");
- if (bind(fileno(IoIFP(io)), (struct sockaddr *)addr, len) >= 0)
- RETPUSHYES;
- else
- RETPUSHUNDEF;
-
-nuts:
- if (dowarn)
- warn("bind() on closed fd");
- errno = EBADF;
- RETPUSHUNDEF;
-#else
- DIE(no_sock_func, "bind");
-#endif
-}
-
-PP(pp_connect)
-{
- dSP;
-#ifdef HAS_SOCKET
- SV *addrstr = POPs;
- char *addr;
- GV *gv = (GV*)POPs;
- register IO *io = GvIOn(gv);
- STRLEN len;
-
- if (!io || !IoIFP(io))
- goto nuts;
-
- addr = SvPV(addrstr, len);
- TAINT_PROPER("connect");
- if (connect(fileno(IoIFP(io)), (struct sockaddr *)addr, len) >= 0)
- RETPUSHYES;
- else
- RETPUSHUNDEF;
-
-nuts:
- if (dowarn)
- warn("connect() on closed fd");
- errno = EBADF;
- RETPUSHUNDEF;
-#else
- DIE(no_sock_func, "connect");
-#endif
-}
-
-PP(pp_listen)
-{
- dSP;
-#ifdef HAS_SOCKET
- int backlog = POPi;
- GV *gv = (GV*)POPs;
- register IO *io = GvIOn(gv);
-
- if (!io || !IoIFP(io))
- goto nuts;
-
- if (listen(fileno(IoIFP(io)), backlog) >= 0)
- RETPUSHYES;
- else
- RETPUSHUNDEF;
-
-nuts:
- if (dowarn)
- warn("listen() on closed fd");
- errno = EBADF;
- RETPUSHUNDEF;
-#else
- DIE(no_sock_func, "listen");
-#endif
-}
-
-PP(pp_accept)
-{
- dSP; dTARGET;
-#ifdef HAS_SOCKET
- GV *ngv;
- GV *ggv;
- register IO *nstio;
- register IO *gstio;
- int len = sizeof buf;
- int fd;
-
- ggv = (GV*)POPs;
- ngv = (GV*)POPs;
-
- if (!ngv)
- goto badexit;
- if (!ggv)
- goto nuts;
-
- gstio = GvIO(ggv);
- if (!gstio || !IoIFP(gstio))
- goto nuts;
-
- nstio = GvIOn(ngv);
- if (IoIFP(nstio))
- do_close(ngv, FALSE);
-
- fd = accept(fileno(IoIFP(gstio)), (struct sockaddr *)buf, &len);
- if (fd < 0)
- goto badexit;
- IoIFP(nstio) = fdopen(fd, "r");
- IoOFP(nstio) = fdopen(fd, "w");
- IoTYPE(nstio) = 's';
- if (!IoIFP(nstio) || !IoOFP(nstio)) {
- if (IoIFP(nstio)) fclose(IoIFP(nstio));
- if (IoOFP(nstio)) fclose(IoOFP(nstio));
- if (!IoIFP(nstio) && !IoOFP(nstio)) close(fd);
- goto badexit;
- }
-
- PUSHp(buf, len);
- RETURN;
-
-nuts:
- if (dowarn)
- warn("accept() on closed fd");
- errno = EBADF;
-
-badexit:
- RETPUSHUNDEF;
-
-#else
- DIE(no_sock_func, "accept");
-#endif
-}
-
-PP(pp_shutdown)
-{
- dSP; dTARGET;
-#ifdef HAS_SOCKET
- int how = POPi;
- GV *gv = (GV*)POPs;
- register IO *io = GvIOn(gv);
-
- if (!io || !IoIFP(io))
- goto nuts;
-
- PUSHi( shutdown(fileno(IoIFP(io)), how) >= 0 );
- RETURN;
-
-nuts:
- if (dowarn)
- warn("shutdown() on closed fd");
- errno = EBADF;
- RETPUSHUNDEF;
-#else
- DIE(no_sock_func, "shutdown");
-#endif
-}
-
-PP(pp_gsockopt)
-{
-#ifdef HAS_SOCKET
- return pp_ssockopt(ARGS);
-#else
- DIE(no_sock_func, "getsockopt");
-#endif
-}
-
-PP(pp_ssockopt)
-{
- dSP;
-#ifdef HAS_SOCKET
- int optype = op->op_type;
- SV *sv;
- int fd;
- unsigned int optname;
- unsigned int lvl;
- GV *gv;
- register IO *io;
-
- if (optype == OP_GSOCKOPT)
- sv = sv_2mortal(NEWSV(22, 257));
- else
- sv = POPs;
- optname = (unsigned int) POPi;
- lvl = (unsigned int) POPi;
-
- gv = (GV*)POPs;
- io = GvIOn(gv);
- if (!io || !IoIFP(io))
- goto nuts;
-
- fd = fileno(IoIFP(io));
- switch (optype) {
- case OP_GSOCKOPT:
- SvCUR_set(sv, 256);
- SvPOK_only(sv);
- if (getsockopt(fd, lvl, optname, SvPVX(sv), (int*)&SvCUR(sv)) < 0)
- goto nuts2;
- PUSHs(sv);
- break;
- case OP_SSOCKOPT:
- if (setsockopt(fd, lvl, optname, SvPVX(sv), SvCUR(sv)) < 0)
- goto nuts2;
- PUSHs(&sv_yes);
- break;
- }
- RETURN;
-
-nuts:
- if (dowarn)
- warn("[gs]etsockopt() on closed fd");
- errno = EBADF;
-nuts2:
- RETPUSHUNDEF;
-
-#else
- DIE(no_sock_func, "setsockopt");
-#endif
-}
-
-PP(pp_getsockname)
-{
-#ifdef HAS_SOCKET
- return pp_getpeername(ARGS);
-#else
- DIE(no_sock_func, "getsockname");
-#endif
-}
-
-PP(pp_getpeername)
-{
- dSP;
-#ifdef HAS_SOCKET
- int optype = op->op_type;
- SV *sv;
- int fd;
- GV *gv = (GV*)POPs;
- register IO *io = GvIOn(gv);
-
- if (!io || !IoIFP(io))
- goto nuts;
-
- sv = sv_2mortal(NEWSV(22, 257));
- SvCUR_set(sv, 256);
- SvPOK_on(sv);
- fd = fileno(IoIFP(io));
- switch (optype) {
- case OP_GETSOCKNAME:
- if (getsockname(fd, (struct sockaddr *)SvPVX(sv), (int*)&SvCUR(sv)) < 0)
- goto nuts2;
- break;
- case OP_GETPEERNAME:
- if (getpeername(fd, (struct sockaddr *)SvPVX(sv), (int*)&SvCUR(sv)) < 0)
- goto nuts2;
- break;
- }
- PUSHs(sv);
- RETURN;
-
-nuts:
- if (dowarn)
- warn("get{sock, peer}name() on closed fd");
- errno = EBADF;
-nuts2:
- RETPUSHUNDEF;
-
-#else
- DIE(no_sock_func, "getpeername");
-#endif
-}
-
-/* Stat calls. */
-
-PP(pp_lstat)
-{
- return pp_stat(ARGS);
-}
-
-PP(pp_stat)
-{
- dSP;
- GV *tmpgv;
- I32 max = 13;
-
- if (op->op_flags & OPf_SPECIAL) {
- tmpgv = cGVOP->op_gv;
- if (tmpgv != defgv) {
- laststype = OP_STAT;
- statgv = tmpgv;
- sv_setpv(statname, "");
- if (!GvIO(tmpgv) || !IoIFP(GvIO(tmpgv)) ||
- fstat(fileno(IoIFP(GvIO(tmpgv))), &statcache) < 0) {
- max = 0;
- laststatval = -1;
- }
- }
- else if (laststatval < 0)
- max = 0;
- }
- else {
- sv_setpv(statname, POPp);
- statgv = Nullgv;
-#ifdef HAS_LSTAT
- laststype = op->op_type;
- if (op->op_type == OP_LSTAT)
- laststatval = lstat(SvPV(statname, na), &statcache);
- else
-#endif
- laststatval = stat(SvPV(statname, na), &statcache);
- if (laststatval < 0) {
- if (dowarn && strchr(SvPV(statname, na), '\n'))
- warn(warn_nl, "stat");
- max = 0;
- }
- }
-
- EXTEND(SP, 13);
- if (GIMME != G_ARRAY) {
- if (max)
- RETPUSHYES;
- else
- RETPUSHUNDEF;
- }
- if (max) {
- PUSHs(sv_2mortal(newSViv((I32)statcache.st_dev)));
- PUSHs(sv_2mortal(newSViv((I32)statcache.st_ino)));
- PUSHs(sv_2mortal(newSViv((I32)statcache.st_mode)));
- PUSHs(sv_2mortal(newSViv((I32)statcache.st_nlink)));
- PUSHs(sv_2mortal(newSViv((I32)statcache.st_uid)));
- PUSHs(sv_2mortal(newSViv((I32)statcache.st_gid)));
- PUSHs(sv_2mortal(newSViv((I32)statcache.st_rdev)));
- PUSHs(sv_2mortal(newSViv((I32)statcache.st_size)));
- PUSHs(sv_2mortal(newSViv((I32)statcache.st_atime)));
- PUSHs(sv_2mortal(newSViv((I32)statcache.st_mtime)));
- PUSHs(sv_2mortal(newSViv((I32)statcache.st_ctime)));
-#ifdef USE_STAT_BLOCKS
- PUSHs(sv_2mortal(newSViv((I32)statcache.st_blksize)));
- PUSHs(sv_2mortal(newSViv((I32)statcache.st_blocks)));
-#else
- PUSHs(sv_2mortal(newSVpv("", 0)));
- PUSHs(sv_2mortal(newSVpv("", 0)));
-#endif
- }
- RETURN;
-}
-
-PP(pp_ftrread)
-{
- I32 result = my_stat(ARGS);
- dSP;
- if (result < 0)
- RETPUSHUNDEF;
- if (cando(S_IRUSR, 0, &statcache))
- RETPUSHYES;
- RETPUSHNO;
-}
-
-PP(pp_ftrwrite)
-{
- I32 result = my_stat(ARGS);
- dSP;
- if (result < 0)
- RETPUSHUNDEF;
- if (cando(S_IWUSR, 0, &statcache))
- RETPUSHYES;
- RETPUSHNO;
-}
-
-PP(pp_ftrexec)
-{
- I32 result = my_stat(ARGS);
- dSP;
- if (result < 0)
- RETPUSHUNDEF;
- if (cando(S_IXUSR, 0, &statcache))
- RETPUSHYES;
- RETPUSHNO;
-}
-
-PP(pp_fteread)
-{
- I32 result = my_stat(ARGS);
- dSP;
- if (result < 0)
- RETPUSHUNDEF;
- if (cando(S_IRUSR, 1, &statcache))
- RETPUSHYES;
- RETPUSHNO;
-}
-
-PP(pp_ftewrite)
-{
- I32 result = my_stat(ARGS);
- dSP;
- if (result < 0)
- RETPUSHUNDEF;
- if (cando(S_IWUSR, 1, &statcache))
- RETPUSHYES;
- RETPUSHNO;
-}
-
-PP(pp_fteexec)
-{
- I32 result = my_stat(ARGS);
- dSP;
- if (result < 0)
- RETPUSHUNDEF;
- if (cando(S_IXUSR, 1, &statcache))
- RETPUSHYES;
- RETPUSHNO;
-}
-
-PP(pp_ftis)
-{
- I32 result = my_stat(ARGS);
- dSP;
- if (result < 0)
- RETPUSHUNDEF;
- RETPUSHYES;
-}
-
-PP(pp_fteowned)
-{
- return pp_ftrowned(ARGS);
-}
-
-PP(pp_ftrowned)
-{
- I32 result = my_stat(ARGS);
- dSP;
- if (result < 0)
- RETPUSHUNDEF;
- if (statcache.st_uid == (op->op_type == OP_FTEOWNED ? euid : uid) )
- RETPUSHYES;
- RETPUSHNO;
-}
-
-PP(pp_ftzero)
-{
- I32 result = my_stat(ARGS);
- dSP;
- if (result < 0)
- RETPUSHUNDEF;
- if (!statcache.st_size)
- RETPUSHYES;
- RETPUSHNO;
-}
-
-PP(pp_ftsize)
-{
- I32 result = my_stat(ARGS);
- dSP; dTARGET;
- if (result < 0)
- RETPUSHUNDEF;
- PUSHi(statcache.st_size);
- RETURN;
-}
-
-PP(pp_ftmtime)
-{
- I32 result = my_stat(ARGS);
- dSP; dTARGET;
- if (result < 0)
- RETPUSHUNDEF;
- PUSHn( (basetime - statcache.st_mtime) / 86400.0 );
- RETURN;
-}
-
-PP(pp_ftatime)
-{
- I32 result = my_stat(ARGS);
- dSP; dTARGET;
- if (result < 0)
- RETPUSHUNDEF;
- PUSHn( (basetime - statcache.st_atime) / 86400.0 );
- RETURN;
-}
-
-PP(pp_ftctime)
-{
- I32 result = my_stat(ARGS);
- dSP; dTARGET;
- if (result < 0)
- RETPUSHUNDEF;
- PUSHn( (basetime - statcache.st_ctime) / 86400.0 );
- RETURN;
-}
-
-PP(pp_ftsock)
-{
- I32 result = my_stat(ARGS);
- dSP;
- if (result < 0)
- RETPUSHUNDEF;
- if (S_ISSOCK(statcache.st_mode))
- RETPUSHYES;
- RETPUSHNO;
-}
-
-PP(pp_ftchr)
-{
- I32 result = my_stat(ARGS);
- dSP;
- if (result < 0)
- RETPUSHUNDEF;
- if (S_ISCHR(statcache.st_mode))
- RETPUSHYES;
- RETPUSHNO;
-}
-
-PP(pp_ftblk)
-{
- I32 result = my_stat(ARGS);
- dSP;
- if (result < 0)
- RETPUSHUNDEF;
- if (S_ISBLK(statcache.st_mode))
- RETPUSHYES;
- RETPUSHNO;
-}
-
-PP(pp_ftfile)
-{
- I32 result = my_stat(ARGS);
- dSP;
- if (result < 0)
- RETPUSHUNDEF;
- if (S_ISREG(statcache.st_mode))
- RETPUSHYES;
- RETPUSHNO;
-}
-
-PP(pp_ftdir)
-{
- I32 result = my_stat(ARGS);
- dSP;
- if (result < 0)
- RETPUSHUNDEF;
- if (S_ISDIR(statcache.st_mode))
- RETPUSHYES;
- RETPUSHNO;
-}
-
-PP(pp_ftpipe)
-{
- I32 result = my_stat(ARGS);
- dSP;
- if (result < 0)
- RETPUSHUNDEF;
- if (S_ISFIFO(statcache.st_mode))
- RETPUSHYES;
- RETPUSHNO;
-}
-
-PP(pp_ftlink)
-{
- I32 result = my_lstat(ARGS);
- dSP;
- if (result < 0)
- RETPUSHUNDEF;
- if (S_ISLNK(statcache.st_mode))
- RETPUSHYES;
- RETPUSHNO;
-}
-
-PP(pp_ftsuid)
-{
- dSP;
-#ifdef S_ISUID
- I32 result = my_stat(ARGS);
- SPAGAIN;
- if (result < 0)
- RETPUSHUNDEF;
- if (statcache.st_mode & S_ISUID)
- RETPUSHYES;
-#endif
- RETPUSHNO;
-}
-
-PP(pp_ftsgid)
-{
- dSP;
-#ifdef S_ISGID
- I32 result = my_stat(ARGS);
- SPAGAIN;
- if (result < 0)
- RETPUSHUNDEF;
- if (statcache.st_mode & S_ISGID)
- RETPUSHYES;
-#endif
- RETPUSHNO;
-}
-
-PP(pp_ftsvtx)
-{
- dSP;
-#ifdef S_ISVTX
- I32 result = my_stat(ARGS);
- SPAGAIN;
- if (result < 0)
- RETPUSHUNDEF;
- if (statcache.st_mode & S_ISVTX)
- RETPUSHYES;
-#endif
- RETPUSHNO;
-}
-
-PP(pp_fttty)
-{
- dSP;
- int fd;
- GV *gv;
- char *tmps;
- if (op->op_flags & OPf_SPECIAL) {
- gv = cGVOP->op_gv;
- tmps = "";
- }
- else
- gv = gv_fetchpv(tmps = POPp, FALSE, SVt_PVIO);
- if (gv && GvIO(gv) && IoIFP(GvIO(gv)))
- fd = fileno(IoIFP(GvIO(gv)));
- else if (isDIGIT(*tmps))
- fd = atoi(tmps);
- else
- RETPUSHUNDEF;
- if (isatty(fd))
- RETPUSHYES;
- RETPUSHNO;
-}
-
-PP(pp_fttext)
-{
- dSP;
- I32 i;
- I32 len;
- I32 odd = 0;
- STDCHAR tbuf[512];
- register STDCHAR *s;
- register IO *io;
- SV *sv;
-
- if (op->op_flags & OPf_SPECIAL) {
- EXTEND(SP, 1);
- if (cGVOP->op_gv == defgv) {
- if (statgv)
- io = GvIO(statgv);
- else {
- sv = statname;
- goto really_filename;
- }
- }
- else {
- statgv = cGVOP->op_gv;
- sv_setpv(statname, "");
- io = GvIO(statgv);
- }
- if (io && IoIFP(io)) {
-#if defined(USE_STD_STDIO) || defined(atarist) /* this will work with atariST */
- fstat(fileno(IoIFP(io)), &statcache);
- if (S_ISDIR(statcache.st_mode)) /* handle NFS glitch */
- if (op->op_type == OP_FTTEXT)
- RETPUSHNO;
- else
- RETPUSHYES;
- if (IoIFP(io)->_cnt <= 0) {
- i = getc(IoIFP(io));
- if (i != EOF)
- (void)ungetc(i, IoIFP(io));
- }
- if (IoIFP(io)->_cnt <= 0) /* null file is anything */
- RETPUSHYES;
- len = IoIFP(io)->_cnt + (IoIFP(io)->_ptr - IoIFP(io)->_base);
- s = IoIFP(io)->_base;
-#else
- DIE("-T and -B not implemented on filehandles");
-#endif
- }
- else {
- if (dowarn)
- warn("Test on unopened file <%s>",
- GvENAME(cGVOP->op_gv));
- errno = EBADF;
- RETPUSHUNDEF;
- }
- }
- else {
- sv = POPs;
- statgv = Nullgv;
- sv_setpv(statname, SvPV(sv, na));
- really_filename:
- i = open(SvPV(sv, na), 0);
- if (i < 0) {
- if (dowarn && strchr(SvPV(sv, na), '\n'))
- warn(warn_nl, "open");
- RETPUSHUNDEF;
- }
- fstat(i, &statcache);
- len = read(i, tbuf, 512);
- (void)close(i);
- if (len <= 0) {
- if (S_ISDIR(statcache.st_mode) && op->op_type == OP_FTTEXT)
- RETPUSHNO; /* special case NFS directories */
- RETPUSHYES; /* null file is anything */
- }
- s = tbuf;
- }
-
- /* now scan s to look for textiness */
-
- for (i = 0; i < len; i++, s++) {
- if (!*s) { /* null never allowed in text */
- odd += len;
- break;
- }
- else if (*s & 128)
- odd++;
- else if (*s < 32 &&
- *s != '\n' && *s != '\r' && *s != '\b' &&
- *s != '\t' && *s != '\f' && *s != 27)
- odd++;
- }
-
- if ((odd * 10 > len) == (op->op_type == OP_FTTEXT)) /* allow 10% odd */
- RETPUSHNO;
- else
- RETPUSHYES;
-}
-
-PP(pp_ftbinary)
-{
- return pp_fttext(ARGS);
-}
-
-/* File calls. */
-
-PP(pp_chdir)
-{
- dSP; dTARGET;
- double value;
- char *tmps;
- SV **svp;
-
- if (MAXARG < 1)
- tmps = Nullch;
- else
- tmps = POPp;
- if (!tmps || !*tmps) {
- svp = hv_fetch(GvHVn(envgv), "HOME", 4, FALSE);
- if (svp)
- tmps = SvPV(*svp, na);
- }
- if (!tmps || !*tmps) {
- svp = hv_fetch(GvHVn(envgv), "LOGDIR", 6, FALSE);
- if (svp)
- tmps = SvPV(*svp, na);
- }
- TAINT_PROPER("chdir");
- PUSHi( chdir(tmps) >= 0 );
- RETURN;
-}
-
-PP(pp_chown)
-{
- dSP; dMARK; dTARGET;
- I32 value;
-#ifdef HAS_CHOWN
- value = (I32)apply(op->op_type, MARK, SP);
- SP = MARK;
- PUSHi(value);
- RETURN;
-#else
- DIE(no_func, "Unsupported function chown");
-#endif
-}
-
-PP(pp_chroot)
-{
- dSP; dTARGET;
- char *tmps;
-#ifdef HAS_CHROOT
- if (MAXARG < 1)
- tmps = SvPVx(GvSV(defgv), na);
- else
- tmps = POPp;
- TAINT_PROPER("chroot");
- PUSHi( chroot(tmps) >= 0 );
- RETURN;
-#else
- DIE(no_func, "chroot");
-#endif
-}
-
-PP(pp_unlink)
-{
- dSP; dMARK; dTARGET;
- I32 value;
- value = (I32)apply(op->op_type, MARK, SP);
- SP = MARK;
- PUSHi(value);
- RETURN;
-}
-
-PP(pp_chmod)
-{
- dSP; dMARK; dTARGET;
- I32 value;
- value = (I32)apply(op->op_type, MARK, SP);
- SP = MARK;
- PUSHi(value);
- RETURN;
-}
-
-PP(pp_utime)
-{
- dSP; dMARK; dTARGET;
- I32 value;
- value = (I32)apply(op->op_type, MARK, SP);
- SP = MARK;
- PUSHi(value);
- RETURN;
-}
-
-PP(pp_rename)
-{
- dSP; dTARGET;
- int anum;
-
- char *tmps2 = POPp;
- char *tmps = SvPV(TOPs, na);
- TAINT_PROPER("rename");
-#ifdef HAS_RENAME
- anum = rename(tmps, tmps2);
-#else
- if (same_dirent(tmps2, tmps)) /* can always rename to same name */
- anum = 1;
- else {
- if (euid || stat(tmps2, &statbuf) < 0 || !S_ISDIR(statbuf.st_mode))
- (void)UNLINK(tmps2);
- if (!(anum = link(tmps, tmps2)))
- anum = UNLINK(tmps);
- }
-#endif
- SETi( anum >= 0 );
- RETURN;
-}
-
-PP(pp_link)
-{
- dSP; dTARGET;
-#ifdef HAS_LINK
- char *tmps2 = POPp;
- char *tmps = SvPV(TOPs, na);
- TAINT_PROPER("link");
- SETi( link(tmps, tmps2) >= 0 );
-#else
- DIE(no_func, "Unsupported function link");
-#endif
- RETURN;
-}
-
-PP(pp_symlink)
-{
- dSP; dTARGET;
-#ifdef HAS_SYMLINK
- char *tmps2 = POPp;
- char *tmps = SvPV(TOPs, na);
- TAINT_PROPER("symlink");
- SETi( symlink(tmps, tmps2) >= 0 );
- RETURN;
-#else
- DIE(no_func, "symlink");
-#endif
-}
-
-PP(pp_readlink)
-{
- dSP; dTARGET;
-#ifdef HAS_SYMLINK
- char *tmps;
- int len;
- if (MAXARG < 1)
- tmps = SvPVx(GvSV(defgv), na);
- else
- tmps = POPp;
- len = readlink(tmps, buf, sizeof buf);
- EXTEND(SP, 1);
- if (len < 0)
- RETPUSHUNDEF;
- PUSHp(buf, len);
- RETURN;
-#else
- EXTEND(SP, 1);
- RETSETUNDEF; /* just pretend it's a normal file */
-#endif
-}
-
-#if !defined(HAS_MKDIR) || !defined(HAS_RMDIR)
-static void
-dooneliner(cmd, filename)
-char *cmd;
-char *filename;
-{
- char mybuf[8192];
- char *s;
- int anum = 1;
- FILE *myfp;
-
- strcpy(mybuf, cmd);
- strcat(mybuf, " ");
- for (s = mybuf+strlen(mybuf); *filename; ) {
- *s++ = '\\';
- *s++ = *filename++;
- }
- strcpy(s, " 2>&1");
- myfp = my_popen(mybuf, "r");
- if (myfp) {
- *mybuf = '\0';
- s = fgets(mybuf, sizeof mybuf, myfp);
- (void)my_pclose(myfp);
- if (s != Nullch) {
- for (errno = 1; errno < sys_nerr; errno++) {
- if (instr(mybuf, sys_errlist[errno])) /* you don't see this */
- return 0;
- }
- errno = 0;
-#ifndef EACCES
-#define EACCES EPERM
-#endif
- if (instr(mybuf, "cannot make"))
- errno = EEXIST;
- else if (instr(mybuf, "existing file"))
- errno = EEXIST;
- else if (instr(mybuf, "ile exists"))
- errno = EEXIST;
- else if (instr(mybuf, "non-exist"))
- errno = ENOENT;
- else if (instr(mybuf, "does not exist"))
- errno = ENOENT;
- else if (instr(mybuf, "not empty"))
- errno = EBUSY;
- else if (instr(mybuf, "cannot access"))
- errno = EACCES;
- else
- errno = EPERM;
- return 0;
- }
- else { /* some mkdirs return no failure indication */
- tmps = SvPVx(st[1], na);
- anum = (stat(tmps, &statbuf) >= 0);
- if (op->op_type == OP_RMDIR)
- anum = !anum;
- if (anum)
- errno = 0;
- else
- errno = EACCES; /* a guess */
- }
- return anum;
- }
- else
- return 0;
-}
-#endif
-
-PP(pp_mkdir)
-{
- dSP; dTARGET;
- int mode = POPi;
- int oldumask;
- char *tmps = SvPV(TOPs, na);
-
- TAINT_PROPER("mkdir");
-#ifdef HAS_MKDIR
- SETi( mkdir(tmps, mode) >= 0 );
-#else
- SETi( dooneliner("mkdir", tmps) );
- oldumask = umask(0)
- umask(oldumask);
- chmod(tmps, (mode & ~oldumask) & 0777);
-#endif
- RETURN;
-}
-
-PP(pp_rmdir)
-{
- dSP; dTARGET;
- char *tmps;
-
- if (MAXARG < 1)
- tmps = SvPVx(GvSV(defgv), na);
- else
- tmps = POPp;
- TAINT_PROPER("rmdir");
-#ifdef HAS_RMDIR
- XPUSHi( rmdir(tmps) >= 0 );
-#else
- XPUSHi( dooneliner("rmdir", tmps) );
-#endif
- RETURN;
-}
-
-/* Directory calls. */
-
-PP(pp_open_dir)
-{
- dSP;
-#if defined(DIRENT) && defined(HAS_READDIR)
- char *dirname = POPp;
- GV *gv = (GV*)POPs;
- register IO *io = GvIOn(gv);
-
- if (!io)
- goto nope;
-
- if (IoDIRP(io))
- closedir(IoDIRP(io));
- if (!(IoDIRP(io) = opendir(dirname)))
- goto nope;
-
- RETPUSHYES;
-nope:
- if (!errno)
- errno = EBADF;
RETPUSHUNDEF;
-#else
- DIE(no_dir_func, "opendir");
-#endif
-}
-
-PP(pp_readdir)
-{
- dSP;
-#if defined(DIRENT) && defined(HAS_READDIR)
-#ifndef I_DIRENT
- struct DIRENT *readdir P((DIR *)); /* XXX is this *ever* needed? */
-#endif
- register struct DIRENT *dp;
- GV *gv = (GV*)POPs;
- register IO *io = GvIOn(gv);
-
- if (!io || !IoDIRP(io))
- goto nope;
-
- if (GIMME == G_ARRAY) {
- /*SUPPRESS 560*/
- while (dp = (struct DIRENT *)readdir(IoDIRP(io))) {
-#ifdef DIRNAMLEN
- XPUSHs(sv_2mortal(newSVpv(dp->d_name, dp->d_namlen)));
-#else
- XPUSHs(sv_2mortal(newSVpv(dp->d_name, 0)));
-#endif
- }
- }
- else {
- if (!(dp = (struct DIRENT *)readdir(IoDIRP(io))))
- goto nope;
-#ifdef DIRNAMLEN
- XPUSHs(sv_2mortal(newSVpv(dp->d_name, dp->d_namlen)));
-#else
- XPUSHs(sv_2mortal(newSVpv(dp->d_name, 0)));
-#endif
- }
- RETURN;
-
-nope:
- if (!errno)
- errno = EBADF;
- if (GIMME == G_ARRAY)
- RETURN;
- else
- RETPUSHUNDEF;
-#else
- DIE(no_dir_func, "readdir");
-#endif
-}
-
-PP(pp_telldir)
-{
- dSP; dTARGET;
-#if defined(HAS_TELLDIR) || defined(telldir)
-#ifndef telldir
- long telldir();
-#endif
- GV *gv = (GV*)POPs;
- register IO *io = GvIOn(gv);
-
- if (!io || !IoDIRP(io))
- goto nope;
-
- PUSHi( telldir(IoDIRP(io)) );
- RETURN;
-nope:
- if (!errno)
- errno = EBADF;
- RETPUSHUNDEF;
-#else
- DIE(no_dir_func, "telldir");
-#endif
-}
-
-PP(pp_seekdir)
-{
- dSP;
-#if defined(HAS_SEEKDIR) || defined(seekdir)
- long along = POPl;
- GV *gv = (GV*)POPs;
- register IO *io = GvIOn(gv);
-
- if (!io || !IoDIRP(io))
- goto nope;
-
- (void)seekdir(IoDIRP(io), along);
-
- RETPUSHYES;
-nope:
- if (!errno)
- errno = EBADF;
- RETPUSHUNDEF;
-#else
- DIE(no_dir_func, "seekdir");
-#endif
-}
-
-PP(pp_rewinddir)
-{
- dSP;
-#if defined(HAS_REWINDDIR) || defined(rewinddir)
- GV *gv = (GV*)POPs;
- register IO *io = GvIOn(gv);
-
- if (!io || !IoDIRP(io))
- goto nope;
-
- (void)rewinddir(IoDIRP(io));
- RETPUSHYES;
-nope:
- if (!errno)
- errno = EBADF;
- RETPUSHUNDEF;
-#else
- DIE(no_dir_func, "rewinddir");
-#endif
-}
-
-PP(pp_closedir)
-{
- dSP;
-#if defined(DIRENT) && defined(HAS_READDIR)
- GV *gv = (GV*)POPs;
- register IO *io = GvIOn(gv);
-
- if (!io || !IoDIRP(io))
- goto nope;
-
- if (closedir(IoDIRP(io)) < 0)
- goto nope;
- IoDIRP(io) = 0;
-
- RETPUSHYES;
-nope:
- if (!errno)
- errno = EBADF;
- RETPUSHUNDEF;
-#else
- DIE(no_dir_func, "closedir");
-#endif
-}
-
-/* Process control. */
-
-PP(pp_fork)
-{
- dSP; dTARGET;
- int childpid;
- GV *tmpgv;
-
- EXTEND(SP, 1);
-#ifdef HAS_FORK
- childpid = fork();
- if (childpid < 0)
- RETSETUNDEF;
- if (!childpid) {
- /*SUPPRESS 560*/
- if (tmpgv = gv_fetchpv("$", TRUE, SVt_PV))
- sv_setiv(GvSV(tmpgv), (I32)getpid());
- hv_clear(pidstatus); /* no kids, so don't wait for 'em */
- }
- PUSHi(childpid);
- RETURN;
-#else
- DIE(no_func, "Unsupported function fork");
-#endif
-}
-
-PP(pp_wait)
-{
- dSP; dTARGET;
- int childpid;
- int argflags;
- I32 value;
-
- EXTEND(SP, 1);
-#ifdef HAS_WAIT
- childpid = wait(&argflags);
- if (childpid > 0)
- pidgone(childpid, argflags);
- value = (I32)childpid;
- statusvalue = (U16)argflags;
- PUSHi(value);
- RETURN;
-#else
- DIE(no_func, "Unsupported function wait");
-#endif
-}
-
-PP(pp_waitpid)
-{
- dSP; dTARGET;
- int childpid;
- int optype;
- int argflags;
- I32 value;
-
-#ifdef HAS_WAIT
- optype = POPi;
- childpid = TOPi;
- childpid = wait4pid(childpid, &argflags, optype);
- value = (I32)childpid;
- statusvalue = (U16)argflags;
- SETi(value);
- RETURN;
-#else
- DIE(no_func, "Unsupported function wait");
-#endif
-}
-
-PP(pp_system)
-{
- dSP; dMARK; dORIGMARK; dTARGET;
- I32 value;
- int childpid;
- int result;
- int status;
- VOIDRET (*ihand)(); /* place to save signal during system() */
- VOIDRET (*qhand)(); /* place to save signal during system() */
-
-#ifdef HAS_FORK
- if (SP - MARK == 1) {
- if (tainting) {
- char *junk = SvPV(TOPs, na);
- TAINT_ENV();
- TAINT_PROPER("system");
- }
- }
- while ((childpid = vfork()) == -1) {
- if (errno != EAGAIN) {
- value = -1;
- SP = ORIGMARK;
- PUSHi(value);
- RETURN;
- }
- sleep(5);
- }
- if (childpid > 0) {
- ihand = signal(SIGINT, SIG_IGN);
- qhand = signal(SIGQUIT, SIG_IGN);
- result = wait4pid(childpid, &status, 0);
- (void)signal(SIGINT, ihand);
- (void)signal(SIGQUIT, qhand);
- statusvalue = (U16)status;
- if (result < 0)
- value = -1;
- else {
- value = (I32)((unsigned int)status & 0xffff);
- }
- do_execfree(); /* free any memory child malloced on vfork */
- SP = ORIGMARK;
- PUSHi(value);
- RETURN;
- }
- if (op->op_flags & OPf_STACKED) {
- SV *really = *++MARK;
- value = (I32)do_aexec(really, MARK, SP);
- }
- else if (SP - MARK != 1)
- value = (I32)do_aexec(Nullsv, MARK, SP);
- else {
- value = (I32)do_exec(SvPVx(sv_mortalcopy(*SP), na));
- }
- _exit(-1);
-#else /* ! FORK */
- if ((op[1].op_type & A_MASK) == A_GV)
- value = (I32)do_aspawn(st[1], arglast);
- else if (arglast[2] - arglast[1] != 1)
- value = (I32)do_aspawn(Nullsv, arglast);
- else {
- value = (I32)do_spawn(SvPVx(sv_mortalcopy(st[2]), na));
- }
- PUSHi(value);
-#endif /* FORK */
- RETURN;
-}
-
-PP(pp_exec)
-{
- dSP; dMARK; dORIGMARK; dTARGET;
- I32 value;
-
- if (op->op_flags & OPf_STACKED) {
- SV *really = *++MARK;
- value = (I32)do_aexec(really, MARK, SP);
- }
- else if (SP - MARK != 1)
- value = (I32)do_aexec(Nullsv, MARK, SP);
- else {
- if (tainting) {
- char *junk = SvPV(*SP, na);
- TAINT_ENV();
- TAINT_PROPER("exec");
- }
- value = (I32)do_exec(SvPVx(sv_mortalcopy(*SP), na));
- }
- SP = ORIGMARK;
- PUSHi(value);
- RETURN;
-}
-
-PP(pp_kill)
-{
- dSP; dMARK; dTARGET;
- I32 value;
-#ifdef HAS_KILL
- value = (I32)apply(op->op_type, MARK, SP);
- SP = MARK;
- PUSHi(value);
- RETURN;
-#else
- DIE(no_func, "Unsupported function kill");
-#endif
-}
-
-PP(pp_getppid)
-{
-#ifdef HAS_GETPPID
- dSP; dTARGET;
- XPUSHi( getppid() );
- RETURN;
-#else
- DIE(no_func, "getppid");
-#endif
-}
-
-PP(pp_getpgrp)
-{
-#ifdef HAS_GETPGRP
- dSP; dTARGET;
- int pid;
- I32 value;
-
- if (MAXARG < 1)
- pid = 0;
- else
- pid = SvIVx(POPs);
-#ifdef _POSIX_SOURCE
- if (pid != 0)
- DIE("POSIX getpgrp can't take an argument");
- value = (I32)getpgrp();
-#else
- value = (I32)getpgrp(pid);
-#endif
- XPUSHi(value);
- RETURN;
-#else
- DIE(no_func, "getpgrp()");
-#endif
-}
-
-PP(pp_setpgrp)
-{
-#ifdef HAS_SETPGRP
- dSP; dTARGET;
- int pgrp = POPi;
- int pid = TOPi;
-
- TAINT_PROPER("setpgrp");
- SETi( setpgrp(pid, pgrp) >= 0 );
- RETURN;
-#else
- DIE(no_func, "setpgrp()");
-#endif
-}
-
-PP(pp_getpriority)
-{
- dSP; dTARGET;
- int which;
- int who;
-#ifdef HAS_GETPRIORITY
- who = POPi;
- which = TOPi;
- SETi( getpriority(which, who) );
- RETURN;
-#else
- DIE(no_func, "getpriority()");
-#endif
-}
-
-PP(pp_setpriority)
-{
- dSP; dTARGET;
- int which;
- int who;
- int niceval;
-#ifdef HAS_SETPRIORITY
- niceval = POPi;
- who = POPi;
- which = TOPi;
- TAINT_PROPER("setpriority");
- SETi( setpriority(which, who, niceval) >= 0 );
- RETURN;
-#else
- DIE(no_func, "setpriority()");
-#endif
-}
-
-/* Time calls. */
-
-PP(pp_time)
-{
- dSP; dTARGET;
- XPUSHi( time(Null(Time_t*)) );
- RETURN;
-}
-
-#ifndef HZ
-#define HZ 60
-#endif
-
-PP(pp_tms)
-{
- dSP;
-
-#if defined(MSDOS) || !defined(HAS_TIMES)
- DIE("times not implemented");
-#else
- EXTEND(SP, 4);
-
- (void)times(&timesbuf);
-
- PUSHs(sv_2mortal(newSVnv(((double)timesbuf.tms_utime)/HZ)));
- if (GIMME == G_ARRAY) {
- PUSHs(sv_2mortal(newSVnv(((double)timesbuf.tms_stime)/HZ)));
- PUSHs(sv_2mortal(newSVnv(((double)timesbuf.tms_cutime)/HZ)));
- PUSHs(sv_2mortal(newSVnv(((double)timesbuf.tms_cstime)/HZ)));
- }
- RETURN;
-#endif /* MSDOS */
-}
-
-PP(pp_localtime)
-{
- return pp_gmtime(ARGS);
-}
-
-PP(pp_gmtime)
-{
- dSP;
- Time_t when;
- struct tm *tmbuf;
- static char *dayname[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
- static char *monname[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
-
- if (MAXARG < 1)
- (void)time(&when);
- else
- when = (Time_t)SvIVx(POPs);
-
- if (op->op_type == OP_LOCALTIME)
- tmbuf = localtime(&when);
- else
- tmbuf = gmtime(&when);
-
- EXTEND(SP, 9);
- if (GIMME != G_ARRAY) {
- dTARGET;
- char mybuf[30];
- if (!tmbuf)
- RETPUSHUNDEF;
- sprintf(mybuf, "%s %s %2d %02d:%02d:%02d %d",
- dayname[tmbuf->tm_wday],
- monname[tmbuf->tm_mon],
- tmbuf->tm_mday,
- tmbuf->tm_hour,
- tmbuf->tm_min,
- tmbuf->tm_sec,
- tmbuf->tm_year + 1900);
- PUSHp(mybuf, strlen(mybuf));
- }
- else if (tmbuf) {
- PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_sec)));
- PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_min)));
- PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_hour)));
- PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_mday)));
- PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_mon)));
- PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_year)));
- PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_wday)));
- PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_yday)));
- PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_isdst)));
- }
- RETURN;
-}
-
-PP(pp_alarm)
-{
- dSP; dTARGET;
- int anum;
-#ifdef HAS_ALARM
- if (MAXARG < 1)
- anum = SvIVx(GvSV(defgv));
- else
- anum = POPi;
- anum = alarm((unsigned int)anum);
- EXTEND(SP, 1);
- if (anum < 0)
- RETPUSHUNDEF;
- PUSHi((I32)anum);
- RETURN;
-#else
- DIE(no_func, "Unsupported function alarm");
- break;
-#endif
-}
-
-PP(pp_sleep)
-{
- dSP; dTARGET;
- char *tmps;
- I32 duration;
- Time_t lasttime;
- Time_t when;
-
- (void)time(&lasttime);
- if (MAXARG < 1)
- pause();
- else {
- duration = POPi;
- sleep((unsigned int)duration);
- }
- (void)time(&when);
- XPUSHi(when - lasttime);
- RETURN;
-}
-
-/* Shared memory. */
-
-PP(pp_shmget)
-{
- return pp_semget(ARGS);
-}
-
-PP(pp_shmctl)
-{
- return pp_semctl(ARGS);
-}
-
-PP(pp_shmread)
-{
- return pp_shmwrite(ARGS);
-}
-
-PP(pp_shmwrite)
-{
-#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
- dSP; dMARK; dTARGET;
- I32 value = (I32)(do_shmio(op->op_type, MARK, SP) >= 0);
- SP = MARK;
- PUSHi(value);
- RETURN;
-#else
- pp_semget(ARGS);
-#endif
-}
-
-/* Message passing. */
-
-PP(pp_msgget)
-{
- return pp_semget(ARGS);
-}
-
-PP(pp_msgctl)
-{
- return pp_semctl(ARGS);
-}
-
-PP(pp_msgsnd)
-{
-#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
- dSP; dMARK; dTARGET;
- I32 value = (I32)(do_msgsnd(MARK, SP) >= 0);
- SP = MARK;
- PUSHi(value);
- RETURN;
-#else
- pp_semget(ARGS);
-#endif
-}
-
-PP(pp_msgrcv)
-{
-#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
- dSP; dMARK; dTARGET;
- I32 value = (I32)(do_msgrcv(MARK, SP) >= 0);
- SP = MARK;
- PUSHi(value);
- RETURN;
-#else
- pp_semget(ARGS);
-#endif
-}
-
-/* Semaphores. */
-
-PP(pp_semget)
-{
-#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
- dSP; dMARK; dTARGET;
- int anum = do_ipcget(op->op_type, MARK, SP);
- SP = MARK;
- if (anum == -1)
- RETPUSHUNDEF;
- PUSHi(anum);
- RETURN;
-#else
- DIE("System V IPC is not implemented on this machine");
-#endif
-}
-
-PP(pp_semctl)
-{
-#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
- dSP; dMARK; dTARGET;
- int anum = do_ipcctl(op->op_type, MARK, SP);
- SP = MARK;
- if (anum == -1)
- RETSETUNDEF;
- if (anum != 0) {
- PUSHi(anum);
- }
- else {
- PUSHp("0 but true",10);
- }
- RETURN;
-#else
- pp_semget(ARGS);
-#endif
-}
-
-PP(pp_semop)
-{
-#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
- dSP; dMARK; dTARGET;
- I32 value = (I32)(do_semop(MARK, SP) >= 0);
- SP = MARK;
- PUSHi(value);
- RETURN;
-#else
- pp_semget(ARGS);
-#endif
-}
-
-/* Eval. */
-
-static void
-save_lines(array, sv)
-AV *array;
-SV *sv;
-{
- register char *s = SvPVX(sv);
- register char *send = SvPVX(sv) + SvCUR(sv);
- register char *t;
- register I32 line = 1;
-
- while (s && s < send) {
- SV *tmpstr = NEWSV(85,0);
-
- sv_upgrade(tmpstr, SVt_PVMG);
- t = strchr(s, '\n');
- if (t)
- t++;
- else
- t = send;
-
- sv_setpvn(tmpstr, s, t - s);
- av_store(array, line++, tmpstr);
- s = t;
- }
-}
-
-OP *
-doeval()
-{
- dSP;
- OP *saveop = op;
- HV *newstash;
-
- in_eval = 1;
-
- /* set up a scratch pad */
-
- SAVEINT(padix);
- SAVESPTR(curpad);
- SAVESPTR(comppad);
- SAVESPTR(comppad_name);
- SAVEINT(comppad_name_fill);
- SAVEINT(min_intro_pending);
- SAVEINT(max_intro_pending);
- comppad = newAV();
- comppad_name = newAV();
- comppad_name_fill = 0;
- min_intro_pending = 0;
- av_push(comppad, Nullsv);
- curpad = AvARRAY(comppad);
- padix = 0;
-
- /* make sure we compile in the right package */
-
- newstash = curcop->cop_stash;
- if (curstash != newstash) {
- SAVESPTR(curstash);
- curstash = newstash;
- }
- SAVESPTR(beginav);
- beginav = 0;
-
- /* try to compile it */
-
- eval_root = Nullop;
- error_count = 0;
- curcop = &compiling;
- rs = "\n";
- rslen = 1;
- rschar = '\n';
- rspara = 0;
- if (yyparse() || error_count || !eval_root) {
- SV **newsp;
- I32 gimme;
- CONTEXT *cx;
- I32 optype;
-
- op = saveop;
- if (eval_root) {
- op_free(eval_root);
- eval_root = Nullop;
- }
- POPBLOCK(cx);
- POPEVAL(cx);
- pop_return();
- lex_end();
- LEAVE;
- if (optype == OP_REQUIRE)
- DIE("%s", SvPVx(GvSV(gv_fetchpv("@",TRUE, SVt_PV)), na));
- rs = nrs;
- rslen = nrslen;
- rschar = nrschar;
- rspara = (nrslen == 2);
- RETPUSHUNDEF;
- }
- rs = nrs;
- rslen = nrslen;
- rschar = nrschar;
- rspara = (nrslen == 2);
- compiling.cop_line = 0;
- SAVEFREESV(comppad_name);
- SAVEFREESV(comppad);
- SAVEFREEOP(eval_root);
-
- DEBUG_x(dump_eval());
-
- /* compiled okay, so do it */
-
- sv_setpv(GvSV(gv_fetchpv("@",TRUE, SVt_PV)),"");
- RETURNOP(eval_start);
-}
-
-PP(pp_require)
-{
- dSP;
- register CONTEXT *cx;
- SV *sv;
- char *name;
- char *tmpname;
- SV** svp;
- I32 gimme = G_SCALAR;
- FILE *tryrsfp = 0;
-
- if (MAXARG < 1) {
- sv = GvSV(defgv);
- EXTEND(SP, 1);
- }
- else
- sv = POPs;
- if (SvNIOK(sv) && !SvPOKp(sv)) {
- if (SvNV(sv) > atof(patchlevel) + 0.000999)
- DIE("Perl %3.3f required--this is only version %s, stopped",
- SvNV(sv),patchlevel);
- RETPUSHYES;
- }
- name = SvPV(sv, na);
- if (op->op_type == OP_REQUIRE &&
- (svp = hv_fetch(GvHVn(incgv), name, SvCUR(sv), 0)) &&
- *svp != &sv_undef)
- RETPUSHYES;
-
- /* prepare to compile file */
-
- tmpname = savestr(name);
- if (*tmpname == '/' ||
- (*tmpname == '.' &&
- (tmpname[1] == '/' ||
- (tmpname[1] == '.' && tmpname[2] == '/'))))
- {
- tryrsfp = fopen(tmpname,"r");
- }
- else {
- AV *ar = GvAVn(incgv);
- I32 i;
-
- for (i = 0; i <= AvFILL(ar); i++) {
- (void)sprintf(buf, "%s/%s",
- SvPVx(*av_fetch(ar, i, TRUE), na), name);
- tryrsfp = fopen(buf, "r");
- if (tryrsfp) {
- char *s = buf;
-
- if (*s == '.' && s[1] == '/')
- s += 2;
- Safefree(tmpname);
- tmpname = savestr(s);
- break;
- }
- }
- }
- compiling.cop_filegv = gv_fetchfile(tmpname);
- Safefree(tmpname);
- tmpname = Nullch;
- if (!tryrsfp) {
- if (op->op_type == OP_REQUIRE) {
- sprintf(tokenbuf,"Can't locate %s in @INC", name);
- if (instr(tokenbuf,".h "))
- strcat(tokenbuf," (change .h to .ph maybe?)");
- if (instr(tokenbuf,".ph "))
- strcat(tokenbuf," (did you run h2ph?)");
- DIE("%s",tokenbuf);
- }
-
- RETPUSHUNDEF;
- }
-
- /* Assume success here to prevent recursive requirement. */
- (void)hv_store(GvHVn(incgv), name, strlen(name),
- newSVsv(GvSV(compiling.cop_filegv)), 0 );
-
- ENTER;
- SAVETMPS;
- lex_start(sv_2mortal(newSVpv("",0)));
- rsfp = tryrsfp;
- name = savestr(name);
- SAVEFREEPV(name);
-
- /* switch to eval mode */
-
- push_return(op->op_next);
- PUSHBLOCK(cx, CXt_EVAL, SP);
- PUSHEVAL(cx, name, compiling.cop_filegv);
-
- compiling.cop_line = 0;
-
- PUTBACK;
- return doeval();
-}
-
-PP(pp_dofile)
-{
- return pp_require(ARGS);
-}
-
-PP(pp_entereval)
-{
- dSP;
- register CONTEXT *cx;
- dPOPss;
- I32 gimme = GIMME;
- char tmpbuf[32];
-
- ENTER;
- SAVETMPS;
- lex_start(sv);
-
- /* switch to eval mode */
-
- sprintf(tmpbuf, "_<(eval %d)", ++evalseq);
- compiling.cop_filegv = gv_fetchfile(tmpbuf+2);
- compiling.cop_line = 1;
- SAVEDELETE(defstash, savestr(tmpbuf), strlen(tmpbuf));
-
- push_return(op->op_next);
- PUSHBLOCK(cx, CXt_EVAL, SP);
- PUSHEVAL(cx, 0, compiling.cop_filegv);
-
- /* prepare to compile string */
-
- if (perldb && curstash != debstash)
- save_lines(GvAV(compiling.cop_filegv), linestr);
- PUTBACK;
- return doeval();
-}
-
-PP(pp_leaveeval)
-{
- dSP;
- register SV **mark;
- SV **newsp;
- I32 gimme;
- register CONTEXT *cx;
- OP *retop;
- I32 optype;
- OP *eroot = eval_root;
-
- POPBLOCK(cx);
- POPEVAL(cx);
- retop = pop_return();
-
- if (gimme == G_SCALAR) {
- MARK = newsp + 1;
- if (MARK <= SP) {
- if (SvFLAGS(TOPs) & SVs_TEMP)
- *MARK = TOPs;
- else
- *MARK = sv_mortalcopy(TOPs);
- }
- else {
- MEXTEND(mark,0);
- *MARK = &sv_undef;
- }
- SP = MARK;
- }
- else {
- for (mark = newsp + 1; mark <= SP; mark++)
- if (!(SvFLAGS(TOPs) & SVs_TEMP))
- *mark = sv_mortalcopy(*mark);
- /* in case LEAVE wipes old return values */
- }
-
- if (optype != OP_ENTEREVAL) {
- char *name = cx->blk_eval.old_name;
-
- if (!(gimme == G_SCALAR ? SvTRUE(*sp) : sp > newsp)) {
- /* Unassume the success we assumed earlier. */
- (void)hv_delete(GvHVn(incgv), name, strlen(name));
-
- if (optype == OP_REQUIRE)
- retop = die("%s did not return a true value", name);
- }
- }
-
- lex_end();
- LEAVE;
- sv_setpv(GvSV(gv_fetchpv("@",TRUE, SVt_PV)),"");
-
- RETURNOP(retop);
-}
-
-PP(pp_evalonce)
-{
- dSP;
-#ifdef NOTDEF
- SP = do_eval(st[1], OP_EVAL, curcop->cop_stash, TRUE,
- GIMME, arglast);
- if (eval_root) {
- SvREFCNT_dec(cSVOP->op_sv);
- op[1].arg_ptr.arg_cmd = eval_root;
- op[1].op_type = (A_CMD|A_DONT);
- op[0].op_type = OP_TRY;
- }
- RETURN;
-
-#endif
- RETURN;
-}
-
-PP(pp_entertry)
-{
- dSP;
- register CONTEXT *cx;
- I32 gimme = GIMME;
-
- ENTER;
- SAVETMPS;
-
- push_return(cLOGOP->op_other->op_next);
- PUSHBLOCK(cx, CXt_EVAL, SP);
- PUSHEVAL(cx, 0, 0);
- eval_root = op; /* Only needed so that goto works right. */
-
- in_eval = 1;
- sv_setpv(GvSV(gv_fetchpv("@",TRUE, SVt_PV)),"");
- RETURN;
-}
-
-PP(pp_leavetry)
-{
- dSP;
- register SV **mark;
- SV **newsp;
- I32 gimme;
- register CONTEXT *cx;
- I32 optype;
-
- POPBLOCK(cx);
- POPEVAL(cx);
- pop_return();
-
- if (gimme == G_SCALAR) {
- MARK = newsp + 1;
- if (MARK <= SP) {
- if (SvFLAGS(TOPs) & (SVs_PADTMP|SVs_TEMP))
- *MARK = TOPs;
- else
- *MARK = sv_mortalcopy(TOPs);
- }
- else {
- MEXTEND(mark,0);
- *MARK = &sv_undef;
- }
- SP = MARK;
- }
- else {
- for (mark = newsp + 1; mark <= SP; mark++)
- if (!(SvFLAGS(TOPs) & (SVs_PADTMP|SVs_TEMP)))
- *mark = sv_mortalcopy(*mark);
- /* in case LEAVE wipes old return values */
- }
-
- LEAVE;
- sv_setpv(GvSV(gv_fetchpv("@",TRUE, SVt_PV)),"");
- RETURN;
-}
-
-/* Get system info. */
-
-PP(pp_ghbyname)
-{
-#ifdef HAS_SOCKET
- return pp_ghostent(ARGS);
-#else
- DIE(no_sock_func, "gethostbyname");
-#endif
-}
-
-PP(pp_ghbyaddr)
-{
-#ifdef HAS_SOCKET
- return pp_ghostent(ARGS);
-#else
- DIE(no_sock_func, "gethostbyaddr");
-#endif
-}
-
-PP(pp_ghostent)
-{
- dSP;
-#ifdef HAS_SOCKET
- I32 which = op->op_type;
- register char **elem;
- register SV *sv;
- struct hostent *gethostbyname();
- struct hostent *gethostbyaddr();
-#ifdef HAS_GETHOSTENT
- struct hostent *gethostent();
-#endif
- struct hostent *hent;
- unsigned long len;
-
- EXTEND(SP, 10);
- if (which == OP_GHBYNAME) {
- hent = gethostbyname(POPp);
- }
- else if (which == OP_GHBYADDR) {
- int addrtype = POPi;
- SV *addrstr = POPs;
- char *addr = SvPV(addrstr, na);
-
- hent = gethostbyaddr(addr, SvCUR(addrstr), addrtype);
- }
- else
-#ifdef HAS_GETHOSTENT
- hent = gethostent();
-#else
- DIE("gethostent not implemented");
-#endif
-
-#ifdef HOST_NOT_FOUND
- if (!hent)
- statusvalue = (U16)h_errno & 0xffff;
-#endif
-
- if (GIMME != G_ARRAY) {
- PUSHs(sv = sv_newmortal());
- if (hent) {
- if (which == OP_GHBYNAME) {
- sv_setpvn(sv, hent->h_addr, hent->h_length);
- }
- else
- sv_setpv(sv, hent->h_name);
- }
- RETURN;
- }
-
- if (hent) {
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setpv(sv, hent->h_name);
- PUSHs(sv = sv_mortalcopy(&sv_no));
- for (elem = hent->h_aliases; *elem; elem++) {
- sv_catpv(sv, *elem);
- if (elem[1])
- sv_catpvn(sv, " ", 1);
- }
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setiv(sv, (I32)hent->h_addrtype);
- PUSHs(sv = sv_mortalcopy(&sv_no));
- len = hent->h_length;
- sv_setiv(sv, (I32)len);
-#ifdef h_addr
- for (elem = hent->h_addr_list; *elem; elem++) {
- XPUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setpvn(sv, *elem, len);
- }
-#else
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setpvn(sv, hent->h_addr, len);
-#endif /* h_addr */
- }
- RETURN;
-#else
- DIE(no_sock_func, "gethostent");
-#endif
-}
-
-PP(pp_gnbyname)
-{
-#ifdef HAS_SOCKET
- return pp_gnetent(ARGS);
-#else
- DIE(no_sock_func, "getnetbyname");
-#endif
-}
-
-PP(pp_gnbyaddr)
-{
-#ifdef HAS_SOCKET
- return pp_gnetent(ARGS);
-#else
- DIE(no_sock_func, "getnetbyaddr");
-#endif
-}
-
-PP(pp_gnetent)
-{
- dSP;
-#ifdef HAS_SOCKET
- I32 which = op->op_type;
- register char **elem;
- register SV *sv;
- struct netent *getnetbyname();
- struct netent *getnetbyaddr();
- struct netent *getnetent();
- struct netent *nent;
-
- if (which == OP_GNBYNAME)
- nent = getnetbyname(POPp);
- else if (which == OP_GNBYADDR) {
- int addrtype = POPi;
- unsigned long addr = U_L(POPn);
- nent = getnetbyaddr((long)addr, addrtype);
- }
- else
- nent = getnetent();
-
- EXTEND(SP, 4);
- if (GIMME != G_ARRAY) {
- PUSHs(sv = sv_newmortal());
- if (nent) {
- if (which == OP_GNBYNAME)
- sv_setiv(sv, (I32)nent->n_net);
- else
- sv_setpv(sv, nent->n_name);
- }
- RETURN;
- }
-
- if (nent) {
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setpv(sv, nent->n_name);
- PUSHs(sv = sv_mortalcopy(&sv_no));
- for (elem = nent->n_aliases; *elem; elem++) {
- sv_catpv(sv, *elem);
- if (elem[1])
- sv_catpvn(sv, " ", 1);
- }
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setiv(sv, (I32)nent->n_addrtype);
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setiv(sv, (I32)nent->n_net);
- }
-
- RETURN;
-#else
- DIE(no_sock_func, "getnetent");
-#endif
-}
-
-PP(pp_gpbyname)
-{
-#ifdef HAS_SOCKET
- return pp_gprotoent(ARGS);
-#else
- DIE(no_sock_func, "getprotobyname");
-#endif
-}
-
-PP(pp_gpbynumber)
-{
-#ifdef HAS_SOCKET
- return pp_gprotoent(ARGS);
-#else
- DIE(no_sock_func, "getprotobynumber");
-#endif
-}
-
-PP(pp_gprotoent)
-{
- dSP;
-#ifdef HAS_SOCKET
- I32 which = op->op_type;
- register char **elem;
- register SV *sv;
- struct protoent *getprotobyname();
- struct protoent *getprotobynumber();
- struct protoent *getprotoent();
- struct protoent *pent;
-
- if (which == OP_GPBYNAME)
- pent = getprotobyname(POPp);
- else if (which == OP_GPBYNUMBER)
- pent = getprotobynumber(POPi);
- else
- pent = getprotoent();
-
- EXTEND(SP, 3);
- if (GIMME != G_ARRAY) {
- PUSHs(sv = sv_newmortal());
- if (pent) {
- if (which == OP_GPBYNAME)
- sv_setiv(sv, (I32)pent->p_proto);
- else
- sv_setpv(sv, pent->p_name);
- }
- RETURN;
- }
-
- if (pent) {
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setpv(sv, pent->p_name);
- PUSHs(sv = sv_mortalcopy(&sv_no));
- for (elem = pent->p_aliases; *elem; elem++) {
- sv_catpv(sv, *elem);
- if (elem[1])
- sv_catpvn(sv, " ", 1);
- }
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setiv(sv, (I32)pent->p_proto);
- }
-
- RETURN;
-#else
- DIE(no_sock_func, "getprotoent");
-#endif
-}
-
-PP(pp_gsbyname)
-{
-#ifdef HAS_SOCKET
- return pp_gservent(ARGS);
-#else
- DIE(no_sock_func, "getservbyname");
-#endif
-}
-
-PP(pp_gsbyport)
-{
-#ifdef HAS_SOCKET
- return pp_gservent(ARGS);
-#else
- DIE(no_sock_func, "getservbyport");
-#endif
-}
-
-PP(pp_gservent)
-{
- dSP;
-#ifdef HAS_SOCKET
- I32 which = op->op_type;
- register char **elem;
- register SV *sv;
- struct servent *getservbyname();
- struct servent *getservbynumber();
- struct servent *getservent();
- struct servent *sent;
-
- if (which == OP_GSBYNAME) {
- char *proto = POPp;
- char *name = POPp;
-
- if (proto && !*proto)
- proto = Nullch;
-
- sent = getservbyname(name, proto);
- }
- else if (which == OP_GSBYPORT) {
- char *proto = POPp;
- int port = POPi;
-
- sent = getservbyport(port, proto);
- }
- else
- sent = getservent();
-
- EXTEND(SP, 4);
- if (GIMME != G_ARRAY) {
- PUSHs(sv = sv_newmortal());
- if (sent) {
- if (which == OP_GSBYNAME) {
-#ifdef HAS_NTOHS
- sv_setiv(sv, (I32)ntohs(sent->s_port));
-#else
- sv_setiv(sv, (I32)(sent->s_port));
-#endif
- }
- else
- sv_setpv(sv, sent->s_name);
- }
- RETURN;
- }
-
- if (sent) {
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setpv(sv, sent->s_name);
- PUSHs(sv = sv_mortalcopy(&sv_no));
- for (elem = sent->s_aliases; *elem; elem++) {
- sv_catpv(sv, *elem);
- if (elem[1])
- sv_catpvn(sv, " ", 1);
- }
- PUSHs(sv = sv_mortalcopy(&sv_no));
-#ifdef HAS_NTOHS
- sv_setiv(sv, (I32)ntohs(sent->s_port));
-#else
- sv_setiv(sv, (I32)(sent->s_port));
-#endif
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setpv(sv, sent->s_proto);
- }
-
- RETURN;
-#else
- DIE(no_sock_func, "getservent");
-#endif
-}
-
-PP(pp_shostent)
-{
- dSP;
-#ifdef HAS_SOCKET
- sethostent(TOPi);
- RETSETYES;
-#else
- DIE(no_sock_func, "sethostent");
-#endif
-}
-
-PP(pp_snetent)
-{
- dSP;
-#ifdef HAS_SOCKET
- setnetent(TOPi);
- RETSETYES;
-#else
- DIE(no_sock_func, "setnetent");
-#endif
-}
-
-PP(pp_sprotoent)
-{
- dSP;
-#ifdef HAS_SOCKET
- setprotoent(TOPi);
- RETSETYES;
-#else
- DIE(no_sock_func, "setprotoent");
-#endif
-}
-
-PP(pp_sservent)
-{
- dSP;
-#ifdef HAS_SOCKET
- setservent(TOPi);
- RETSETYES;
-#else
- DIE(no_sock_func, "setservent");
-#endif
-}
-
-PP(pp_ehostent)
-{
- dSP;
-#ifdef HAS_SOCKET
- endhostent();
- EXTEND(sp,1);
- RETPUSHYES;
-#else
- DIE(no_sock_func, "endhostent");
-#endif
-}
-
-PP(pp_enetent)
-{
- dSP;
-#ifdef HAS_SOCKET
- endnetent();
- EXTEND(sp,1);
- RETPUSHYES;
-#else
- DIE(no_sock_func, "endnetent");
-#endif
-}
-
-PP(pp_eprotoent)
-{
- dSP;
-#ifdef HAS_SOCKET
- endprotoent();
- EXTEND(sp,1);
- RETPUSHYES;
-#else
- DIE(no_sock_func, "endprotoent");
-#endif
-}
-
-PP(pp_eservent)
-{
- dSP;
-#ifdef HAS_SOCKET
- endservent();
- EXTEND(sp,1);
- RETPUSHYES;
-#else
- DIE(no_sock_func, "endservent");
-#endif
-}
-
-PP(pp_gpwnam)
-{
-#ifdef HAS_PASSWD
- return pp_gpwent(ARGS);
-#else
- DIE(no_func, "getpwnam");
-#endif
-}
-
-PP(pp_gpwuid)
-{
-#ifdef HAS_PASSWD
- return pp_gpwent(ARGS);
-#else
- DIE(no_func, "getpwuid");
-#endif
-}
-
-PP(pp_gpwent)
-{
- dSP;
-#ifdef HAS_PASSWD
- I32 which = op->op_type;
- register AV *ary = stack;
- register SV *sv;
- struct passwd *pwent;
-
- if (which == OP_GPWNAM)
- pwent = getpwnam(POPp);
- else if (which == OP_GPWUID)
- pwent = getpwuid(POPi);
- else
- pwent = (struct passwd *)getpwent();
-
- EXTEND(SP, 10);
- if (GIMME != G_ARRAY) {
- PUSHs(sv = sv_newmortal());
- if (pwent) {
- if (which == OP_GPWNAM)
- sv_setiv(sv, (I32)pwent->pw_uid);
- else
- sv_setpv(sv, pwent->pw_name);
- }
- RETURN;
- }
-
- if (pwent) {
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setpv(sv, pwent->pw_name);
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setpv(sv, pwent->pw_passwd);
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setiv(sv, (I32)pwent->pw_uid);
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setiv(sv, (I32)pwent->pw_gid);
- PUSHs(sv = sv_mortalcopy(&sv_no));
-#ifdef PWCHANGE
- sv_setiv(sv, (I32)pwent->pw_change);
-#else
-#ifdef PWQUOTA
- sv_setiv(sv, (I32)pwent->pw_quota);
-#else
-#ifdef PWAGE
- sv_setpv(sv, pwent->pw_age);
-#endif
-#endif
-#endif
- PUSHs(sv = sv_mortalcopy(&sv_no));
-#ifdef PWCLASS
- sv_setpv(sv, pwent->pw_class);
-#else
-#ifdef PWCOMMENT
- sv_setpv(sv, pwent->pw_comment);
-#endif
-#endif
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setpv(sv, pwent->pw_gecos);
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setpv(sv, pwent->pw_dir);
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setpv(sv, pwent->pw_shell);
-#ifdef PWEXPIRE
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setiv(sv, (I32)pwent->pw_expire);
-#endif
- }
- RETURN;
-#else
- DIE(no_func, "getpwent");
-#endif
-}
-
-PP(pp_spwent)
-{
- dSP; dTARGET;
-#ifdef HAS_PASSWD
- setpwent();
- RETPUSHYES;
-#else
- DIE(no_func, "setpwent");
-#endif
-}
-
-PP(pp_epwent)
-{
- dSP; dTARGET;
-#ifdef HAS_PASSWD
- endpwent();
- RETPUSHYES;
-#else
- DIE(no_func, "endpwent");
-#endif
-}
-
-PP(pp_ggrnam)
-{
-#ifdef HAS_GROUP
- return pp_ggrent(ARGS);
-#else
- DIE(no_func, "getgrnam");
-#endif
-}
-
-PP(pp_ggrgid)
-{
-#ifdef HAS_GROUP
- return pp_ggrent(ARGS);
-#else
- DIE(no_func, "getgrgid");
-#endif
-}
-
-PP(pp_ggrent)
-{
- dSP;
-#ifdef HAS_GROUP
- I32 which = op->op_type;
- register char **elem;
- register SV *sv;
- struct group *grent;
-
- if (which == OP_GGRNAM)
- grent = getgrnam(POPp);
- else if (which == OP_GGRGID)
- grent = getgrgid(POPi);
- else
- grent = (struct group *)getgrent();
-
- EXTEND(SP, 4);
- if (GIMME != G_ARRAY) {
- PUSHs(sv = sv_newmortal());
- if (grent) {
- if (which == OP_GGRNAM)
- sv_setiv(sv, (I32)grent->gr_gid);
- else
- sv_setpv(sv, grent->gr_name);
- }
- RETURN;
- }
-
- if (grent) {
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setpv(sv, grent->gr_name);
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setpv(sv, grent->gr_passwd);
- PUSHs(sv = sv_mortalcopy(&sv_no));
- sv_setiv(sv, (I32)grent->gr_gid);
- PUSHs(sv = sv_mortalcopy(&sv_no));
- for (elem = grent->gr_mem; *elem; elem++) {
- sv_catpv(sv, *elem);
- if (elem[1])
- sv_catpvn(sv, " ", 1);
- }
- }
-
- RETURN;
-#else
- DIE(no_func, "getgrent");
-#endif
-}
-
-PP(pp_sgrent)
-{
- dSP; dTARGET;
-#ifdef HAS_GROUP
- setgrent();
- RETPUSHYES;
-#else
- DIE(no_func, "setgrent");
-#endif
-}
-
-PP(pp_egrent)
-{
- dSP; dTARGET;
-#ifdef HAS_GROUP
- endgrent();
- RETPUSHYES;
-#else
- DIE(no_func, "endgrent");
-#endif
-}
-
-PP(pp_getlogin)
-{
- dSP; dTARGET;
-#ifdef HAS_GETLOGIN
- char *tmps;
- EXTEND(SP, 1);
- if (!(tmps = getlogin()))
- RETPUSHUNDEF;
- PUSHp(tmps, strlen(tmps));
- RETURN;
-#else
- DIE(no_func, "getlogin");
-#endif
-}
-
-/* Miscellaneous. */
-
-PP(pp_syscall)
-{
-#ifdef HAS_SYSCALL
- dSP; dMARK; dORIGMARK; dTARGET;
- register I32 items = SP - MARK;
- unsigned long a[20];
- register I32 i = 0;
- I32 retval = -1;
-
- if (tainting) {
- while (++MARK <= SP) {
- if (SvRMAGICAL(*MARK) && mg_find(*MARK, 't'))
- tainted = TRUE;
- }
- MARK = ORIGMARK;
- TAINT_PROPER("syscall");
- }
-
- /* This probably won't work on machines where sizeof(long) != sizeof(int)
- * or where sizeof(long) != sizeof(char*). But such machines will
- * not likely have syscall implemented either, so who cares?
- */
- while (++MARK <= SP) {
- if (SvNIOK(*MARK) || !i)
- a[i++] = SvIV(*MARK);
- else
- a[i++] = (unsigned long)SvPVX(*MARK);
- if (i > 15)
- break;
- }
- switch (items) {
- default:
- DIE("Too many args to syscall");
- case 0:
- DIE("Too few args to syscall");
- case 1:
- retval = syscall(a[0]);
- break;
- case 2:
- retval = syscall(a[0],a[1]);
- break;
- case 3:
- retval = syscall(a[0],a[1],a[2]);
- break;
- case 4:
- retval = syscall(a[0],a[1],a[2],a[3]);
- break;
- case 5:
- retval = syscall(a[0],a[1],a[2],a[3],a[4]);
- break;
- case 6:
- retval = syscall(a[0],a[1],a[2],a[3],a[4],a[5]);
- break;
- case 7:
- retval = syscall(a[0],a[1],a[2],a[3],a[4],a[5],a[6]);
- break;
- case 8:
- retval = syscall(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7]);
- break;
-#ifdef atarist
- case 9:
- retval = syscall(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]);
- break;
- case 10:
- retval = syscall(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]);
- break;
- case 11:
- retval = syscall(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],
- a[10]);
- break;
- case 12:
- retval = syscall(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],
- a[10],a[11]);
- break;
- case 13:
- retval = syscall(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],
- a[10],a[11],a[12]);
- break;
- case 14:
- retval = syscall(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],
- a[10],a[11],a[12],a[13]);
- break;
-#endif /* atarist */
- }
- SP = ORIGMARK;
- PUSHi(retval);
- RETURN;
-#else
- DIE(no_func, "syscall");
-#endif
}