if_perl.xs
上传用户:gddssl
上传日期:2007-01-06
资源大小:1003k
文件大小:15k
源码类别:

编辑器/阅读器

开发平台:

DOS

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  */
  8. /*
  9.  * if_perl.xs: Main code for Perl interface support.
  10.  * Mostly written by Sven Verdoolaege.
  11.  */
  12. #define _memory_h /* avoid memset redeclaration */
  13. #define IN_PERL_FILE /* don't include if_perl.pro from proto.h */
  14. #include "vim.h"
  15. /*
  16.  * Avoid clashes between Perl and Vim namespace.
  17.  */
  18. #undef MAGIC
  19. #undef NORMAL
  20. #undef STRLEN
  21. #undef FF
  22. #undef OP_DELETE
  23. #ifdef __BORLANDC__
  24. #define NOPROTO 1
  25. #endif
  26. #include <EXTERN.h>
  27. #include <perl.h>
  28. #include <XSUB.h>
  29. /*
  30.  * Work around clashes between Perl and Vim namespace. proto.h doesn't
  31.  * include if_perl.pro and perlsfio.pro when IN_PERL_FILE is defined, because
  32.  * we need the CV typedef.  proto.h can't be moved to after including
  33.  * if_perl.h, because we get all sorts of name clashes then.
  34.  */
  35. #ifndef PROTO
  36. # include "proto/if_perl.pro"
  37. # include "proto/if_perlsfio.pro"
  38. #endif
  39. static void *perl_interp = NULL;
  40. static void xs_init __ARGS((void));
  41. static void VIM_init __ARGS((void));
  42. /*
  43.  * perl_init(): initialize perl interpreter
  44.  * We have to call perl_parse to initialize some structures,
  45.  * there's nothing to actually parse.
  46.  */
  47.     static void
  48. perl_init()
  49. {
  50.     char *bootargs[] = { "VI", NULL };
  51.     static char *args[] = { "", "-e", "" };
  52.     perl_interp = perl_alloc();
  53.     perl_construct(perl_interp);
  54.     perl_parse(perl_interp, xs_init, 3, args, 0);
  55.     perl_call_argv("VIM::bootstrap", (long)G_DISCARD, bootargs);
  56.     VIM_init();
  57. #ifdef USE_SFIO
  58.     sfdisc(PerlIO_stdout(), sfdcnewvim());
  59.     sfdisc(PerlIO_stderr(), sfdcnewvim());
  60.     sfsetbuf(PerlIO_stdout(), NULL, 0);
  61.     sfsetbuf(PerlIO_stderr(), NULL, 0);
  62. #endif
  63. }
  64. /*
  65.  * perl_end(): clean up after ourselves
  66.  */
  67.     void
  68. perl_end()
  69. {
  70.     if (perl_interp)
  71.     {
  72. perl_run(perl_interp);
  73. perl_destruct(perl_interp);
  74. perl_free(perl_interp);
  75.     }
  76. }
  77. /*
  78.  * msg_split(): send a message to the message handling routines
  79.  * split at 'n' first though.
  80.  */
  81.     void
  82. msg_split(s, attr)
  83.     char_u *s;
  84.     int attr; /* highlighting attributes */
  85. {
  86.     char *next;
  87.     char *token = (char *)s;
  88.     while ((next = strchr(token, 'n')))
  89.     {
  90. *next++ = ''; /* replace n with  */
  91. msg_attr((char_u *)token, attr);
  92. token = next;
  93.     }
  94.     if (*token)
  95. msg_attr((char_u *)token, attr);
  96. }
  97. #ifndef WANT_EVAL
  98. /*
  99.  * This stub is needed because an "#ifdef WANT_EVAL" around Eval() doesn't work properly.
  100.  */
  101.     char_u *
  102. eval_to_string(arg, nextcmd)
  103.     char_u *arg;
  104.     char_u **nextcmd;
  105. {
  106.     return NULL;
  107. }
  108. #endif
  109. /*
  110.  * Create a new reference to an SV pointing to the SCR structure
  111.  * The perl_private part of the SCR structure points to the SV,
  112.  * so there can only be one such SV for a particular SCR structure.
  113.  * When the last reference has gone (DESTROY is called),
  114.  * perl_private is reset; When the screen goes away before
  115.  * all references are gone, the value of the SV is reset;
  116.  * any subsequent use of any of those reference will produce
  117.  * a warning. (see typemap)
  118.  */
  119. #define newANYrv(TYPE)
  120. static SV *
  121. new ## TYPE ## rv(rv, ptr)
  122.     SV *rv;
  123.     TYPE *ptr;
  124. {
  125.     sv_upgrade(rv, SVt_RV);
  126.     if (!ptr->perl_private)
  127.     {
  128. ptr->perl_private = newSV(0);
  129. sv_setiv(ptr->perl_private, (IV)ptr);
  130.     }
  131.     else
  132. SvREFCNT_inc(ptr->perl_private);
  133.     SvRV(rv) = ptr->perl_private;
  134.     SvROK_on(rv);
  135.     return sv_bless(rv, gv_stashpv("VI" #TYPE, TRUE));
  136. }
  137. newANYrv(WIN)
  138. newANYrv(BUF)
  139. /*
  140.  * perl_win_free
  141.  * Remove all refences to the window to be destroyed
  142.  */
  143.     void
  144. perl_win_free(wp)
  145.     WIN *wp;
  146. {
  147.     if (wp->perl_private)
  148. sv_setiv((SV *)wp->perl_private, 0);
  149.     return;
  150. }
  151.     void
  152. perl_buf_free(bp)
  153.     BUF *bp;
  154. {
  155.     if (bp->perl_private)
  156. sv_setiv((SV *)bp->perl_private, 0);
  157.     return;
  158. }
  159. #ifndef PROTO
  160. I32 cur_val(IV iv, SV *sv);
  161. /*
  162.  * Handler for the magic variables $main::curwin and $main::curbuf.
  163.  * The handler is put into the magic vtbl for these variables.
  164.  * (This is effectively a C-level equivalent of a tied variable).
  165.  * There is no "set" function as the variables are read-only.
  166.  */
  167. I32 cur_val(IV iv, SV *sv)
  168. {
  169.     SV *rv;
  170.     if (iv == 0)
  171. rv = newWINrv(newSV(0), curwin);
  172.     else
  173. rv = newBUFrv(newSV(0), curbuf);
  174.     sv_setsv(sv, rv);
  175.     return 0;
  176. }
  177. #endif /* !PROTO */
  178. struct ufuncs cw_funcs = { cur_val, 0, 0 };
  179. struct ufuncs cb_funcs = { cur_val, 0, 1 };
  180. /*
  181.  * VIM_init(): Vim-specific initialisation.
  182.  * Make the magical main::curwin and main::curbuf variables
  183.  */
  184.     static void
  185. VIM_init()
  186. {
  187.     static char cw[] = "main::curwin";
  188.     static char cb[] = "main::curbuf";
  189.     MAGIC *m;
  190.     SV *sv;
  191.     sv = perl_get_sv(cw, TRUE);
  192.     sv_magic(sv, NULL, 'U', cw, strlen(cw));
  193.     m = mg_find(sv, 'U');
  194.     m->mg_ptr = (char *)&cw_funcs;
  195.     SvREADONLY_on(sv);
  196.     sv = perl_get_sv(cb, TRUE);
  197.     sv_magic(sv, NULL, 'U', cb, strlen(cb));
  198.     m = mg_find(sv, 'U');
  199.     m->mg_ptr = (char *)&cb_funcs;
  200.     SvREADONLY_on(sv);
  201. }
  202.     int
  203. do_perl(eap)
  204.     EXARG *eap;
  205. {
  206.     char *err;
  207.     STRLEN length;
  208.     SV *sv;
  209.     dSP;
  210.     if (!perl_interp)
  211.     {
  212. perl_init();
  213. SPAGAIN;
  214.     }
  215.     ENTER;
  216.     SAVETMPS;
  217.     sv = newSVpv((char *)eap->arg, 0);
  218.     perl_eval_sv(sv, G_DISCARD | G_NOARGS);
  219.     SvREFCNT_dec(sv);
  220.     err = SvPV(GvSV(errgv), length);
  221.     FREETMPS;
  222.     LEAVE;
  223.     if (!length)
  224. return OK;
  225.     msg_split((char_u *)err, highlight_attr[HLF_E]);
  226.     return FAIL;
  227.     
  228. }
  229.     static int
  230. replace_line(line, end)
  231.     linenr_t *line, *end;
  232. {
  233.     char *str;
  234.     if (SvOK(GvSV(defgv)))
  235.     {
  236. str = SvPV(GvSV(defgv), na);
  237. ml_replace(*line, (char_u *)str, 1);
  238. #ifdef SYNTAX_HL
  239. syn_changed(*line); /* recompute syntax hl. for this line */
  240. #endif
  241.     }
  242.     else
  243.     {
  244. mark_adjust(*line, *line, MAXLNUM, -1);
  245. ml_delete((*line)--, FALSE);
  246. (*end)--;
  247.     }
  248.     changed();
  249.     return OK;
  250. }
  251.     int
  252. do_perldo(eap)
  253.     EXARG *eap;
  254. {
  255.     STRLEN length;
  256.     SV *sv;
  257.     char *str;
  258.     linenr_t i;
  259.     dSP;
  260.     if (bufempty())
  261. return FAIL;
  262.     if (!perl_interp)
  263.     {
  264. perl_init();
  265. SPAGAIN;
  266.     }
  267.     length = strlen((char *)eap->arg);
  268.     sv = newSV(length + sizeof("sub VIM::perldo {")-1 + 1);
  269.     sv_setpvn(sv, "sub VIM::perldo {", sizeof("sub VIM::perldo {")-1);
  270.     sv_catpvn(sv, (char *)eap->arg, length);
  271.     sv_catpvn(sv, "}", 1);
  272.     perl_eval_sv(sv, G_DISCARD | G_NOARGS);
  273.     SvREFCNT_dec(sv);
  274.     str = SvPV(GvSV(errgv), length);
  275.     if (length)
  276. goto err;
  277.     if (u_save(eap->line1 - 1, eap->line2 + 1) != OK)
  278. return FAIL;
  279.     ENTER;
  280.     SAVETMPS;
  281.     for (i = eap->line1; i <= eap->line2; i++)
  282.     {
  283. sv_setpv(GvSV(defgv),(char *)ml_get(i));
  284. PUSHMARK(sp);
  285. perl_call_pv("VIM::perldo", G_SCALAR | G_EVAL);
  286. str = SvPV(GvSV(errgv), length);
  287. if (length)
  288.     break;
  289. SPAGAIN;
  290. if (SvTRUEx(POPs))
  291. {
  292.     if (replace_line(&i, &eap->line2) != OK)
  293.     {
  294. PUTBACK;
  295. break;
  296.     }
  297. }
  298. PUTBACK;
  299.     }
  300.     FREETMPS;
  301.     LEAVE;
  302.     adjust_cursor();
  303.     update_screen(NOT_VALID);
  304.     if (!length)
  305. return OK;
  306. err:
  307.     msg_split((char_u *)str, highlight_attr[HLF_E]);
  308.     return FAIL;
  309. }
  310. /* Register any extra external extensions */
  311. extern void 
  312. #ifdef __BORLANDC__
  313. __import
  314. #endif
  315. boot_DynaLoader _((CV* cv));
  316. extern void boot_VIM _((CV* cv));
  317.     static void
  318. xs_init()
  319. {
  320. #if 0
  321.     dXSUB_SYS;     /* causes an error with Perl 5.003_97 */
  322. #endif
  323.     char *file = __FILE__;
  324.     newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
  325.     newXS("VIM::bootstrap", boot_VIM, file);
  326. }
  327. typedef WIN * VIWIN;
  328. typedef BUF * VIBUF;
  329. MODULE = VIM     PACKAGE = VIM
  330. void
  331. Msg(text, hl=NULL)
  332.     char *text;
  333.     char *hl;
  334.     PREINIT:
  335.     int attr;
  336.     int id;
  337.     PPCODE:
  338.     if (text != NULL)
  339.     {
  340. attr = 0;
  341. if (hl != NULL)
  342. {
  343.     id = syn_name2id((char_u *)hl);
  344.     if (id != 0)
  345. attr = syn_id2attr(id);
  346. }
  347. msg_split((char_u *)text, attr);
  348.     }
  349. void
  350. SetOption(line)
  351.     char *line;
  352.     PPCODE:
  353.     if (line != NULL)
  354. do_set((char_u *)line);
  355.     update_screen(NOT_VALID);
  356. void
  357. DoCommand(line)
  358.     char *line;
  359.     PPCODE:
  360.     if (line != NULL)
  361. do_cmdline((char_u *)line, NULL, NULL, DOCMD_VERBOSE + DOCMD_NOWAIT);
  362. void
  363. Eval(str)
  364.     char *str;
  365.     PREINIT:
  366. char_u *value;
  367.     PPCODE:
  368. value = eval_to_string((char_u *)str, (char_u**)0);
  369. if (value == NULL)
  370. {
  371.     XPUSHs(sv_2mortal(newSViv(0)));
  372.     XPUSHs(sv_2mortal(newSVpv("", 0)));
  373. }
  374. else
  375. {
  376.     XPUSHs(sv_2mortal(newSViv(1)));
  377.     XPUSHs(sv_2mortal(newSVpv((char *)value, 0)));
  378.     vim_free(value);
  379. }
  380. void
  381. Buffers(...)
  382.     PREINIT:
  383.     BUF *vimbuf;
  384.     int i, b;
  385.     PPCODE:
  386.     if (items == 0)
  387.     {
  388. if (GIMME == G_SCALAR)
  389. {
  390.     i = 0;
  391.     for (vimbuf = firstbuf; vimbuf; vimbuf = vimbuf->b_next)
  392. ++i;
  393.     XPUSHs(sv_2mortal(newSViv(i)));
  394. }
  395. else
  396. {
  397.     for (vimbuf = firstbuf; vimbuf; vimbuf = vimbuf->b_next)
  398. XPUSHs(newBUFrv(newSV(0), vimbuf));
  399. }
  400.     }
  401.     else
  402.     {
  403. for (i = 0; i < items; i++)
  404. {
  405.     SV *sv = ST(i);
  406.     if (SvIOK(sv))
  407. b = SvIV(ST(i));
  408.     else
  409.     {
  410. char_u *pat;
  411. int len;
  412. pat = (char_u *)SvPV(sv, len);
  413. ++emsg_off;
  414. b = buflist_findpat(pat, pat+len);
  415. --emsg_off;
  416.     }
  417.     if (b >= 0)
  418.     {
  419. vimbuf = buflist_findnr(b);
  420. if (vimbuf)
  421.     XPUSHs(newBUFrv(newSV(0), vimbuf));
  422.     }
  423. }
  424.     }
  425. void
  426. Windows(...)
  427.     PREINIT:
  428.     WIN *vimwin;
  429.     int i, w;
  430.     PPCODE:
  431.     if (items == 0)
  432.     {
  433. if (GIMME == G_SCALAR)
  434.     XPUSHs(sv_2mortal(newSViv(win_count())));
  435. else
  436. {
  437.     for (vimwin = firstwin; vimwin != NULL; vimwin = vimwin->w_next)
  438. XPUSHs(newWINrv(newSV(0), vimwin));
  439. }
  440.     }
  441.     else
  442.     {
  443. for (i = 0; i < items; i++)
  444. {
  445.     w = SvIV(ST(i));
  446.     vimwin = win_goto_nr(w);
  447.     if (vimwin)
  448. XPUSHs(newWINrv(newSV(0), vimwin));
  449. }
  450.     }
  451. MODULE = VIM     PACKAGE = VIWIN
  452. void
  453. DESTROY(win)
  454.     VIWIN win
  455.     CODE:
  456.     if (win_valid(win))
  457. win->perl_private = 0;
  458. SV *
  459. Buffer(win)
  460.     VIWIN win
  461.     CODE:
  462.     if (!win_valid(win))
  463. win = curwin;
  464.     RETVAL = newBUFrv(newSV(0), win->w_buffer);
  465.     OUTPUT:
  466.     RETVAL
  467. void
  468. SetHeight(win, height)
  469.     VIWIN win
  470.     int height;
  471.     PREINIT:
  472.     WIN *savewin;
  473.     PPCODE:
  474.     if (!win_valid(win))
  475. win = curwin;
  476.     savewin = curwin;
  477.     curwin = win;
  478.     win_setheight(height);
  479.     curwin = savewin;
  480. void
  481. Cursor(win, ...)
  482.     VIWIN win
  483.     PPCODE:
  484.     if(items == 1)
  485.     {
  486.       EXTEND(sp, 2);
  487.       if (!win_valid(win))
  488.   win = curwin;
  489.       PUSHs(sv_2mortal(newSViv(win->w_cursor.lnum)));
  490.       PUSHs(sv_2mortal(newSViv(win->w_cursor.col)));
  491.     }
  492.     else if(items == 3)
  493.     {
  494.       int lnum, col;
  495.       if (!win_valid(win))
  496.   win = curwin;
  497.       lnum = SvIV(ST(1));
  498.       col = SvIV(ST(2));
  499.       win->w_cursor.lnum = lnum;
  500.       win->w_cursor.col = col;
  501.       adjust_cursor();     /* put cursor on an existing line */
  502.       update_screen(NOT_VALID);
  503.     }
  504. MODULE = VIM     PACKAGE = VIBUF
  505. void
  506. DESTROY(vimbuf)
  507.     VIBUF vimbuf;
  508.     CODE:
  509.     if (buf_valid(vimbuf))
  510. vimbuf->perl_private = 0;
  511. void
  512. Name(vimbuf)
  513.     VIBUF vimbuf;
  514.     PPCODE:
  515.     if (!buf_valid(vimbuf))
  516. vimbuf = curbuf;
  517.     /* No file name returns an empty string */
  518.     if (vimbuf->b_fname == NULL)
  519. XPUSHs(sv_2mortal(newSVpv("", 0)));
  520.     else
  521. XPUSHs(sv_2mortal(newSVpv((char *)vimbuf->b_fname, 0)));
  522. void
  523. Number(vimbuf)
  524.     VIBUF vimbuf;
  525.     PPCODE:
  526.     if (!buf_valid(vimbuf))
  527. vimbuf = curbuf;
  528.     XPUSHs(sv_2mortal(newSViv(vimbuf->b_fnum)));
  529. void
  530. Count(vimbuf)
  531.     VIBUF vimbuf;
  532.     PPCODE:
  533.     if (!buf_valid(vimbuf))
  534. vimbuf = curbuf;
  535.     XPUSHs(sv_2mortal(newSViv(vimbuf->b_ml.ml_line_count)));
  536. void
  537. Get(vimbuf, ...)
  538.     VIBUF vimbuf;
  539.     PREINIT:
  540.     char_u *line;
  541.     int i;
  542.     long lnum;
  543.     PPCODE:
  544.     if (buf_valid(vimbuf))
  545.     {
  546. for (i = 1; i < items; i++)
  547. {
  548.     lnum = SvIV(ST(i));
  549.     if (lnum > 0 && lnum <= vimbuf->b_ml.ml_line_count)
  550.     {
  551. line = ml_get_buf(vimbuf, lnum, FALSE);
  552. XPUSHs(sv_2mortal(newSVpv((char *)line, 0)));
  553.     }
  554. }
  555.     }
  556. void
  557. Set(vimbuf, ...)
  558.     VIBUF vimbuf;
  559.     PREINIT:
  560.     int i;
  561.     long lnum;
  562.     char *line;
  563.     BUF *savebuf;
  564.     PPCODE:
  565.     if (buf_valid(vimbuf))
  566.     {
  567. if (items < 3)
  568.     croak("Usage: VIBUF::Set(vimbuf, lnum, @lines)");
  569. lnum = SvIV(ST(1));
  570. for(i=2; i<items; i++, lnum++)
  571. {
  572.     line = SvPV(ST(i),na);
  573.     if(lnum > 0 && lnum <= vimbuf->b_ml.ml_line_count && line != NULL)
  574.     {
  575. savebuf = curbuf;
  576. curbuf = vimbuf;
  577. if (u_savesub(lnum) == OK)
  578. {
  579.     ml_replace(lnum, (char_u *)line, TRUE);
  580.     changed();
  581. #ifdef SYNTAX_HL
  582.     syn_changed(lnum); /* recompute syntax hl. for this line */
  583. #endif
  584. }
  585. curbuf = savebuf;
  586. update_curbuf(NOT_VALID);
  587.     }
  588. }
  589.     }
  590. void
  591. Delete(vimbuf, ...)
  592.     VIBUF vimbuf;
  593.     PREINIT:
  594.     long i, lnum = 0, count = 0;
  595.     BUF *savebuf;
  596.     PPCODE:
  597.     if (buf_valid(vimbuf))
  598.     {
  599. if (items == 2)
  600. {
  601.     lnum = SvIV(ST(1));
  602.     count = 1;
  603. }
  604. else if (items == 3)
  605. {
  606.     lnum = SvIV(ST(1));
  607.     count = 1 + SvIV(ST(2)) - lnum;
  608.     if(count == 0)
  609. count = 1;
  610.     if(count < 0)
  611.     {
  612. lnum -= count;
  613. count = -count;
  614.     }
  615. }
  616. if (items >= 2)
  617. {
  618.     for (i=0; i<count; i++)
  619.     {
  620. if (lnum > 0 && lnum <= vimbuf->b_ml.ml_line_count)
  621. {
  622.     savebuf = curbuf;
  623.     curbuf = vimbuf;
  624.     if (u_savedel(lnum, 1) == OK)
  625.     {
  626. mark_adjust(lnum, lnum, MAXLNUM, -1);
  627. ml_delete(lnum, 0);
  628. changed();
  629.     }
  630.     curbuf = savebuf;
  631.     update_curbuf(NOT_VALID);
  632. }
  633.     }
  634. }
  635.     }
  636. void
  637. Append(vimbuf, ...)
  638.     VIBUF vimbuf;
  639.     PREINIT:
  640.     int i;
  641.     long lnum;
  642.     char *line;
  643.     BUF *savebuf;
  644.     PPCODE:
  645.     if (buf_valid(vimbuf))
  646.     {
  647. if (items < 3)
  648.     croak("Usage: VIBUF::Append(vimbuf, lnum, @lines)");
  649. lnum = SvIV(ST(1));
  650. for(i=2; i<items; i++, lnum++)
  651. {
  652.     line = SvPV(ST(i),na);
  653.     if(lnum >= 0 && lnum <= vimbuf->b_ml.ml_line_count && line != NULL)
  654.     {
  655. savebuf = curbuf;
  656. curbuf = vimbuf;
  657. if (u_inssub(lnum + 1) == OK)
  658. {
  659.     mark_adjust(lnum + 1, MAXLNUM, 1L, 0L);
  660.     ml_append(lnum, (char_u *)line, (colnr_t)0, FALSE);
  661.     changed();
  662. }
  663. curbuf = savebuf;
  664. update_curbuf(NOT_VALID);
  665.     }
  666. }
  667.     }