Hi list,

Actually, Perl users cannot use 'print' operator for wrinting
directly in standard IO witch embed perl interpreter.

The attached patch add a minimal implementation of PerlIO Layer
feature and try to use it for STDOUT/STDERR.


Please check it.

Regards,
Damien

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.
diff --git a/src/if_perl.xs b/src/if_perl.xs
--- a/src/if_perl.xs
+++ b/src/if_perl.xs
@@ -52,7 +52,9 @@
 #include <EXTERN.h>
 #include <perl.h>
 #include <XSUB.h>
-
+#if defined(PERLIO_LAYERS) && !defined(USE_SFIO)
+# include <perliol.h>
+#endif
 
 /*
  * Work around clashes between Perl and Vim namespace.	proto.h doesn't
@@ -279,6 +281,10 @@
 #   define PL_thr_key *dll_PL_thr_key
 #  endif
 # endif
+# if defined(PERLIO_LAYERS) && !defined(USE_SFIO)
+#  define PerlIOBase_pushed dll_PerlIOBase_pushed
+#  define PerlIO_define_layer dll_PerlIO_define_layer
+# endif
 
 /*
  * Declare HANDLE for perl.dll and function pointers.
@@ -422,6 +428,10 @@
 static perl_key* (*Perl_Gthr_key_ptr)_((pTHX));
 #endif
 static void (*boot_DynaLoader)_((pTHX_ CV*));
+#if defined(PERLIO_LAYERS) && !defined(USE_SFIO)
+static IV (*PerlIOBase_pushed)(pTHX_ PerlIO *, const char *, SV *, PerlIO_funcs *);
+static void (*PerlIO_define_layer)(pTHX_ PerlIO_funcs *);
+#endif
 
 /*
  * Table of name to function pointer of perl.
@@ -554,6 +564,10 @@
     {"Perl_Gthr_key_ptr", (PERL_PROC*)&Perl_Gthr_key_ptr},
 #endif
     {"boot_DynaLoader", (PERL_PROC*)&boot_DynaLoader},
+#if defined(PERLIO_LAYERS) && !defined(USE_SFIO)
+    {"PerlIOBase_pushed", (PERL_PROC*)&PerlIOBase_pushed},
+    {"PerlIO_define_layer", (PERL_PROC*)&PerlIO_define_layer},
+#endif
     {"", NULL},
 };
 
@@ -620,6 +634,10 @@
 }
 #endif /* DYNAMIC_PERL */
 
+#if defined(PERLIO_LAYERS) && !defined(USE_SFIO)
+static void vim_IOLayer_init(void);
+#endif
+
 /*
  * perl_init(): initialize perl interpreter
  * We have to call perl_parse to initialize some structures,
@@ -645,6 +663,8 @@
     sfdisc(PerlIO_stderr(), sfdcnewvim());
     sfsetbuf(PerlIO_stdout(), NULL, 0);
     sfsetbuf(PerlIO_stderr(), NULL, 0);
+#elif defined(PERLIO_LAYERS)
+    vim_IOLayer_init();
 #endif
 }
 
@@ -1038,6 +1058,70 @@
     }
 }
 
+#if defined(PERLIO_LAYERS) && !defined(USE_SFIO)
+typedef struct {
+    struct _PerlIO base;
+    int attr;
+} PerlIOVim;
+
+    static IV
+PerlIOVim_pushed(pTHX_ PerlIO *f, const char *mode,
+		 SV *arg, PerlIO_funcs *tab
+  )
+{
+    PerlIOVim *s = PerlIOSelf(f, PerlIOVim);
+    s->attr = 0;
+    if (arg && SvPOK(arg)) {
+	int id = syn_name2id(SvPV_nolen(arg));
+	if (id != 0)
+	    s->attr = syn_id2attr(id);
+    }
+    return PerlIOBase_pushed(aTHX_ f, mode, (SV *)NULL, tab);
+}
+
+    static SSize_t
+PerlIOVim_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
+{
+    char_u *str;
+    PerlIOVim * s = PerlIOSelf(f, PerlIOVim);
+
+    str = vim_strnsave((char_u *)vbuf, count);
+    if (str == NULL)
+	return 0;
+    msg_split((char *)str, s->attr);
+    vim_free(str);
+
+    return count;
+}
+
+static PERLIO_FUNCS_DECL(PerlIO_Vim) = {
+    sizeof(PerlIO_funcs),
+    "Vim",
+    sizeof(PerlIOVim),
+    PERLIO_K_DUMMY,	/* flags */
+    PerlIOVim_pushed,
+    NULL,		/* popped */
+    NULL,		/* open */
+    NULL,		/* binmode */
+    NULL,		/* arg */
+    NULL,		/* fileno */
+    NULL,		/* dup */
+    NULL,		/* read */
+    NULL,		/* unread */
+    PerlIOVim_write,
+    /* ... */
+};
+
+/* Use Vim routine for print operator */
+    static void
+vim_IOLayer_init(void)
+{
+    PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_Vim));
+    (void)eval_pv(   "binmode(STDOUT, ':Vim')"
+                "  && binmode(STDERR, ':Vim(ErrorMsg)');", 0);
+}
+#endif /* PERLIO_LAYERS && !USE_SFIO */
+
 #ifndef FEAT_WINDOWS
 int win_valid(win_T *w) { return TRUE; }
 int win_count() { return 1; }

Raspunde prin e-mail lui