From ac4bbf55f6d6b9b252dd90fe800626850022b690 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 10 Dec 2017 22:04:43 +0300 Subject: *: Hide list implementation in other files as well --- src/nvim/quickfix.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 1fc585f0c9..56d11c21ab 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -156,6 +156,7 @@ typedef struct { FILE *fd; typval_T *tv; char_u *p_str; + list_T *p_list; listitem_T *p_li; buf_T *buf; linenr_T buflnum; @@ -516,17 +517,17 @@ static int qf_get_next_list_line(qfstate_T *state) // Get the next line from the supplied list while (p_li != NULL - && (p_li->li_tv.v_type != VAR_STRING - || p_li->li_tv.vval.v_string == NULL)) { - p_li = p_li->li_next; // Skip non-string items + && (TV_LIST_ITEM_TV(p_li)->v_type != VAR_STRING + || TV_LIST_ITEM_TV(p_li)->vval.v_string == NULL)) { + p_li = TV_LIST_ITEM_NEXT(state->p_list, p_li); // Skip non-string items. } - if (p_li == NULL) { // End of the list + if (p_li == NULL) { // End of the list. state->p_li = NULL; return QF_END_OF_INPUT; } - len = STRLEN(p_li->li_tv.vval.v_string); + len = STRLEN(TV_LIST_ITEM_TV(p_li)->vval.v_string); if (len > IOSIZE - 2) { state->linebuf = qf_grow_linebuf(state, len); } else { @@ -534,9 +535,10 @@ static int qf_get_next_list_line(qfstate_T *state) state->linelen = len; } - STRLCPY(state->linebuf, p_li->li_tv.vval.v_string, state->linelen + 1); + STRLCPY(state->linebuf, TV_LIST_ITEM_TV(p_li)->vval.v_string, + state->linelen + 1); - state->p_li = p_li->li_next; // next item + state->p_li = TV_LIST_ITEM_NEXT(state->p_list, p_li); return QF_OK; } @@ -983,7 +985,7 @@ qf_init_ext( ) { qfstate_T state = { NULL, 0, NULL, 0, NULL, NULL, NULL, NULL, - NULL, 0, 0 }; + NULL, NULL, 0, 0 }; qffields_T fields = { NULL, NULL, 0, 0L, 0, false, NULL, 0, 0, 0 }; qfline_T *old_last = NULL; bool adding = false; @@ -1064,7 +1066,8 @@ qf_init_ext( if (tv->v_type == VAR_STRING) { state.p_str = tv->vval.v_string; } else if (tv->v_type == VAR_LIST) { - state.p_li = tv->vval.v_list->lv_first; + state.p_list = tv->vval.v_list; + state.p_li = tv_list_first(tv->vval.v_list); } state.tv = tv; } @@ -4100,7 +4103,6 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict) static int qf_add_entries(qf_info_T *qi, list_T *list, char_u *title, int action) { - listitem_T *li; dict_T *d; qfline_T *old_last = NULL; int retval = OK; @@ -4117,13 +4119,15 @@ static int qf_add_entries(qf_info_T *qi, list_T *list, char_u *title, qf_store_title(qi, title); } - for (li = list->lv_first; li != NULL; li = li->li_next) { - if (li->li_tv.v_type != VAR_DICT) - continue; /* Skip non-dict items */ + TV_LIST_ITER_CONST(list, li, { + if (TV_LIST_ITEM_TV(li)->v_type != VAR_DICT) { + continue; // Skip non-dict items. + } - d = li->li_tv.vval.v_dict; - if (d == NULL) + d = TV_LIST_ITEM_TV(li)->vval.v_dict; + if (d == NULL) { continue; + } char *const filename = tv_dict_get_string(d, "filename", true); int bufnum = (int)tv_dict_get_number(d, "bufnr"); @@ -4175,7 +4179,7 @@ static int qf_add_entries(qf_info_T *qi, list_T *list, char_u *title, retval = FAIL; break; } - } + }); if (qi->qf_lists[qi->qf_curlist].qf_index == 0) { // no valid entry -- cgit From 83f77c80c084a0390b5a6efd364b33620c9f3d10 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 10 Dec 2017 22:33:05 +0300 Subject: quickfix: Fix :cexpr and :lexpr --- src/nvim/quickfix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 56d11c21ab..a4dc9c68ce 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -4403,7 +4403,7 @@ void ex_cexpr(exarg_T *eap) typval_T tv; if (eval0(eap->arg, &tv, NULL, true) != FAIL) { if ((tv.v_type == VAR_STRING && tv.vval.v_string != NULL) - || (tv.v_type == VAR_LIST && tv.vval.v_list != NULL)) { + || tv.v_type == VAR_LIST) { if (qf_init_ext(qi, NULL, NULL, &tv, p_efm, (eap->cmdidx != CMD_caddexpr && eap->cmdidx != CMD_laddexpr), -- cgit From d5bce42b524708a54243658e87b1e3bd9c7acdf3 Mon Sep 17 00:00:00 2001 From: Michael Schupikov Date: Sat, 23 Sep 2017 09:56:44 +0200 Subject: vim-patch:8.0.0074 Problem: Cannot make Vim fail on an internal error. Solution: Add IEMSG() and IEMSG2(). (Domenique Pelle) Avoid reporting an internal error without mentioning where. https://github.com/vim/vim/commit/95f096030ed1a8afea028f2ea295d6f6a70f466f Signed-off-by: Michael Schupikov --- src/nvim/quickfix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 1fc585f0c9..3df025a51d 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -2853,7 +2853,7 @@ static void qf_fill_buffer(qf_info_T *qi, buf_T *buf, qfline_T *old_last) if (old_last == NULL) { if (buf != curbuf) { - EMSG2(_(e_intern2), "qf_fill_buffer()"); + internal_error("qf_fill_buffer()"); return; } -- cgit From c162bc629440afaf8910f1a29f1dfdb03f898101 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sat, 16 Dec 2017 21:50:20 -0500 Subject: vim-patch:8.0.0420: text garbled when the system encoding differs from 'encoding' Problem: When running :make the output may be in the system encoding, different from 'encoding'. Solution: Add the 'makeencoding' option. (Ken Takata) https://github.com/vim/vim/commit/2c7292dc5bbf155fe2192d417363b8c085759cad --- src/nvim/quickfix.c | 56 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 13 deletions(-) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 3df025a51d..844ff071c9 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -160,6 +160,7 @@ typedef struct { buf_T *buf; linenr_T buflnum; linenr_T lnumlast; + vimconv_T vc; } qfstate_T; typedef struct { @@ -204,7 +205,8 @@ qf_init ( char_u *efile, char_u *errorformat, int newlist, /* TRUE: start a new error list */ - char_u *qf_title + char_u *qf_title, + char_u *enc ) { qf_info_T *qi = &ql_info; @@ -214,8 +216,8 @@ qf_init ( } return qf_init_ext(qi, efile, curbuf, NULL, errorformat, newlist, - (linenr_T)0, (linenr_T)0, - qf_title); + (linenr_T)0, (linenr_T)0, + qf_title, enc); } // Maximum number of bytes allowed per line while reading an errorfile. @@ -638,6 +640,22 @@ retry: } else { state->linebuf = IObuff; } + + // Convert a line if it contains a non-ASCII character + if (state->vc.vc_type != CONV_NONE && has_non_ascii(state->linebuf)) { + char_u *line = string_convert(&state->vc, state->linebuf, &state->linelen); + if (line != NULL) { + if (state->linelen < IOSIZE) { + STRLCPY(state->linebuf, line, state->linelen + 1); + xfree(line); + } else { + xfree(state->growbuf); + state->linebuf = state->growbuf = line; + state->growbufsiz = state->linelen < LINE_MAXLEN + ? state->linelen : LINE_MAXLEN; + } + } + } return QF_OK; } @@ -979,12 +997,12 @@ qf_init_ext( int newlist, /* TRUE: start a new error list */ linenr_T lnumfirst, /* first line number to use */ linenr_T lnumlast, /* last line number to use */ - char_u *qf_title + char_u *qf_title, + char_u *enc ) { - qfstate_T state = { NULL, 0, NULL, 0, NULL, NULL, NULL, NULL, - NULL, 0, 0 }; - qffields_T fields = { NULL, NULL, 0, 0L, 0, false, NULL, 0, 0, 0 }; + qfstate_T state; + qffields_T fields; qfline_T *old_last = NULL; bool adding = false; static efm_T *fmt_first = NULL; @@ -997,6 +1015,13 @@ qf_init_ext( xfree(qf_last_bufname); qf_last_bufname = NULL; + memset(&state, 0, sizeof(state)); + memset(&fields, 0, sizeof(fields)); + state.vc.vc_type = CONV_NONE; + if (enc != NULL && *enc != NUL) { + convert_setup(&state.vc, enc, p_enc); + } + fields.namebuf = xmalloc(CMDBUFFSIZE + 1); fields.errmsglen = CMDBUFFSIZE + 1; fields.errmsg = xmalloc(fields.errmsglen); @@ -1147,6 +1172,10 @@ qf_init_end: qf_update_buffer(qi, old_last); + if (state.vc.vc_type != CONV_NONE) { + convert_setup(&state.vc, NULL, NULL); + } + return retval; } @@ -3024,6 +3053,7 @@ void ex_make(exarg_T *eap) qf_info_T *qi = &ql_info; int res; char_u *au_name = NULL; + char_u *enc = (*curbuf->b_p_menc != NUL) ? curbuf->b_p_menc : p_menc; /* Redirect ":grep" to ":vimgrep" if 'grepprg' is "internal". */ if (grep_internal(eap->cmdidx)) { @@ -3083,9 +3113,8 @@ void ex_make(exarg_T *eap) res = qf_init(wp, fname, (eap->cmdidx != CMD_make && eap->cmdidx != CMD_lmake) ? p_gefm : p_efm, - (eap->cmdidx != CMD_grepadd - && eap->cmdidx != CMD_lgrepadd), - *eap->cmdlinep); + (eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_lgrepadd), + *eap->cmdlinep, enc); if (wp != NULL) qi = GET_LOC_LIST(wp); if (au_name != NULL) { @@ -3429,6 +3458,7 @@ void ex_cfile(exarg_T *eap) if (*eap->arg != NUL) set_string_option_direct((char_u *)"ef", -1, eap->arg, OPT_FREE, 0); + char_u *enc = (*curbuf->b_p_menc != NUL) ? curbuf->b_p_menc : p_menc; /* * This function is used by the :cfile, :cgetfile and :caddfile * commands. @@ -3441,7 +3471,7 @@ void ex_cfile(exarg_T *eap) */ if (qf_init(wp, p_ef, p_efm, (eap->cmdidx != CMD_caddfile && eap->cmdidx != CMD_laddfile), - *eap->cmdlinep) > 0 + *eap->cmdlinep, enc) > 0 && (eap->cmdidx == CMD_cfile || eap->cmdidx == CMD_lfile)) { if (au_name != NULL) @@ -4338,7 +4368,7 @@ void ex_cbuffer(exarg_T *eap) if (qf_init_ext(qi, NULL, buf, NULL, p_efm, (eap->cmdidx != CMD_caddbuffer && eap->cmdidx != CMD_laddbuffer), - eap->line1, eap->line2, qf_title) > 0) { + eap->line1, eap->line2, qf_title, NULL) > 0) { if (au_name != NULL) { apply_autocmds(EVENT_QUICKFIXCMDPOST, (char_u *)au_name, curbuf->b_fname, true, curbuf); @@ -4403,7 +4433,7 @@ void ex_cexpr(exarg_T *eap) if (qf_init_ext(qi, NULL, NULL, &tv, p_efm, (eap->cmdidx != CMD_caddexpr && eap->cmdidx != CMD_laddexpr), - (linenr_T)0, (linenr_T)0, *eap->cmdlinep) > 0) { + (linenr_T)0, (linenr_T)0, *eap->cmdlinep, NULL) > 0) { if (au_name != NULL) { apply_autocmds(EVENT_QUICKFIXCMDPOST, (char_u *)au_name, curbuf->b_fname, true, curbuf); -- cgit From db0685a663a7d86d960f22e18f4e8e5041f80833 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sun, 17 Dec 2017 11:17:30 -0500 Subject: lint --- src/nvim/quickfix.c | 54 ++++++++++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 28 deletions(-) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 844ff071c9..696f123871 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -194,20 +194,19 @@ typedef struct { static char_u *qf_last_bufname = NULL; static bufref_T qf_last_bufref = { NULL, 0, 0 }; -/* - * Read the errorfile "efile" into memory, line by line, building the error - * list. Set the error list's title to qf_title. - * Return -1 for error, number of errors for success. - */ -int -qf_init ( - win_T *wp, - char_u *efile, - char_u *errorformat, - int newlist, /* TRUE: start a new error list */ - char_u *qf_title, - char_u *enc -) +/// Read the errorfile "efile" into memory, line by line, building the error +/// list. Set the error list's title to qf_title. +/// +/// @params wp If non-NULL, make a location list +/// @params efile If non-NULL, errorfile to parse +/// @params errorformat 'errorformat' string used to parse the error lines +/// @params newlist If true, create a new error list +/// @params qf_title If non-NULL, title of the error list +/// @params enc If non-NULL, encoding used to parse errors +/// +/// @returns -1 for error, number of errors for success. +int qf_init(win_T *wp, char_u *efile, char_u *errorformat, int newlist, + char_u *qf_title, char_u *enc) { qf_info_T *qi = &ql_info; @@ -994,9 +993,9 @@ qf_init_ext( buf_T *buf, typval_T *tv, char_u *errorformat, - int newlist, /* TRUE: start a new error list */ - linenr_T lnumfirst, /* first line number to use */ - linenr_T lnumlast, /* last line number to use */ + int newlist, // TRUE: start a new error list + linenr_T lnumfirst, // first line number to use + linenr_T lnumlast, // last line number to use char_u *qf_title, char_u *enc ) @@ -3115,8 +3114,9 @@ void ex_make(exarg_T *eap) && eap->cmdidx != CMD_lmake) ? p_gefm : p_efm, (eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_lgrepadd), *eap->cmdlinep, enc); - if (wp != NULL) + if (wp != NULL) { qi = GET_LOC_LIST(wp); + } if (au_name != NULL) { apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, curbuf->b_fname, TRUE, curbuf); @@ -3459,16 +3459,14 @@ void ex_cfile(exarg_T *eap) set_string_option_direct((char_u *)"ef", -1, eap->arg, OPT_FREE, 0); char_u *enc = (*curbuf->b_p_menc != NUL) ? curbuf->b_p_menc : p_menc; - /* - * This function is used by the :cfile, :cgetfile and :caddfile - * commands. - * :cfile always creates a new quickfix list and jumps to the - * first error. - * :cgetfile creates a new quickfix list but doesn't jump to the - * first error. - * :caddfile adds to an existing quickfix list. If there is no - * quickfix list then a new list is created. - */ + // This function is used by the :cfile, :cgetfile and :caddfile + // commands. + // :cfile always creates a new quickfix list and jumps to the + // first error. + // :cgetfile creates a new quickfix list but doesn't jump to the + // first error. + // :caddfile adds to an existing quickfix list. If there is no + // quickfix list then a new list is created. if (qf_init(wp, p_ef, p_efm, (eap->cmdidx != CMD_caddfile && eap->cmdidx != CMD_laddfile), *eap->cmdlinep, enc) > 0 -- cgit From 853634881335eb9fe4c593710fbb8c71324e1690 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sun, 17 Dec 2017 20:56:01 -0500 Subject: vim-patch:8.0.0484: :lhelpgrep does not fail after a successful one Problem: Using :lhelpgrep with an argument that should fail does not produce an error if the previous :helpgrep worked. Solution: Use another way to detect that autocommands made the quickfix info invalid. (Yegappan Lakshmanan) https://github.com/vim/vim/commit/ee85df37634dfb0c40ae5de0b4f246aef460b392 --- src/nvim/quickfix.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 696f123871..6d59d15515 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -4502,6 +4502,9 @@ void ex_helpgrep(exarg_T *eap) } } + // Autocommands may change the list. Save it for later comparison + qf_info_T *save_qi = qi; + regmatch.regprog = vim_regcomp(eap->arg, RE_MAGIC + RE_STRING); regmatch.rm_ic = FALSE; if (regmatch.regprog != NULL) { @@ -4614,10 +4617,11 @@ void ex_helpgrep(exarg_T *eap) if (au_name != NULL) { apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, - curbuf->b_fname, TRUE, curbuf); - if (!new_qi && qi != &ql_info && qf_find_buf(qi) == NULL) - /* autocommands made "qi" invalid */ + curbuf->b_fname, true, curbuf); + if (!new_qi && qi != save_qi && qf_find_buf(qi) == NULL) { + // autocommands made "qi" invalid return; + } } /* Jump to first match. */ -- cgit From fb8592b7ba673f230f144dc8c29e5dffc33fc50a Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 18 Dec 2017 14:26:49 -0500 Subject: vim-patch:8.0.0517: there is no way to remove quickfix lists Problem: There is no way to remove quickfix lists (for testing). Solution: Add the 'f' action to setqflist(). Add tests. (Yegappan Lakshmanan) https://github.com/vim/vim/commit/b6fa30ccc39cdb7f1d07b99fe2f4c6b61671dac2 --- src/nvim/quickfix.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 6d59d15515..c7326c46fe 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -4267,6 +4267,16 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action) return retval; } +static void qf_free_stack(win_T *wp, qf_info_T *qi) +{ + qf_free_all(wp); + if (wp == NULL) { + // quickfix list + qi->qf_curlist = 0; + qi->qf_listcount = 0; + } +} + // Populate the quickfix list with the items supplied in the list // of dictionaries. "title" will be copied to w:quickfix_title // "action" is 'a' for add, 'r' for replace. Otherwise create a new list. @@ -4280,7 +4290,10 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title, qi = ll_get_or_alloc_list(wp); } - if (what != NULL) { + if (action == 'f') { + // Free the entire quickfix or location list stack + qf_free_stack(wp, qi); + } else if (what != NULL) { retval = qf_set_properties(qi, what, action); } else { retval = qf_add_entries(qi, list, title, action); -- cgit From f0bd2bc39aeb7797e3dd5c14797606dac45c8a75 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 18 Dec 2017 14:36:13 -0500 Subject: vim-patch:8.0.0536: quickfix window not updated when freeing quickfix stack Problem: Quickfix window not updated when freeing quickfix stack. Solution: Update the quickfix window. (Yegappan Lakshmanan) https://github.com/vim/vim/commit/69f40be64555d50f603c6f22722cf762aaa6bbc1 --- src/nvim/quickfix.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index c7326c46fe..9a4341f3a4 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -4267,13 +4267,57 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action) return retval; } +// Find the non-location list window with the specified location list. +static win_T * find_win_with_ll(qf_info_T *qi) +{ + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + if ((wp->w_llist == qi) && !bt_quickfix(wp->w_buffer)) { + return wp; + } + } + + return NULL; +} + +// Free the entire quickfix/location list stack. +// If the quickfix/location list window is open, then clear it. static void qf_free_stack(win_T *wp, qf_info_T *qi) { + win_T *qfwin = qf_find_win(qi); + + if (qfwin != NULL) { + // If the quickfix/location list window is open, then clear it + if (qi->qf_curlist < qi->qf_listcount) { + qf_free(qi, qi->qf_curlist); + } + qf_update_buffer(qi, NULL); + } + + win_T *llwin = NULL; + win_T *orig_wp = wp; + if (wp != NULL && IS_LL_WINDOW(wp)) { + // If in the location list window, then use the non-location list + // window with this location list (if present) + llwin = find_win_with_ll(qi); + if (llwin != NULL) { + wp = llwin; + } + } + qf_free_all(wp); if (wp == NULL) { // quickfix list qi->qf_curlist = 0; qi->qf_listcount = 0; + } else if (IS_LL_WINDOW(orig_wp)) { + // If the location list window is open, then create a new empty location + // list + qf_info_T *new_ll = ll_new_list(); + orig_wp->w_llist_ref = new_ll; + if (llwin != NULL) { + llwin->w_llist = new_ll; + new_ll->qf_refcount++; + } } } -- cgit From 765ff94b5be90bc33eb8eba3fdfe3e910124450d Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 18 Dec 2017 14:56:49 -0500 Subject: vim-patch:8.0.0584: memory leak when executing quickfix tests Problem: Memory leak when executing quickfix tests. Solution: Free the list reference. (Yegappan Lakshmanan) https://github.com/vim/vim/commit/d788f6fe89c77262c474de323f5dab6d1c814e27 --- src/nvim/quickfix.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 9a4341f3a4..73ad14ab22 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -4313,6 +4313,10 @@ static void qf_free_stack(win_T *wp, qf_info_T *qi) // If the location list window is open, then create a new empty location // list qf_info_T *new_ll = ll_new_list(); + + // first free the list reference in the location list window + ll_free_all(&orig_wp->w_llist_ref); + orig_wp->w_llist_ref = new_ll; if (llwin != NULL) { llwin->w_llist = new_ll; -- cgit From 1b2d386a852fcdf1f7509dc29f2a26ab8e5b59ca Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 18 Dec 2017 21:35:40 -0500 Subject: vim-patch:8.0.0565: using freed memory in :caddbuf Problem: Using freed memory in :caddbuf after clearing quickfix list. (Dominique Pelle) Solution: Set qf_last to NULL. https://github.com/vim/vim/commit/31bdd13c335533c749993b57dcd980a87373139e --- src/nvim/quickfix.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 73ad14ab22..be998077c0 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -2411,6 +2411,7 @@ static void qf_free(qf_info_T *qi, int idx) qi->qf_lists[idx].qf_ptr = NULL; qi->qf_lists[idx].qf_title = NULL; qi->qf_lists[idx].qf_index = 0; + qi->qf_lists[idx].qf_last = NULL; qf_clean_dir_stack(&qi->qf_dir_stack); qi->qf_directory = NULL; -- cgit From dd2739286195c8953a31346908f02a85563a3fa2 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 18 Dec 2017 21:37:11 -0500 Subject: vim-patch:8.0.0574: get only one quickfix list after :caddbuf Problem: Get only one quickfix list after :caddbuf. Solution: Reset qf_multiline. (Yegappan Lakshmanan) https://github.com/vim/vim/commit/99895eac1cf71be43ece7e14b50e206e041fbe9f --- src/nvim/quickfix.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index be998077c0..ee3bb1dfba 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -2411,12 +2411,18 @@ static void qf_free(qf_info_T *qi, int idx) qi->qf_lists[idx].qf_ptr = NULL; qi->qf_lists[idx].qf_title = NULL; qi->qf_lists[idx].qf_index = 0; + qi->qf_lists[idx].qf_start = NULL; qi->qf_lists[idx].qf_last = NULL; + qi->qf_lists[idx].qf_ptr = NULL; + qi->qf_lists[idx].qf_nonevalid = true; qf_clean_dir_stack(&qi->qf_dir_stack); qi->qf_directory = NULL; qf_clean_dir_stack(&qi->qf_file_stack); qi->qf_currfile = NULL; + qi->qf_multiline = false; + qi->qf_multiignore = false; + qi->qf_multiscan = false; } /* -- cgit From 4d2d844c12e1a94a5d3cbe93794bb04ef6fb8377 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 18 Dec 2017 21:40:34 -0500 Subject: vim-patch:8.0.0580: cannot set the valid flag with setqflist() Problem: Cannot set the valid flag with setqflist(). Solution: Add the "valid" argument. (Yegappan Lakshmanan, closes vim/vim#1642) https://github.com/vim/vim/commit/f1d21c8cc83f40c815b6bf13cd2043152db533ee --- src/nvim/quickfix.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index ee3bb1dfba..d77cec4fd8 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -4189,6 +4189,11 @@ static int qf_add_entries(qf_info_T *qi, list_T *list, char_u *title, bufnum = 0; } + // If the 'valid' field is present it overrules the detected value. + if (tv_dict_find(d, "valid", -1) != NULL) { + valid = (int)tv_dict_get_number(d, "valid"); + } + int status = qf_add_entry(qi, NULL, // dir (char_u *)filename, -- cgit From 20708a07bfc1de2c56657123c41bb52919a728d8 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Tue, 19 Dec 2017 08:39:09 -0500 Subject: vim-patch:8.0.0590: cannot add a context to locations Problem: Cannot add a context to locations. Solution: Add the "context" entry in location entries. (Yegappan Lakshmanan, closes vim/vim#1012) https://github.com/vim/vim/commit/8f77c5a4ec756f3f866bd6b18feb6fca6f2a2e91 --- src/nvim/quickfix.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index d77cec4fd8..e7d11df833 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -85,6 +85,7 @@ typedef struct qf_list_S { int qf_nonevalid; // TRUE if not a single valid entry found char_u *qf_title; // title derived from the command that created // the error list + typval_T *qf_ctx; // context set by setqflist/setloclist } qf_list_T; struct qf_info_S { @@ -1409,6 +1410,13 @@ void copy_loclist(win_T *from, win_T *to) else to_qfl->qf_title = NULL; + if (from_qfl->qf_ctx != NULL) { + to_qfl->qf_ctx = xcalloc(1, sizeof(typval_T)); + tv_copy(from_qfl->qf_ctx, to_qfl->qf_ctx); + } else { + to_qfl->qf_ctx = NULL; + } + if (from_qfl->qf_count) { qfline_T *from_qfp; qfline_T *prevp; @@ -2410,6 +2418,8 @@ static void qf_free(qf_info_T *qi, int idx) qi->qf_lists[idx].qf_start = NULL; qi->qf_lists[idx].qf_ptr = NULL; qi->qf_lists[idx].qf_title = NULL; + tv_free(qi->qf_lists[idx].qf_ctx); + qi->qf_lists[idx].qf_ctx = NULL; qi->qf_lists[idx].qf_index = 0; qi->qf_lists[idx].qf_start = NULL; qi->qf_lists[idx].qf_last = NULL; @@ -4060,6 +4070,7 @@ enum { QF_GETLIST_ITEMS = 0x2, QF_GETLIST_NR = 0x4, QF_GETLIST_WINID = 0x8, + QF_GETLIST_CONTEXT = 0x10, QF_GETLIST_ALL = 0xFF }; @@ -4110,6 +4121,10 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict) flags |= QF_GETLIST_WINID; } + if (tv_dict_find(what, S_LEN("context")) != NULL) { + flags |= QF_GETLIST_CONTEXT; + } + if (flags & QF_GETLIST_TITLE) { char_u *t = qi->qf_lists[qf_idx].qf_title; if (t == NULL) { @@ -4127,6 +4142,18 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict) } } + if ((status == OK) && (flags & QF_GETLIST_CONTEXT)) { + if (qi->qf_lists[qf_idx].qf_ctx != NULL) { + di = tv_dict_item_alloc_len(S_LEN("context")); + if (di != NULL) { + tv_copy(qi->qf_lists[qf_idx].qf_ctx, &di->di_tv); + tv_dict_add(retdict, di); + } + } else { + status = tv_dict_add_str(retdict, S_LEN("context"), ""); + } + } + return status; } @@ -4276,6 +4303,14 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action) } } + if ((di = tv_dict_find(what, S_LEN("context"))) != NULL) { + tv_free(qi->qf_lists[qi->qf_curlist].qf_ctx); + + typval_T *ctx = xcalloc(1, sizeof(typval_T)); + tv_copy(&di->di_tv, ctx); + qi->qf_lists[qi->qf_curlist].qf_ctx = ctx; + } + return retval; } @@ -4362,6 +4397,42 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title, return retval; } +static bool mark_quickfix_ctx(qf_info_T *qi, int copyID) +{ + bool abort = false; + + for (int i = 0; i < LISTCOUNT && !abort; i++) { + typval_T *ctx = qi->qf_lists[i].qf_ctx; + if (ctx != NULL && ctx->v_type != VAR_NUMBER + && ctx->v_type != VAR_STRING && ctx->v_type != VAR_FLOAT) { + abort = set_ref_in_item(ctx, copyID, NULL, NULL); + } + } + + return abort; +} + +/// Mark the context of the quickfix list and the location lists (if present) as +/// "in use". So that garabage collection doesn't free the context. +bool set_ref_in_quickfix(int copyID) +{ + bool abort = mark_quickfix_ctx(&ql_info, copyID); + if (abort) { + return abort; + } + + FOR_ALL_TAB_WINDOWS(tp, win) { + if (win->w_llist != NULL) { + abort = mark_quickfix_ctx(win->w_llist, copyID); + if (abort) { + return abort; + } + } + } + + return abort; +} + /* * ":[range]cbuffer [bufnr]" command. * ":[range]caddbuffer [bufnr]" command. -- cgit From 6fcadab3ce16ff29be53176f8658e61819691df1 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Tue, 19 Dec 2017 10:41:50 -0500 Subject: vim-patch:8.0.0595: Coverity warning for not checking return value Problem: Coverity warning for not checking return value of dict_add(). Solution: Check the return value for FAIL. https://github.com/vim/vim/commit/beb9cb19c660484488a71a25eda46ab0fa579278 --- src/nvim/quickfix.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index e7d11df833..df735e32a9 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -4147,7 +4147,9 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict) di = tv_dict_item_alloc_len(S_LEN("context")); if (di != NULL) { tv_copy(qi->qf_lists[qf_idx].qf_ctx, &di->di_tv); - tv_dict_add(retdict, di); + if (tv_dict_add(retdict, di) == FAIL) { + tv_dict_item_free(di); + } } } else { status = tv_dict_add_str(retdict, S_LEN("context"), ""); -- cgit From cdd86f42cf93135d1c4dddcc2ba13b9798034350 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Tue, 19 Dec 2017 10:48:31 -0500 Subject: vim-patch:8.0.0597: off-by-one error in size computation Problem: Off-by-one error in buffer size computation. Solution: Use ">=" instead of ">". (Lemonboy, closes vim/vim#1694) https://github.com/vim/vim/commit/253f9128779f315ea670f9b4a17446b7b4c74927 --- src/nvim/quickfix.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index df735e32a9..3608a41a6e 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -801,7 +801,7 @@ restofline: fields->type = *regmatch.startp[i]; } if (fmt_ptr->flags == '+' && !qi->qf_multiscan) { // %+ - if (linelen > fields->errmsglen) { + if (linelen >= fields->errmsglen) { // linelen + null terminator fields->errmsg = xrealloc(fields->errmsg, linelen + 1); fields->errmsglen = linelen + 1; @@ -812,7 +812,7 @@ restofline: continue; } len = (size_t)(regmatch.endp[i] - regmatch.startp[i]); - if (len > fields->errmsglen) { + if (len >= fields->errmsglen) { // len + null terminator fields->errmsg = xrealloc(fields->errmsg, len + 1); fields->errmsglen = len + 1; @@ -889,7 +889,7 @@ restofline: fields->namebuf[0] = NUL; // no match found, remove file name fields->lnum = 0; // don't jump to this line fields->valid = false; - if (linelen > fields->errmsglen) { + if (linelen >= fields->errmsglen) { // linelen + null terminator fields->errmsg = xrealloc(fields->errmsg, linelen + 1); fields->errmsglen = linelen + 1; -- cgit From 190814bdae496c0ce4dfb524f9bb5ee7a09b4f60 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Tue, 19 Dec 2017 10:53:59 -0500 Subject: vim-patch:8.0.0606: cannot set the context for a specified quickfix list Problem: Cannot set the context for a specified quickfix list. Solution: Use the list index instead of the current list. (Yegappan Lakshmanan) https://github.com/vim/vim/commit/6e62da3e14d32f76f60d5cc8b267059923842f17 --- src/nvim/quickfix.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 3608a41a6e..c5d03e73f1 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -4278,7 +4278,10 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action) if ((di = tv_dict_find(what, S_LEN("nr"))) != NULL) { // Use the specified quickfix/location list if (di->di_tv.v_type == VAR_NUMBER) { - qf_idx = (int)di->di_tv.vval.v_number - 1; + // for zero use the current list + if (di->di_tv.vval.v_number != 0) { + qf_idx = (int)di->di_tv.vval.v_number - 1; + } if (qf_idx < 0 || qf_idx >= qi->qf_listcount) { return FAIL; } @@ -4306,11 +4309,11 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action) } if ((di = tv_dict_find(what, S_LEN("context"))) != NULL) { - tv_free(qi->qf_lists[qi->qf_curlist].qf_ctx); + tv_free(qi->qf_lists[qf_idx].qf_ctx); typval_T *ctx = xcalloc(1, sizeof(typval_T)); tv_copy(&di->di_tv, ctx); - qi->qf_lists[qi->qf_curlist].qf_ctx = ctx; + qi->qf_lists[qf_idx].qf_ctx = ctx; } return retval; -- cgit From 697fb05c580ab01cfd97f84632e608e951b80cbf Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sat, 30 Dec 2017 01:17:31 -0500 Subject: vim-patch:8.0.0608: cannot manipulate other than the current quickfix list Problem: Cannot manipulate other than the current quickfix list. Solution: Pass the list index to quickfix functions. (Yegappan Lakshmanan) https://github.com/vim/vim/commit/a3921f48c6b31a035c80fda49925dd3b42df0dec --- src/nvim/quickfix.c | 67 +++++++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 30 deletions(-) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index f85009dca8..bf2993b320 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -1121,6 +1121,7 @@ qf_init_ext( } if (qf_add_entry(qi, + qi->qf_curlist, qi->qf_directory, (*fields.namebuf || qi->qf_directory) ? fields.namebuf : ((qi->qf_currfile && fields.valid) @@ -1182,12 +1183,12 @@ qf_init_end: return retval; } -static void qf_store_title(qf_info_T *qi, char_u *title) +static void qf_store_title(qf_info_T *qi, int qf_idx, char_u *title) { if (title != NULL) { char_u *p = xmalloc(STRLEN(title) + 2); - qi->qf_lists[qi->qf_curlist].qf_title = p; + qi->qf_lists[qf_idx].qf_title = p; sprintf((char *)p, ":%s", (char *)title); } } @@ -1217,7 +1218,7 @@ static void qf_new_list(qf_info_T *qi, char_u *qf_title) } else qi->qf_curlist = qi->qf_listcount++; memset(&qi->qf_lists[qi->qf_curlist], 0, (size_t)(sizeof(qf_list_T))); - qf_store_title(qi, qf_title); + qf_store_title(qi, qi->qf_curlist, qf_title); } /* @@ -1260,6 +1261,7 @@ void qf_free_all(win_T *wp) /// Add an entry to the end of the list of errors. /// /// @param qi quickfix list +/// @param qf_idx list index /// @param dir optional directory name /// @param fname file name or NULL /// @param bufnum buffer number or zero @@ -1273,9 +1275,10 @@ void qf_free_all(win_T *wp) /// @param valid valid entry /// /// @returns OK or FAIL. -static int qf_add_entry(qf_info_T *qi, char_u *dir, char_u *fname, int bufnum, - char_u *mesg, long lnum, int col, char_u vis_col, - char_u *pattern, int nr, char_u type, char_u valid) +static int qf_add_entry(qf_info_T *qi, int qf_idx, char_u *dir, char_u *fname, + int bufnum, char_u *mesg, long lnum, int col, + char_u vis_col, char_u *pattern, int nr, char_u type, + char_u valid) { qfline_T *qfp = xmalloc(sizeof(qfline_T)); qfline_T **lastp; // pointer to qf_last or NULL @@ -1306,12 +1309,12 @@ static int qf_add_entry(qf_info_T *qi, char_u *dir, char_u *fname, int bufnum, qfp->qf_type = (char_u)type; qfp->qf_valid = valid; - lastp = &qi->qf_lists[qi->qf_curlist].qf_last; - if (qi->qf_lists[qi->qf_curlist].qf_count == 0) { + lastp = &qi->qf_lists[qf_idx].qf_last; + if (qi->qf_lists[qf_idx].qf_count == 0) { /* first element in the list */ - qi->qf_lists[qi->qf_curlist].qf_start = qfp; - qi->qf_lists[qi->qf_curlist].qf_ptr = qfp; - qi->qf_lists[qi->qf_curlist].qf_index = 0; + qi->qf_lists[qf_idx].qf_start = qfp; + qi->qf_lists[qf_idx].qf_ptr = qfp; + qi->qf_lists[qf_idx].qf_index = 0; qfp->qf_prev = NULL; } else { assert(*lastp); @@ -1321,12 +1324,11 @@ static int qf_add_entry(qf_info_T *qi, char_u *dir, char_u *fname, int bufnum, qfp->qf_next = NULL; qfp->qf_cleared = false; *lastp = qfp; - qi->qf_lists[qi->qf_curlist].qf_count++; - if (qi->qf_lists[qi->qf_curlist].qf_index == 0 && qfp->qf_valid) { + qi->qf_lists[qf_idx].qf_count++; + if (qi->qf_lists[qf_idx].qf_index == 0 && qfp->qf_valid) { /* first valid entry */ - qi->qf_lists[qi->qf_curlist].qf_index = - qi->qf_lists[qi->qf_curlist].qf_count; - qi->qf_lists[qi->qf_curlist].qf_ptr = qfp; + qi->qf_lists[qf_idx].qf_index = qi->qf_lists[qf_idx].qf_count; + qi->qf_lists[qf_idx].qf_ptr = qfp; } return OK; @@ -1429,6 +1431,7 @@ void copy_loclist(win_T *from, win_T *to) i < from_qfl->qf_count && from_qfp != NULL; i++, from_qfp = from_qfp->qf_next) { if (qf_add_entry(to->w_llist, + to->w_llist->qf_curlist, NULL, NULL, 0, @@ -3704,6 +3707,7 @@ void ex_vimgrep(exarg_T *eap) // dummy buffer, unless duplicate_name is set, then the // buffer will be wiped out below. if (qf_add_entry(qi, + qi->qf_curlist, NULL, // dir fname, duplicate_name ? 0 : buf->b_fnum, @@ -4164,23 +4168,24 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict) /// Add list of entries to quickfix/location list. Each list entry is /// a dictionary with item information. -static int qf_add_entries(qf_info_T *qi, list_T *list, char_u *title, - int action) +static int qf_add_entries(qf_info_T *qi, int qf_idx, list_T *list, + char_u *title, int action) { dict_T *d; qfline_T *old_last = NULL; int retval = OK; bool did_bufnr_emsg = false; - if (action == ' ' || qi->qf_curlist == qi->qf_listcount) { + if (action == ' ' || qf_idx == qi->qf_listcount) { // make place for a new list qf_new_list(qi, title); - } else if (action == 'a' && qi->qf_lists[qi->qf_curlist].qf_count > 0) { + qf_idx = qi->qf_curlist; + } else if (action == 'a' && qi->qf_lists[qf_idx].qf_count > 0) { // Adding to existing list, use last entry. - old_last = qi->qf_lists[qi->qf_curlist].qf_last; + old_last = qi->qf_lists[qf_idx].qf_last; } else if (action == 'r') { - qf_free(qi, qi->qf_curlist); - qf_store_title(qi, title); + qf_free(qi, qf_idx); + qf_store_title(qi, qf_idx, title); } TV_LIST_ITER_CONST(list, li, { @@ -4228,6 +4233,7 @@ static int qf_add_entries(qf_info_T *qi, list_T *list, char_u *title, } int status = qf_add_entry(qi, + qf_idx, NULL, // dir (char_u *)filename, bufnum, @@ -4250,16 +4256,16 @@ static int qf_add_entries(qf_info_T *qi, list_T *list, char_u *title, } }); - if (qi->qf_lists[qi->qf_curlist].qf_index == 0) { + if (qi->qf_lists[qf_idx].qf_index == 0) { // no valid entry - qi->qf_lists[qi->qf_curlist].qf_nonevalid = true; + qi->qf_lists[qf_idx].qf_nonevalid = true; } else { - qi->qf_lists[qi->qf_curlist].qf_nonevalid = false; + qi->qf_lists[qf_idx].qf_nonevalid = false; } if (action != 'a') { - qi->qf_lists[qi->qf_curlist].qf_ptr = qi->qf_lists[qi->qf_curlist].qf_start; - if (qi->qf_lists[qi->qf_curlist].qf_count > 0) { - qi->qf_lists[qi->qf_curlist].qf_index = 1; + qi->qf_lists[qf_idx].qf_ptr = qi->qf_lists[qf_idx].qf_start; + if (qi->qf_lists[qf_idx].qf_count > 0) { + qi->qf_lists[qf_idx].qf_index = 1; } } @@ -4400,7 +4406,7 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title, } else if (what != NULL) { retval = qf_set_properties(qi, what, action); } else { - retval = qf_add_entries(qi, list, title, action); + retval = qf_add_entries(qi, qi->qf_curlist, list, title, action); } return retval; @@ -4718,6 +4724,7 @@ void ex_helpgrep(exarg_T *eap) line[--l] = NUL; if (qf_add_entry(qi, + qi->qf_curlist, NULL, // dir fnames[fi], 0, -- cgit From caf94c72c51b3595676907c66e6259785a87420b Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sat, 30 Dec 2017 07:56:12 -0500 Subject: lint --- src/nvim/quickfix.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index bf2993b320..120a449690 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -1186,10 +1186,11 @@ qf_init_end: static void qf_store_title(qf_info_T *qi, int qf_idx, char_u *title) { if (title != NULL) { - char_u *p = xmalloc(STRLEN(title) + 2); + size_t len = STRLEN(title) + 1; + char_u *p = xmallocz(len); qi->qf_lists[qf_idx].qf_title = p; - sprintf((char *)p, ":%s", (char *)title); + snprintf((char *)p, len + 1, ":%s", (char *)title); } } @@ -1311,7 +1312,7 @@ static int qf_add_entry(qf_info_T *qi, int qf_idx, char_u *dir, char_u *fname, lastp = &qi->qf_lists[qf_idx].qf_last; if (qi->qf_lists[qf_idx].qf_count == 0) { - /* first element in the list */ + // first element in the list qi->qf_lists[qf_idx].qf_start = qfp; qi->qf_lists[qf_idx].qf_ptr = qfp; qi->qf_lists[qf_idx].qf_index = 0; @@ -1326,7 +1327,7 @@ static int qf_add_entry(qf_info_T *qi, int qf_idx, char_u *dir, char_u *fname, *lastp = qfp; qi->qf_lists[qf_idx].qf_count++; if (qi->qf_lists[qf_idx].qf_index == 0 && qfp->qf_valid) { - /* first valid entry */ + // first valid entry qi->qf_lists[qf_idx].qf_index = qi->qf_lists[qf_idx].qf_count; qi->qf_lists[qf_idx].qf_ptr = qfp; } -- cgit From 6742fd8aead06e45f19b59222f96ccdcb1748e4c Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sat, 30 Dec 2017 23:39:51 -0500 Subject: vim-patch:8.0.0634: cannot easily get to the last quickfix list Problem: Cannot easily get to the last quickfix list. Solution: Add "$" as a value for the "nr" argument of getqflist() and setqflist(). (Yegappan Lakshmanan) https://github.com/vim/vim/commit/875feea6ce223462d55543735143d747dcaf4287 --- src/nvim/quickfix.c | 47 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 12 deletions(-) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 120a449690..1d368bf87a 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -4088,16 +4088,22 @@ enum { int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict) { qf_info_T *qi = &ql_info; + dictitem_T *di; if (wp != NULL) { qi = GET_LOC_LIST(wp); if (qi == NULL) { + // If querying for the size of the location list, return 0 + if (((di = tv_dict_find(what, S_LEN("nr"))) != NULL) + && (di->di_tv.v_type == VAR_STRING) + && strequal((const char *)di->di_tv.vval.v_string, "$")) { + return tv_dict_add_nr(retdict, S_LEN("nr"), 0); + } return FAIL; } } int status = OK; - dictitem_T *di; int flags = QF_GETLIST_NONE; int qf_idx = qi->qf_curlist; // default is the current list @@ -4110,6 +4116,17 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict) if (qf_idx < 0 || qf_idx >= qi->qf_listcount) { return FAIL; } + } else if (qi->qf_listcount == 0) { // stack is empty + return FAIL; + } + flags |= QF_GETLIST_NR; + } else if (di->di_tv.v_type == VAR_STRING + && strequal((const char *)di->di_tv.vval.v_string, "$")) { + // Get the last quickfix list number + if (qi->qf_listcount > 0) { + qf_idx = qi->qf_listcount - 1; + } else { + qf_idx = -1; // Quickfix stack is empty } flags |= QF_GETLIST_NR; } else { @@ -4117,20 +4134,22 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict) } } - if (tv_dict_find(what, S_LEN("all")) != NULL) { - flags |= QF_GETLIST_ALL; - } + if (qf_idx != -1) { + if (tv_dict_find(what, S_LEN("all")) != NULL) { + flags |= QF_GETLIST_ALL; + } - if (tv_dict_find(what, S_LEN("title")) != NULL) { - flags |= QF_GETLIST_TITLE; - } + if (tv_dict_find(what, S_LEN("title")) != NULL) { + flags |= QF_GETLIST_TITLE; + } - if (tv_dict_find(what, S_LEN("winid")) != NULL) { - flags |= QF_GETLIST_WINID; - } + if (tv_dict_find(what, S_LEN("winid")) != NULL) { + flags |= QF_GETLIST_WINID; + } - if (tv_dict_find(what, S_LEN("context")) != NULL) { - flags |= QF_GETLIST_CONTEXT; + if (tv_dict_find(what, S_LEN("context")) != NULL) { + flags |= QF_GETLIST_CONTEXT; + } } if (flags & QF_GETLIST_TITLE) { @@ -4296,6 +4315,10 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action) if (qf_idx < 0 || qf_idx >= qi->qf_listcount) { return FAIL; } + } else if (di->di_tv.v_type == VAR_STRING + && strequal((const char *)di->di_tv.vval.v_string, "$") + && qi->qf_listcount > 0) { + qf_idx = qi->qf_listcount - 1; } else { return FAIL; } -- cgit From d0c4bd23f78ee00943725ea77a63f2a223dba66b Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sun, 31 Dec 2017 00:36:35 -0500 Subject: vim-patch:8.0.0657: cannot get and set quickfix list items Problem: Cannot get and set quickfix list items. Solution: Add the "items" argument to getqflist() and setqflist(). (Yegappan Lakshmanan) https://github.com/vim/vim/commit/6a8958db259d4444da6e6956e54a6513c1af8860 --- src/nvim/quickfix.c | 81 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 63 insertions(+), 18 deletions(-) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 1d368bf87a..224e43008d 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -76,18 +76,25 @@ struct qfline_S { */ #define LISTCOUNT 10 +/// Quickfix/Location list definition +/// +/// Usually the list contains one or more entries. But an empty list can be +/// created using setqflist()/setloclist() with a title and/or user context +/// information and entries can be added later using setqflist()/setloclist(). typedef struct qf_list_S { - qfline_T *qf_start; // pointer to the first error - qfline_T *qf_last; // pointer to the last error - qfline_T *qf_ptr; // pointer to the current error - int qf_count; // number of errors (0 means no error list) - int qf_index; // current index in the error list - int qf_nonevalid; // TRUE if not a single valid entry found - char_u *qf_title; // title derived from the command that created - // the error list - typval_T *qf_ctx; // context set by setqflist/setloclist + qfline_T *qf_start; ///< pointer to the first error + qfline_T *qf_last; ///< pointer to the last error + qfline_T *qf_ptr; ///< pointer to the current error + int qf_count; ///< number of errors (0 means empty list) + int qf_index; ///< current index in the error list + int qf_nonevalid; ///< TRUE if not a single valid entry found + char_u *qf_title; ///< title derived from the command that created + ///< the error list or set by setqflist + typval_T *qf_ctx; ///< context set by setqflist/setloclist } qf_list_T; +/// Quickfix/Location list stack definition +/// Contains a list of quickfix/location lists (qf_list_T) struct qf_info_S { /* * Count of references to this list. Used only for location lists. @@ -1185,6 +1192,9 @@ qf_init_end: static void qf_store_title(qf_info_T *qi, int qf_idx, char_u *title) { + xfree(qi->qf_lists[qf_idx].qf_title); + qi->qf_lists[qf_idx].qf_title = NULL; + if (title != NULL) { size_t len = STRLEN(title) + 1; char_u *p = xmallocz(len); @@ -2396,8 +2406,9 @@ void qf_history(exarg_T *eap) } } -/// Free all the entries in the error list "idx". -static void qf_free(qf_info_T *qi, int idx) +/// Free all the entries in the error list "idx". Note that other information +/// associated with the list like context and title are not freed. +static void qf_free_items(qf_info_T *qi, int idx) { qfline_T *qfp; qfline_T *qfpnext; @@ -2421,12 +2432,9 @@ static void qf_free(qf_info_T *qi, int idx) qi->qf_lists[idx].qf_start = qfpnext; qi->qf_lists[idx].qf_count--; } - xfree(qi->qf_lists[idx].qf_title); + qi->qf_lists[idx].qf_start = NULL; qi->qf_lists[idx].qf_ptr = NULL; - qi->qf_lists[idx].qf_title = NULL; - tv_free(qi->qf_lists[idx].qf_ctx); - qi->qf_lists[idx].qf_ctx = NULL; qi->qf_lists[idx].qf_index = 0; qi->qf_lists[idx].qf_start = NULL; qi->qf_lists[idx].qf_last = NULL; @@ -2442,6 +2450,18 @@ static void qf_free(qf_info_T *qi, int idx) qi->qf_multiscan = false; } +/// Free error list "idx". Frees all the entries in the quickfix list, +/// associated context information and the title. +static void qf_free(qf_info_T *qi, int idx) +{ + qf_free_items(qi, idx); + + xfree(qi->qf_lists[idx].qf_title); + qi->qf_lists[idx].qf_title = NULL; + tv_free(qi->qf_lists[idx].qf_ctx); + qi->qf_lists[idx].qf_ctx = NULL; +} + /* * qf_mark_adjust: adjust marks */ @@ -4150,6 +4170,10 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict) if (tv_dict_find(what, S_LEN("context")) != NULL) { flags |= QF_GETLIST_CONTEXT; } + + if (tv_dict_find(what, S_LEN("items")) != NULL) { + flags |= QF_GETLIST_ITEMS; + } } if (flags & QF_GETLIST_TITLE) { @@ -4168,6 +4192,11 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict) status = tv_dict_add_nr(retdict, S_LEN("winid"), win->handle); } } + if ((status == OK) && (flags & QF_GETLIST_ITEMS)) { + list_T *l = tv_list_alloc(); + (void)get_errorlist(wp, qf_idx, l); + tv_dict_add_list(retdict, S_LEN("items"), l); + } if ((status == OK) && (flags & QF_GETLIST_CONTEXT)) { if (qi->qf_lists[qf_idx].qf_ctx != NULL) { @@ -4204,7 +4233,7 @@ static int qf_add_entries(qf_info_T *qi, int qf_idx, list_T *list, // Adding to existing list, use last entry. old_last = qi->qf_lists[qf_idx].qf_last; } else if (action == 'r') { - qf_free(qi, qf_idx); + qf_free_items(qi, qf_idx); qf_store_title(qi, qf_idx, title); } @@ -4312,17 +4341,24 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action) if (di->di_tv.vval.v_number != 0) { qf_idx = (int)di->di_tv.vval.v_number - 1; } - if (qf_idx < 0 || qf_idx >= qi->qf_listcount) { + + if ((action == ' ' || action == 'a') && qf_idx == qi->qf_listcount) { + // When creating a new list, accept qf_idx pointing to the next + // non-available list + newlist = true; + } else if (qf_idx < 0 || qf_idx >= qi->qf_listcount) { return FAIL; + } else { + newlist = false; // use the specified list } } else if (di->di_tv.v_type == VAR_STRING && strequal((const char *)di->di_tv.vval.v_string, "$") && qi->qf_listcount > 0) { qf_idx = qi->qf_listcount - 1; + newlist = false; } else { return FAIL; } - newlist = false; // use the specified list } if (newlist) { @@ -4341,6 +4377,15 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action) retval = OK; } } + if ((di = tv_dict_find(what, S_LEN("items"))) != NULL) { + if (di->di_tv.v_type == VAR_LIST) { + char_u *title_save = vim_strsave(qi->qf_lists[qf_idx].qf_title); + + retval = qf_add_entries(qi, qf_idx, di->di_tv.vval.v_list, + title_save, action == ' ' ? 'a' : action); + xfree(title_save); + } + } if ((di = tv_dict_find(what, S_LEN("context"))) != NULL) { tv_free(qi->qf_lists[qf_idx].qf_ctx); -- cgit From 9ea1752d60589e8fc5e7184144bc6d1c1b9f16a3 Mon Sep 17 00:00:00 2001 From: ZyX Date: Wed, 3 Jan 2018 00:00:16 +0300 Subject: *: Provide list length when allocating lists --- src/nvim/quickfix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 224e43008d..63252df3dc 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -4193,7 +4193,7 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict) } } if ((status == OK) && (flags & QF_GETLIST_ITEMS)) { - list_T *l = tv_list_alloc(); + list_T *l = tv_list_alloc(kListLenMayKnow); (void)get_errorlist(wp, qf_idx, l); tv_dict_add_list(retdict, S_LEN("items"), l); } -- cgit From 2d99b81ab5b7481e20c03376f0f40924daff491f Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Fri, 12 Jan 2018 08:32:28 +0100 Subject: shell: use msg_outtrans_len_attr for :!cmd fixes #7830 and #7788 --- src/nvim/quickfix.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 63252df3dc..ea2d13761c 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -3148,10 +3148,9 @@ void ex_make(exarg_T *eap) } msg_start(); MSG_PUTS(":!"); - msg_outtrans((char_u *) cmd); // show what we are doing + msg_outtrans((char_u *)cmd); // show what we are doing - // let the shell know if we are redirecting output or not - do_shell((char_u *) cmd, *p_sp != NUL ? kShellOptDoOut : 0); + do_shell((char_u *)cmd, 0); res = qf_init(wp, fname, (eap->cmdidx != CMD_make -- cgit From 6116af02efaaa67bdfe8bcabb5c46cf8e3293686 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 2 Feb 2018 03:04:09 +0100 Subject: vim-patch:8.0.1403: using freed buffer in grep command Problem: Using freed buffer in grep command. (gy741, Dominique Pelle) Solution: Lock the dummy buffer to avoid autocommands wiping it out. https://github.com/vim/vim/commit/4fb921e388b9a042573ab06cce36e92874954197 --- src/nvim/quickfix.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index ea2d13761c..1aeadcec4a 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -3909,6 +3909,7 @@ load_dummy_buffer ( bufref_T newbuf_to_wipe; int failed = true; aco_save_T aco; + int readfile_result; // Allocate a buffer without putting it in the buffer list. newbuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY); @@ -3922,7 +3923,9 @@ load_dummy_buffer ( /* need to open the memfile before putting the buffer in a window */ if (ml_open(newbuf) == OK) { - /* set curwin/curbuf to buf and save a few things */ + // Make sure this buffer isn't wiped out by auto commands. + newbuf->b_locked++; + // set curwin/curbuf to buf and save a few things aucmd_prepbuf(&aco, newbuf); /* Need to set the filename for autocommands. */ @@ -3936,9 +3939,11 @@ load_dummy_buffer ( curbuf->b_flags &= ~BF_DUMMY; newbuf_to_wipe.br_buf = NULL; - if (readfile(fname, NULL, - (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM, - NULL, READ_NEW | READ_DUMMY) == OK + readfile_result = readfile(fname, NULL, (linenr_T)0, (linenr_T)0, + (linenr_T)MAXLNUM, NULL, + READ_NEW | READ_DUMMY); + newbuf->b_locked--; + if (readfile_result == OK && !got_int && !(curbuf->b_flags & BF_NEW)) { failed = FALSE; -- cgit From 7ae41442088a4b1b1cd324b683defd87998ba75c Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sat, 24 Mar 2018 13:56:55 +0100 Subject: refactor/rename: path_try_shorten_fname() --- src/nvim/quickfix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 1aeadcec4a..2d8c353f92 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -3649,8 +3649,8 @@ void ex_vimgrep(exarg_T *eap) cur_qf_start = qi->qf_lists[qi->qf_curlist].qf_start; seconds = (time_t)0; - for (fi = 0; fi < fcount && !got_int && tomatch > 0; ++fi) { - fname = path_shorten_fname_if_possible(fnames[fi]); + for (fi = 0; fi < fcount && !got_int && tomatch > 0; fi++) { + fname = path_try_shorten_fname(fnames[fi]); if (time(NULL) > seconds) { /* Display the file name every second or so, show the user we are * working on it. */ -- cgit From 607e0d2202053a2db290f00d99364f4895917f39 Mon Sep 17 00:00:00 2001 From: ZyX Date: Wed, 4 Jan 2017 18:45:10 +0300 Subject: shada: Save numbered marks Problems so far: - Marks in the current instance are not adjusted. - Duplicates are not removed (not that it works in Vim either now, not at 8.0.134 at least). --- src/nvim/quickfix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/quickfix.c') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 2d8c353f92..46124e0672 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -3029,7 +3029,7 @@ static void qf_fill_buffer(qf_info_T *qi, buf_T *buf, qfline_T *old_last) /* * Return TRUE if "buf" is the quickfix buffer. */ -int bt_quickfix(buf_T *buf) +int bt_quickfix(const buf_T *const buf) { return buf != NULL && buf->b_p_bt[0] == 'q'; } -- cgit