To: vim-dev@vim.org Subject: Patch 5.6a.024 Fcc: outbox From: Bram Moolenaar ------------ Patch 5.6a.024 Problem: Using an autocommand to delete a buffer when leaving it can cause a crash when jumping to a tag. (Franz Gorkotte) Solution: In do_tag(), store tagstacklen before jumping to another buffer. Check tagstackidx after jumping to another buffer. Add extra check in win_split() if tagname isn't NULL. Files: src/tag.c, src/window.c *** ../vim-5.6a.23/src/tag.c Mon Dec 20 09:59:16 1999 --- src/tag.c Thu Jan 13 14:14:32 2000 *************** *** 203,211 **** */ if ((tagstack[tagstackidx].tagname = vim_strsave(tag)) == NULL) { ! --tagstacklen; goto end_do_tag; } new_tag = TRUE; save_pos = TRUE; /* save the cursor position below */ } --- 203,213 ---- */ if ((tagstack[tagstackidx].tagname = vim_strsave(tag)) == NULL) { ! curwin->w_tagstacklen = tagstacklen - 1; goto end_do_tag; } + curwin->w_tagstacklen = tagstacklen; + new_tag = TRUE; save_pos = TRUE; /* save the cursor position below */ } *************** *** 238,262 **** emsg(topmsg); goto end_do_tag; } ! if (tagstack[tagstackidx].fmark.fnum != curbuf->b_fnum) { /* * Jump to other file. If this fails (e.g. because the * file was changed) keep original position in tag stack. */ ! if (buflist_getfile(tagstack[tagstackidx].fmark.fnum, ! tagstack[tagstackidx].fmark.mark.lnum, ! GETF_SETMARK, forceit) == FAIL) { tagstackidx = oldtagstackidx; /* back to old posn */ goto end_do_tag; } } else ! curwin->w_cursor.lnum ! = tagstack[tagstackidx].fmark.mark.lnum; ! curwin->w_cursor.col = tagstack[tagstackidx].fmark.mark.col; curwin->w_set_curswant = TRUE; /* remove the old list of matches */ FreeWild(num_matches, matches); #ifdef USE_CSCOPE --- 240,268 ---- emsg(topmsg); goto end_do_tag; } ! ! /* Make a copy of the fmark, autocommands may invalidate the ! * tagstack before it's used. */ ! saved_fmark = tagstack[tagstackidx].fmark; ! if (saved_fmark.fnum != curbuf->b_fnum) { /* * Jump to other file. If this fails (e.g. because the * file was changed) keep original position in tag stack. */ ! if (buflist_getfile(saved_fmark.fnum, saved_fmark.mark.lnum, ! GETF_SETMARK, forceit) == FAIL) { tagstackidx = oldtagstackidx; /* back to old posn */ goto end_do_tag; } } else ! curwin->w_cursor.lnum = saved_fmark.mark.lnum; ! curwin->w_cursor.col = saved_fmark.mark.col; curwin->w_set_curswant = TRUE; + adjust_cursor(); + /* remove the old list of matches */ FreeWild(num_matches, matches); #ifdef USE_CSCOPE *************** *** 322,330 **** tagstack[tagstackidx].fmark.fnum = curbuf->b_fnum; } ! /* curwin will change in the call to jumpto_tag() if ":stag" was used */ curwin->w_tagstackidx = tagstackidx; - curwin->w_tagstacklen = tagstacklen; if (type != DT_SELECT && type != DT_JUMP) curwin->w_tagstack[tagstackidx].cur_match = cur_match; } --- 328,337 ---- tagstack[tagstackidx].fmark.fnum = curbuf->b_fnum; } ! /* Curwin will change in the call to jumpto_tag() if ":stag" was used ! * or an autocommand jumps to another window; store value of ! * tagstackidx now. */ curwin->w_tagstackidx = tagstackidx; if (type != DT_SELECT && type != DT_JUMP) curwin->w_tagstack[tagstackidx].cur_match = cur_match; } *************** *** 695,714 **** } EMSG2("File \"%s\" does not exist", nofile_fname); } - #ifdef USE_CSCOPE else jumped_to_tag = TRUE; #endif } break; } end_do_tag: ! if (use_tagstack) ! { curwin->w_tagstackidx = tagstackidx; - curwin->w_tagstacklen = tagstacklen; - } postponed_split = 0; /* don't split next time */ #ifdef USE_CSCOPE --- 702,725 ---- } EMSG2("File \"%s\" does not exist", nofile_fname); } else + { + /* We may have jumped to another window, check that + * tagstackidx is still valid. */ + if (tagstackidx > curwin->w_tagstacklen) + tagstackidx = curwin->w_tagstackidx; + #ifdef USE_CSCOPE jumped_to_tag = TRUE; #endif + } } break; } end_do_tag: ! /* Only store the new index when using tha tagstack and it's valid. */ ! if (use_tagstack && tagstackidx <= curwin->w_tagstacklen) curwin->w_tagstackidx = tagstackidx; postponed_split = 0; /* don't split next time */ #ifdef USE_CSCOPE *** ../vim-5.6a.23/src/window.c Mon Dec 20 09:59:07 1999 --- src/window.c Thu Jan 13 10:59:45 2000 *************** *** 473,480 **** */ for (i = 0; i < curwin->w_tagstacklen; i++) { ! wp->w_tagstack[i].fmark = curwin->w_tagstack[i].fmark; ! wp->w_tagstack[i].tagname = vim_strsave(curwin->w_tagstack[i].tagname); } wp->w_tagstackidx = curwin->w_tagstackidx; wp->w_tagstacklen = curwin->w_tagstacklen; --- 473,481 ---- */ for (i = 0; i < curwin->w_tagstacklen; i++) { ! wp->w_tagstack[i] = curwin->w_tagstack[i]; ! if (wp->w_tagstack[i].tagname != NULL) ! wp->w_tagstack[i].tagname = vim_strsave(wp->w_tagstack[i].tagname); } wp->w_tagstackidx = curwin->w_tagstackidx; wp->w_tagstacklen = curwin->w_tagstacklen; *** ../vim-5.6a.23/src/version.c Wed Jan 12 21:22:23 2000 --- src/version.c Thu Jan 13 14:15:59 2000 *************** *** 420,421 **** --- 420,423 ---- { /* Add new patch number below this line */ + /**/ + 24, /**/ -- hundred-and-one symptoms of being an internet addict: 141. You'd rather go to http://www.weather.com/ than look out your window. --/-/---- Bram Moolenaar ---- Bram@moolenaar.net ---- Bram@vim.org ---\-\-- \ \ www.vim.org/iccf www.moolenaar.net www.vim.org / /