move startglob out of pp_hot.c
[p5sagit/p5-mst-13.2.git] / doio.c
diff --git a/doio.c b/doio.c
index 3e36ea3..1ac381b 100644 (file)
--- a/doio.c
+++ b/doio.c
 #include <signal.h>
 #endif
 
-#ifdef SOCKS_64BIT_BUG
-typedef struct __s64_iobuffer {
-    struct __s64_iobuffer *next, *last;                /* Queue pointer */
-    PerlIO *fp;                                        /* assigned file pointer */
-    int cnt;                                   /* Buffer counter */
-    int size;                                  /* Buffer size */
-    int *buffer;                               /* the buffer */
-} S64_IOB;
-
-#endif
-
 bool
 Perl_do_open(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
             int rawmode, int rawperm, PerlIO *supplied_fp)
@@ -237,7 +226,6 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
                len = tend-type;
            }
            if (*name == '\0') { /* command is missing 19990114 */
-               dTHR;
                if (ckWARN(WARN_PIPE))
                    Perl_warner(aTHX_ WARN_PIPE, "Missing command in piped open");
                errno = EPIPE;
@@ -247,7 +235,6 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
                TAINT_ENV();
            TAINT_PROPER("piped open");
            if (!num_svs && name[len-1] == '|') {
-               dTHR;
                name[--len] = '\0' ;
                if (ckWARN(WARN_PIPE))
                    Perl_warner(aTHX_ WARN_PIPE, "Can't open bidirectional pipe");
@@ -401,7 +388,6 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
                len  = tend-type;
            }
            if (*name == '\0') { /* command is missing 19990114 */
-               dTHR;
                if (ckWARN(WARN_PIPE))
                    Perl_warner(aTHX_ WARN_PIPE, "Missing command in piped open");
                errno = EPIPE;
@@ -440,13 +426,11 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
        }
     }
     if (!fp) {
-       dTHR;
        if (ckWARN(WARN_NEWLINE) && IoTYPE(io) == IoTYPE_RDONLY && strchr(name, '\n'))
            Perl_warner(aTHX_ WARN_NEWLINE, PL_warn_nl, "open");
        goto say_false;
     }
     if (IoTYPE(io) && IoTYPE(io) != IoTYPE_PIPE && IoTYPE(io) != IoTYPE_STD) {
-       dTHR;
        if (PerlLIO_fstat(PerlIO_fileno(fp),&PL_statbuf) < 0) {
            (void)PerlIO_close(fp);
            goto say_false;
@@ -475,14 +459,14 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
     }
     if (saveifp) {             /* must use old fp? */
         /* If fd is less that PL_maxsysfd i.e. STDIN..STDERR
-           then dup the new fileno down 
+           then dup the new fileno down
          */
        fd = PerlIO_fileno(saveifp);
        if (saveofp) {
            PerlIO_flush(saveofp);      /* emulate PerlIO_close() */
            if (saveofp != saveifp) {   /* was a socket? */
                PerlIO_close(saveofp);
-                /* This looks very suspect - NI-S 24 Nov 2000 */ 
+                /* This looks very suspect - NI-S 24 Nov 2000 */
                if (fd > 2)
                    Safefree(saveofp);  /* ??? */
            }
@@ -544,7 +528,6 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
 
     IoFLAGS(io) &= ~IOf_NOLINE;
     if (writing) {
-       dTHR;
        if (IoTYPE(io) == IoTYPE_SOCKET
            || (IoTYPE(io) == IoTYPE_WRONLY && S_ISCHR(PL_statbuf.st_mode)) )
        {
@@ -608,7 +591,6 @@ Perl_nextargv(pTHX_ register GV *gv)
     }
     PL_filemode = 0;
     while (av_len(GvAV(gv)) >= 0) {
-       dTHR;
        STRLEN oldlen;
        sv = av_shift(GvAV(gv));
        SAVEFREESV(sv);
@@ -757,7 +739,6 @@ Perl_nextargv(pTHX_ register GV *gv)
            return IoIFP(GvIOp(gv));
        }
        else {
-           dTHR;
            if (ckWARN_d(WARN_INPLACE)) {
                int eno = errno;
                if (PerlLIO_stat(PL_oldname, &PL_statbuf) >= 0
@@ -852,7 +833,6 @@ Perl_do_close(pTHX_ GV *gv, bool not_implicit)
     io = GvIO(gv);
     if (!io) {         /* never opened */
        if (not_implicit) {
-           dTHR;
            if (ckWARN(WARN_UNOPENED)) /* no check for closed here */
                report_evil_fh(gv, io, PL_op->op_type);
            SETERRNO(EBADF,SS$_IVCHAN);
@@ -908,7 +888,6 @@ Perl_io_close(pTHX_ IO *io, bool not_implicit)
 bool
 Perl_do_eof(pTHX_ GV *gv)
 {
-    dTHR;
     register IO *io;
     int ch;
 
@@ -975,11 +954,8 @@ Perl_do_tell(pTHX_ GV *gv)
 #endif
        return PerlIO_tell(fp);
     }
-    {
-       dTHR;
-       if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
-           report_evil_fh(gv, io, PL_op->op_type);
-    }
+    if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
+       report_evil_fh(gv, io, PL_op->op_type);
     SETERRNO(EBADF,RMS$_IFI);
     return (Off_t)-1;
 }
@@ -997,11 +973,8 @@ Perl_do_seek(pTHX_ GV *gv, Off_t pos, int whence)
 #endif
        return PerlIO_seek(fp, pos, whence) >= 0;
     }
-    {
-       dTHR;
-       if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
-           report_evil_fh(gv, io, PL_op->op_type);
-    }
+    if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
+       report_evil_fh(gv, io, PL_op->op_type);
     SETERRNO(EBADF,RMS$_IFI);
     return FALSE;
 }
@@ -1014,11 +987,8 @@ Perl_do_sysseek(pTHX_ GV *gv, Off_t pos, int whence)
 
     if (gv && (io = GvIO(gv)) && (fp = IoIFP(io)))
        return PerlLIO_lseek(PerlIO_fileno(fp), pos, whence);
-    {
-       dTHR;
-       if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
-           report_evil_fh(gv, io, PL_op->op_type);
-    }
+    if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
+       report_evil_fh(gv, io, PL_op->op_type);
     SETERRNO(EBADF,RMS$_IFI);
     return (Off_t)-1;
 }
@@ -1163,11 +1133,8 @@ Perl_do_print(pTHX_ register SV *sv, PerlIO *fp)
     }
     switch (SvTYPE(sv)) {
     case SVt_NULL:
-       {
-           dTHR;
-           if (ckWARN(WARN_UNINITIALIZED))
-               report_uninit();
-       }
+       if (ckWARN(WARN_UNINITIALIZED))
+           report_uninit();
        return TRUE;
     case SVt_IV:
        if (SvIOK(sv)) {
@@ -1181,12 +1148,14 @@ Perl_do_print(pTHX_ register SV *sv, PerlIO *fp)
        }
        /* FALL THROUGH */
     default:
-#if 0
-       /* XXX Fix this when the I/O disciplines arrive. XXX */
-       if (DO_UTF8(sv))
-           sv_utf8_downgrade(sv, FALSE);
-#endif
-       tmps = SvPV(sv, len);
+       if (PerlIO_isutf8(fp)) {
+           tmps = SvPVutf8(sv, len);
+       }
+       else {
+           if (DO_UTF8(sv))
+               sv_utf8_downgrade(sv, FALSE);
+           tmps = SvPV(sv, len);
+       }
        break;
     }
     /* To detect whether the process is about to overstep its
@@ -1298,7 +1267,6 @@ Perl_do_aexec5(pTHX_ SV *really, register SV **mark, register SV **sp,
     STRLEN n_a;
 
     if (sp > mark) {
-       dTHR;
        New(401,PL_Argv, sp - mark + 1, char*);
        a = PL_Argv;
        while (++mark <= sp) {
@@ -1311,9 +1279,9 @@ Perl_do_aexec5(pTHX_ SV *really, register SV **mark, register SV **sp,
        if (*PL_Argv[0] != '/') /* will execvp use PATH? */
            TAINT_ENV();                /* testing IFS here is overkill, probably */
        if (really && *(tmps = SvPV(really, n_a)))
-           PerlProc_execvp(tmps,PL_Argv);
+           PerlProc_execvp(tmps,EXEC_ARGV_CAST(PL_Argv));
        else
-           PerlProc_execvp(PL_Argv[0],PL_Argv);
+           PerlProc_execvp(PL_Argv[0],EXEC_ARGV_CAST(PL_Argv));
        if (ckWARN(WARN_EXEC))
            Perl_warner(aTHX_ WARN_EXEC, "Can't exec \"%s\": %s",
                PL_Argv[0], Strerror(errno));
@@ -1446,7 +1414,6 @@ Perl_do_exec3(pTHX_ char *cmd, int fd, int do_report)
            goto doshell;
        }
        {
-           dTHR;
            int e = errno;
 
            if (ckWARN(WARN_EXEC))
@@ -1467,7 +1434,6 @@ Perl_do_exec3(pTHX_ char *cmd, int fd, int do_report)
 I32
 Perl_apply(pTHX_ I32 type, register SV **mark, register SV **sp)
 {
-    dTHR;
     register I32 val;
     register I32 val2;
     register I32 tot = 0;
@@ -1752,7 +1718,6 @@ Perl_ingroup(pTHX_ Gid_t testgid, Uid_t effective)
 I32
 Perl_do_ipcget(pTHX_ I32 optype, SV **mark, SV **sp)
 {
-    dTHR;
     key_t key;
     I32 n, flags;
 
@@ -1785,7 +1750,6 @@ Perl_do_ipcget(pTHX_ I32 optype, SV **mark, SV **sp)
 I32
 Perl_do_ipcctl(pTHX_ I32 optype, SV **mark, SV **sp)
 {
-    dTHR;
     SV *astr;
     char *a;
     I32 id, n, cmd, infosize, getinfo;
@@ -1910,7 +1874,6 @@ I32
 Perl_do_msgsnd(pTHX_ SV **mark, SV **sp)
 {
 #ifdef HAS_MSG
-    dTHR;
     SV *mstr;
     char *mbuf;
     I32 id, msize, flags;
@@ -1933,7 +1896,6 @@ I32
 Perl_do_msgrcv(pTHX_ SV **mark, SV **sp)
 {
 #ifdef HAS_MSG
-    dTHR;
     SV *mstr;
     char *mbuf;
     long mtype;
@@ -1971,7 +1933,6 @@ I32
 Perl_do_semop(pTHX_ SV **mark, SV **sp)
 {
 #ifdef HAS_SEM
-    dTHR;
     SV *opstr;
     char *opbuf;
     I32 id;
@@ -1996,7 +1957,6 @@ I32
 Perl_do_shmio(pTHX_ I32 optype, SV **mark, SV **sp)
 {
 #ifdef HAS_SHM
-    dTHR;
     SV *mstr;
     char *mbuf, *shm;
     I32 id, mpos, msize;
@@ -2051,152 +2011,149 @@ Perl_do_shmio(pTHX_ I32 optype, SV **mark, SV **sp)
 
 #endif /* SYSV IPC */
 
-#ifdef SOCKS_64BIT_BUG
-
-/**
- ** getc and ungetc wrappers for the 64 bit problems with SOCKS 5 support
- ** Workaround to the problem, that SOCKS maps a socket 'getc' to revc
- ** without checking the ungetc buffer.
- **/
-
-static S64_IOB *s64_buffer = (S64_IOB *) NULL;
-
-/* initialize the buffer area */
-/* required after a fork(2) call in order to remove side effects */
-void Perl_do_s64_init_buffer() {
-    s64_buffer = (S64_IOB *) NULL;
-}
-
-/* get a buffered stream pointer */
-static S64_IOB *S_s64_get_buffer( PerlIO *fp) {
-    S64_IOB *ptr = s64_buffer;
-    while( ptr && ptr->fp != fp)
-       ptr = ptr->next;
-    return( ptr);
-}
-
-/* create a buffered stream pointer */
-static S64_IOB *S_s64_create_buffer( PerlIO *f) {
-    S64_IOB *ptr = malloc( sizeof( S64_IOB));
-    if( ptr) {
-       ptr->fp = f;
-       ptr->cnt = ptr->size = 0;
-       ptr->buffer = (int *) NULL;
-       ptr->next = s64_buffer;
-       ptr->last = (S64_IOB *) NULL;
-       if( s64_buffer) s64_buffer->last = ptr;
-       s64_buffer = ptr;
-    }
-    return( ptr);
-}
-
-/* delete a buffered stream pointer */
-void Perl_do_s64_delete_buffer( PerlIO *f) {
-    S64_IOB *ptr = _s64_get_buffer(f);
-    if( ptr) {
-       /* fix the stream pointer according to the bytes buffered */
-       /* required, if this is called in a seek-context */
-       if( ptr->cnt) fseek(f,-ptr->cnt,SEEK_CUR);
-       if( ptr->buffer) free( ptr->buffer);
-       if( ptr->last)
-           ptr->last->next = ptr->next;
-       else
-           s64_buffer = ptr->next;
-       free( ptr);
-    }
-}
-
-/* internal buffer management */
-#define _S64_BUFFER_SIZE 32
-static int S_s64_malloc( S64_IOB *ptr) {
-    if( ptr) {
-       if( !ptr->buffer) {
-           ptr->buffer = (int *) calloc( _S64_BUFFER_SIZE, sizeof( int));
-           ptr->size = ptr->cnt = 0;
-       } else {
-           ptr->buffer = (int *) realloc( ptr->buffer, ptr->size + _S64_BUFFER_SIZE);
-       }
-       
-       if( !ptr->buffer)
-           return( 0);
-       
-       ptr->size += _S64_BUFFER_SIZE;
-       
-       return( 1);
-    }
-
-    return( 0);
-}
-
-/* SOCKS 64 bit getc replacement */
-int Perl_do_s64_getc( PerlIO *f) {
-    S64_IOB *ptr = _s64_get_buffer(f);
-    if( ptr) {
-       if( ptr->cnt)
-           return( ptr->buffer[--ptr->cnt]);
-    }
-    return( getc(f));
-}
-
-/* SOCKS 64 bit ungetc replacement */
-int Perl_do_s64_ungetc( int ch, PerlIO *f) {
-    S64_IOB *ptr = _s64_get_buffer(f);
+/*
+=for apidoc start_glob
 
-    if( !ptr) ptr=_s64_create_buffer(f);
-    if( !ptr) return( EOF);
-    if( !ptr->buffer || (ptr->buffer && ptr->cnt >= ptr->size))
-       if( !_s64_malloc( ptr)) return( EOF);
-    ptr->buffer[ptr->cnt++] = ch;
+Function called by C<do_readline> to spawn a glob (or do the glob inside
+perl on VMS). This code used to be inline, but now perl uses C<File::Glob>
+this glob starter is only used by miniperl during the build proccess.
+Moving it away shrinks pp_hot.c; shrinking pp_hot.c helps speed perl up.
 
-    return( ch);
-}
+=cut
+*/
 
-/* SOCKS 64 bit fread replacement */
-SSize_t        Perl_do_s64_fread(void *buf, SSize_t count, PerlIO* f) {
-    SSize_t len = 0;
-    char *bufptr = (char *) buf;
-    S64_IOB *ptr = _s64_get_buffer(f);
-    if( ptr) {
-       while( ptr->cnt && count) {
-           *bufptr++ = ptr->buffer[--ptr->cnt];
-           count--, len++;
+PerlIO *
+Perl_start_glob (pTHX_ SV *tmpglob, IO *io)
+{
+    SV *tmpcmd = NEWSV(55, 0);
+    PerlIO *fp;
+    ENTER;
+    SAVEFREESV(tmpcmd);
+#ifdef VMS /* expand the wildcards right here, rather than opening a pipe, */
+           /* since spawning off a process is a real performance hit */
+    {
+#include <descrip.h>
+#include <lib$routines.h>
+#include <nam.h>
+#include <rmsdef.h>
+       char rslt[NAM$C_MAXRSS+1+sizeof(unsigned short int)] = {'\0','\0'};
+       char vmsspec[NAM$C_MAXRSS+1];
+       char *rstr = rslt + sizeof(unsigned short int), *begin, *end, *cp;
+       char tmpfnam[L_tmpnam] = "SYS$SCRATCH:";
+       $DESCRIPTOR(dfltdsc,"SYS$DISK:[]*.*;");
+       PerlIO *tmpfp;
+       STRLEN i;
+       struct dsc$descriptor_s wilddsc
+           = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
+       struct dsc$descriptor_vs rsdsc
+           = {sizeof rslt, DSC$K_DTYPE_VT, DSC$K_CLASS_VS, rslt};
+       unsigned long int cxt = 0, sts = 0, ok = 1, hasdir = 0, hasver = 0, isunix = 0;
+
+       /* We could find out if there's an explicit dev/dir or version
+          by peeking into lib$find_file's internal context at
+          ((struct NAM *)((struct FAB *)cxt)->fab$l_nam)->nam$l_fnb
+          but that's unsupported, so I don't want to do it now and
+          have it bite someone in the future. */
+       strcat(tmpfnam,PerlLIO_tmpnam(NULL));
+       cp = SvPV(tmpglob,i);
+       for (; i; i--) {
+           if (cp[i] == ';') hasver = 1;
+           if (cp[i] == '.') {
+               if (sts) hasver = 1;
+               else sts = 1;
+           }
+           if (cp[i] == '/') {
+               hasdir = isunix = 1;
+               break;
+           }
+           if (cp[i] == ']' || cp[i] == '>' || cp[i] == ':') {
+               hasdir = 1;
+               break;
+           }
        }
-    }
-    if( count)
-       len += (SSize_t)fread(bufptr,1,count,f);
-
-    return( len);
-}
-
-/* SOCKS 64 bit fseek replacement */
-int    Perl_do_s64_seek(PerlIO* f, Off_t offset, int whence) {
-    S64_IOB *ptr = _s64_get_buffer(f);
-
-    /* Simply clear the buffer and seek if the position is absolute */
-    if( SEEK_SET == whence || SEEK_END == whence) {
-       if( ptr) ptr->cnt = 0;
-
-    /* In case of relative positioning clear the buffer and calculate */
-    /* a fixed offset */
-    } else if( SEEK_CUR == whence) {
-       if( ptr) {
-           offset -= (Off_t)ptr->cnt;
-           ptr->cnt = 0;
+       if ((tmpfp = PerlIO_open(tmpfnam,"w+","fop=dlt")) != NULL) {
+           Stat_t st;
+           if (!PerlLIO_stat(SvPVX(tmpglob),&st) && S_ISDIR(st.st_mode))
+               ok = ((wilddsc.dsc$a_pointer = tovmspath(SvPVX(tmpglob),vmsspec)) != NULL);
+           else ok = ((wilddsc.dsc$a_pointer = tovmsspec(SvPVX(tmpglob),vmsspec)) != NULL);
+           if (ok) wilddsc.dsc$w_length = (unsigned short int) strlen(wilddsc.dsc$a_pointer);
+           while (ok && ((sts = lib$find_file(&wilddsc,&rsdsc,&cxt,
+                                              &dfltdsc,NULL,NULL,NULL))&1)) {
+               end = rstr + (unsigned long int) *rslt;
+               if (!hasver) while (*end != ';') end--;
+               *(end++) = '\n';  *end = '\0';
+               for (cp = rstr; *cp; cp++) *cp = _tolower(*cp);
+               if (hasdir) {
+                   if (isunix) trim_unixpath(rstr,SvPVX(tmpglob),1);
+                   begin = rstr;
+               }
+               else {
+                   begin = end;
+                   while (*(--begin) != ']' && *begin != '>') ;
+                   ++begin;
+               }
+               ok = (PerlIO_puts(tmpfp,begin) != EOF);
+           }
+           if (cxt) (void)lib$find_file_end(&cxt);
+           if (ok && sts != RMS$_NMF &&
+               sts != RMS$_DNF && sts != RMS$_FNF) ok = 0;
+           if (!ok) {
+               if (!(sts & 1)) {
+                   SETERRNO((sts == RMS$_SYN ? EINVAL : EVMSERR),sts);
+               }
+               PerlIO_close(tmpfp);
+               fp = NULL;
+           }
+           else {
+               PerlIO_rewind(tmpfp);
+               IoTYPE(io) = IoTYPE_RDONLY;
+               IoIFP(io) = fp = tmpfp;
+               IoFLAGS(io) &= ~IOf_UNTAINT;  /* maybe redundant */
+           }
        }
     }
-
-    /* leave out buffer untouched otherwise, because fseek will fail */
-    /* seek now */
-    return( fseeko( f, offset, whence));
-}
-
-/* SOCKS 64 bit ftell replacement */
-Off_t  Perl_do_s64_tell(PerlIO* f) {
-    Off_t offset = 0;
-    S64_IOB *ptr = _s64_get_buffer(f);
-    if( ptr)
-       offset = ptr->cnt;
-    return( ftello(f) - offset);
+#else /* !VMS */
+#ifdef MACOS_TRADITIONAL
+    sv_setpv(tmpcmd, "glob ");
+    sv_catsv(tmpcmd, tmpglob);
+    sv_catpv(tmpcmd, " |");
+#else
+#ifdef DOSISH
+#ifdef OS2
+    sv_setpv(tmpcmd, "for a in ");
+    sv_catsv(tmpcmd, tmpglob);
+    sv_catpv(tmpcmd, "; do echo \"$a\\0\\c\"; done |");
+#else
+#ifdef DJGPP
+    sv_setpv(tmpcmd, "/dev/dosglob/"); /* File System Extension */
+    sv_catsv(tmpcmd, tmpglob);
+#else
+    sv_setpv(tmpcmd, "perlglob ");
+    sv_catsv(tmpcmd, tmpglob);
+    sv_catpv(tmpcmd, " |");
+#endif /* !DJGPP */
+#endif /* !OS2 */
+#else /* !DOSISH */
+#if defined(CSH)
+    sv_setpvn(tmpcmd, PL_cshname, PL_cshlen);
+    sv_catpv(tmpcmd, " -cf 'set nonomatch; glob ");
+    sv_catsv(tmpcmd, tmpglob);
+    sv_catpv(tmpcmd, "' 2>/dev/null |");
+#else
+    sv_setpv(tmpcmd, "echo ");
+    sv_catsv(tmpcmd, tmpglob);
+#if 'z' - 'a' == 25
+    sv_catpv(tmpcmd, "|tr -s ' \t\f\r' '\\012\\012\\012\\012'|");
+#else
+    sv_catpv(tmpcmd, "|tr -s ' \t\f\r' '\\n\\n\\n\\n'|");
+#endif
+#endif /* !CSH */
+#endif /* !DOSISH */
+#endif /* MACOS_TRADITIONAL */
+    (void)do_open(PL_last_in_gv, SvPVX(tmpcmd), SvCUR(tmpcmd),
+                 FALSE, O_RDONLY, 0, Nullfp);
+    fp = IoIFP(io);
+#endif /* !VMS */
+    LEAVE;
+    return fp;
 }
-
-#endif