This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Unicode 4.1.0
[perl5.git] / pp_sys.c
index 3071f1b..cf188f0 100644 (file)
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -1,7 +1,7 @@
 /*    pp_sys.c
  *
  *    Copyright (C) 1995, 1996, 1997, 1998, 1999,
- *    2000, 2001, 2002, 2003, 2004, by Larry Wall and others
+ *    2000, 2001, 2002, 2003, 2004, 2005, by Larry Wall and others
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
@@ -322,16 +322,16 @@ PP(pp_backtick)
     STRLEN n_a;
     char *tmps = POPpx;
     I32 gimme = GIMME_V;
-    char *mode = "r";
+    const char *mode = "r";
 
     TAINT_PROPER("``");
     if (PL_op->op_private & OPpOPEN_IN_RAW)
        mode = "rb";
     else if (PL_op->op_private & OPpOPEN_IN_CRLF)
        mode = "rt";
-    fp = PerlProc_popen(tmps, mode);
+    fp = PerlProc_popen(tmps, (char *)mode);
     if (fp) {
-       char *type = NULL;
+        const char *type = NULL;
        if (PL_curcop->cop_io) {
            type = SvPV_nolen(PL_curcop->cop_io);
        }
@@ -345,13 +345,14 @@ PP(pp_backtick)
                ;
        }
        else if (gimme == G_SCALAR) {
-           SV *oldrs = PL_rs;
+           ENTER;
+           SAVESPTR(PL_rs);
            PL_rs = &PL_sv_undef;
            sv_setpv(TARG, ""); /* note that this preserves previous buffer */
            while (sv_gets(TARG, fp, SvCUR(TARG)) != Nullch)
                /*SUPPRESS 530*/
                ;
-           PL_rs = oldrs;
+           LEAVE;
            XPUSHs(TARG);
            SvTAINTED_on(TARG);
        }
@@ -432,7 +433,7 @@ PP(pp_warn)
 {
     dSP; dMARK;
     SV *tmpsv;
-    char *tmps;
+    const char *tmps;
     STRLEN len;
     if (SP - MARK != 1) {
        dTARGET;
@@ -462,7 +463,7 @@ PP(pp_warn)
 PP(pp_die)
 {
     dSP; dMARK;
-    char *tmps;
+    const char *tmps;
     SV *tmpsv;
     STRLEN len;
     bool multiarg = 0;
@@ -504,7 +505,7 @@ PP(pp_die)
                    sv_setsv(error,*PL_stack_sp--);
                }
            }
-           DIE(aTHX_ Nullformat);
+           DIE_NULL;
        }
        else {
            if (SvPOK(error) && SvCUR(error))
@@ -789,7 +790,7 @@ PP(pp_tie)
     GV *gv;
     SV *sv;
     I32 markoff = MARK - PL_stack_base;
-    char *methname;
+    const char *methname;
     int how = PERL_MAGIC_tied;
     U32 items;
 
@@ -1337,16 +1338,16 @@ PP(pp_leavewrite)
                if (!IoFMT_NAME(io))
                    IoFMT_NAME(io) = savepv(GvNAME(gv));
                topname = sv_2mortal(Perl_newSVpvf(aTHX_ "%s_TOP", GvNAME(gv)));
-               topgv = gv_fetchpv(SvPVX(topname), FALSE, SVt_PVFM);
+               topgv = gv_fetchsv(topname, FALSE, SVt_PVFM);
                if ((topgv && GvFORM(topgv)) ||
                  !gv_fetchpv("top",FALSE,SVt_PVFM))
-                   IoTOP_NAME(io) = savepv(SvPVX(topname));
+                   IoTOP_NAME(io) = savesvpv(topname);
                else
-                   IoTOP_NAME(io) = savepv("top");
+                   IoTOP_NAME(io) = savepvn("top", 3);
            }
            topgv = gv_fetchpv(IoTOP_NAME(io),FALSE, SVt_PVFM);
            if (!topgv || !GvFORM(topgv)) {
-               IoLINES_LEFT(io) = 100000000;
+               IoLINES_LEFT(io) = IoPAGE_LEN(io);
                goto forget_top;
            }
            IoTOP_GV(io) = topgv;
@@ -1555,6 +1556,8 @@ PP(pp_sysread)
     STRLEN blen;
     MAGIC *mg;
     int fp_utf8;
+    int buffer_utf8;
+    SV *read_target;
     Size_t got = 0;
     Size_t wanted;
     bool charstart = FALSE;
@@ -1602,9 +1605,11 @@ PP(pp_sysread)
        buffer = SvPVutf8_force(bufsv, blen);
        /* UTF-8 may not have been set if they are all low bytes */
        SvUTF8_on(bufsv);
+       buffer_utf8 = 0;
     }
     else {
        buffer = SvPV_force(bufsv, blen);
+       buffer_utf8 = !IN_BYTES && SvUTF8(bufsv);
     }
     if (length < 0)
        DIE(aTHX_ "Negative length");
@@ -1672,11 +1677,30 @@ PP(pp_sysread)
     }
  more_bytes:
     bufsize = SvCUR(bufsv);
+    /* Allocating length + offset + 1 isn't perfect in the case of reading
+       bytes from a byte file handle into a UTF8 buffer, but it won't harm us
+       unduly.
+       (should be 2 * length + offset + 1, or possibly something longer if
+       PL_encoding is true) */
     buffer  = SvGROW(bufsv, (STRLEN)(length+offset+1));
     if (offset > bufsize) { /* Zero any newly allocated space */
        Zero(buffer+bufsize, offset-bufsize, char);
     }
     buffer = buffer + offset;
+    if (!buffer_utf8) {
+       read_target = bufsv;
+    } else {
+       /* Best to read the bytes into a new SV, upgrade that to UTF8, then
+          concatenate it to the current buffer.  */
+
+       /* Truncate the existing buffer to the start of where we will be
+          reading to:  */
+       SvCUR_set(bufsv, offset);
+
+       read_target = sv_newmortal();
+       SvUPGRADE(read_target, SVt_PV);
+       buffer = SvGROW(read_target, (STRLEN)(length + 1));
+    }
 
     if (PL_op->op_type == OP_SYSREAD) {
 #ifdef PERL_SOCK_SYSREAD_IS_RECV
@@ -1716,9 +1740,9 @@ PP(pp_sysread)
                report_evil_fh(gv, io, OP_phoney_OUTPUT_ONLY);
        goto say_undef;
     }
-    SvCUR_set(bufsv, count+(buffer - SvPVX(bufsv)));
-    *SvEND(bufsv) = '\0';
-    (void)SvPOK_only(bufsv);
+    SvCUR_set(read_target, count+(buffer - SvPVX(read_target)));
+    *SvEND(read_target) = '\0';
+    (void)SvPOK_only(read_target);
     if (fp_utf8 && !IN_BYTES) {
        /* Look at utf8 we got back and count the characters */
        char *bend = buffer + count;
@@ -1754,6 +1778,11 @@ PP(pp_sysread)
        count = got;
        SvUTF8_on(bufsv);
     }
+    else if (buffer_utf8) {
+       /* Let svcatsv upgrade the bytes we read in to utf8.
+          The buffer is a mortal so will be freed soon.  */
+       sv_catsv_nomg(bufsv, read_target);
+    }
     SvSETMAGIC(bufsv);
     /* This should not be marked tainted if the fp is marked clean */
     if (!(IoFLAGS(io) & IOf_UNTAINT))
@@ -1939,7 +1968,7 @@ PP(pp_eof)
                if ((IoFLAGS(io) & IOf_START) && av_len(GvAVn(gv)) < 0) {
                    IoLINES(io) = 0;
                    IoFLAGS(io) &= ~IOf_START;
-                   do_open(gv, "-", 1, FALSE, O_RDONLY, 0, Nullfp);
+                   do_open(gv, (char *)"-", 1, FALSE, O_RDONLY, 0, Nullfp);
                    sv_setpvn(GvSV(gv), "-", 1);
                    SvSETMAGIC(GvSV(gv));
                }
@@ -2081,15 +2110,13 @@ PP(pp_truncate)
      * might not be signed: if it is not, clever compilers will moan. */
     /* XXX Configure probe for the signedness of the length type of *truncate() needed? XXX */
     SETERRNO(0,0);
-#if defined(HAS_TRUNCATE) || defined(HAS_CHSIZE) || defined(F_FREESP)
     {
-        STRLEN n_a;
        int result = 1;
        GV *tmpgv;
        IO *io;
 
        if (PL_op->op_flags & OPf_SPECIAL) {
-           tmpgv = gv_fetchpv(POPpx, FALSE, SVt_PVIO);
+           tmpgv = gv_fetchsv(POPs, FALSE, SVt_PVIO);
 
        do_ftruncate_gv:
            if (!GvIO(tmpgv))
@@ -2116,7 +2143,8 @@ PP(pp_truncate)
        else {
            SV *sv = POPs;
            char *name;
-       
+           STRLEN n_a;
+
            if (SvTYPE(sv) == SVt_PVGV) {
                tmpgv = (GV*)sv;                /* *main::FRED for example */
                goto do_ftruncate_gv;
@@ -2156,9 +2184,6 @@ PP(pp_truncate)
            SETERRNO(EBADF,RMS_IFI);
        RETPUSHUNDEF;
     }
-#else
-    DIE(aTHX_ "truncate not implemented");
-#endif
 }
 
 PP(pp_fcntl)
@@ -2171,7 +2196,7 @@ PP(pp_ioctl)
     dSP; dTARGET;
     SV *argsv = POPs;
     unsigned int func = POPu;
-    int optype = PL_op->op_type;
+    const int optype = PL_op->op_type;
     char *s;
     IV retval;
     GV *gv = (GV*)POPs;
@@ -2818,12 +2843,10 @@ PP(pp_stat)
        }
        sv_setpv(PL_statname, SvPV(sv,n_a));
        PL_statgv = Nullgv;
-#ifdef HAS_LSTAT
        PL_laststype = PL_op->op_type;
        if (PL_op->op_type == OP_LSTAT)
            PL_laststatval = PerlLIO_lstat(SvPV(PL_statname, n_a), &PL_statcache);
        else
-#endif
            PL_laststatval = PerlLIO_stat(SvPV(PL_statname, n_a), &PL_statcache);
        if (PL_laststatval < 0) {
            if (ckWARN(WARN_NEWLINE) && strchr(SvPV(PL_statname, n_a), '\n'))
@@ -3320,8 +3343,7 @@ PP(pp_fttty)
     dSP;
     int fd;
     GV *gv;
-    char *tmps = Nullch;
-    STRLEN n_a;
+    SV *tmpsv = Nullsv;
 
     STACKED_FTEST_CHECK;
 
@@ -3332,12 +3354,18 @@ PP(pp_fttty)
     else if (SvROK(TOPs) && isGV(SvRV(TOPs)))
        gv = (GV*)SvRV(POPs);
     else
-       gv = gv_fetchpv(tmps = POPpx, FALSE, SVt_PVIO);
+       gv = gv_fetchsv(tmpsv = POPs, FALSE, SVt_PVIO);
 
     if (GvIO(gv) && IoIFP(GvIOp(gv)))
        fd = PerlIO_fileno(IoIFP(GvIOp(gv)));
-    else if (tmps && isDIGIT(*tmps))
-       fd = atoi(tmps);
+    else if (tmpsv && SvOK(tmpsv)) {
+       STRLEN n_a;
+       char *tmps = SvPV(tmpsv, n_a);
+       if (isDIGIT(*tmps))
+           fd = atoi(tmps);
+       else 
+           RETPUSHUNDEF;
+    }
     else
        RETPUSHUNDEF;
     if (PerlLIO_isatty(fd))
@@ -3432,7 +3460,6 @@ PP(pp_fttext)
        sv = POPs;
       really_filename:
        PL_statgv = Nullgv;
-       PL_laststatval = -1;
        PL_laststype = OP_STAT;
        sv_setpv(PL_statname, SvPV(sv, n_a));
        if (!(fp = PerlIO_open(SvPVX(PL_statname), "r"))) {
@@ -4500,9 +4527,9 @@ 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",
+    const struct tm *tmbuf;
+    static const char *dayname[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+    static const char *monname[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
                              "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
 
     if (MAXARG < 1)
@@ -5836,3 +5863,13 @@ lockf_emulate_flock(int fd, int operation)
 }
 
 #endif /* LOCKF_EMULATE_FLOCK */
+
+/*
+ * Local variables:
+ * c-indentation-style: bsd
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ *
+ * vim: shiftwidth=4:
+*/