To: vim_dev@googlegroups.com Subject: Patch 7.4.1729 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.4.1729 Problem: The Perl interface cannot use 'print' operator for writing directly in standard IO. Solution: Add a minimal implementation of PerlIO Layer feature and try to use it for STDOUT/STDERR. (Damien) Files: src/if_perl.xs, src/testdir/test_perl.vim *** ../vim-7.4.1728/src/if_perl.xs 2016-04-02 14:17:55.621482124 +0200 --- src/if_perl.xs 2016-04-14 14:08:34.696507168 +0200 *************** *** 57,63 **** #include #include #include ! /* * Work around clashes between Perl and Vim namespace. proto.h doesn't --- 57,65 ---- #include #include #include ! #if defined(PERLIO_LAYERS) && !defined(USE_SFIO) ! # include ! #endif /* * Work around clashes between Perl and Vim namespace. proto.h doesn't *************** *** 293,298 **** --- 295,304 ---- # define Perl_av_fetch dll_Perl_av_fetch # define Perl_av_len dll_Perl_av_len # define Perl_sv_2nv_flags dll_Perl_sv_2nv_flags + # 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. *************** *** 445,450 **** --- 451,460 ---- static SV** (*Perl_av_fetch)(pTHX_ AV *, SSize_t, I32); static SSize_t (*Perl_av_len)(pTHX_ AV *); static NV (*Perl_sv_2nv_flags)(pTHX_ SV *const, const I32); + #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. *************** *** 584,589 **** --- 594,603 ---- {"Perl_av_fetch", (PERL_PROC*)&Perl_av_fetch}, {"Perl_av_len", (PERL_PROC*)&Perl_av_len}, {"Perl_sv_2nv_flags", (PERL_PROC*)&Perl_sv_2nv_flags}, + #if defined(PERLIO_LAYERS) && !defined(USE_SFIO) + {"PerlIOBase_pushed", (PERL_PROC*)&PerlIOBase_pushed}, + {"PerlIO_define_layer", (PERL_PROC*)&PerlIO_define_layer}, + #endif {"", NULL}, }; *************** *** 646,651 **** --- 660,669 ---- } #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, *************** *** 671,676 **** --- 689,696 ---- sfdisc(PerlIO_stderr(), sfdcnewvim()); sfsetbuf(PerlIO_stdout(), NULL, 0); sfsetbuf(PerlIO_stderr(), NULL, 0); + #elif defined(PERLIO_LAYERS) + vim_IOLayer_init(); #endif } *************** *** 1307,1312 **** --- 1327,1408 ---- } } + #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((char_u *)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_u *)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, + NULL, /* seek */ + NULL, /* tell */ + NULL, /* close */ + NULL, /* flush */ + NULL, /* fill */ + NULL, /* eof */ + NULL, /* error */ + NULL, /* clearerr */ + NULL, /* setlinebuf */ + NULL, /* get_base */ + NULL, /* get_bufsiz */ + NULL, /* get_ptr */ + NULL, /* get_cnt */ + NULL /* set_ptrcnt */ + }; + + /* 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) *** ../vim-7.4.1728/src/testdir/test_perl.vim 2016-01-17 22:05:09.286375447 +0100 --- src/testdir/test_perl.vim 2016-04-14 14:07:16.657322496 +0200 *************** *** 92,94 **** --- 92,105 ---- perl VIM::SetOption('et') call assert_true(&et) endf + + function Test_stdio() + redir =>l:out + perl <