diff options
-rw-r--r-- | runtime/doc/if_mzsch.txt | 97 | ||||
-rw-r--r-- | src/Make_ming.mak | 26 | ||||
-rw-r--r-- | src/Make_mvc.mak | 27 | ||||
-rw-r--r-- | src/Makefile | 8 | ||||
-rwxr-xr-x | src/auto/configure | 74 | ||||
-rw-r--r-- | src/config.mk.in | 2 | ||||
-rw-r--r-- | src/configure.in | 63 | ||||
-rw-r--r-- | src/eval.c | 2 | ||||
-rw-r--r-- | src/if_mzsch.c | 1341 | ||||
-rw-r--r-- | src/if_mzsch.h | 28 | ||||
-rw-r--r-- | src/main.c | 6 | ||||
-rw-r--r-- | src/proto/if_mzsch.pro | 8 | ||||
-rw-r--r-- | src/version.c | 2 |
13 files changed, 1132 insertions, 552 deletions
diff --git a/runtime/doc/if_mzsch.txt b/runtime/doc/if_mzsch.txt index 87298eccf..d22544419 100644 --- a/runtime/doc/if_mzsch.txt +++ b/runtime/doc/if_mzsch.txt @@ -1,4 +1,4 @@ -*if_mzsch.txt* For Vim version 7.2. Last change: 2008 Jun 28 +*if_mzsch.txt* For Vim version 7.2. Last change: 2009 May 26 VIM REFERENCE MANUAL by Sergey Khorev @@ -42,10 +42,6 @@ Note: On FreeBSD you should use the "drscheme" port. *:mzfile* *:mzf* :[range]mzf[ile] {file} Execute the MzScheme script in {file}. {not in Vi} - All statements are executed in the namespace of the - buffer that was current during :mzfile start. - If you want to access other namespaces, use - 'parameterize'. All of these commands do essentially the same thing - they execute a piece of MzScheme code, with the "current range" set to the given line @@ -54,8 +50,6 @@ range. In the case of :mzscheme, the code to execute is in the command-line. In the case of :mzfile, the code to execute is the contents of the given file. -Each buffer has its own MzScheme namespace. Global namespace is bound to -the "global-namespace" value from the 'vimext' module. MzScheme interface defines exception exn:vim, derived from exn. It is raised for various Vim errors. @@ -79,40 +73,8 @@ To avoid clashes with MzScheme, consider using prefix when requiring module, e.g.: > :mzscheme (require (prefix vim- vimext)) < -All the examples below assume this naming scheme. Note that you need to do -this again for every buffer. +All the examples below assume this naming scheme. -The auto-instantiation can be achieved with autocommands, e.g. you can put -something like this in your .vimrc (EOFs should not have indentation): > - function s:MzRequire() - if has("mzscheme") - :mz << EOF - (require (prefix vim- vimext)) - (let ((buf (vim-get-buff-by-name (vim-eval "expand(\"<afile>\")")))) - (when (and buf (not (eq? buf (vim-curr-buff)))) - (parameterize ((current-namespace (vim-get-buff-namespace buf))) - (namespace-attach-module vim-global-namespace 'vimext) - (namespace-require '(prefix vim vimext))))) - EOF - endif - endfunction - - function s:MzStartup() - if has("mzscheme") - au BufNew,BufNewFile,BufAdd,BufReadPre * :call s:MzRequire() - :mz << EOF - (current-library-collection-paths - (cons - (build-path (find-system-path 'addon-dir) (version) "collects") - (current-library-collection-paths))) - EOF - endif - endfunction - - call s:MzStartup() -< - -The global namespace just instantiated this module with the prefix "vimext:". *mzscheme-sandbox* When executed in the |sandbox|, access to some filesystem and Vim interface procedures is restricted. @@ -121,15 +83,20 @@ procedures is restricted. 2. Examples *mzscheme-examples* > :mzscheme (display "Hello") + :mz (display (string-append "Using MzScheme version " (version))) + :mzscheme (require (prefix vim- vimext)) ; for MzScheme < 4.x + :mzscheme (require (prefix-in vim- 'vimext)) ; MzScheme 4.x :mzscheme (vim-set-buff-line 10 "This is line #10") < Inline script usage: > function! <SID>SetFirstLine() :mz << EOF (display "!!!") + (require (prefix vim- vimext)) + ; for newer versions (require (prefix-in vim- 'vimext)) (vim-set-buff-line 1 "This is line #1") (vim-beep) - EOF + EOF endfunction nmap <F9> :call <SID>SetFirstLine() <CR> @@ -137,17 +104,33 @@ Inline script usage: > File execution: > :mzfile supascript.scm < -Accessing the current buffer namespace from an MzScheme program running in -another buffer within |:mzfile|-executed script : > - ; Move to the window below - (vim-command "wincmd j") - ; execute in the context of buffer, to which window belongs - ; assume that buffer has 'textstring' defined - (parameterize ((current-namespace - (vim-get-buff-namespace (vim-curr-buff)))) - (eval '(vim-set-buff-line 1 textstring))) +Vim exception handling: > + :mz << EOF + (require (prefix vim- vimext)) + ; for newer versions (require (prefix-in vim- 'vimext)) + (with-handlers + ([exn:vim? (lambda (e) (display (exn-message e)))]) + (vim-eval "nonsense-string")) + EOF < +Auto-instantiation of vimext module (can be placed in your |vimrc|): > + function! MzRequire() + :redir => l:mzversion + :mz (version) + :redir END + if strpart(l:mzversion, 1, 1) < "4" + " MzScheme versions < 4.x: + :mz (require (prefix vim- vimext)) + else + " newer versions: + :mz (require (prefix-in vim- 'vimext)) + endif + endfunction + if has("mzscheme") + silent call MzRequire() + endif +< ============================================================================== 3. Threads *mzscheme-threads* @@ -168,11 +151,11 @@ interface. Common ------ (command {command-string}) Perform the vim ":Ex" style command. - (eval {expr-string}) Evaluate the vim expression to a string. - A |List| is turned into a string by - joining the items and inserting line - breaks. - NOTE clashes with MzScheme eval + (eval {expr-string}) Evaluate the vim expression into + respective MzScheme object: |Lists| are + represented as Scheme lists, + |Dictionaries| as hash tables. + NOTE the name clashes with MzScheme eval (range-start) Start/End of the range passed with (range-end) the Scheme command. (beep) beep @@ -186,7 +169,6 @@ Common be set. The symbol 'global can be passed as {buffer-or-window}. Then |:setglobal| will be used. - global-namespace The MzScheme main namespace. Buffers *mzscheme-buffer* ------- @@ -228,7 +210,6 @@ Buffers *mzscheme-buffer* if there is no such buffer. (get-buff-by-num {buffernum}) Get a buffer by its number (return #f if there is no buffer with this number). - (get-buff-namespace [buffer]) Get buffer namespace. Windows *mzscheme-window* ------ @@ -250,7 +231,7 @@ Windows *mzscheme-window* (set-cursor (line . col) [window]) Set cursor position. ============================================================================== -5. Dynamic loading *mzscheme-dynamic* +5. Dynamic loading *mzscheme-dynamic* *E812* On MS-Windows the MzScheme libraries can be loaded dynamically. The |:version| output then includes |+mzscheme/dyn|. diff --git a/src/Make_ming.mak b/src/Make_ming.mak index 6d28e4668..e0717b62a 100644 --- a/src/Make_ming.mak +++ b/src/Make_ming.mak @@ -115,8 +115,21 @@ ifndef MZSCHEME_VER MZSCHEME_VER=205_000 endif +ifndef MZSCHEME_PRECISE_GC +MZSCHEME_PRECISE_GC=no +endif + +# for version 4.x we need to generate byte-code for Scheme base +ifndef MZSCHEME_GENERATE_BASE +MZSCHEME_GENERATE_BASE=no +endif + ifeq (no,$(DYNAMIC_MZSCHEME)) +ifeq (yes,$(MZSCHEME_PRECISE_GC)) +MZSCHEME_LIB=-lmzsch$(MZSCHEME_VER) +else MZSCHEME_LIB = -lmzsch$(MZSCHEME_VER) -lmzgc$(MZSCHEME_VER) +endif # the modern MinGW can dynamically link to dlls directly. # point MZSCHEME_DLLS to where you put libmzschXXXXXXX.dll and libgcXXXXXXX.dll ifndef MZSCHEME_DLLS @@ -410,6 +423,13 @@ endif ifdef MZSCHEME OBJ += $(OUTDIR)/if_mzsch.o MZSCHEME_INCL = if_mzsch.h +ifeq (yes,$(MZSCHEME_GENERATE_BASE)) +CFLAGS += -DINCLUDE_MZSCHEME_BASE +MZ_EXTRA_DEP += mzscheme_base.c +endif +ifeq (yes,$(MZSCHEME_PRECISE_GC)) +CFLAGS += -DMZ_PRECISE_GC +endif endif ifdef PYTHON OBJ += $(OUTDIR)/if_python.o @@ -588,6 +608,12 @@ if_perl.c: if_perl.xs typemap $(OUTDIR)/netbeans.o: netbeans.c $(INCL) $(NBDEBUG_INCL) $(NBDEBUG_SRC) $(CC) -c $(CFLAGS) netbeans.c -o $(OUTDIR)/netbeans.o +$(OUTDIR)/if_mzsch.o: if_mzsch.c $(INCL) if_mzsch.h $(MZ_EXTRA_DEP) + $(CC) -c $(CFLAGS) if_mzsch.c -o $(OUTDIR)/if_mzsch.o + +mzscheme_base.c: + $(MZSCHEME)/mzc --c-mods mzscheme_base.c ++lib scheme/base + pathdef.c: $(INCL) ifneq (sh.exe, $(SHELL)) @echo creating pathdef.c diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak index 545c94d34..178258696 100644 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -34,6 +34,7 @@ # MZSCHEME=[Path to MzScheme directory] # DYNAMIC_MZSCHEME=yes (to load the MzScheme DLLs dynamically) # MZSCHEME_VER=[version, 205_000, ...] +# MZSCHEME_DEBUG=no # # Perl interface: # PERL=[Path to Perl directory] @@ -621,15 +622,37 @@ PYTHON_LIB = $(PYTHON)\libs\python$(PYTHON_VER).lib MZSCHEME_VER = 205_000 !endif CFLAGS = $(CFLAGS) -DFEAT_MZSCHEME -I $(MZSCHEME)\include +!if EXIST("$(MZSCHEME)\collects\scheme\base.ss") +# for MzScheme 4.x we need to include byte code for basic Scheme stuff +MZSCHEME_EXTRA_DEP = mzscheme_base.c +CFLAGS = $(CFLAGS) -DINCLUDE_MZSCHEME_BASE +!endif +!if EXIST("$(MZSCHEME)\lib\msvc\libmzsch$(MZSCHEME_VER).lib") \ + && !EXIST("$(MZSCHEME)\lib\msvc\libmzgc$(MZSCHEME_VER).lib") +!message Building with Precise GC +MZSCHEME_PRECISE_GC = yes +CFLAGS = $(CFLAGS) -DMZ_PRECISE_GC +!endif !if "$(DYNAMIC_MZSCHEME)" == "yes" +!if "$(MZSCHEME_PRECISE_GC)" == "yes" +!error MzScheme with Precise GC cannot be loaded dynamically +!endif !message MzScheme DLLs will be loaded dynamically CFLAGS = $(CFLAGS) -DDYNAMIC_MZSCHEME \ -DDYNAMIC_MZSCH_DLL=\"libmzsch$(MZSCHEME_VER).dll\" \ -DDYNAMIC_MZGC_DLL=\"libmzgc$(MZSCHEME_VER).dll\" !else +!if "$(MZSCHEME_DEBUG)" == "yes" +CFLAGS = $(CFLAGS) -DMZSCHEME_FORCE_GC +!endif +!if "$(MZSCHEME_PRECISE_GC)" == "yes" +# Precise GC does not use separate dll +MZSCHEME_LIB = $(MZSCHEME)\lib\msvc\libmzsch$(MZSCHEME_VER).lib +!else MZSCHEME_LIB = $(MZSCHEME)\lib\msvc\libmzgc$(MZSCHEME_VER).lib \ $(MZSCHEME)\lib\msvc\libmzsch$(MZSCHEME_VER).lib !endif +!endif MZSCHEME_OBJ = $(OUTDIR)\if_mzsch.obj !endif @@ -930,9 +953,11 @@ $(OUTDIR)/if_perl.obj: $(OUTDIR) if_perl.c $(INCL) $(OUTDIR)/if_perlsfio.obj: $(OUTDIR) if_perlsfio.c $(INCL) $(CC) $(CFLAGS) $(PERL_INC) if_perlsfio.c -$(OUTDIR)/if_mzsch.obj: $(OUTDIR) if_mzsch.c $(INCL) +$(OUTDIR)/if_mzsch.obj: $(OUTDIR) if_mzsch.c $(INCL) $(MZSCHEME_EXTRA_DEP) $(CC) $(CFLAGS) if_mzsch.c \ -DMZSCHEME_COLLECTS=\"$(MZSCHEME:\=\\)\\collects\" +mzscheme_base.c: + $(MZSCHEME)\mzc --c-mods mzscheme_base.c ++lib scheme/base $(OUTDIR)/if_python.obj: $(OUTDIR) if_python.c $(INCL) $(CC) $(CFLAGS) $(PYTHON_INC) if_python.c diff --git a/src/Makefile b/src/Makefile index e6d26b164..02b8d6cb8 100644 --- a/src/Makefile +++ b/src/Makefile @@ -536,7 +536,7 @@ CClink = $(CC) # Use this with GCC to check for mistakes, unused arguments, etc. #CFLAGS = -g -Wall -Wextra -Wmissing-prototypes -Wunreachable-code #PYTHON_CFLAGS_EXTRA = -Wno-missing-field-initializers -#MZSCHEME_CFLAGS_EXTRA = -Wno-unreachable-code +#MZSCHEME_CFLAGS_EXTRA = -Wno-unreachable-code -Wno-unused-parameter # EFENCE - Electric-Fence malloc debugging: catches memory accesses beyond # allocated memory (and makes every malloc()/free() very slow). @@ -2200,6 +2200,7 @@ clean celan: testclean -rm -f $(TOOLS) auto/osdef.h auto/pathdef.c auto/if_perl.c -rm -f conftest* *~ auto/link.sed -rm -rf $(APPDIR) + -rm -rf mzscheme_base.c if test -d $(PODIR); then \ cd $(PODIR); $(MAKE) prefix=$(DESTDIR)$(prefix) clean; \ fi @@ -2433,8 +2434,11 @@ objects/if_cscope.o: if_cscope.c objects/if_xcmdsrv.o: if_xcmdsrv.c $(CCC) -o $@ if_xcmdsrv.c -objects/if_mzsch.o: if_mzsch.c +objects/if_mzsch.o: if_mzsch.c $(MZSCHEME_EXTRA) $(CCC) -o $@ $(MZSCHEME_CFLAGS_EXTRA) if_mzsch.c + +mzscheme_base.c: + $(MZSCHEME_MZC) --c-mods mzscheme_base.c ++lib scheme/base objects/if_perl.o: auto/if_perl.c $(CCC) -o $@ auto/if_perl.c diff --git a/src/auto/configure b/src/auto/configure index 596e0349d..42f4784dd 100755 --- a/src/auto/configure +++ b/src/auto/configure @@ -701,6 +701,8 @@ PERL_SRC shrpenv vi_cv_perllib vi_cv_path_perl +MZSCHEME_MZC +MZSCHEME_EXTRA MZSCHEME_CFLAGS MZSCHEME_LIBS MZSCHEME_PRO @@ -4641,8 +4643,8 @@ $as_echo_n "checking PLTHOME environment var... " >&6; } $as_echo "\"$PLTHOME\"" >&6; } vi_cv_path_mzscheme_pfx="$PLTHOME" else - { $as_echo "$as_me:$LINENO: result: \"not set\"" >&5 -$as_echo "\"not set\"" >&6; } + { $as_echo "$as_me:$LINENO: result: not set" >&5 +$as_echo "not set" >&6; } # Extract the first word of "mzscheme", so it can be a program name with args. set dummy mzscheme; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 @@ -4697,16 +4699,16 @@ $as_echo_n "checking MzScheme install prefix... " >&6; } if test "${vi_cv_path_mzscheme_pfx+set}" = set; then $as_echo_n "(cached) " >&6 else - vi_cv_path_mzscheme_pfx=` - ${vi_cv_path_mzscheme} -evm \ - "(display (simplify-path \ + echo "(display (simplify-path \ (build-path (call-with-values \ (lambda () (split-path (find-system-path (quote exec-file)))) \ - (lambda (base name must-be-dir?) base)) (quote up))))"` + (lambda (base name must-be-dir?) base)) (quote up))))" > mzdirs.scm + vi_cv_path_mzscheme_pfx=`${vi_cv_path_mzscheme} -r mzdirs.scm | \ + sed -e 's+/$++'` fi { $as_echo "$as_me:$LINENO: result: $vi_cv_path_mzscheme_pfx" >&5 $as_echo "$vi_cv_path_mzscheme_pfx" >&6; } - vi_cv_path_mzscheme_pfx=`echo "$vi_cv_path_mzscheme_pfx" | sed 's+/$++'` + rm -f mzdirs.scm fi fi fi @@ -4716,21 +4718,32 @@ $as_echo "$vi_cv_path_mzscheme_pfx" >&6; } { $as_echo "$as_me:$LINENO: checking if scheme.h can be found in $vi_cv_path_mzscheme_pfx/include" >&5 $as_echo_n "checking if scheme.h can be found in $vi_cv_path_mzscheme_pfx/include... " >&6; } if test -f $vi_cv_path_mzscheme_pfx/include/scheme.h; then - { $as_echo "$as_me:$LINENO: result: \"yes\"" >&5 -$as_echo "\"yes\"" >&6; } + SCHEME_INC=${vi_cv_path_mzscheme_pfx}/include + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } else - { $as_echo "$as_me:$LINENO: result: \"no\"" >&5 -$as_echo "\"no\"" >&6; } - { $as_echo "$as_me:$LINENO: checking if scheme.h can be found in $vi_cv_path_mzscheme_pfx/plt/include" >&5 -$as_echo_n "checking if scheme.h can be found in $vi_cv_path_mzscheme_pfx/plt/include... " >&6; } + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } + { $as_echo "$as_me:$LINENO: checking if scheme.h can be found in $vi_cv_path_mzscheme_pfx/include/plt" >&5 +$as_echo_n "checking if scheme.h can be found in $vi_cv_path_mzscheme_pfx/include/plt... " >&6; } if test -f $vi_cv_path_mzscheme_pfx/include/plt/scheme.h; then - { $as_echo "$as_me:$LINENO: result: \"yes\"" >&5 -$as_echo "\"yes\"" >&6; } - SCHEME_INC=/plt + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + SCHEME_INC=${vi_cv_path_mzscheme_pfx}/include/plt else - { $as_echo "$as_me:$LINENO: result: \"no\"" >&5 -$as_echo "\"no\"" >&6; } - vi_cv_path_mzscheme_pfx= + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } + { $as_echo "$as_me:$LINENO: checking if scheme.h can be found in /usr/include/plt/" >&5 +$as_echo_n "checking if scheme.h can be found in /usr/include/plt/... " >&6; } + if test -f /usr/include/plt/scheme.h; then + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + SCHEME_INC=/usr/include/plt + else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } + vi_cv_path_mzscheme_pfx= + fi fi fi fi @@ -4738,21 +4751,34 @@ $as_echo "\"no\"" >&6; } if test "X$vi_cv_path_mzscheme_pfx" != "X"; then if test "x$MACOSX" = "xyes"; then MZSCHEME_LIBS="-framework PLT_MzScheme" + elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzscheme3m.a"; then + MZSCHEME_LIBS="${vi_cv_path_mzscheme_pfx}/lib/libmzscheme3m.a" + MZSCHEME_CFLAGS="-DMZ_PRECISE_GC" elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a"; then MZSCHEME_LIBS="${vi_cv_path_mzscheme_pfx}/lib/libmzscheme.a ${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a" else - MZSCHEME_LIBS="-L${vi_cv_path_mzscheme_pfx}/lib -lmzscheme -lmzgc" + if test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzscheme3m.so"; then + MZSCHEME_LIBS="-L${vi_cv_path_mzscheme_pfx}/lib -lmzscheme3m" + MZSCHEME_CFLAGS="-DMZ_PRECISE_GC" + else + MZSCHEME_LIBS="-L${vi_cv_path_mzscheme_pfx}/lib -lmzscheme -lmzgc" + fi if test "$GCC" = yes; then - MZSCHEME_LIBS="$MZSCHEME_LIBS -Wl,-rpath -Wl,${vi_cv_path_mzscheme_pfx}/lib" + MZSCHEME_LIBS="${MZSCHEME_LIBS} -Wl,-rpath -Wl,${vi_cv_path_mzscheme_pfx}/lib" elif test "`(uname) 2>/dev/null`" = SunOS && uname -r | grep '^5' >/dev/null; then - MZSCHEME_LIBS="$MZSCHEME_LIBS -R ${vi_cv_path_mzscheme_pfx}/lib" + MZSCHEME_LIBS="${MZSCHEME_LIBS} -R ${vi_cv_path_mzscheme_pfx}/lib" fi fi if test -d $vi_cv_path_mzscheme_pfx/lib/plt/collects; then SCHEME_COLLECTS=lib/plt/ fi - MZSCHEME_CFLAGS="-I${vi_cv_path_mzscheme_pfx}/include${SCHEME_INC} \ + if test -f "${vi_cv_path_mzscheme_pfx}/${SCHEME_COLLECTS}collects/scheme/base.ss" ; then + MZSCHEME_EXTRA="mzscheme_base.c" + MZSCHEME_CFLAGS="${MZSCHEME_CFLAGS} -DINCLUDE_MZSCHEME_BASE" + MZSCHEME_MZC="${vi_cv_path_mzscheme_pfx}/bin/mzc" + fi + MZSCHEME_CFLAGS="${MZSCHEME_CFLAGS} -I${SCHEME_INC} \ -DMZSCHEME_COLLECTS='\"${vi_cv_path_mzscheme_pfx}/${SCHEME_COLLECTS}collects\"'" MZSCHEME_SRC="if_mzsch.c" MZSCHEME_OBJ="objects/if_mzsch.o" @@ -4767,6 +4793,8 @@ _ACEOF + + fi diff --git a/src/config.mk.in b/src/config.mk.in index 9590d445a..f36e676c1 100644 --- a/src/config.mk.in +++ b/src/config.mk.in @@ -41,6 +41,8 @@ MZSCHEME_SRC = @MZSCHEME_SRC@ MZSCHEME_OBJ = @MZSCHEME_OBJ@ MZSCHEME_CFLAGS = @MZSCHEME_CFLAGS@ MZSCHEME_PRO = @MZSCHEME_PRO@ +MZSCHEME_EXTRA = @MZSCHEME_EXTRA@ +MZSCHEME_MZC = @MZSCHEME_MZC@ PERL = @vi_cv_path_perl@ PERLLIB = @vi_cv_perllib@ diff --git a/src/configure.in b/src/configure.in index a644d941f..eb7db7674 100644 --- a/src/configure.in +++ b/src/configure.in @@ -414,7 +414,7 @@ if test "$enable_mzschemeinterp" = "yes"; then AC_MSG_RESULT("$PLTHOME") vi_cv_path_mzscheme_pfx="$PLTHOME" else - AC_MSG_RESULT("not set") + AC_MSG_RESULT(not set) dnl -- try to find MzScheme executable AC_PATH_PROG(vi_cv_path_mzscheme, mzscheme) @@ -430,14 +430,16 @@ if test "$enable_mzschemeinterp" = "yes"; then if test "X$vi_cv_path_mzscheme" != "X"; then dnl -- find where MzScheme thinks it was installed AC_CACHE_CHECK(MzScheme install prefix,vi_cv_path_mzscheme_pfx, - [ vi_cv_path_mzscheme_pfx=` - ${vi_cv_path_mzscheme} -evm \ - "(display (simplify-path \ + dnl different versions of MzScheme differ in command line processing + dnl use universal approach + echo "(display (simplify-path \ (build-path (call-with-values \ (lambda () (split-path (find-system-path (quote exec-file)))) \ - (lambda (base name must-be-dir?) base)) (quote up))))"` ]) - dnl Remove a trailing slash. - vi_cv_path_mzscheme_pfx=`echo "$vi_cv_path_mzscheme_pfx" | sed 's+/$++'` + (lambda (base name must-be-dir?) base)) (quote up))))" > mzdirs.scm + dnl Remove a trailing slash + [ vi_cv_path_mzscheme_pfx=`${vi_cv_path_mzscheme} -r mzdirs.scm | \ + sed -e 's+/$++'` ]) + rm -f mzdirs.scm fi fi fi @@ -446,16 +448,24 @@ if test "$enable_mzschemeinterp" = "yes"; then if test "X$vi_cv_path_mzscheme_pfx" != "X"; then AC_MSG_CHECKING(if scheme.h can be found in $vi_cv_path_mzscheme_pfx/include) if test -f $vi_cv_path_mzscheme_pfx/include/scheme.h; then - AC_MSG_RESULT("yes") + SCHEME_INC=${vi_cv_path_mzscheme_pfx}/include + AC_MSG_RESULT(yes) else - AC_MSG_RESULT("no") - AC_MSG_CHECKING(if scheme.h can be found in $vi_cv_path_mzscheme_pfx/plt/include) + AC_MSG_RESULT(no) + AC_MSG_CHECKING(if scheme.h can be found in $vi_cv_path_mzscheme_pfx/include/plt) if test -f $vi_cv_path_mzscheme_pfx/include/plt/scheme.h; then - AC_MSG_RESULT("yes") - SCHEME_INC=/plt + AC_MSG_RESULT(yes) + SCHEME_INC=${vi_cv_path_mzscheme_pfx}/include/plt else - AC_MSG_RESULT("no") - vi_cv_path_mzscheme_pfx= + AC_MSG_RESULT(no) + AC_MSG_CHECKING(if scheme.h can be found in /usr/include/plt/) + if test -f /usr/include/plt/scheme.h; then + AC_MSG_RESULT(yes) + SCHEME_INC=/usr/include/plt + else + AC_MSG_RESULT(no) + vi_cv_path_mzscheme_pfx= + fi fi fi fi @@ -463,23 +473,38 @@ if test "$enable_mzschemeinterp" = "yes"; then if test "X$vi_cv_path_mzscheme_pfx" != "X"; then if test "x$MACOSX" = "xyes"; then MZSCHEME_LIBS="-framework PLT_MzScheme" + elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzscheme3m.a"; then + MZSCHEME_LIBS="${vi_cv_path_mzscheme_pfx}/lib/libmzscheme3m.a" + MZSCHEME_CFLAGS="-DMZ_PRECISE_GC" elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a"; then MZSCHEME_LIBS="${vi_cv_path_mzscheme_pfx}/lib/libmzscheme.a ${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a" else - MZSCHEME_LIBS="-L${vi_cv_path_mzscheme_pfx}/lib -lmzscheme -lmzgc" + dnl Using shared objects + if test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzscheme3m.so"; then + MZSCHEME_LIBS="-L${vi_cv_path_mzscheme_pfx}/lib -lmzscheme3m" + MZSCHEME_CFLAGS="-DMZ_PRECISE_GC" + else + MZSCHEME_LIBS="-L${vi_cv_path_mzscheme_pfx}/lib -lmzscheme -lmzgc" + fi if test "$GCC" = yes; then dnl Make Vim remember the path to the library. For when it's not in dnl $LD_LIBRARY_PATH. - MZSCHEME_LIBS="$MZSCHEME_LIBS -Wl,-rpath -Wl,${vi_cv_path_mzscheme_pfx}/lib" + MZSCHEME_LIBS="${MZSCHEME_LIBS} -Wl,-rpath -Wl,${vi_cv_path_mzscheme_pfx}/lib" elif test "`(uname) 2>/dev/null`" = SunOS && uname -r | grep '^5' >/dev/null; then - MZSCHEME_LIBS="$MZSCHEME_LIBS -R ${vi_cv_path_mzscheme_pfx}/lib" + MZSCHEME_LIBS="${MZSCHEME_LIBS} -R ${vi_cv_path_mzscheme_pfx}/lib" fi fi if test -d $vi_cv_path_mzscheme_pfx/lib/plt/collects; then SCHEME_COLLECTS=lib/plt/ fi - MZSCHEME_CFLAGS="-I${vi_cv_path_mzscheme_pfx}/include${SCHEME_INC} \ + if test -f "${vi_cv_path_mzscheme_pfx}/${SCHEME_COLLECTS}collects/scheme/base.ss" ; then + dnl need to generate bytecode for MzScheme base + MZSCHEME_EXTRA="mzscheme_base.c" + MZSCHEME_CFLAGS="${MZSCHEME_CFLAGS} -DINCLUDE_MZSCHEME_BASE" + MZSCHEME_MZC="${vi_cv_path_mzscheme_pfx}/bin/mzc" + fi + MZSCHEME_CFLAGS="${MZSCHEME_CFLAGS} -I${SCHEME_INC} \ -DMZSCHEME_COLLECTS='\"${vi_cv_path_mzscheme_pfx}/${SCHEME_COLLECTS}collects\"'" MZSCHEME_SRC="if_mzsch.c" MZSCHEME_OBJ="objects/if_mzsch.o" @@ -491,6 +516,8 @@ if test "$enable_mzschemeinterp" = "yes"; then AC_SUBST(MZSCHEME_PRO) AC_SUBST(MZSCHEME_LIBS) AC_SUBST(MZSCHEME_CFLAGS) + AC_SUBST(MZSCHEME_EXTRA) + AC_SUBST(MZSCHEME_MZC) fi diff --git a/src/eval.c b/src/eval.c index 2e3d9fd77..bf0c3030f 100644 --- a/src/eval.c +++ b/src/eval.c @@ -5866,7 +5866,7 @@ list_equal(l1, l2, ic) return item1 == NULL && item2 == NULL; } -#if defined(FEAT_PYTHON) || defined(PROTO) +#if defined(FEAT_PYTHON) || defined(FEAT_MZSCHEME) || defined(PROTO) /* * Return the dictitem that an entry in a hashtable points to. */ diff --git a/src/if_mzsch.c b/src/if_mzsch.c index 7f43cab6e..017f8041e 100644 --- a/src/if_mzsch.c +++ b/src/if_mzsch.c @@ -4,6 +4,8 @@ * Original work by Brent Fulgham <bfulgham@debian.org> * (Based on lots of help from Matthew Flatt) * + * TODO Convert byte-strings to char strings? + * * This consists of six parts: * 1. MzScheme interpreter main program * 2. Routines that handle the external interface between MzScheme and @@ -18,7 +20,7 @@ * garbage collector will do it self * 2. Requires at least NORMAL features. I can't imagine why one may want * to build with SMALL or TINY features but with MzScheme interface. - * 3. I don't use K&R-style functions. Anyway, MzScheme headers are ANSI. + * 3. I don't use K&R-style functions. Anyways, MzScheme headers are ANSI. */ #include "vim.h" @@ -29,14 +31,15 @@ * depend". */ #if defined(FEAT_MZSCHEME) || defined(PROTO) +#include <assert.h> + /* Base data structures */ #define SCHEME_VIMBUFFERP(obj) SAME_TYPE(SCHEME_TYPE(obj), mz_buffer_type) #define SCHEME_VIMWINDOWP(obj) SAME_TYPE(SCHEME_TYPE(obj), mz_window_type) typedef struct { - Scheme_Type tag; - Scheme_Env *env; + Scheme_Object so; buf_T *buf; } vim_mz_buffer; @@ -44,7 +47,7 @@ typedef struct typedef struct { - Scheme_Type tag; + Scheme_Object so; win_T *win; } vim_mz_window; @@ -67,19 +70,6 @@ typedef struct Scheme_Object *port; } Port_Info; -/* info for closed prim */ -/* - * data have different means: - * for do_eval it is char* - * for do_apply is Apply_Onfo* - * for do_load is Port_Info* - */ -typedef struct -{ - void *data; - Scheme_Env *env; -} Cmd_Info; - /* info for do_apply */ typedef struct { @@ -122,7 +112,6 @@ static Scheme_Object *set_buffer_line_list(void *, int, Scheme_Object **); static Scheme_Object *insert_buffer_line_list(void *, int, Scheme_Object **); static Scheme_Object *get_range_start(void *, int, Scheme_Object **); static Scheme_Object *get_range_end(void *, int, Scheme_Object **); -static Scheme_Object *get_buffer_namespace(void *, int, Scheme_Object **); static vim_mz_buffer *get_vim_curr_buffer(void); /* Window-related commands */ @@ -163,8 +152,6 @@ static int vim_error_check(void); static int do_mzscheme_command(exarg_T *, void *, Scheme_Closed_Prim *what); static void startup_mzscheme(void); static char *string_to_line(Scheme_Object *obj); -static int mzscheme_io_init(void); -static void mzscheme_interface_init(vim_mz_buffer *self); static void do_output(char *mesg, long len); static void do_printf(char *format, ...); static void do_flush(void); @@ -174,19 +161,52 @@ static Scheme_Object *extract_exn_message(Scheme_Object *v); static Scheme_Object *do_eval(void *, int noargc, Scheme_Object **noargv); static Scheme_Object *do_load(void *, int noargc, Scheme_Object **noargv); static Scheme_Object *do_apply(void *, int noargc, Scheme_Object **noargv); -static void register_vim_exn(Scheme_Env *env); +static void register_vim_exn(void); static vim_mz_buffer *get_buffer_arg(const char *fname, int argnum, int argc, Scheme_Object **argv); static vim_mz_window *get_window_arg(const char *fname, int argnum, int argc, Scheme_Object **argv); -static void add_vim_exn(Scheme_Env *env); static int line_in_range(linenr_T, buf_T *); static void check_line_range(linenr_T, buf_T *); static void mz_fix_cursor(int lo, int hi, int extra); -static int eval_in_namespace(void *, Scheme_Closed_Prim *, Scheme_Env *, - Scheme_Object **ret); -static void make_modules(Scheme_Env *); +static int eval_with_exn_handling(void *, Scheme_Closed_Prim *, + Scheme_Object **ret); +static void make_modules(void); +static void init_exn_catching_apply(void); +static int mzscheme_env_main(Scheme_Env *env, int argc, char **argv); +static int mzscheme_init(void); +#ifdef FEAT_EVAL +static Scheme_Object *vim_to_mzscheme(typval_T *vim_value, int depth, + Scheme_Hash_Table *visited); +#endif + +#ifdef MZ_PRECISE_GC +static int buffer_size_proc(void *obj) +{ + return gcBYTES_TO_WORDS(sizeof(vim_mz_buffer)); +} +static int buffer_mark_proc(void *obj) +{ + return buffer_size_proc(obj); +} +static int buffer_fixup_proc(void *obj) +{ + return buffer_size_proc(obj); +} +static int window_size_proc(void *obj) +{ + return gcBYTES_TO_WORDS(sizeof(vim_mz_window)); +} +static int window_mark_proc(void *obj) +{ + return window_size_proc(obj); +} +static int window_fixup_proc(void *obj) +{ + return window_size_proc(obj); +} +#endif #ifdef DYNAMIC_MZSCHEME @@ -260,8 +280,6 @@ static Scheme_Object *(*dll_scheme_make_closed_prim_w_arity) (Scheme_Closed_Prim *prim, void *data, const char *name, mzshort mina, mzshort maxa); static Scheme_Object *(*dll_scheme_make_integer_value)(long i); -static Scheme_Object *(*dll_scheme_make_namespace)(int argc, - Scheme_Object *argv[]); static Scheme_Object *(*dll_scheme_make_pair)(Scheme_Object *car, Scheme_Object *cdr); static Scheme_Object *(*dll_scheme_make_prim_w_arity)(Scheme_Prim *prim, @@ -311,6 +329,17 @@ static Scheme_Object *(*dll_scheme_char_string_to_byte_string) static Scheme_Object *(*dll_scheme_char_string_to_path) (Scheme_Object *s); # endif +static Scheme_Hash_Table *(*dll_scheme_make_hash_table)(int type); +static void (*dll_scheme_hash_set)(Scheme_Hash_Table *table, + Scheme_Object *key, Scheme_Object *value); +static Scheme_Object *(*dll_scheme_hash_get)(Scheme_Hash_Table *table, + Scheme_Object *key); +static Scheme_Object *(*dll_scheme_make_double)(double d); +# ifdef INCLUDE_MZSCHEME_BASE +static Scheme_Object *(*dll_scheme_make_sized_byte_string)(char *chars, + long len, int copy); +static Scheme_Object *(*dll_scheme_namespace_require)(Scheme_Object *req); +# endif /* arrays are imported directly */ # define scheme_eof dll_scheme_eof @@ -368,7 +397,6 @@ static Scheme_Object *(*dll_scheme_char_string_to_path) # define scheme_lookup_global dll_scheme_lookup_global # define scheme_make_closed_prim_w_arity dll_scheme_make_closed_prim_w_arity # define scheme_make_integer_value dll_scheme_make_integer_value -# define scheme_make_namespace dll_scheme_make_namespace # define scheme_make_pair dll_scheme_make_pair # define scheme_make_prim_w_arity dll_scheme_make_prim_w_arity # if MZSCHEME_VERSION_MAJOR < 299 @@ -403,6 +431,14 @@ static Scheme_Object *(*dll_scheme_char_string_to_path) # define scheme_char_string_to_path \ dll_scheme_char_string_to_path # endif +# define scheme_make_hash_table dll_scheme_make_hash_table +# define scheme_hash_set dll_scheme_hash_set +# define scheme_hash_get dll_scheme_hash_get +# define scheme_make_double dll_scheme_make_double +# ifdef INCLUDE_MZSCHEME_BASE +# define scheme_make_sized_byte_string dll_scheme_make_sized_byte_string +# define scheme_namespace_require dll_scheme_namespace_require +# endif typedef struct { @@ -468,7 +504,6 @@ static Thunk_Info mzsch_imports[] = { {"scheme_make_closed_prim_w_arity", (void **)&dll_scheme_make_closed_prim_w_arity}, {"scheme_make_integer_value", (void **)&dll_scheme_make_integer_value}, - {"scheme_make_namespace", (void **)&dll_scheme_make_namespace}, {"scheme_make_pair", (void **)&dll_scheme_make_pair}, {"scheme_make_prim_w_arity", (void **)&dll_scheme_make_prim_w_arity}, # if MZSCHEME_VERSION_MAJOR < 299 @@ -502,9 +537,16 @@ static Thunk_Info mzsch_imports[] = { {"scheme_current_config", (void **)&dll_scheme_current_config}, {"scheme_char_string_to_byte_string", (void **)&dll_scheme_char_string_to_byte_string}, - {"scheme_char_string_to_path", - (void **)&dll_scheme_char_string_to_path}, + {"scheme_char_string_to_path", (void **)&dll_scheme_char_string_to_path}, # endif + {"scheme_make_hash_table", (void **)&dll_scheme_make_hash_table}, + {"scheme_hash_set", (void **)&dll_scheme_hash_set}, + {"scheme_hash_get", (void **)&dll_scheme_hash_get}, + {"scheme_make_double", (void **)&dll_scheme_make_double}, +# ifdef INCLUDE_MZSCHEME_BASE + {"scheme_make_sized_byte_string", (void **)&dll_scheme_make_sized_byte_string}, + {"scheme_namespace_require", (void **)&dll_scheme_namespace_require}, +#endif {NULL, NULL}}; static HINSTANCE hMzGC = 0; @@ -592,6 +634,11 @@ dynamic_mzscheme_end(void) } #endif /* DYNAMIC_MZSCHEME */ +/* need to put it here for dynamic stuff to work */ +#ifdef INCLUDE_MZSCHEME_BASE +# include "mzscheme_base.c" +#endif + /* *======================================================================== * 1. MzScheme interpreter startup @@ -601,21 +648,22 @@ dynamic_mzscheme_end(void) static Scheme_Type mz_buffer_type; static Scheme_Type mz_window_type; -static int initialized = 0; +static int initialized = FALSE; /* global environment */ static Scheme_Env *environment = NULL; /* output/error handlers */ static Scheme_Object *curout = NULL; static Scheme_Object *curerr = NULL; -/* vim:exn exception */ +/* exn:vim exception */ static Scheme_Object *exn_catching_apply = NULL; static Scheme_Object *exn_p = NULL; static Scheme_Object *exn_message = NULL; static Scheme_Object *vim_exn = NULL; /* Vim Error exception */ - /* values for exn:vim - constructor, predicate, accessors etc */ -static Scheme_Object *vim_exn_names = NULL; -static Scheme_Object *vim_exn_values = NULL; + +#if !defined(MZ_PRECISE_GC) || MZSCHEME_VERSION_MAJOR < 400 +static void *stack_base = NULL; +#endif static long range_start; static long range_end; @@ -668,10 +716,10 @@ static void remove_timer(void); timer_proc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime) # elif defined(FEAT_GUI_GTK) static gint -timer_proc(gpointer data UNUSED) +timer_proc(gpointer data) # elif defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) static void -timer_proc(XtPointer timed_out UNUSED, XtIntervalId *interval_id UNUSED) +timer_proc(XtPointer timed_out, XtIntervalId *interval_id) # elif defined(FEAT_GUI_MAC) pascal void timer_proc(EventLoopTimerRef theTimer, void *userData) @@ -751,12 +799,64 @@ mzscheme_end(void) #endif } + void +mzscheme_main(void) +{ +#if defined(MZ_PRECISE_GC) && MZSCHEME_VERSION_MAJOR >= 400 + /* use trampoline for precise GC in MzScheme >= 4.x */ + scheme_main_setup(TRUE, mzscheme_env_main, 0, NULL); +#else + mzscheme_env_main(NULL, 0, NULL); +#endif +} + + static int +mzscheme_env_main(Scheme_Env *env, int argc, char **argv) +{ + /* neither argument nor return values are used */ +#ifdef MZ_PRECISE_GC +# if MZSCHEME_VERSION_MAJOR < 400 + /* + * Starting from version 4.x, embedding applications must use + * scheme_main_setup/scheme_main_stack_setup trampolines + * rather than setting stack base directly with scheme_set_stack_base + */ + Scheme_Object *dummy = NULL; + MZ_GC_DECL_REG(1); + MZ_GC_VAR_IN_REG(0, dummy); + + stack_base = &__gc_var_stack__; +# else + /* environment has been created by us by Scheme */ + environment = env; +# endif + /* + * In 4.x, all activities must be performed inside trampoline + * so we are forced to initialise GC immediately + * This can be postponed in 3.x but I see no point in implementing + * a feature which will work in older versions only. + * One would better use conservative GC if he needs dynamic MzScheme + */ + mzscheme_init(); +#else + int dummy = 0; + stack_base = (void *)&dummy; +#endif + main_loop(FALSE, FALSE); +#if defined(MZ_PRECISE_GC) && MZSCHEME_VERSION_MAJOR < 400 + /* releasing dummy */ + MZ_GC_REG(); + MZ_GC_UNREG(); +#endif + return 0; +} + static void startup_mzscheme(void) { - Scheme_Object *proc_make_security_guard; - - scheme_set_stack_base(NULL, 1); +#if !defined(MZ_PRECISE_GC) || MZSCHEME_VERSION_MAJOR < 400 + scheme_set_stack_base(stack_base, 1); +#endif MZ_REGISTER_STATIC(environment); MZ_REGISTER_STATIC(curout); @@ -765,10 +865,35 @@ startup_mzscheme(void) MZ_REGISTER_STATIC(exn_p); MZ_REGISTER_STATIC(exn_message); MZ_REGISTER_STATIC(vim_exn); - MZ_REGISTER_STATIC(vim_exn_names); - MZ_REGISTER_STATIC(vim_exn_values); +#if !defined(MZ_PRECISE_GC) || MZSCHEME_VERSION_MAJOR < 400 + /* in newer versions of precise GC the initial env has been created */ environment = scheme_basic_env(); +#endif + MZ_GC_CHECK(); + +#ifdef INCLUDE_MZSCHEME_BASE + { + /* + * versions 4.x do not provide Scheme bindings by defaults + * we need to add them explicitly + */ + Scheme_Object *scheme_base_symbol = NULL; + MZ_GC_DECL_REG(1); + MZ_GC_VAR_IN_REG(0, scheme_base_symbol); + MZ_GC_REG(); + /* invoke function from generated and included base.c */ + declare_modules(environment); + scheme_base_symbol = scheme_intern_symbol("scheme/base"); + MZ_GC_CHECK(); + scheme_namespace_require(scheme_base_symbol); + MZ_GC_CHECK(); + MZ_GC_UNREG(); + } +#endif + register_vim_exn(); + /* use new environment to initialise exception handling */ + init_exn_catching_apply(); /* redirect output */ scheme_console_output = do_output; @@ -776,48 +901,131 @@ startup_mzscheme(void) #ifdef MZSCHEME_COLLECTS /* setup 'current-library-collection-paths' parameter */ - scheme_set_param(scheme_config, MZCONFIG_COLLECTION_PATHS, - scheme_make_pair( # if MZSCHEME_VERSION_MAJOR >= 299 - scheme_char_string_to_path( - scheme_byte_string_to_char_string( - scheme_make_byte_string(MZSCHEME_COLLECTS))), + { + Scheme_Object *coll_byte_string = NULL; + Scheme_Object *coll_char_string = NULL; + Scheme_Object *coll_path = NULL; + Scheme_Object *coll_pair = NULL; + Scheme_Config *config = NULL; + + MZ_GC_DECL_REG(5); + MZ_GC_VAR_IN_REG(0, coll_byte_string); + MZ_GC_VAR_IN_REG(1, coll_char_string); + MZ_GC_VAR_IN_REG(2, coll_path); + MZ_GC_VAR_IN_REG(3, coll_pair); + MZ_GC_VAR_IN_REG(4, config); + MZ_GC_REG(); + coll_byte_string = scheme_make_byte_string(MZSCHEME_COLLECTS); + MZ_GC_CHECK(); + coll_char_string = scheme_byte_string_to_char_string(coll_byte_string); + MZ_GC_CHECK(); + coll_path = scheme_char_string_to_path(coll_char_string); + MZ_GC_CHECK(); + coll_pair = scheme_make_pair(coll_path, scheme_null); + MZ_GC_CHECK(); + config = scheme_config; + MZ_GC_CHECK(); + scheme_set_param(config, MZCONFIG_COLLECTION_PATHS, coll_pair); + MZ_GC_CHECK(); + MZ_GC_UNREG(); + } # else - scheme_make_string(MZSCHEME_COLLECTS), + { + Scheme_Object *coll_string = NULL; + Scheme_Object *coll_pair = NULL; + Scheme_Config *config = NULL; + + MZ_GC_DECL_REG(3); + MZ_GC_VAR_IN_REG(0, coll_string); + MZ_GC_VAR_IN_REG(1, coll_pair); + MZ_GC_VAR_IN_REG(2, config); + MZ_GC_REG(); + coll_string = scheme_make_string(MZSCHEME_COLLECTS); + MZ_GC_CHECK(); + coll_pair = scheme_make_pair(coll_string, scheme_null); + MZ_GC_CHECK(); + config = scheme_config; + MZ_GC_CHECK(); + scheme_set_param(config, MZCONFIG_COLLECTION_PATHS, coll_pair); + MZ_GC_CHECK(); + MZ_GC_UNREG(); + } # endif - scheme_null)); #endif #ifdef HAVE_SANDBOX - /* setup sandbox guards */ - proc_make_security_guard = scheme_lookup_global( - scheme_intern_symbol("make-security-guard"), - environment); - if (proc_make_security_guard != NULL) { - Scheme_Object *args[3]; - Scheme_Object *guard; - args[0] = scheme_get_param(scheme_config, MZCONFIG_SECURITY_GUARD); - args[1] = scheme_make_prim_w_arity(sandbox_file_guard, - "sandbox-file-guard", 3, 3); - args[2] = scheme_make_prim_w_arity(sandbox_network_guard, - "sandbox-network-guard", 4, 4); - guard = scheme_apply(proc_make_security_guard, 3, args); - scheme_set_param(scheme_config, MZCONFIG_SECURITY_GUARD, guard); + Scheme_Object *make_security_guard = NULL; + MZ_GC_DECL_REG(1); + MZ_GC_VAR_IN_REG(0, make_security_guard); + MZ_GC_REG(); + +#if MZSCHEME_VERSION_MAJOR < 400 + { + Scheme_Object *make_security_guard_symbol = NULL; + MZ_GC_DECL_REG(1); + MZ_GC_VAR_IN_REG(0, make_security_guard_symbol); + MZ_GC_REG(); + make_security_guard_symbol = scheme_intern_symbol("make-security-guard"); + MZ_GC_CHECK(); + make_security_guard = scheme_lookup_global( + make_security_guard_symbol, environment); + MZ_GC_UNREG(); + } +#else + make_security_guard = scheme_builtin_value("make-security-guard"); + MZ_GC_CHECK(); +#endif + + /* setup sandbox guards */ + if (make_security_guard != NULL) + { + Scheme_Object *args[3] = {NULL, NULL, NULL}; + Scheme_Object *guard = NULL; + Scheme_Config *config = NULL; + MZ_GC_DECL_REG(5); + MZ_GC_ARRAY_VAR_IN_REG(0, args, 3); + MZ_GC_VAR_IN_REG(3, guard); + MZ_GC_VAR_IN_REG(4, config); + MZ_GC_REG(); + config = scheme_config; + MZ_GC_CHECK(); + args[0] = scheme_get_param(config, MZCONFIG_SECURITY_GUARD); + MZ_GC_CHECK(); + args[1] = scheme_make_prim_w_arity(sandbox_file_guard, + "sandbox-file-guard", 3, 3); + args[2] = scheme_make_prim_w_arity(sandbox_network_guard, + "sandbox-network-guard", 4, 4); + guard = scheme_apply(make_security_guard, 3, args); + MZ_GC_CHECK(); + scheme_set_param(config, MZCONFIG_SECURITY_GUARD, guard); + MZ_GC_CHECK(); + MZ_GC_UNREG(); + } + MZ_GC_UNREG(); } #endif /* Create buffer and window types for use in Scheme code */ mz_buffer_type = scheme_make_type("<vim-buffer>"); + MZ_GC_CHECK(); mz_window_type = scheme_make_type("<vim-window>"); + MZ_GC_CHECK(); +#ifdef MZ_PRECISE_GC + GC_register_traversers(mz_buffer_type, + buffer_size_proc, buffer_mark_proc, buffer_fixup_proc, + TRUE, TRUE); + GC_register_traversers(mz_window_type, + window_size_proc, window_mark_proc, window_fixup_proc, + TRUE, TRUE); +#endif - register_vim_exn(environment); - make_modules(environment); + make_modules(); /* * setup callback to receive notifications * whether thread scheduling is (or not) required */ scheme_notify_multithread = notify_multithread; - initialized = 1; } /* @@ -827,102 +1035,66 @@ startup_mzscheme(void) static int mzscheme_init(void) { - int do_require = FALSE; - if (!initialized) { - do_require = TRUE; #ifdef DYNAMIC_MZSCHEME if (!mzscheme_enabled(TRUE)) { - EMSG(_("???: Sorry, this command is disabled, the MzScheme library could not be loaded.")); + EMSG(_("E812: Sorry, this command is disabled, the MzScheme libraries could not be loaded.")); return -1; } #endif startup_mzscheme(); - - if (mzscheme_io_init()) - return -1; - + initialized = TRUE; } - /* recreate ports each call effectivelly clearing these ones */ - curout = scheme_make_string_output_port(); - curerr = scheme_make_string_output_port(); - scheme_set_param(scheme_config, MZCONFIG_OUTPUT_PORT, curout); - scheme_set_param(scheme_config, MZCONFIG_ERROR_PORT, curerr); - - if (do_require) { - /* auto-instantiate in basic env */ - eval_in_namespace("(require (prefix vimext: vimext))", do_eval, - environment, NULL); + Scheme_Config *config = NULL; + MZ_GC_DECL_REG(1); + MZ_GC_VAR_IN_REG(0, config); + MZ_GC_REG(); + config = scheme_config; + MZ_GC_CHECK(); + /* recreate ports each call effectivelly clearing these ones */ + curout = scheme_make_string_output_port(); + MZ_GC_CHECK(); + curerr = scheme_make_string_output_port(); + MZ_GC_CHECK(); + scheme_set_param(config, MZCONFIG_OUTPUT_PORT, curout); + MZ_GC_CHECK(); + scheme_set_param(config, MZCONFIG_ERROR_PORT, curerr); + MZ_GC_CHECK(); + MZ_GC_UNREG(); } return 0; } /* - * This routine fills the namespace with various important routines that can - * be used within MzScheme. - */ - static void -mzscheme_interface_init(vim_mz_buffer *mzbuff) -{ - Scheme_Object *attach; - - mzbuff->env = (Scheme_Env *)scheme_make_namespace(0, NULL); - - /* - * attach instantiated modules from global namespace - * so they can be easily instantiated in the buffer namespace - */ - attach = scheme_lookup_global( - scheme_intern_symbol("namespace-attach-module"), - environment); - - if (attach != NULL) - { - Scheme_Object *ret; - Scheme_Object *args[2]; - - args[0] = (Scheme_Object *)environment; - args[1] = scheme_intern_symbol("vimext"); - - ret = (Scheme_Object *)mzvim_apply(attach, 2, args); - } - - add_vim_exn(mzbuff->env); -} - -/* *======================================================================== * 2. External Interface *======================================================================== */ /* - * Evaluate command in namespace with exception handling + * Evaluate command with exception handling */ static int -eval_in_namespace(void *data, Scheme_Closed_Prim *what, Scheme_Env *env, - Scheme_Object **ret) +eval_with_exn_handling(void *data, Scheme_Closed_Prim *what, Scheme_Object **ret) { - Scheme_Object *value; - Scheme_Object *exn; - Cmd_Info info; /* closure info */ + Scheme_Object *value = NULL; + Scheme_Object *exn = NULL; + Scheme_Object *prim = NULL; - info.data = data; - info.env = env; + MZ_GC_DECL_REG(3); + MZ_GC_VAR_IN_REG(0, value); + MZ_GC_VAR_IN_REG(1, exn); + MZ_GC_VAR_IN_REG(2, prim); + MZ_GC_REG(); - scheme_set_param(scheme_config, MZCONFIG_ENV, - (Scheme_Object *) env); - /* - * ensure all evaluations will be in current buffer namespace, - * the second argument to scheme_eval_string isn't enough! - */ - value = _apply_thunk_catch_exceptions( - scheme_make_closed_prim_w_arity(what, &info, "mzvim", 0, 0), - &exn); + prim = scheme_make_closed_prim_w_arity(what, data, "mzvim", 0, 0); + MZ_GC_CHECK(); + value = _apply_thunk_catch_exceptions(prim, &exn); + MZ_GC_CHECK(); if (!value) { @@ -930,9 +1102,11 @@ eval_in_namespace(void *data, Scheme_Closed_Prim *what, Scheme_Env *env, /* Got an exn? */ if (value) { - scheme_display(value, curerr); /* Send to stderr-vim */ + scheme_display(value, curerr); /* Send to stderr-vim */ + MZ_GC_CHECK(); do_flush(); } + MZ_GC_UNREG(); /* `raise' was called on some arbitrary value */ return FAIL; } @@ -941,9 +1115,13 @@ eval_in_namespace(void *data, Scheme_Closed_Prim *what, Scheme_Env *env, *ret = value; /* Print any result, as long as it's not a void */ else if (!SCHEME_VOIDP(value)) + { scheme_display(value, curout); /* Send to stdout-vim */ + MZ_GC_CHECK(); + } do_flush(); + MZ_GC_UNREG(); return OK; } @@ -957,7 +1135,7 @@ do_mzscheme_command(exarg_T *eap, void *data, Scheme_Closed_Prim *what) range_start = eap->line1; range_end = eap->line2; - return eval_in_namespace(data, what, get_vim_curr_buffer()->env, NULL); + return eval_with_exn_handling(data, what, NULL); } /* @@ -974,6 +1152,7 @@ mzscheme_buffer_free(buf_T *buf) bp->buf = INVALID_BUFFER_VALUE; buf->b_mzscheme_ref = NULL; scheme_gc_ptr_ok(bp); + MZ_GC_CHECK(); } } @@ -990,6 +1169,7 @@ mzscheme_window_free(win_T *win) wp->win = INVALID_WINDOW_VALUE; win->w_mzscheme_ref = NULL; scheme_gc_ptr_ok(wp); + MZ_GC_CHECK(); } } @@ -1014,18 +1194,6 @@ ex_mzscheme(exarg_T *eap) } } -/* eval MzScheme string */ - void * -mzvim_eval_string(char_u *str) -{ - Scheme_Object *ret = NULL; - if (mzscheme_init()) - return FAIL; - - eval_in_namespace(str, do_eval, get_vim_curr_buffer()->env, &ret); - return ret; -} - /* * apply MzScheme procedure with arguments, * handling errors @@ -1033,43 +1201,65 @@ mzvim_eval_string(char_u *str) Scheme_Object * mzvim_apply(Scheme_Object *proc, int argc, Scheme_Object **argv) { - Apply_Info data; - Scheme_Object *ret = NULL; - if (mzscheme_init()) return FAIL; - - data.proc = proc; - data.argc = argc; - data.argv = argv; - - eval_in_namespace(&data, do_apply, get_vim_curr_buffer()->env, &ret); - return ret; + else + { + Apply_Info data = {NULL, 0, NULL}; + Scheme_Object *ret = NULL; + + MZ_GC_DECL_REG(5); + MZ_GC_VAR_IN_REG(0, ret); + MZ_GC_VAR_IN_REG(1, data.proc); + MZ_GC_ARRAY_VAR_IN_REG(2, data.argv, argc); + MZ_GC_REG(); + + data.proc = proc; + data.argc = argc; + data.argv = argv; + + eval_with_exn_handling(&data, do_apply, &ret); + MZ_GC_UNREG(); + return ret; + } } static Scheme_Object * do_load(void *data, int noargc, Scheme_Object **noargv) { - Cmd_Info *info = (Cmd_Info *)data; - Scheme_Object *result = scheme_void; - Scheme_Object *expr; - char_u *file = scheme_malloc_fail_ok( - scheme_malloc_atomic, MAXPATHL + 1); - Port_Info *pinfo = (Port_Info *)(info->data); + Scheme_Object *expr = NULL; + Scheme_Object *result = NULL; + char *file = NULL; + Port_Info *pinfo = (Port_Info *)data; + + MZ_GC_DECL_REG(3); + MZ_GC_VAR_IN_REG(0, expr); + MZ_GC_VAR_IN_REG(1, result); + MZ_GC_VAR_IN_REG(2, file); + MZ_GC_REG(); + + file = (char *)scheme_malloc_fail_ok(scheme_malloc_atomic, MAXPATHL + 1); + MZ_GC_CHECK(); /* make Vim expansion */ - expand_env((char_u *)pinfo->name, file, MAXPATHL); - /* scheme_load looks strange working with namespaces and error handling*/ + expand_env((char_u *)pinfo->name, (char_u *)file, MAXPATHL); pinfo->port = scheme_open_input_file(file, "mzfile"); - scheme_count_lines(pinfo->port); /* to get accurate read error location*/ + MZ_GC_CHECK(); + scheme_count_lines(pinfo->port); /* to get accurate read error location*/ + MZ_GC_CHECK(); /* Like REPL but print only last result */ while (!SCHEME_EOFP(expr = scheme_read(pinfo->port))) - result = scheme_eval(expr, info->env); + { + result = scheme_eval(expr, environment); + MZ_GC_CHECK(); + } /* errors will be caught in do_mzscheme_comamnd and ex_mzfile */ scheme_close_input_port(pinfo->port); + MZ_GC_CHECK(); pinfo->port = NULL; + MZ_GC_UNREG(); return result; } @@ -1077,13 +1267,20 @@ do_load(void *data, int noargc, Scheme_Object **noargv) void ex_mzfile(exarg_T *eap) { - Port_Info pinfo; + Port_Info pinfo = {NULL, NULL}; + + MZ_GC_DECL_REG(1); + MZ_GC_VAR_IN_REG(0, pinfo.port); + MZ_GC_REG(); pinfo.name = (char *)eap->arg; - pinfo.port = NULL; if (do_mzscheme_command(eap, &pinfo, do_load) != OK && pinfo.port != NULL) /* looks like port was not closed */ + { scheme_close_input_port(pinfo.port); + MZ_GC_CHECK(); + } + MZ_GC_UNREG(); } @@ -1103,14 +1300,12 @@ init_exn_catching_apply(void) "(with-handlers ([void (lambda (exn) (cons #f exn))]) " "(cons #t (thunk))))"; - /* make sure we have a namespace with the standard syntax: */ - Scheme_Env *env = (Scheme_Env *)scheme_make_namespace(0, NULL); - add_vim_exn(env); - - exn_catching_apply = scheme_eval_string(e, env); - exn_p = scheme_lookup_global(scheme_intern_symbol("exn?"), env); - exn_message = scheme_lookup_global( - scheme_intern_symbol("exn-message"), env); + exn_catching_apply = scheme_eval_string(e, environment); + MZ_GC_CHECK(); + exn_p = scheme_builtin_value("exn?"); + MZ_GC_CHECK(); + exn_message = scheme_builtin_value("exn-message"); + MZ_GC_CHECK(); } } @@ -1124,8 +1319,6 @@ _apply_thunk_catch_exceptions(Scheme_Object *f, Scheme_Object **exn) { Scheme_Object *v; - init_exn_catching_apply(); - v = _scheme_apply(exn_catching_apply, 1, &f); /* v is a pair: (cons #t value) or (cons #f exn) */ @@ -1141,8 +1334,6 @@ _apply_thunk_catch_exceptions(Scheme_Object *f, Scheme_Object **exn) static Scheme_Object * extract_exn_message(Scheme_Object *v) { - init_exn_catching_apply(); - if (SCHEME_TRUEP(_scheme_apply(exn_p, 1, &v))) return _scheme_apply(exn_message, 1, &v); else @@ -1152,16 +1343,13 @@ extract_exn_message(Scheme_Object *v) static Scheme_Object * do_eval(void *s, int noargc, Scheme_Object **noargv) { - Cmd_Info *info = (Cmd_Info *)s; - - return scheme_eval_string_all((char *)(info->data), info->env, TRUE); + return scheme_eval_string_all((char *)s, environment, TRUE); } static Scheme_Object * do_apply(void *a, int noargc, Scheme_Object **noargv) { - Apply_Info *info = (Apply_Info *)(((Cmd_Info *)a)->data); - + Apply_Info *info = (Apply_Info *)a; return scheme_apply(info->proc, info->argc, info->argv); } @@ -1219,6 +1407,7 @@ do_flush(void) long length; buff = scheme_get_sized_string_output(curerr, &length); + MZ_GC_CHECK(); if (length) { do_err_output(buff, length); @@ -1226,17 +1415,11 @@ do_flush(void) } buff = scheme_get_sized_string_output(curout, &length); + MZ_GC_CHECK(); if (length) do_output(buff, length); } - static int -mzscheme_io_init(void) -{ - /* Nothing needed so far... */ - return 0; -} - /* *======================================================================== * 4. Implementation of the Vim Features for MzScheme @@ -1263,22 +1446,30 @@ vim_command(void *data, int argc, Scheme_Object **argv) vim_eval(void *data, int argc, Scheme_Object **argv) { #ifdef FEAT_EVAL - Vim_Prim *prim = (Vim_Prim *)data; - char *expr; - char *str; - Scheme_Object *result; + Vim_Prim *prim = (Vim_Prim *)data; + char *expr; + Scheme_Object *result; + /* hash table to store visited values to avoid infinite loops */ + Scheme_Hash_Table *visited = NULL; + typval_T *vim_result; - expr = SCHEME_STR_VAL(GUARANTEE_STRING(prim->name, 0)); + MZ_GC_DECL_REG(1); + MZ_GC_VAR_IN_REG(0, visited); + MZ_GC_REG(); - str = (char *)eval_to_string((char_u *)expr, NULL, TRUE); + visited = scheme_make_hash_table(SCHEME_hash_ptr); + MZ_GC_CHECK(); - if (str == NULL) - raise_vim_exn(_("invalid expression")); + expr = SCHEME_STR_VAL(GUARANTEE_STRING(prim->name, 0)); + vim_result = eval_expr((char_u *)expr, NULL); - result = scheme_make_string(str); + if (vim_result == NULL) + raise_vim_exn(_("invalid expression")); - vim_free(str); + result = vim_to_mzscheme(vim_result, 1, visited); + free_tv(vim_result); + MZ_GC_UNREG(); return result; #else raise_vim_exn(_("expressions disabled at compile time")); @@ -1318,7 +1509,7 @@ get_option(void *data, int argc, Scheme_Object **argv) Vim_Prim *prim = (Vim_Prim *)data; char_u *name; long value; - char_u *strval; + char *strval; int rc; Scheme_Object *rval; int opt_flags = 0; @@ -1333,6 +1524,7 @@ get_option(void *data, int argc, Scheme_Object **argv) { MZ_REGISTER_STATIC(M_global); M_global = scheme_intern_symbol("global"); + MZ_GC_CHECK(); } if (argv[1] == M_global) @@ -1354,7 +1546,7 @@ get_option(void *data, int argc, Scheme_Object **argv) scheme_wrong_type(prim->name, "vim-buffer/window", 1, argc, argv); } - rc = get_option_value(name, &value, &strval, opt_flags); + rc = get_option_value(name, &value, (char_u **)&strval, opt_flags); curbuf = save_curb; curwin = save_curw; @@ -1364,6 +1556,7 @@ get_option(void *data, int argc, Scheme_Object **argv) return scheme_make_integer_value(value); case 0: rval = scheme_make_string(strval); + MZ_GC_CHECK(); vim_free(strval); return rval; case -1: @@ -1393,6 +1586,7 @@ set_option(void *data, int argc, Scheme_Object **argv) { MZ_REGISTER_STATIC(M_global); M_global = scheme_intern_symbol("global"); + MZ_GC_CHECK(); } if (argv[1] == M_global) @@ -1463,7 +1657,10 @@ get_window_list(void *data, int argc, Scheme_Object **argv) for (w = firstwin; w != NULL; w = w->w_next) if (w->w_buffer == buf->buf) + { list = scheme_make_pair(window_new(w), list); + MZ_GC_CHECK(); + } return list; } @@ -1471,7 +1668,11 @@ get_window_list(void *data, int argc, Scheme_Object **argv) static Scheme_Object * window_new(win_T *win) { - vim_mz_window *self; + vim_mz_window *self = NULL; + + MZ_GC_DECL_REG(1); + MZ_GC_VAR_IN_REG(0, self); + MZ_GC_REG(); /* We need to handle deletion of windows underneath us. * If we add a "w_mzscheme_ref" field to the win_T structure, @@ -1485,13 +1686,14 @@ window_new(win_T *win) return win->w_mzscheme_ref; self = scheme_malloc_fail_ok(scheme_malloc, sizeof(vim_mz_window)); - vim_memset(self, 0, sizeof(vim_mz_window)); scheme_dont_gc_ptr(self); /* because win isn't visible to GC */ + MZ_GC_CHECK(); win->w_mzscheme_ref = self; self->win = win; - self->tag = mz_window_type; + self->so.type = mz_window_type; + MZ_GC_UNREG(); return (Scheme_Object *)(self); } @@ -1660,7 +1862,6 @@ set_cursor(void *data, int argc, Scheme_Object **argv) /* *=========================================================================== * 6. Vim Buffer-related Manipulation Functions - * Note that each buffer should have its own private namespace. *=========================================================================== */ @@ -1669,14 +1870,14 @@ set_cursor(void *data, int argc, Scheme_Object **argv) mzscheme_open_buffer(void *data, int argc, Scheme_Object **argv) { Vim_Prim *prim = (Vim_Prim *)data; - char *fname; + char_u *fname; int num = 0; Scheme_Object *onum; #ifdef HAVE_SANDBOX sandbox_check(); #endif - fname = SCHEME_STR_VAL(GUARANTEE_STRING(prim->name, 0)); + fname = (char_u *)SCHEME_STR_VAL(GUARANTEE_STRING(prim->name, 0)); /* TODO make open existing file */ num = buflist_add(fname, BLN_LISTED | BLN_CURBUF); @@ -1712,7 +1913,7 @@ get_buffer_by_name(void *data, int argc, Scheme_Object **argv) buf_T *buf; char_u *fname; - fname = SCHEME_STR_VAL(GUARANTEE_STRING(prim->name, 0)); + fname = (char_u *)SCHEME_STR_VAL(GUARANTEE_STRING(prim->name, 0)); for (buf = firstbuf; buf; buf = buf->b_next) if (buf->b_ffname == NULL || buf->b_sfname == NULL) @@ -1783,7 +1984,7 @@ get_buffer_name(void *data, int argc, Scheme_Object **argv) Vim_Prim *prim = (Vim_Prim *)data; vim_mz_buffer *buf = get_buffer_arg(prim->name, 0, argc, argv); - return scheme_make_string(buf->buf->b_ffname); + return scheme_make_string((char *)buf->buf->b_ffname); } /* (curr-buff) */ @@ -1796,7 +1997,11 @@ get_curr_buffer(void *data, int argc, Scheme_Object **argv) static Scheme_Object * buffer_new(buf_T *buf) { - vim_mz_buffer *self; + vim_mz_buffer *self = NULL; + + MZ_GC_DECL_REG(1); + MZ_GC_VAR_IN_REG(0, self); + MZ_GC_REG(); /* We need to handle deletion of buffers underneath us. * If we add a "b_mzscheme_ref" field to the buf_T structure, @@ -1806,15 +2011,14 @@ buffer_new(buf_T *buf) return buf->b_mzscheme_ref; self = scheme_malloc_fail_ok(scheme_malloc, sizeof(vim_mz_buffer)); - vim_memset(self, 0, sizeof(vim_mz_buffer)); - scheme_dont_gc_ptr(self); /* because buf isn't visible to GC */ + scheme_dont_gc_ptr(self); /* because buf isn't visible to GC */ + MZ_GC_CHECK(); buf->b_mzscheme_ref = self; self->buf = buf; - self->tag = mz_buffer_type; - - mzscheme_interface_init(self); /* Set up namespace */ + self->so.type = mz_buffer_type; + MZ_GC_UNREG(); return (Scheme_Object *)(self); } @@ -1845,14 +2049,14 @@ get_buffer_line(void *data, int argc, Scheme_Object **argv) Vim_Prim *prim = (Vim_Prim *)data; vim_mz_buffer *buf; int linenr; - char *line; + char_u *line; buf = get_buffer_arg(prim->name, 1, argc, argv); linenr = SCHEME_INT_VAL(GUARANTEE_INTEGER(prim->name, 0)); line = ml_get_buf(buf->buf, (linenr_T)linenr, FALSE); raise_if_error(); - return scheme_make_string(line); + return scheme_make_string((char *)line); } @@ -1869,7 +2073,11 @@ get_buffer_line_list(void *data, int argc, Scheme_Object **argv) Vim_Prim *prim = (Vim_Prim *)data; vim_mz_buffer *buf; int i, hi, lo, n; - Scheme_Object *list; + Scheme_Object *list = NULL; + + MZ_GC_DECL_REG(1); + MZ_GC_VAR_IN_REG(0, list); + MZ_GC_REG(); buf = get_buffer_arg(prim->name, 2, argc, argv); list = scheme_null; @@ -1897,8 +2105,9 @@ get_buffer_line_list(void *data, int argc, Scheme_Object **argv) /* Set the list item */ list = scheme_make_pair(str, list); + MZ_GC_CHECK(); } - + MZ_GC_UNREG(); return list; } @@ -1925,11 +2134,14 @@ set_buffer_line(void *data, int argc, Scheme_Object **argv) */ Vim_Prim *prim = (Vim_Prim *)data; vim_mz_buffer *buf; - Scheme_Object *line; + Scheme_Object *line = NULL; char *save; - buf_T *savebuf; int n; + MZ_GC_DECL_REG(1); + MZ_GC_VAR_IN_REG(0, line); + MZ_GC_REG(); + #ifdef HAVE_SANDBOX sandbox_check(); #endif @@ -1943,7 +2155,8 @@ set_buffer_line(void *data, int argc, Scheme_Object **argv) if (SCHEME_FALSEP(line)) { - savebuf = curbuf; + buf_T *savebuf = curbuf; + curbuf = buf->buf; if (u_savedel((linenr_T)n, 1L) == FAIL) @@ -1962,33 +2175,56 @@ set_buffer_line(void *data, int argc, Scheme_Object **argv) curbuf = savebuf; + MZ_GC_UNREG(); raise_if_error(); return scheme_void; } + else + { + /* Otherwise it's a line */ + buf_T *savebuf = curbuf; - /* Otherwise it's a line */ - save = string_to_line(line); - savebuf = curbuf; + save = string_to_line(line); - curbuf = buf->buf; + curbuf = buf->buf; + + if (u_savesub((linenr_T)n) == FAIL) + { + curbuf = savebuf; + vim_free(save); + raise_vim_exn(_("cannot save undo information")); + } + else if (ml_replace((linenr_T)n, (char_u *)save, TRUE) == FAIL) + { + curbuf = savebuf; + vim_free(save); + raise_vim_exn(_("cannot replace line")); + } + else + { + vim_free(save); + changed_bytes((linenr_T)n, 0); + } - if (u_savesub((linenr_T)n) == FAIL) - { - curbuf = savebuf; - raise_vim_exn(_("cannot save undo information")); - } - else if (ml_replace((linenr_T)n, (char_u *)save, TRUE) == FAIL) - { curbuf = savebuf; - raise_vim_exn(_("cannot replace line")); - } - else - changed_bytes((linenr_T)n, 0); - curbuf = savebuf; + /* Check that the cursor is not beyond the end of the line now. */ + if (buf->buf == curwin->w_buffer) + check_cursor_col(); - raise_if_error(); - return scheme_void; + MZ_GC_UNREG(); + raise_if_error(); + return scheme_void; + } +} + + static void +free_array(char **array) +{ + char **curr = array; + while (*curr != NULL) + vim_free(*curr++); + vim_free(array); } /* @@ -2013,15 +2249,15 @@ set_buffer_line_list(void *data, int argc, Scheme_Object **argv) * 3. Anything else - this is an error. */ Vim_Prim *prim = (Vim_Prim *)data; - vim_mz_buffer *buf; - Scheme_Object *line_list; - Scheme_Object *line; - Scheme_Object *rest; - char **array; - buf_T *savebuf; + vim_mz_buffer *buf = NULL; + Scheme_Object *line_list = NULL; int i, old_len, new_len, hi, lo; long extra; + MZ_GC_DECL_REG(1); + MZ_GC_VAR_IN_REG(0, line_list); + MZ_GC_REG(); + #ifdef HAVE_SANDBOX sandbox_check(); #endif @@ -2047,7 +2283,7 @@ set_buffer_line_list(void *data, int argc, Scheme_Object **argv) if (SCHEME_FALSEP(line_list) || SCHEME_NULLP(line_list)) { - savebuf = curbuf; + buf_T *savebuf = curbuf; curbuf = buf->buf; if (u_savedel((linenr_T)lo, (long)old_len) == FAIL) @@ -2070,98 +2306,121 @@ set_buffer_line_list(void *data, int argc, Scheme_Object **argv) curbuf = savebuf; + MZ_GC_UNREG(); raise_if_error(); return scheme_void; } + else + { + buf_T *savebuf = curbuf; + + /* List */ + new_len = scheme_proper_list_length(line_list); + MZ_GC_CHECK(); + if (new_len < 0) /* improper or cyclic list */ + scheme_wrong_type(prim->name, "proper list", + 2, argc, argv); + else + { + char **array = NULL; + Scheme_Object *line = NULL; + Scheme_Object *rest = NULL; - /* List */ - new_len = scheme_proper_list_length(line_list); - if (new_len < 0) /* improper or cyclic list */ - scheme_wrong_type(prim->name, "proper list", - 2, argc, argv); + MZ_GC_DECL_REG(2); + MZ_GC_VAR_IN_REG(0, line); + MZ_GC_VAR_IN_REG(1, rest); + MZ_GC_REG(); - /* Using MzScheme allocator, so we don't need to free this and - * can safely keep pointers to GC collected strings - */ - array = (char **)scheme_malloc_fail_ok(scheme_malloc, - (unsigned)(new_len * sizeof(char *))); + array = (char **)alloc(new_len * sizeof(char *)); + vim_memset(array, 0, new_len * sizeof(char *)); - rest = line_list; - for (i = 0; i < new_len; ++i) - { - line = SCHEME_CAR(rest); - rest = SCHEME_CDR(rest); - if (!SCHEME_STRINGP(line)) - scheme_wrong_type(prim->name, "string-list", 2, argc, argv); - array[i] = string_to_line(line); - } + rest = line_list; + for (i = 0; i < new_len; ++i) + { + line = SCHEME_CAR(rest); + rest = SCHEME_CDR(rest); + if (!SCHEME_STRINGP(line)) + { + free_array(array); + scheme_wrong_type(prim->name, "string-list", 2, argc, argv); + } + array[i] = string_to_line(line); + } - savebuf = curbuf; - curbuf = buf->buf; + curbuf = buf->buf; - if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL) - { - curbuf = savebuf; - raise_vim_exn(_("cannot save undo information")); - } + if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL) + { + curbuf = savebuf; + free_array(array); + raise_vim_exn(_("cannot save undo information")); + } - /* - * If the size of the range is reducing (ie, new_len < old_len) we - * need to delete some old_len. We do this at the start, by - * repeatedly deleting line "lo". - */ - for (i = 0; i < old_len - new_len; ++i) - { - if (ml_delete((linenr_T)lo, FALSE) == FAIL) - { - curbuf = savebuf; - raise_vim_exn(_("cannot delete line")); - } - extra--; - } + /* + * If the size of the range is reducing (ie, new_len < old_len) we + * need to delete some old_len. We do this at the start, by + * repeatedly deleting line "lo". + */ + for (i = 0; i < old_len - new_len; ++i) + { + if (ml_delete((linenr_T)lo, FALSE) == FAIL) + { + curbuf = savebuf; + free_array(array); + raise_vim_exn(_("cannot delete line")); + } + extra--; + } - /* - * For as long as possible, replace the existing old_len with the - * new old_len. This is a more efficient operation, as it requires - * less memory allocation and freeing. - */ - for (i = 0; i < old_len && i < new_len; i++) - if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], TRUE) == FAIL) - { - curbuf = savebuf; - raise_vim_exn(_("cannot replace line")); - } + /* + * For as long as possible, replace the existing old_len with the + * new old_len. This is a more efficient operation, as it requires + * less memory allocation and freeing. + */ + for (i = 0; i < old_len && i < new_len; i++) + if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], TRUE) == FAIL) + { + curbuf = savebuf; + free_array(array); + raise_vim_exn(_("cannot replace line")); + } - /* - * Now we may need to insert the remaining new_len. We don't need to - * free the string passed back because MzScheme has control of that - * memory. - */ - while (i < new_len) - { - if (ml_append((linenr_T)(lo + i - 1), - (char_u *)array[i], 0, FALSE) == FAIL) - { - curbuf = savebuf; - raise_vim_exn(_("cannot insert line")); + /* + * Now we may need to insert the remaining new_len. We don't need to + * free the string passed back because MzScheme has control of that + * memory. + */ + while (i < new_len) + { + if (ml_append((linenr_T)(lo + i - 1), + (char_u *)array[i], 0, FALSE) == FAIL) + { + curbuf = savebuf; + free_array(array); + raise_vim_exn(_("cannot insert line")); + } + ++i; + ++extra; + } + MZ_GC_UNREG(); + free_array(array); } - ++i; - ++extra; - } - /* - * Adjust marks. Invalidate any which lie in the - * changed range, and move any in the remainder of the buffer. - */ - mark_adjust((linenr_T)lo, (linenr_T)(hi - 1), (long)MAXLNUM, (long)extra); - changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra); + /* + * Adjust marks. Invalidate any which lie in the + * changed range, and move any in the remainder of the buffer. + */ + mark_adjust((linenr_T)lo, (linenr_T)(hi - 1), (long)MAXLNUM, (long)extra); + changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra); - if (buf->buf == curwin->w_buffer) - mz_fix_cursor(lo, hi, extra); - curbuf = savebuf; + if (buf->buf == curwin->w_buffer) + mz_fix_cursor(lo, hi, extra); + curbuf = savebuf; - raise_if_error(); - return scheme_void; + MZ_GC_UNREG(); + raise_if_error(); + return scheme_void; + } } /* @@ -2179,15 +2438,15 @@ set_buffer_line_list(void *data, int argc, Scheme_Object **argv) insert_buffer_line_list(void *data, int argc, Scheme_Object **argv) { Vim_Prim *prim = (Vim_Prim *)data; - vim_mz_buffer *buf; - Scheme_Object *list; - Scheme_Object *line; - Scheme_Object *rest; - char **array; - char *str; - buf_T *savebuf; + vim_mz_buffer *buf = NULL; + Scheme_Object *list = NULL; + char *str = NULL; int i, n, size; + MZ_GC_DECL_REG(1); + MZ_GC_VAR_IN_REG(0, list); + MZ_GC_REG(); + #ifdef HAVE_SANDBOX sandbox_check(); #endif @@ -2206,89 +2465,99 @@ insert_buffer_line_list(void *data, int argc, Scheme_Object **argv) check_line_range(n, buf->buf); if (SCHEME_STRINGP(list)) { - str = string_to_line(list); + buf_T *savebuf = curbuf; - savebuf = curbuf; + str = string_to_line(list); curbuf = buf->buf; if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL) { curbuf = savebuf; + vim_free(str); raise_vim_exn(_("cannot save undo information")); } else if (ml_append((linenr_T)n, (char_u *)str, 0, FALSE) == FAIL) { curbuf = savebuf; + vim_free(str); raise_vim_exn(_("cannot insert line")); } else + { + vim_free(str); appended_lines_mark((linenr_T)n, 1L); + } curbuf = savebuf; update_screen(VALID); + MZ_GC_UNREG(); raise_if_error(); return scheme_void; } /* List */ size = scheme_proper_list_length(list); + MZ_GC_CHECK(); if (size < 0) /* improper or cyclic list */ scheme_wrong_type(prim->name, "proper list", 2, argc, argv); - - /* Using MzScheme allocator, so we don't need to free this and - * can safely keep pointers to GC collected strings - */ - array = (char **)scheme_malloc_fail_ok( - scheme_malloc, (unsigned)(size * sizeof(char *))); - - rest = list; - for (i = 0; i < size; ++i) + else { - line = SCHEME_CAR(rest); - rest = SCHEME_CDR(rest); - array[i] = string_to_line(line); - } + Scheme_Object *line = NULL; + Scheme_Object *rest = NULL; + char **array; + buf_T *savebuf = curbuf; - savebuf = curbuf; - curbuf = buf->buf; + MZ_GC_DECL_REG(2); + MZ_GC_VAR_IN_REG(0, line); + MZ_GC_VAR_IN_REG(1, rest); + MZ_GC_REG(); - if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL) - { - curbuf = savebuf; - raise_vim_exn(_("cannot save undo information")); - } - else - { + array = (char **)alloc(size * sizeof(char *)); + vim_memset(array, 0, size * sizeof(char *)); + + rest = list; for (i = 0; i < size; ++i) - if (ml_append((linenr_T)(n + i), (char_u *)array[i], - 0, FALSE) == FAIL) - { - curbuf = savebuf; - raise_vim_exn(_("cannot insert line")); - } + { + line = SCHEME_CAR(rest); + rest = SCHEME_CDR(rest); + array[i] = string_to_line(line); + } - if (i > 0) - appended_lines_mark((linenr_T)n, (long)i); - } + curbuf = buf->buf; - curbuf = savebuf; - update_screen(VALID); + if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL) + { + curbuf = savebuf; + free_array(array); + raise_vim_exn(_("cannot save undo information")); + } + else + { + for (i = 0; i < size; ++i) + if (ml_append((linenr_T)(n + i), (char_u *)array[i], + 0, FALSE) == FAIL) + { + curbuf = savebuf; + free_array(array); + raise_vim_exn(_("cannot insert line")); + } + if (i > 0) + appended_lines_mark((linenr_T)n, (long)i); + } + free_array(array); + MZ_GC_UNREG(); + curbuf = savebuf; + update_screen(VALID); + } + + MZ_GC_UNREG(); raise_if_error(); return scheme_void; } -/* (get-buff-namespace [buffer]) */ - static Scheme_Object * -get_buffer_namespace(void *data, int argc, Scheme_Object **argv) -{ - Vim_Prim *prim = (Vim_Prim *)data; - - return (Scheme_Object *)get_buffer_arg(prim->name, 0, argc, argv)->env; -} - /* * Predicates */ @@ -2343,40 +2612,172 @@ vim_window_validp(void *data, int argc, Scheme_Object **argv) /* * Convert an MzScheme string into a Vim line. * - * The result is in allocated memory. All internal nulls are replaced by - * newline characters. It is an error for the string to contain newline - * characters. + * All internal nulls are replaced by newline characters. + * It is an error for the string to contain newline characters. * + * Returns pointer to Vim allocated memory */ static char * string_to_line(Scheme_Object *obj) { - char *str; + char *scheme_str = NULL; + char *vim_str = NULL; long len; int i; - str = scheme_display_to_string(obj, &len); + scheme_str = scheme_display_to_string(obj, &len); /* Error checking: String must not contain newlines, as we * are replacing a single line, and we must replace it with * a single line. */ - if (memchr(str, '\n', len)) + if (memchr(scheme_str, '\n', len)) scheme_signal_error(_("string cannot contain newlines")); + vim_str = (char *)alloc(len + 1); + /* Create a copy of the string, with internal nulls replaced by * newline characters, as is the vim convention. */ for (i = 0; i < len; ++i) { - if (str[i] == '\0') - str[i] = '\n'; + if (scheme_str[i] == '\0') + vim_str[i] = '\n'; + else + vim_str[i] = scheme_str[i]; + } + + vim_str[i] = '\0'; + + MZ_GC_CHECK(); + return vim_str; +} + +#ifdef FEAT_EVAL +/* + * Convert Vim value into MzScheme, adopted from if_python.c + */ + static Scheme_Object * +vim_to_mzscheme(typval_T *vim_value, int depth, Scheme_Hash_Table *visited) +{ + Scheme_Object *result = NULL; + int new_value = TRUE; + + MZ_GC_DECL_REG(1); + MZ_GC_VAR_IN_REG(0, result); + MZ_GC_REG(); + + /* Avoid infinite recursion */ + if (depth > 100) + { + MZ_GC_UNREG(); + return scheme_void; + } + + /* Check if we run into a recursive loop. The item must be in visited + * then and we can use it again. + */ + result = scheme_hash_get(visited, (Scheme_Object *)vim_value); + MZ_GC_CHECK(); + if (result != NULL) /* found, do nothing */ + new_value = FALSE; + else if (vim_value->v_type == VAR_STRING) + { + result = scheme_make_string((char *)vim_value->vval.v_string); + MZ_GC_CHECK(); + } + else if (vim_value->v_type == VAR_NUMBER) + { + result = scheme_make_integer((long)vim_value->vval.v_number); + MZ_GC_CHECK(); + } +# ifdef FEAT_FLOAT + else if (vim_value->v_type == VAR_FLOAT) + { + result = scheme_make_double((double)vim_value->vval.v_float); + MZ_GC_CHECK(); + } +# endif + else if (vim_value->v_type == VAR_LIST) + { + list_T *list = vim_value->vval.v_list; + listitem_T *curr; + + if (list == NULL || list->lv_first == NULL) + result = scheme_null; + else + { + Scheme_Object *obj = NULL; + + MZ_GC_DECL_REG(1); + MZ_GC_VAR_IN_REG(0, obj); + MZ_GC_REG(); + + curr = list->lv_last; + obj = vim_to_mzscheme(&curr->li_tv, depth + 1, visited); + result = scheme_make_pair(obj, scheme_null); + MZ_GC_CHECK(); + + while (curr != list->lv_first) + { + curr = curr->li_prev; + obj = vim_to_mzscheme(&curr->li_tv, depth + 1, visited); + result = scheme_make_pair(obj, result); + MZ_GC_CHECK(); + } + } + MZ_GC_UNREG(); } + else if (vim_value->v_type == VAR_DICT) + { + Scheme_Object *key = NULL; + Scheme_Object *obj = NULL; - str[i] = '\0'; + MZ_GC_DECL_REG(2); + MZ_GC_VAR_IN_REG(0, key); + MZ_GC_VAR_IN_REG(1, obj); + MZ_GC_REG(); - return str; + result = (Scheme_Object *)scheme_make_hash_table(SCHEME_hash_ptr); + MZ_GC_CHECK(); + if (vim_value->vval.v_dict != NULL) + { + hashtab_T *ht = &vim_value->vval.v_dict->dv_hashtab; + long_u todo = ht->ht_used; + hashitem_T *hi; + dictitem_T *di; + + for (hi = ht->ht_array; todo > 0; ++hi) + { + if (!HASHITEM_EMPTY(hi)) + { + --todo; + + di = dict_lookup(hi); + obj = vim_to_mzscheme(&di->di_tv, depth + 1, visited); + key = scheme_make_string((char *)hi->hi_key); + MZ_GC_CHECK(); + scheme_hash_set((Scheme_Hash_Table *)result, key, obj); + MZ_GC_CHECK(); + } + } + } + MZ_GC_UNREG(); + } + else + { + result = scheme_void; + new_value = FALSE; + } + if (new_value) + { + scheme_hash_set(visited, (Scheme_Object *)vim_value, result); + MZ_GC_CHECK(); + } + MZ_GC_UNREG(); + return result; } +#endif /* * Check to see whether a Vim error has been reported, or a keyboard @@ -2392,50 +2793,59 @@ vim_error_check(void) * register Scheme exn:vim */ static void -register_vim_exn(Scheme_Env *env) +register_vim_exn(void) { - Scheme_Object *exn_name = scheme_intern_symbol("exn:vim"); + int nc = 0; + int i; + Scheme_Object *struct_exn = NULL; + Scheme_Object *exn_name = NULL; + + MZ_GC_DECL_REG(2); + MZ_GC_VAR_IN_REG(0, struct_exn); + MZ_GC_VAR_IN_REG(1, exn_name); + MZ_GC_REG(); + + exn_name = scheme_intern_symbol("exn:vim"); + MZ_GC_CHECK(); + struct_exn = scheme_builtin_value("struct:exn"); + MZ_GC_CHECK(); if (vim_exn == NULL) vim_exn = scheme_make_struct_type(exn_name, - scheme_builtin_value("struct:exn"), NULL, 0, 0, NULL, NULL + struct_exn, NULL, 0, 0, NULL, NULL #if MZSCHEME_VERSION_MAJOR >= 299 , NULL #endif ); - if (vim_exn_values == NULL) + { - int nc = 0; - - Scheme_Object **exn_names = scheme_make_struct_names( - exn_name, scheme_null, 0, &nc); - Scheme_Object **exn_values = scheme_make_struct_values( - vim_exn, exn_names, nc, 0); - - vim_exn_names = scheme_make_vector(nc, scheme_false); - vim_exn_values = scheme_make_vector(nc, scheme_false); - /* remember names and values */ - mch_memmove(SCHEME_VEC_ELS(vim_exn_names), exn_names, - nc * sizeof(Scheme_Object *)); - mch_memmove(SCHEME_VEC_ELS(vim_exn_values), exn_values, - nc * sizeof(Scheme_Object *)); + Scheme_Object **tmp = NULL; + Scheme_Object *exn_names[5] = {NULL, NULL, NULL, NULL, NULL}; + Scheme_Object *exn_values[5] = {NULL, NULL, NULL, NULL, NULL}; + MZ_GC_DECL_REG(6); + MZ_GC_ARRAY_VAR_IN_REG(0, exn_names, 5); + MZ_GC_ARRAY_VAR_IN_REG(3, exn_values, 5); + MZ_GC_REG(); + + tmp = scheme_make_struct_names(exn_name, scheme_null, 0, &nc); + assert(nc <= 5); + mch_memmove(exn_names, tmp, nc * sizeof(Scheme_Object *)); + MZ_GC_CHECK(); + + tmp = scheme_make_struct_values(vim_exn, exn_names, nc, 0); + mch_memmove(exn_values, tmp, nc * sizeof(Scheme_Object *)); + MZ_GC_CHECK(); + + for (i = 0; i < nc; i++) + { + scheme_add_global_symbol(exn_names[i], + exn_values[i], environment); + MZ_GC_CHECK(); + } + MZ_GC_UNREG(); } - - add_vim_exn(env); -} - -/* - * Add stuff of exn:vim to env - */ - static void -add_vim_exn(Scheme_Env *env) -{ - int i; - - for (i = 0; i < SCHEME_VEC_SIZE(vim_exn_values); i++) - scheme_add_global_symbol(SCHEME_VEC_ELS(vim_exn_names)[i], - SCHEME_VEC_ELS(vim_exn_values)[i], env); + MZ_GC_UNREG(); } /* @@ -2444,26 +2854,54 @@ add_vim_exn(Scheme_Env *env) void raise_vim_exn(const char *add_info) { - Scheme_Object *argv[2]; - char_u *fmt = _("Vim error: ~a"); + char *fmt = _("Vim error: ~a"); + Scheme_Object *argv[2] = {NULL, NULL}; + Scheme_Object *exn = NULL; + + MZ_GC_DECL_REG(4); + MZ_GC_ARRAY_VAR_IN_REG(0, argv, 2); + MZ_GC_VAR_IN_REG(3, exn); + MZ_GC_REG(); if (add_info != NULL) { - Scheme_Object *info = scheme_make_string(add_info); - argv[0] = scheme_byte_string_to_char_string(scheme_make_string( - scheme_format(fmt, strlen(fmt), 1, &info, NULL))); + char *c_string = NULL; + Scheme_Object *byte_string = NULL; + Scheme_Object *info = NULL; + + MZ_GC_DECL_REG(3); + MZ_GC_VAR_IN_REG(0, c_string); + MZ_GC_VAR_IN_REG(1, byte_string); + MZ_GC_VAR_IN_REG(2, info); + MZ_GC_REG(); + + info = scheme_make_string(add_info); + MZ_GC_CHECK(); + c_string = scheme_format(fmt, STRLEN(fmt), 1, &info, NULL); + MZ_GC_CHECK(); + byte_string = scheme_make_string(c_string); + MZ_GC_CHECK(); + argv[0] = scheme_byte_string_to_char_string(byte_string); + MZ_GC_CHECK(); SCHEME_SET_IMMUTABLE(argv[0]); + MZ_GC_UNREG(); } else argv[0] = scheme_make_string(_("Vim error")); + MZ_GC_CHECK(); #if MZSCHEME_VERSION_MAJOR < 360 argv[1] = scheme_current_continuation_marks(); + MZ_GC_CHECK(); #else argv[1] = scheme_current_continuation_marks(NULL); + MZ_GC_CHECK(); #endif - scheme_raise(scheme_make_struct_instance(vim_exn, 2, argv)); + exn = scheme_make_struct_instance(vim_exn, 2, argv); + MZ_GC_CHECK(); + scheme_raise(exn); + MZ_GC_UNREG(); } void @@ -2570,6 +3008,8 @@ mz_fix_cursor(int lo, int hi, int extra) curwin->w_cursor.lnum = lo; check_cursor(); } + else + check_cursor_col(); changed_cline_bef_curs(); } invalidate_botline(); @@ -2595,7 +3035,6 @@ static Vim_Prim prims[]= {mzscheme_open_buffer, "open-buff", 1, 1}, {get_buffer_by_name, "get-buff-by-name", 1, 1}, {get_buffer_by_num, "get-buff-by-num", 1, 1}, - {get_buffer_namespace, "get-buff-namespace", 0, 1}, /* * Window-related commands */ @@ -2653,23 +3092,35 @@ get_vim_curr_window(void) } static void -make_modules(Scheme_Env *env) -{ - int i; - Scheme_Env *mod; - - mod = scheme_primitive_module(scheme_intern_symbol("vimext"), env); +make_modules() +{ + int i; + Scheme_Env *mod = NULL; + Scheme_Object *vimext_symbol = NULL; + Scheme_Object *closed_prim = NULL; + + MZ_GC_DECL_REG(3); + MZ_GC_VAR_IN_REG(0, mod); + MZ_GC_VAR_IN_REG(1, vimext_symbol); + MZ_GC_VAR_IN_REG(2, closed_prim); + MZ_GC_REG(); + + vimext_symbol = scheme_intern_symbol("vimext"); + MZ_GC_CHECK(); + mod = scheme_primitive_module(vimext_symbol, environment); + MZ_GC_CHECK(); /* all prims made closed so they can access their own names */ - for (i = 0; i < sizeof(prims)/sizeof(prims[0]); i++) + for (i = 0; i < (int)(sizeof(prims)/sizeof(prims[0])); i++) { Vim_Prim *prim = prims + i; - scheme_add_global(prim->name, - scheme_make_closed_prim_w_arity(prim->prim, prim, prim->name, - prim->mina, prim->maxa), - mod); + closed_prim = scheme_make_closed_prim_w_arity(prim->prim, prim, prim->name, + prim->mina, prim->maxa); + scheme_add_global(prim->name, closed_prim, mod); + MZ_GC_CHECK(); } - scheme_add_global("global-namespace", (Scheme_Object *)environment, mod); scheme_finish_primitive_module(mod); + MZ_GC_CHECK(); + MZ_GC_UNREG(); } #ifdef HAVE_SANDBOX @@ -2697,21 +3148,25 @@ sandbox_file_guard(int argc, Scheme_Object **argv) { MZ_REGISTER_STATIC(M_write); M_write = scheme_intern_symbol("write"); + MZ_GC_CHECK(); } if (M_read == NULL) { MZ_REGISTER_STATIC(M_read); M_read = scheme_intern_symbol("read"); + MZ_GC_CHECK(); } if (M_execute == NULL) { MZ_REGISTER_STATIC(M_execute); M_execute = scheme_intern_symbol("execute"); + MZ_GC_CHECK(); } if (M_delete == NULL) { MZ_REGISTER_STATIC(M_delete); M_delete = scheme_intern_symbol("delete"); + MZ_GC_CHECK(); } while (!SCHEME_NULLP(requested_access)) diff --git a/src/if_mzsch.h b/src/if_mzsch.h index b745cce9e..45888919b 100644 --- a/src/if_mzsch.h +++ b/src/if_mzsch.h @@ -11,6 +11,7 @@ /* #ifdef needed for "make depend" */ #ifdef FEAT_MZSCHEME +# include <schvers.h> # include <scheme.h> #endif @@ -46,4 +47,31 @@ # define scheme_byte_string_to_char_string(obj) (obj) #endif +/* Precise GC macros */ +#ifndef MZ_GC_DECL_REG +# define MZ_GC_DECL_REG(size) /* empty */ +#endif +#ifndef MZ_GC_VAR_IN_REG +# define MZ_GC_VAR_IN_REG(x, v) /* empty */ +#endif +#ifndef MZ_GC_ARRAY_VAR_IN_REG +# define MZ_GC_ARRAY_VAR_IN_REG(x, v, l) /* empty */ +#endif +#ifndef MZ_GC_REG +# define MZ_GC_REG() /* empty */ +#endif +#ifndef MZ_GC_UNREG +# define MZ_GC_UNREG() /* empty */ +#endif + +#ifdef MZSCHEME_FORCE_GC +/* + * force garbage collection to check all references are registered + * seg faults will indicate not registered refs + */ +# define MZ_GC_CHECK() scheme_collect_garbage(); +#else +# define MZ_GC_CHECK() /* empty */ +#endif + #endif /* _IF_MZSCH_H_ */ diff --git a/src/main.c b/src/main.c index c0dd12142..84aa146e7 100644 --- a/src/main.c +++ b/src/main.c @@ -935,8 +935,14 @@ main /* * Call the main command loop. This never returns. + * For embedded MzScheme the main_loop will be called by Scheme + * for proper stack tracking */ +#ifndef FEAT_MZSCHEME main_loop(FALSE, FALSE); +#else + mzscheme_main(); +#endif return 0; } diff --git a/src/proto/if_mzsch.pro b/src/proto/if_mzsch.pro index 522ac9423..f61a087d6 100644 --- a/src/proto/if_mzsch.pro +++ b/src/proto/if_mzsch.pro @@ -15,10 +15,6 @@ void mzvim_reset_timer __ARGS((void)); void *mzvim_eval_string __ARGS((char_u *str)); struct Scheme_Object *mzvim_apply __ARGS((struct Scheme_Object *, int argc, struct Scheme_Object **)); -int mzthreads_allowed (void); -#ifdef FEAT_GUI_KDE -void timer_proc (void); -void mzscheme_kde_start_timer (void); -void mzscheme_kde_stop_timer (void); -#endif +int mzthreads_allowed __ARGS((void)); +void mzscheme_main __ARGS((void)); /* vim: set ft=c : */ diff --git a/src/version.c b/src/version.c index 7282b6b57..52e08a9c7 100644 --- a/src/version.c +++ b/src/version.c @@ -677,6 +677,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 191, +/**/ 190, /**/ 189, |