| To: vim-dev@vim.org |
| Subject: patch 7.1.120 |
| Fcc: outbox |
| From: Bram Moolenaar <Bram@moolenaar.net> |
| Mime-Version: 1.0 |
| Content-Type: text/plain; charset=ISO-8859-1 |
| Content-Transfer-Encoding: 8bit |
| |
| |
| Patch 7.1.120 |
| Problem: Can't properly check memory leaks while running tests. |
| Solution: Add an argument to garbagecollect(). Delete functions and |
| variables in the test scripts. |
| Files: runtime/doc/eval.txt, src/eval.c, src/globals.h, src/main.c, |
| src/testdir/Makefile, src/testdir/test14.in, |
| src/testdir/test26.in, src/testdir/test34.in, |
| src/testdir/test45.in, src/testdir/test47.in, |
| src/testdir/test49.in, src/testdir/test55.in, |
| src/testdir/test56.in, src/testdir/test58.in, |
| src/testdir/test59.in, src/testdir/test60.in, |
| src/testdir/test60.vim, src/testdir/test62.in, |
| src/testdir/test63.in, src/testdir/test64.in |
| |
| |
| |
| |
| |
| *** 1,4 **** |
| ! *eval.txt* For Vim version 7.1. Last change: 2007 Jul 25 |
| |
| |
| VIM REFERENCE MANUAL by Bram Moolenaar |
| --- 1,4 ---- |
| ! *eval.txt* For Vim version 7.1. Last change: 2007 Sep 25 |
| |
| |
| VIM REFERENCE MANUAL by Bram Moolenaar |
| |
| *** 1603,1609 **** |
| foldtextresult( {lnum}) String text for closed fold at {lnum} |
| foreground( ) Number bring the Vim window to the foreground |
| function( {name}) Funcref reference to function {name} |
| ! garbagecollect() none free memory, breaking cyclic references |
| get( {list}, {idx} [, {def}]) any get item {idx} from {list} or {def} |
| get( {dict}, {key} [, {def}]) any get item {key} from {dict} or {def} |
| getbufline( {expr}, {lnum} [, {end}]) |
| --- 1603,1609 ---- |
| foldtextresult( {lnum}) String text for closed fold at {lnum} |
| foreground( ) Number bring the Vim window to the foreground |
| function( {name}) Funcref reference to function {name} |
| ! garbagecollect( [at_exit]) none free memory, breaking cyclic references |
| get( {list}, {idx} [, {def}]) any get item {idx} from {list} or {def} |
| get( {dict}, {key} [, {def}]) any get item {key} from {dict} or {def} |
| getbufline( {expr}, {lnum} [, {end}]) |
| |
| *** 2673,2679 **** |
| {name} can be a user defined function or an internal function. |
| |
| |
| ! garbagecollect() *garbagecollect()* |
| Cleanup unused |Lists| and |Dictionaries| that have circular |
| references. There is hardly ever a need to invoke this |
| function, as it is automatically done when Vim runs out of |
| --- 2673,2679 ---- |
| {name} can be a user defined function or an internal function. |
| |
| |
| ! garbagecollect([at_exit]) *garbagecollect()* |
| Cleanup unused |Lists| and |Dictionaries| that have circular |
| references. There is hardly ever a need to invoke this |
| function, as it is automatically done when Vim runs out of |
| |
| *** 2683,2688 **** |
| --- 2683,2691 ---- |
| This is useful if you have deleted a very big |List| and/or |
| |Dictionary| with circular references in a script that runs |
| for a long time. |
| + When the optional "at_exit" argument is one, garbage |
| + collection will also be done when exiting Vim, if it wasn't |
| + done before. This is useful when checking for memory leaks. |
| |
| get({list}, {idx} [, {default}]) *get()* |
| Get item {idx} from |List| {list}. When this item is not |
| |
| |
| |
| *** 6128,6133 **** |
| --- 6128,6134 ---- |
| /* Only do this once. */ |
| want_garbage_collect = FALSE; |
| may_garbage_collect = FALSE; |
| + garbage_collect_at_exit = FALSE; |
| |
| /* |
| * 1. Go through all accessible variables and mark all lists and dicts |
| |
| *** 7110,7116 **** |
| {"foldtextresult", 1, 1, f_foldtextresult}, |
| {"foreground", 0, 0, f_foreground}, |
| {"function", 1, 1, f_function}, |
| ! {"garbagecollect", 0, 0, f_garbagecollect}, |
| {"get", 2, 3, f_get}, |
| {"getbufline", 2, 3, f_getbufline}, |
| {"getbufvar", 2, 2, f_getbufvar}, |
| --- 7111,7117 ---- |
| {"foldtextresult", 1, 1, f_foldtextresult}, |
| {"foreground", 0, 0, f_foreground}, |
| {"function", 1, 1, f_function}, |
| ! {"garbagecollect", 0, 1, f_garbagecollect}, |
| {"get", 2, 3, f_get}, |
| {"getbufline", 2, 3, f_getbufline}, |
| {"getbufvar", 2, 2, f_getbufvar}, |
| |
| *** 9719,9724 **** |
| --- 9720,9728 ---- |
| /* This is postponed until we are back at the toplevel, because we may be |
| * using Lists and Dicts internally. E.g.: ":echo [garbagecollect()]". */ |
| want_garbage_collect = TRUE; |
| + |
| + if (argvars[0].v_type != VAR_UNKNOWN && get_tv_number(&argvars[0]) == 1) |
| + garbage_collect_at_exit = TRUE; |
| } |
| |
| /* |
| |
| |
| |
| *** 301,313 **** |
| #endif |
| |
| #ifdef FEAT_EVAL |
| ! /* Garbage collection can only take place when we are sure there are no Lists |
| * or Dictionaries being used internally. This is flagged with |
| * "may_garbage_collect" when we are at the toplevel. |
| * "want_garbage_collect" is set by the garbagecollect() function, which means |
| ! * we do garbage collection before waiting for a char at the toplevel. */ |
| EXTERN int may_garbage_collect INIT(= FALSE); |
| EXTERN int want_garbage_collect INIT(= FALSE); |
| |
| /* ID of script being sourced or was sourced to define the current function. */ |
| EXTERN scid_T current_SID INIT(= 0); |
| --- 301,317 ---- |
| #endif |
| |
| #ifdef FEAT_EVAL |
| ! /* |
| ! * Garbage collection can only take place when we are sure there are no Lists |
| * or Dictionaries being used internally. This is flagged with |
| * "may_garbage_collect" when we are at the toplevel. |
| * "want_garbage_collect" is set by the garbagecollect() function, which means |
| ! * we do garbage collection before waiting for a char at the toplevel. |
| ! * "garbage_collect_at_exit" indicates garbagecollect(1) was called. |
| ! */ |
| EXTERN int may_garbage_collect INIT(= FALSE); |
| EXTERN int want_garbage_collect INIT(= FALSE); |
| + EXTERN int garbage_collect_at_exit INIT(= FALSE); |
| |
| /* ID of script being sourced or was sourced to define the current function. */ |
| EXTERN scid_T current_SID INIT(= 0); |
| |
| |
| |
| *** 1334,1339 **** |
| --- 1334,1343 ---- |
| #ifdef FEAT_CSCOPE |
| cs_end(); |
| #endif |
| + #ifdef FEAT_EVAL |
| + if (garbage_collect_at_exit) |
| + garbage_collect(); |
| + #endif |
| |
| mch_exit(exitval); |
| } |
| |
| |
| |
| *** 6,12 **** |
| |
| # Uncomment this line for using valgrind. |
| # The output goes into a file "valgrind.$PID" (sorry, no test number). |
| ! # VALGRIND = valgrind --tool=memcheck --num-callers=15 --logfile=valgrind |
| |
| SCRIPTS = test1.out test2.out test3.out test4.out test5.out test6.out \ |
| test7.out test8.out test9.out test10.out test11.out \ |
| --- 6,12 ---- |
| |
| # Uncomment this line for using valgrind. |
| # The output goes into a file "valgrind.$PID" (sorry, no test number). |
| ! # VALGRIND = valgrind --tool=memcheck --leak-check=yes --num-callers=15 --logfile=valgrind |
| |
| SCRIPTS = test1.out test2.out test3.out test4.out test5.out test6.out \ |
| test7.out test8.out test9.out test10.out test11.out \ |
| |
| *** 39,45 **** |
| $(SCRIPTS) $(SCRIPTS_GUI): $(VIMPROG) |
| |
| clean: |
| ! -rm -rf *.out *.failed *.rej *.orig test.log tiny.vim small.vim mbyte.vim test.ok X* viminfo |
| |
| test1.out: test1.in |
| -rm -f $*.failed tiny.vim small.vim mbyte.vim test.ok X* viminfo |
| --- 39,45 ---- |
| $(SCRIPTS) $(SCRIPTS_GUI): $(VIMPROG) |
| |
| clean: |
| ! -rm -rf *.out *.failed *.rej *.orig test.log tiny.vim small.vim mbyte.vim test.ok X* valgrind.pid* viminfo |
| |
| test1.out: test1.in |
| -rm -f $*.failed tiny.vim small.vim mbyte.vim test.ok X* viminfo |
| |
| *** 65,70 **** |
| --- 65,74 ---- |
| else echo $* NO OUTPUT >>test.log; \ |
| fi" |
| -rm -rf X* test.ok viminfo |
| + |
| + test49.out: test49.vim |
| + |
| + test60.out: test60.vim |
| |
| nolog: |
| -echo Test results: >test.log |
| |
| |
| |
| *** 18,23 **** |
| --- 18,24 ---- |
| : let tt = "o\<C-V>65\<C-V>x42\<C-V>o103 \<C-V>33a\<C-V>xfg\<C-V>o78\<Esc>" |
| :endif |
| :exe "normal " . tt |
| + :unlet tt |
| :.w >>test.out |
| :set vb |
| /^Piece |
| |
| |
| |
| *** 37,42 **** |
| --- 37,43 ---- |
| : endif |
| : endif |
| :endwhile |
| + :unlet i j |
| :'t,$w! test.out |
| :qa! |
| ENDTEST |
| |
| |
| |
| *** 52,58 **** |
| ---*--- |
| (one |
| (two |
| ! [(one again:$-5,$wq! test.out |
| ENDTEST |
| |
| here |
| --- 52,66 ---- |
| ---*--- |
| (one |
| (two |
| ! [(one again:$-5,$w! test.out |
| ! :delfunc Table |
| ! :delfunc Compute |
| ! :delfunc Expr1 |
| ! :delfunc Expr2 |
| ! :delfunc ListItem |
| ! :delfunc ListReset |
| ! :unlet retval counter |
| ! :q! |
| ENDTEST |
| |
| here |
| |
| |
| |
| *** 55,60 **** |
| --- 55,61 ---- |
| /kk$ |
| :call append("$", foldlevel(".")) |
| :/^last/+1,$w! test.out |
| + :delfun Flvl |
| :qa! |
| ENDTEST |
| |
| |
| |
| |
| *** 34,39 **** |
| --- 34,40 ---- |
| :call append("$", two) |
| :call append("$", three) |
| :$-2,$w! test.out |
| + :unlet one two three |
| :qa! |
| ENDTEST |
| |
| |
| |
| |
| *** 1,13 **** |
| This is a test of the script language. |
| |
| If after adding a new test, the test output doesn't appear properly in |
| ! test49.failed, try to add one ore more "G"s at the line before ENDTEST. |
| |
| STARTTEST |
| :so small.vim |
| :se nocp nomore viminfo+=nviminfo |
| :so test49.vim |
| ! GGGGGGGGGG"rp:.-,$wq! test.out |
| ENDTEST |
| |
| Results of test49.vim: |
| --- 1,29 ---- |
| This is a test of the script language. |
| |
| If after adding a new test, the test output doesn't appear properly in |
| ! test49.failed, try to add one ore more "G"s at the line ending in "test.out" |
| |
| STARTTEST |
| :so small.vim |
| :se nocp nomore viminfo+=nviminfo |
| :so test49.vim |
| ! GGGGGGGGGGGGGG"rp:.-,$w! test.out |
| ! :" |
| ! :" make valgrind happy |
| ! :redir => funclist |
| ! :silent func |
| ! :redir END |
| ! :for line in split(funclist, "\n") |
| ! : let name = matchstr(line, 'function \zs[A-Z]\w*\ze(') |
| ! : if name != '' |
| ! : exe "delfunc " . name |
| ! : endif |
| ! :endfor |
| ! :for v in keys(g:) |
| ! : silent! exe "unlet " . v |
| ! :endfor |
| ! :unlet v |
| ! :qa! |
| ENDTEST |
| |
| Results of test49.vim: |
| |
| |
| |
| *** 345,350 **** |
| --- 345,354 ---- |
| :endfun |
| :call Test(1, 2, [3, 4], {5: 6}) " This may take a while |
| :" |
| + :delfunc Test |
| + :unlet dict |
| + :call garbagecollect(1) |
| + :" |
| :/^start:/,$wq! test.out |
| ENDTEST |
| |
| |
| |
| |
| *** 17,21 **** |
| fun s:DoNothing() |
| call append(line('$'), "nothing line") |
| endfun |
| ! nnoremap <buffer> _x :call <SID>DoNothing()<bar>call <SID>DoLast()<cr> |
| end: |
| --- 17,21 ---- |
| fun s:DoNothing() |
| call append(line('$'), "nothing line") |
| endfun |
| ! nnoremap <buffer> _x :call <SID>DoNothing()<bar>call <SID>DoLast()<bar>delfunc <SID>DoNothing<bar>delfunc <SID>DoLast<cr> |
| end: |
| |
| |
| |
| *** 86,91 **** |
| --- 86,92 ---- |
| :$put =str |
| `m]s:let [str, a] = spellbadword() |
| :$put =str |
| + :unlet str a |
| :" |
| :" Postponed prefixes |
| :call TestOne('2', '1') |
| |
| *** 99,104 **** |
| --- 100,109 ---- |
| :" |
| :" NOSLITSUGS |
| :call TestOne('8', '8') |
| + :" |
| + :" clean up for valgrind |
| + :delfunc TestOne |
| + :set spl= enc=latin1 |
| :" |
| gg:/^test output:/,$wq! test.out |
| ENDTEST |
| |
| |
| |
| *** 90,95 **** |
| --- 90,96 ---- |
| :$put =str |
| `m]s:let [str, a] = spellbadword() |
| :$put =str |
| + :unlet str a |
| :" |
| :" Postponed prefixes |
| :call TestOne('2', '1') |
| |
| *** 100,105 **** |
| --- 101,110 ---- |
| :call TestOne('5', '5') |
| :call TestOne('6', '6') |
| :call TestOne('7', '7') |
| + :" |
| + :" clean up for valgrind |
| + :delfunc TestOne |
| + :set spl= enc=latin1 |
| :" |
| gg:/^test output:/,$wq! test.out |
| ENDTEST |
| |
| |
| |
| *** 569,574 **** |
| --- 569,577 ---- |
| redir END |
| endfunction |
| :call TestExists() |
| + :delfunc TestExists |
| + :delfunc RunTest |
| + :delfunc TestFuncArg |
| :edit! test.out |
| :set ff=unix |
| :w |
| |
| |
| |
| *** 94,97 **** |
| --- 94,98 ---- |
| else |
| echo "FAILED" |
| endif |
| + unlet str |
| |
| |
| |
| |
| *** 7,12 **** |
| --- 7,13 ---- |
| :let nr = tabpagenr() |
| :q |
| :call append(line('$'), 'tab page ' . nr) |
| + :unlet nr |
| :" |
| :" Open three tab pages and use ":tabdo" |
| :0tabnew |
| |
| *** 23,28 **** |
| --- 24,30 ---- |
| :q! |
| :call append(line('$'), line1) |
| :call append(line('$'), line2) |
| + :unlet line1 line2 |
| :" |
| :" |
| :/^Results/,$w! test.out |
| |
| |
| |
| *** 60,66 **** |
| :else |
| : let @r .= "FAILED\n" |
| :endif |
| ! :" --- Check that "matchdelete()" returns 0 if succesfull and otherwise -1. |
| :let @r .= "*** Test 6: " |
| :let m = matchadd("MyGroup1", "TODO") |
| :let r1 = matchdelete(m) |
| --- 60,66 ---- |
| :else |
| : let @r .= "FAILED\n" |
| :endif |
| ! :" --- Check that "matchdelete()" returns 0 if successful and otherwise -1. |
| :let @r .= "*** Test 6: " |
| :let m = matchadd("MyGroup1", "TODO") |
| :let r1 = matchdelete(m) |
| |
| *** 117,123 **** |
| :" --- Check that "setmatches()" will not add two matches with the same ID. The |
| :" --- expected behaviour (for now) is to add the first match but not the |
| :" --- second and to return 0 (even though it is a matter of debate whether |
| ! :" --- this can be considered succesfull behaviour). |
| :let @r .= "*** Test 9: " |
| :let r1 = setmatches([{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}, {'group': 'MyGroup2', 'pattern': 'FIXME', 'priority': 10, 'id': 1}]) |
| :if getmatches() == [{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}] && r1 == 0 |
| --- 117,123 ---- |
| :" --- Check that "setmatches()" will not add two matches with the same ID. The |
| :" --- expected behaviour (for now) is to add the first match but not the |
| :" --- second and to return 0 (even though it is a matter of debate whether |
| ! :" --- this can be considered successful behaviour). |
| :let @r .= "*** Test 9: " |
| :let r1 = setmatches([{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}, {'group': 'MyGroup2', 'pattern': 'FIXME', 'priority': 10, 'id': 1}]) |
| :if getmatches() == [{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}] && r1 == 0 |
| |
| *** 127,133 **** |
| :endif |
| :call clearmatches() |
| :unlet r1 |
| ! :" --- Check that "setmatches()" returns 0 if succesfull and otherwise -1. |
| :" --- (A range of valid and invalid input values are tried out to generate the |
| :" --- return values.) |
| :let @r .= "*** Test 10: " |
| --- 127,133 ---- |
| :endif |
| :call clearmatches() |
| :unlet r1 |
| ! :" --- Check that "setmatches()" returns 0 if successful and otherwise -1. |
| :" --- (A range of valid and invalid input values are tried out to generate the |
| :" --- return values.) |
| :let @r .= "*** Test 10: " |
| |
| |
| |
| *** 44,51 **** |
| --- 44,53 ---- |
| : $put ='ERROR: pat: \"' . t[0] . '\", text: \"' . t[1] . '\", submatch ' . i . ': \"' . l[i] . '\", expected: \"' . e . '\"' |
| : endif |
| : endfor |
| + : unlet i |
| : endif |
| :endfor |
| + :unlet t tl e l |
| :/^Results/,$wq! test.out |
| ENDTEST |
| |
| |
| |
| |
| *** 668,669 **** |
| --- 668,671 ---- |
| { /* Add new patch number below this line */ |
| + /**/ |
| + 120, |
| /**/ |
| |
| -- |
| BEDEVERE: How do you know so much about swallows? |
| ARTHUR: Well you have to know these things when you're a king, you know. |
| "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD |
| |
| /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ |
| /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ |
| \\\ download, build and distribute -- http://www.A-A-P.org /// |
| \\\ help me help AIDS victims -- http://ICCF-Holland.org /// |