Integrate perlio:
Jarkko Hietaniemi [Sat, 16 Jun 2001 18:52:26 +0000 (18:52 +0000)]
[ 10640]
Disable :win32 layer as default till I get it working

[ 10632]
Work-in-progress win32 layer semi-functional, checking
for UNIX breakage.

[ 10627]
Work in progress UNIX-side edit of win32 PerLIO layer

p4raw-link: @10640 on //depot/perlio: 2f8118af5e6ae8b76fdc332011717931c71acde6
p4raw-link: @10632 on //depot/perlio: 0c4128adc5f62cd332ae4fa5bc8999c95d611d36
p4raw-link: @10627 on //depot/perlio: a8c08ecdc5ffec9869657a967edfe7b74a713a27

p4raw-id: //depot/perl@10641

MANIFEST
perlio.c
perliol.h
win32/makefile.mk
win32/win32io.c [new file with mode: 0644]

index deb8320..fc03838 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -2013,6 +2013,7 @@ win32/vmem.h              Perl "host" memory manager
 win32/win32.c          Win32 port
 win32/win32.h          Win32 port
 win32/win32iop.h       Win32 port
+win32/win32io.c                Win32 PerlIO layer support
 win32/win32sck.c       Win32 port
 win32/win32thread.c    Win32 functions for threads
 win32/win32thread.h    Win32 port mapping to threads
index 2d57fb6..c9b7f72 100644 (file)
--- a/perlio.c
+++ b/perlio.c
@@ -476,8 +476,14 @@ PerlIO_pop(pTHX_ PerlIO *f)
   {
    PerlIO_debug("PerlIO_pop f=%p %s\n",f,l->tab->name);
    if (l->tab->Popped)
-    (*l->tab->Popped)(f);
-   *f = l->next;
+    {
+     /* If popped returns non-zero do not free its layer structure
+        it has either done so itself, or it is shared and still in use
+      */
+     if ((*l->tab->Popped)(f) != 0)
+      return;
+    }
+   *f = l->next;;
    PerlMemShared_free(l);
   }
 }
@@ -758,10 +764,16 @@ PerlIO_default_layers(pTHX)
  if (!PerlIO_def_layerlist)
   {
    const char *s  = (PL_tainting) ? Nullch : PerlEnv_getenv("PERLIO");
-   PerlIO_def_layerlist = PerlIO_list_alloc();
-
-   PerlIO_define_layer(aTHX_ &PerlIO_raw);
+   PerlIO_funcs *osLayer = &PerlIO_unix;
+   PerlIO_def_layerlist  = PerlIO_list_alloc();
    PerlIO_define_layer(aTHX_ &PerlIO_unix);
+#ifdef WIN32
+   PerlIO_define_layer(aTHX_ &PerlIO_win32);
+#if 0
+   osLayer = &PerlIO_win32;
+#endif
+#endif
+   PerlIO_define_layer(aTHX_ &PerlIO_raw);
    PerlIO_define_layer(aTHX_ &PerlIO_perlio);
    PerlIO_define_layer(aTHX_ &PerlIO_stdio);
    PerlIO_define_layer(aTHX_ &PerlIO_crlf);
@@ -770,7 +782,7 @@ PerlIO_default_layers(pTHX)
 #endif
    PerlIO_define_layer(aTHX_ &PerlIO_utf8);
    PerlIO_define_layer(aTHX_ &PerlIO_byte);
-   PerlIO_list_push(PerlIO_def_layerlist,PerlIO_find_layer(aTHX_ PerlIO_unix.name,0,0),&PL_sv_undef);
+   PerlIO_list_push(PerlIO_def_layerlist,PerlIO_find_layer(aTHX_ osLayer->name,0,0),&PL_sv_undef);
    if (s)
     {
      PerlIO_parse_layers(aTHX_ PerlIO_def_layerlist,s);
@@ -1881,6 +1893,8 @@ int
 PerlIOUnix_oflags(const char *mode)
 {
  int oflags = -1;
+ if (*mode == 'I' || *mode == '#')
+  mode++;
  switch(*mode)
   {
    case 'r':
@@ -2611,7 +2625,7 @@ PerlIOBuf_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, IV n, const char
    if (*mode == 'I')
     {
      init = 1;
-     mode++;
+     /* mode++; */
     }
    f = (*tab->Open)(aTHX_ tab, layers, n-1, mode,fd,imode,perm,NULL,narg,args);
    if (f)
index e9f6a97..b659de0 100644 (file)
--- a/perliol.h
+++ b/perliol.h
@@ -107,7 +107,9 @@ EXT PerlIO_funcs PerlIO_pending;
 #ifdef HAS_MMAP
 EXT PerlIO_funcs PerlIO_mmap;
 #endif
-
+#ifdef WIN32
+EXT PerlIO_funcs PerlIO_win32;
+#endif
 extern PerlIO *PerlIO_allocate(pTHX);
 extern SV *PerlIO_arg_fetch(PerlIO_list_t *av,IV n);
 #define PerlIOArg PerlIO_arg_fetch(layers,n)
@@ -169,6 +171,8 @@ extern STDCHAR *PerlIOBuf_get_ptr    (PerlIO *f);
 extern SSize_t PerlIOBuf_get_cnt    (PerlIO *f);
 extern void    PerlIOBuf_set_ptrcnt (PerlIO *f, STDCHAR *ptr, SSize_t cnt);
 
+extern int     PerlIOUnix_oflags    (const char *mode);
+
 /*--------------------------------------------------------------------------------------*/
 
 #endif /* _PERLIOL_H */
index e9b9b54..4e2ff83 100644 (file)
@@ -687,6 +687,7 @@ EXTRACORE_SRC       += ..\perlio.c
 \r
 WIN32_SRC      =               \\r
                .\win32.c       \\r
+               .\win32io.c     \\r
                .\win32sck.c    \\r
                .\win32thread.c\r
 \r
diff --git a/win32/win32io.c b/win32/win32io.c
new file mode 100644 (file)
index 0000000..b707172
--- /dev/null
@@ -0,0 +1,325 @@
+#define PERL_NO_GET_CONTEXT
+#define WIN32_LEAN_AND_MEAN
+#define WIN32IO_IS_STDIO
+#include <tchar.h>
+#ifdef __GNUC__
+#define Win32_Winsock
+#endif
+#include <windows.h>
+
+#include <sys/stat.h>
+#include "EXTERN.h"
+#include "perl.h"
+#include "perliol.h"
+
+#define NO_XSLOCKS
+#include "XSUB.h"
+
+/* Bottom-most level for Win32 case */
+
+typedef struct
+{
+ struct _PerlIO base;       /* The generic part */
+ HANDLE                h;          /* OS level handle */
+ IV            refcnt;     /* REFCNT for the "fd" this represents */
+ int           fd;         /* UNIX like file descriptor - index into fdtable */
+} PerlIOWin32;
+
+PerlIOWin32 *fdtable[256];
+IV max_open_fd = -1;
+
+IV
+PerlIOWin32_popped(PerlIO *f)
+{
+ PerlIOWin32 *s = PerlIOSelf(f,PerlIOWin32);
+ if (--s->refcnt > 0)
+  {
+   *f = PerlIOBase(f)->next;
+   return 1;
+  }
+ fdtable[s->fd] = NULL;
+ return 0;
+}
+
+IV
+PerlIOWin32_fileno(PerlIO *f)
+{
+ return PerlIOSelf(f,PerlIOWin32)->fd;
+}
+
+IV
+PerlIOWin32_pushed(PerlIO *f, const char *mode, SV *arg)
+{
+ IV code = PerlIOBase_pushed(f,mode,arg);
+ if (*PerlIONext(f))
+  {
+   PerlIOWin32 *s = PerlIOSelf(f,PerlIOWin32);
+   s->fd     = PerlIO_fileno(PerlIONext(f));
+  }
+ PerlIOBase(f)->flags |= PERLIO_F_OPEN;
+ return code;
+}
+
+PerlIO *
+PerlIOWin32_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, IV n, const char *mode, int fd, int imode, int perm, PerlIO *f, int narg, SV **args)
+{
+ const char *tmode = mode;
+ HANDLE h = INVALID_HANDLE_VALUE;
+ if (f)
+  {
+   /* Close if already open */
+   if (PerlIOBase(f)->flags & PERLIO_F_OPEN)
+    (*PerlIOBase(f)->tab->Close)(f);
+  }
+ if (narg > 0)
+  {
+   char *path = SvPV_nolen(*args);
+   DWORD  access = 0;
+   DWORD  share  = 0;
+   DWORD  create = -1;
+   DWORD  attr   = FILE_ATTRIBUTE_NORMAL;
+   if (*mode == '#')
+    {
+     /* sysopen - imode is UNIX-like O_RDONLY etc.
+        - do_open has converted that back to string form in mode as well
+        - perm is UNIX like permissions
+      */
+     mode++;
+    }
+   else
+    {
+     /* Normal open - decode mode string */
+    }
+   switch(*mode)
+    {
+     case 'r':
+      access  = GENERIC_READ;
+      create  = OPEN_EXISTING;
+      if (*++mode == '+')
+       {
+        access |= GENERIC_WRITE;
+        create  = OPEN_ALWAYS;
+        mode++;
+       }
+      break;
+
+     case 'w':
+      access  = GENERIC_WRITE;
+      create  = TRUNCATE_EXISTING;
+      if (*++mode == '+')
+       {
+        access |= GENERIC_READ;
+        mode++;
+       }
+      break;
+
+     case 'a':
+      access = GENERIC_WRITE;
+      create  = OPEN_ALWAYS;
+      if (*++mode == '+')
+       {
+        access |= GENERIC_READ;
+        mode++;
+       }
+      break;
+    }
+   if (*mode == 'b')
+    {
+     mode++;
+    }
+   else if (*mode == 't')
+    {
+     mode++;
+    }
+   if (*mode || create == -1)
+    {
+     SETERRNO(EINVAL,LIB$_INVARG);
+     return NULL;
+    }
+   if (!(access & GENERIC_WRITE))
+    share = FILE_SHARE_READ;
+   h = CreateFile(path,access,share,NULL,create,attr,NULL);
+   if (h == INVALID_HANDLE_VALUE)
+    {
+     if (create == TRUNCATE_EXISTING)
+      h = CreateFile(path,access,share,NULL,(create = OPEN_ALWAYS),attr,NULL);
+    }
+  }
+ else
+  {
+   /* fd open */
+   h = INVALID_HANDLE_VALUE;
+   if (fd >= 0 && fd <= max_open_fd)
+    {
+     PerlIOWin32 *s = fdtable[fd];
+     if (s)
+      {
+       s->refcnt++;
+       if (!f)
+        f = PerlIO_allocate(aTHX);
+       *f = &s->base;
+       return f;
+      }
+    }
+   if (*mode == 'I')
+    {
+     mode++;
+     switch(fd)
+      {
+       case 0:
+        h = GetStdHandle(STD_INPUT_HANDLE);
+        break;
+       case 1:
+        h = GetStdHandle(STD_OUTPUT_HANDLE);
+        break;
+       case 2:
+        h = GetStdHandle(STD_ERROR_HANDLE);
+        break;
+      }
+    }
+  }
+ if (h != INVALID_HANDLE_VALUE)
+  fd = win32_open_osfhandle((long) h, PerlIOUnix_oflags(tmode));
+ if (fd >= 0)
+  {
+   PerlIOWin32 *s;
+   if (!f)
+    f = PerlIO_allocate(aTHX);
+   s = PerlIOSelf(PerlIO_push(aTHX_ f,self,tmode,PerlIOArg),PerlIOWin32);
+   s->h      = h;
+   s->fd     = fd;
+   s->refcnt = 1;
+   if (fd >= 0) 
+    {
+     fdtable[fd] = s; 
+     if (fd > max_open_fd)
+      max_open_fd = fd;
+    } 
+   return f;
+  }
+ if (f)
+  {
+   /* FIXME: pop layers ??? */
+  }
+ return NULL;
+}
+
+SSize_t
+PerlIOWin32_read(PerlIO *f, void *vbuf, Size_t count)
+{
+ PerlIOWin32 *s = PerlIOSelf(f,PerlIOWin32);
+ DWORD len;
+ if (!(PerlIOBase(f)->flags & PERLIO_F_CANREAD))
+  return 0;
+ if (ReadFile(s->h,vbuf,count,&len,NULL))
+  {
+   return len;
+  }
+ else
+  {
+   if (GetLastError() != NO_ERROR)
+    {
+     PerlIOBase(f)->flags |= PERLIO_F_ERROR;
+     return -1;
+    }
+   else
+    {
+     if (count != 0)
+      PerlIOBase(f)->flags |= PERLIO_F_EOF;
+     return 0;
+    }
+  }
+}
+
+SSize_t
+PerlIOWin32_write(PerlIO *f, const void *vbuf, Size_t count)
+{
+ PerlIOWin32 *s = PerlIOSelf(f,PerlIOWin32);
+ DWORD len;
+ if (WriteFile(s->h,vbuf,count,&len,NULL))
+  {
+   return len;
+  }
+ else
+  {
+   PerlIOBase(f)->flags |= PERLIO_F_ERROR;
+   return -1;
+  }
+}
+
+IV
+PerlIOWin32_seek(PerlIO *f, Off_t offset, int whence)
+{
+ static const DWORD where[3] = { FILE_BEGIN, FILE_CURRENT, FILE_END };
+ PerlIOWin32 *s = PerlIOSelf(f,PerlIOWin32);
+ DWORD high = (sizeof(offset) > sizeof(DWORD)) ? (DWORD)(offset >> 32) : 0;
+ DWORD low  = (DWORD) offset;
+ DWORD res  = SetFilePointer(s->h,low,&high,where[whence]);
+ if (res != 0xFFFFFFFF || GetLastError() != NO_ERROR)
+  {
+   return 0;
+  }
+ else
+  {
+   return -1;
+  }
+}
+
+Off_t
+PerlIOWin32_tell(PerlIO *f)
+{
+ PerlIOWin32 *s = PerlIOSelf(f,PerlIOWin32);
+ DWORD high = 0;
+ DWORD res  = SetFilePointer(s->h,0,&high,FILE_CURRENT);
+ if (res != 0xFFFFFFFF || GetLastError() != NO_ERROR)
+  {
+   return ((Off_t) high << 32) | res;
+  }
+ return (Off_t) -1;
+}
+
+IV
+PerlIOWin32_close(PerlIO *f)
+{
+ PerlIOWin32 *s = PerlIOSelf(f,PerlIOWin32);
+ if (s->refcnt == 1)
+  {
+   if (CloseHandle(s->h))
+    {
+     s->h = INVALID_HANDLE_VALUE;
+     return -1;
+    }
+  }
+ PerlIOBase(f)->flags &= ~PERLIO_F_OPEN;
+ return 0;
+}
+
+PerlIO_funcs PerlIO_win32 = {
+ "win32",
+ sizeof(PerlIOWin32),
+ PERLIO_K_RAW,
+ PerlIOWin32_pushed,
+ PerlIOWin32_popped,
+ PerlIOWin32_open,
+ NULL,                 /* getarg */
+ PerlIOWin32_fileno,
+ PerlIOWin32_read,
+ PerlIOBase_unread,
+ PerlIOWin32_write,
+ PerlIOWin32_seek,
+ PerlIOWin32_tell,
+ PerlIOWin32_close,
+ PerlIOBase_noop_ok,   /* flush */
+ PerlIOBase_noop_fail, /* fill */
+ PerlIOBase_eof,
+ PerlIOBase_error,
+ PerlIOBase_clearerr,
+ PerlIOBase_setlinebuf,
+ NULL, /* get_base */
+ NULL, /* get_bufsiz */
+ NULL, /* get_ptr */
+ NULL, /* get_cnt */
+ NULL, /* set_ptrcnt */
+};
+
+