Hello everybody,
trying to build a better Swank interface for VIM I found that it's relatively
hard to return values from a perl function.
To solve that problem I'm providing two patches:
* The first allows setting and getting variables from embedded perl scripts.
This one is simple; I think it's safe to use it.
* The second is the bigger one; it defines a new perleval() function that
calls an arbitrary perl function in array context with up to 18 parameters,
and returns the results.
Here I would like to get feedback, and/or fixes for the perl interface.
Regards,
Phil
--
Versioning your /etc, /home or even your whole installation?
Try fsvs (fsvs.tigris.org)!
--
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
diff -r bfade53bcafb src/auto/config.mk
--- a/src/auto/config.mk Fri Dec 17 20:24:01 2010 +0100
+++ b/src/auto/config.mk Fri Dec 17 21:34:26 2010 +0100
@@ -1,5 +1,169 @@
-the first targets to make vim are: scratch config myself
-srcdir = .
-VIMNAME = vim
-EXNAME = ex
-VIEWNAME = view
+#
+# config.mk.in -- autoconf template for Vim on Unix vim:ts=8:sw=8:
+#
+# DO NOT EDIT config.mk!! It will be overwritten by configure.
+# Edit Makefile and run "make" or run ./configure with other arguments.
+#
+# Configure does not edit the makefile directly. This method is not the
+# standard use of GNU autoconf, but it has two advantages:
+# a) The user can override every choice made by configure.
+# b) Modifications to the makefile are not lost when configure is run.
+#
+# I hope this is worth being nonstandard. jw.
+
+
+
+VIMNAME = vim
+EXNAME = ex
+VIEWNAME = view
+
+CC = gcc
+DEFS = -DHAVE_CONFIG_H
+CFLAGS = -g -O2 -D_FORTIFY_SOURCE=1
+CPPFLAGS =
+srcdir = .
+
+LDFLAGS = -Wl,-E -Wl,--as-needed
+LIBS = -lm -lncurses -lnsl
+TAGPRG = ctags -I INIT+ --fields=+S
+
+CPP = gcc -E
+CPP_MM = M
+DEPEND_CFLAGS_FILTER = | sed 's+-I */+-isystem /+g'
+LINK_AS_NEEDED = yes
+X_CFLAGS =
+X_LIBS_DIR =
+X_PRE_LIBS = -lSM -lICE
+X_EXTRA_LIBS = -lXdmcp -lSM -lICE
+X_LIBS = -lXt -lX11
+
+LUA_LIBS =
+LUA_SRC =
+LUA_OBJ =
+LUA_CFLAGS =
+LUA_PRO =
+
+MZSCHEME_LIBS =
+MZSCHEME_SRC =
+MZSCHEME_OBJ =
+MZSCHEME_CFLAGS =
+MZSCHEME_PRO =
+MZSCHEME_EXTRA =
+MZSCHEME_MZC =
+
+PERL = /usr/bin/perl
+PERLLIB = /usr/share/perl/5.10
+PERL_LIBS = -Wl,-E -fstack-protector -L/usr/local/lib -L/usr/lib/perl/5.10/CORE -lperl -ldl -lm -lpthread -lcrypt
+SHRPENV =
+PERL_SRC = auto/if_perl.c if_perlsfio.c
+PERL_OBJ = objects/if_perl.o objects/if_perlsfio.o
+PERL_PRO = if_perl.pro if_perlsfio.pro
+PERL_CFLAGS = -D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/lib/perl/5.10/CORE
+
+PYTHON_SRC =
+PYTHON_OBJ =
+PYTHON_CFLAGS =
+PYTHON_LIBS =
+PYTHON_CONFDIR =
+PYTHON_GETPATH_CFLAGS =
+
+PYTHON3_SRC =
+PYTHON3_OBJ =
+PYTHON3_CFLAGS =
+PYTHON3_LIBS =
+PYTHON3_CONFDIR =
+
+TCL =
+TCL_SRC =
+TCL_OBJ =
+TCL_PRO =
+TCL_CFLAGS =
+TCL_LIBS =
+
+HANGULIN_SRC =
+HANGULIN_OBJ =
+
+WORKSHOP_SRC =
+WORKSHOP_OBJ =
+
+NETBEANS_SRC = netbeans.c
+NETBEANS_OBJ = objects/netbeans.o
+
+RUBY =
+RUBY_SRC =
+RUBY_OBJ =
+RUBY_PRO =
+RUBY_CFLAGS =
+RUBY_LIBS =
+
+SNIFF_SRC =
+SNIFF_OBJ =
+
+AWK = gawk
+
+STRIP = strip
+
+EXEEXT =
+
+COMPILEDBY =
+
+INSTALLVIMDIFF = installvimdiff
+INSTALLGVIMDIFF = installgvimdiff
+INSTALL_LANGS = install-languages
+INSTALL_TOOL_LANGS = install-tool-languages
+
+### sed command to fix quotes while creating pathdef.c
+QUOTESED = sed -e 's/[\\"]/\\&/g' -e 's/\\"/"/' -e 's/\\";$$/";/'
+
+### Line break character as octal number for "tr"
+NL = "\\012"
+
+### Top directory for everything
+prefix = /usr/local
+
+### Top directory for the binary
+exec_prefix = ${prefix}
+
+### Prefix for location of data files
+BINDIR = ${exec_prefix}/bin
+
+### For autoconf 2.60 and later (avoid a warning)
+datarootdir = ${prefix}/share
+
+### Prefix for location of data files
+DATADIR = ${datarootdir}
+
+### Prefix for location of man pages
+MANDIR = ${datarootdir}/man
+
+### Do we have a GUI
+GUI_INC_LOC = -pthread -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include
+GUI_LIB_LOC =
+GUI_SRC = $(GTK_SRC)
+GUI_OBJ = $(GTK_OBJ)
+GUI_DEFS = $(GTK_DEFS)
+GUI_IPATH = $(GTK_IPATH)
+GUI_LIBS_DIR = $(GTK_LIBS_DIR)
+GUI_LIBS1 = $(GTK_LIBS1)
+GUI_LIBS2 = $(GTK_LIBS2)
+GUI_INSTALL = $(GTK_INSTALL)
+GUI_TARGETS = $(GTK_TARGETS)
+GUI_MAN_TARGETS = $(GTK_MAN_TARGETS)
+GUI_TESTTARGET = $(GTK_TESTTARGET)
+GUI_TESTARG = $(GTK_TESTARG)
+GUI_BUNDLE = $(GTK_BUNDLE)
+NARROW_PROTO =
+GUI_X_LIBS =
+MOTIF_LIBNAME =
+GTK_LIBNAME = -pthread -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lpangoft2-1.0 -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lcairo -lgio-2.0 -lpango-1.0 -lfreetype -lfontconfig -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lrt -lglib-2.0
+
+### Any OS dependent extra source and object file
+OS_EXTRA_SRC =
+OS_EXTRA_OBJ =
+
+### If the *.po files are to be translated to *.mo files.
+MAKEMO = yes
+
+# Make sure that "make first" will run "make all" once configure has done its
+# work. This is needed when using the Makefile in the top directory.
+first: all
diff -r bfade53bcafb src/if_perl.xs
--- a/src/if_perl.xs Fri Dec 17 20:24:01 2010 +0100
+++ b/src/if_perl.xs Fri Dec 17 21:34:26 2010 +0100
@@ -959,6 +959,27 @@
update_screen(NOT_VALID);
void
+SetVar(name, val)
+ char *name;
+ char *val;
+
+ PPCODE:
+ if (name != NULL)
+ set_internal_string_var(name, val);
+ update_screen(NOT_VALID);
+
+
+void
+GetVar(name)
+ char *name;
+
+ PPCODE:
+ if (name != NULL)
+ XPUSHs(sv_2mortal(newSVpv((char *)get_var_value(name), 0)));
+ update_screen(NOT_VALID);
+
+
+void
DoCommand(line)
char *line;
diff -r bfade53bcafb src/Makefile
--- a/src/Makefile Fri Dec 17 20:24:01 2010 +0100
+++ b/src/Makefile Fri Dec 17 23:04:19 2010 +0100
@@ -2367,8 +2367,9 @@
auto/if_perl.c: if_perl.xs
$(PERL) -e 'unless ( $$] >= 5.005 ) { for (qw(na defgv errgv)) { print "#define PL_$$_ $$_\n" }}' > $@
- $(PERL) $(PERLLIB)/ExtUtils/xsubpp -prototypes -typemap \
- $(PERLLIB)/ExtUtils/typemap if_perl.xs >> $@
+ $(PERL) $(PERLLIB)/ExtUtils/xsubpp -prototypes \
+ -typemap $(PERLLIB)/ExtUtils/typemap \
+ -typemap if_perl_typemap if_perl.xs >> $@
auto/osdef.h: auto/config.h osdef.sh osdef1.h.in osdef2.h.in
CC="$(CC) $(OSDEF_CFLAGS)" srcdir=$(srcdir) sh $(srcdir)/osdef.sh
diff -r bfade53bcafb src/eval.c
--- a/src/eval.c Fri Dec 17 20:24:01 2010 +0100
+++ b/src/eval.c Fri Dec 17 23:04:19 2010 +0100
@@ -645,6 +645,9 @@
static void f_nextnonblank __ARGS((typval_T *argvars, typval_T *rettv));
static void f_nr2char __ARGS((typval_T *argvars, typval_T *rettv));
static void f_pathshorten __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_PERL
+void f_perleval __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
#ifdef FEAT_FLOAT
static void f_pow __ARGS((typval_T *argvars, typval_T *rettv));
#endif
@@ -7839,6 +7843,9 @@
{"nextnonblank", 1, 1, f_nextnonblank},
{"nr2char", 1, 1, f_nr2char},
{"pathshorten", 1, 1, f_pathshorten},
+#ifdef FEAT_PERL
+ {"perleval", 1, 19, f_perleval},
+#endif
#ifdef FEAT_FLOAT
{"pow", 2, 2, f_pow},
#endif
diff -r bfade53bcafb src/if_perl.xs
--- a/src/if_perl.xs Fri Dec 17 20:24:01 2010 +0100
+++ b/src/if_perl.xs Fri Dec 17 23:04:19 2010 +0100
@@ -886,6 +887,135 @@
}
}
+
+void
+f_perleval(argvars, rettv)
+ typval_T *argvars;
+ typval_T *rettv;
+{
+ char_u *cmd;
+ char_u buf[NUMBUFLEN];
+ int count, i;
+ STRLEN len;
+ SV *sv;
+ list_T *retlist;
+ I32 ax;
+ typval_T *v;
+ char *cp;
+
+ if (perl_interp == NULL)
+ {
+#ifdef DYNAMIC_PERL
+ if (!perl_enabled(TRUE))
+ {
+ EMSG(_(e_noperl));
+ return;
+ }
+#endif
+ perl_init();
+ }
+
+ dSP;
+
+ ENTER;
+ SAVETMPS;
+
+ PUSHMARK(SP);
+ EXTEND(SP, 20);
+ if (argvars[0].v_type != VAR_STRING) {
+ return;
+ }
+
+ cmd = argvars[0].vval.v_string;
+
+ for(i=1; i<20; i++)
+ {
+ sv = NULL;
+ // see perlcall
+ switch(argvars[i].v_type)
+ {
+ case VAR_NUMBER:
+ sv = newSViv(argvars[i].vval.v_number);
+ break;
+ case VAR_STRING:
+ sv = newSVpv(argvars[i].vval.v_string,
+ argvars[i].vval.v_string ?
+ strlen(argvars[i].vval.v_string) : 0);
+ break;
+ case VAR_FLOAT:
+ sv = newSVnv(argvars[i].vval.v_float);
+ break;
+
+ case VAR_LIST:
+ case VAR_DICT:
+ /* These two could be supported, I think. */
+ break;
+
+ case VAR_FUNC:
+ break;
+ default:
+ case VAR_UNKNOWN:
+ break;
+ }
+
+ if (!sv)
+ break;
+
+ XPUSHs(sv_2mortal(sv));
+ }
+
+ PUTBACK;
+
+ count = call_pv(cmd, G_ARRAY | G_EVAL);
+
+ SPAGAIN;
+
+ SP -= count;
+ ax = (SP - PL_stack_base) + 1;
+
+
+ retlist = list_alloc();
+ if (retlist == NULL)
+ return;
+ retlist->lv_refcount = 1;
+
+
+ v = (typval_T *)alloc(sizeof(typval_T));
+ if (v == NULL)
+ return;
+ v->v_lock = VAR_LOCKED; // Is this correct ???
+
+ for(i=0; i<count; i++) {
+ // See perlguts
+ if (SvIOK(ST(i))) {
+ v->v_type = VAR_NUMBER;
+ v->vval.v_number = SvIV(ST(i));
+ } else if (SvNOK(ST(i))) {
+ v->v_type = VAR_FLOAT;
+ v->vval.v_float = SvNV(ST(i));
+ } else if (SvPOK(ST(i))) {
+ v->v_type = VAR_STRING;
+ cp = SvPV(ST(i), len);
+ v->vval.v_string = vim_strnsave(cp, len);
+ } else
+ continue;
+
+ list_append_tv(retlist, v);
+ clear_tv(v);
+ }
+
+ rettv->v_type = VAR_LIST;
+ rettv->v_lock = 0;
+ rettv->vval.v_list = retlist;
+
+
+ PUTBACK;
+
+ FREETMPS;
+ LEAVE;
+}
+
+
#ifndef FEAT_WINDOWS
int win_valid(win_T *w) { return TRUE; }
int win_count() { return 1; }