1 /* vi:set ts=8 sts=4 sw=4 noet: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * 5 * Do ":help uganda" in Vim to read copying and usage conditions. 6 * Do ":help credits" in Vim to see a list of people who contributed. 7 * See README.txt for an overview of the Vim source code. 8 */ 9 10 /* 11 * quickfix.c: functions for quickfix mode, using a file with error messages 12 */ 13 14 #include "vim.h" 15 16 #if defined(FEAT_QUICKFIX) || defined(PROTO) 17 18 struct dir_stack_T 19 { 20 struct dir_stack_T *next; 21 char_u *dirname; 22 }; 23 24 /* 25 * For each error the next struct is allocated and linked in a list. 26 */ 27 typedef struct qfline_S qfline_T; 28 struct qfline_S 29 { 30 qfline_T *qf_next; /* pointer to next error in the list */ 31 qfline_T *qf_prev; /* pointer to previous error in the list */ 32 linenr_T qf_lnum; /* line number where the error occurred */ 33 int qf_fnum; /* file number for the line */ 34 int qf_col; /* column where the error occurred */ 35 int qf_nr; /* error number */ 36 char_u *qf_module; /* module name for this error */ 37 char_u *qf_pattern; /* search pattern for the error */ 38 char_u *qf_text; /* description of the error */ 39 char_u qf_viscol; /* set to TRUE if qf_col is screen column */ 40 char_u qf_cleared; /* set to TRUE if line has been deleted */ 41 char_u qf_type; /* type of the error (mostly 'E'); 1 for 42 :helpgrep */ 43 char_u qf_valid; /* valid error message detected */ 44 }; 45 46 /* 47 * There is a stack of error lists. 48 */ 49 #define LISTCOUNT 10 50 #define INVALID_QFIDX (-1) 51 52 /* 53 * Quickfix/Location list definition 54 * Contains a list of entries (qfline_T). qf_start points to the first entry 55 * and qf_last points to the last entry. qf_count contains the list size. 56 * 57 * Usually the list contains one or more entries. But an empty list can be 58 * created using setqflist()/setloclist() with a title and/or user context 59 * information and entries can be added later using setqflist()/setloclist(). 60 */ 61 typedef struct qf_list_S 62 { 63 int_u qf_id; /* Unique identifier for this list */ 64 qfline_T *qf_start; /* pointer to the first error */ 65 qfline_T *qf_last; /* pointer to the last error */ 66 qfline_T *qf_ptr; /* pointer to the current error */ 67 int qf_count; /* number of errors (0 means empty list) */ 68 int qf_index; /* current index in the error list */ 69 int qf_nonevalid; /* TRUE if not a single valid entry found */ 70 char_u *qf_title; /* title derived from the command that created 71 * the error list or set by setqflist */ 72 typval_T *qf_ctx; /* context set by setqflist/setloclist */ 73 74 struct dir_stack_T *qf_dir_stack; 75 char_u *qf_directory; 76 struct dir_stack_T *qf_file_stack; 77 char_u *qf_currfile; 78 int qf_multiline; 79 int qf_multiignore; 80 int qf_multiscan; 81 long qf_changedtick; 82 } qf_list_T; 83 84 /* 85 * Quickfix/Location list stack definition 86 * Contains a list of quickfix/location lists (qf_list_T) 87 */ 88 struct qf_info_S 89 { 90 /* 91 * Count of references to this list. Used only for location lists. 92 * When a location list window reference this list, qf_refcount 93 * will be 2. Otherwise, qf_refcount will be 1. When qf_refcount 94 * reaches 0, the list is freed. 95 */ 96 int qf_refcount; 97 int qf_listcount; /* current number of lists */ 98 int qf_curlist; /* current error list */ 99 qf_list_T qf_lists[LISTCOUNT]; 100 }; 101 102 static qf_info_T ql_info; /* global quickfix list */ 103 static int_u last_qf_id = 0; /* Last used quickfix list id */ 104 105 #define FMT_PATTERNS 11 /* maximum number of % recognized */ 106 107 /* 108 * Structure used to hold the info of one part of 'errorformat' 109 */ 110 typedef struct efm_S efm_T; 111 struct efm_S 112 { 113 regprog_T *prog; /* pre-formatted part of 'errorformat' */ 114 efm_T *next; /* pointer to next (NULL if last) */ 115 char_u addr[FMT_PATTERNS]; /* indices of used % patterns */ 116 char_u prefix; /* prefix of this format line: */ 117 /* 'D' enter directory */ 118 /* 'X' leave directory */ 119 /* 'A' start of multi-line message */ 120 /* 'E' error message */ 121 /* 'W' warning message */ 122 /* 'I' informational message */ 123 /* 'C' continuation line */ 124 /* 'Z' end of multi-line message */ 125 /* 'G' general, unspecific message */ 126 /* 'P' push file (partial) message */ 127 /* 'Q' pop/quit file (partial) message */ 128 /* 'O' overread (partial) message */ 129 char_u flags; /* additional flags given in prefix */ 130 /* '-' do not include this line */ 131 /* '+' include whole line in message */ 132 int conthere; /* %> used */ 133 }; 134 135 static efm_T *fmt_start = NULL; /* cached across qf_parse_line() calls */ 136 137 static int qf_init_ext(qf_info_T *qi, int qf_idx, char_u *efile, buf_T *buf, typval_T *tv, char_u *errorformat, int newlist, linenr_T lnumfirst, linenr_T lnumlast, char_u *qf_title, char_u *enc); 138 static void qf_new_list(qf_info_T *qi, char_u *qf_title); 139 static int qf_add_entry(qf_info_T *qi, int qf_idx, char_u *dir, char_u *fname, char_u *module, int bufnum, char_u *mesg, long lnum, int col, int vis_col, char_u *pattern, int nr, int type, int valid); 140 static qf_info_T *ll_new_list(void); 141 static void qf_free(qf_info_T *qi, int idx); 142 static char_u *qf_types(int, int); 143 static int qf_get_fnum(qf_info_T *qi, int qf_idx, char_u *, char_u *); 144 static char_u *qf_push_dir(char_u *, struct dir_stack_T **, int is_file_stack); 145 static char_u *qf_pop_dir(struct dir_stack_T **); 146 static char_u *qf_guess_filepath(qf_info_T *qi, int qf_idx, char_u *); 147 static void qf_fmt_text(char_u *text, char_u *buf, int bufsize); 148 static int qf_win_pos_update(qf_info_T *qi, int old_qf_index); 149 static win_T *qf_find_win(qf_info_T *qi); 150 static buf_T *qf_find_buf(qf_info_T *qi); 151 static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last); 152 static void qf_set_title_var(qf_info_T *qi); 153 static void qf_fill_buffer(qf_info_T *qi, buf_T *buf, qfline_T *old_last); 154 static char_u *get_mef_name(void); 155 static buf_T *load_dummy_buffer(char_u *fname, char_u *dirname_start, char_u *resulting_dir); 156 static void wipe_dummy_buffer(buf_T *buf, char_u *dirname_start); 157 static void unload_dummy_buffer(buf_T *buf, char_u *dirname_start); 158 static qf_info_T *ll_get_or_alloc_list(win_T *); 159 160 /* Quickfix window check helper macro */ 161 #define IS_QF_WINDOW(wp) (bt_quickfix(wp->w_buffer) && wp->w_llist_ref == NULL) 162 /* Location list window check helper macro */ 163 #define IS_LL_WINDOW(wp) (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL) 164 /* 165 * Return location list for window 'wp' 166 * For location list window, return the referenced location list 167 */ 168 #define GET_LOC_LIST(wp) (IS_LL_WINDOW(wp) ? wp->w_llist_ref : wp->w_llist) 169 170 /* 171 * Looking up a buffer can be slow if there are many. Remember the last one 172 * to make this a lot faster if there are multiple matches in the same file. 173 */ 174 static char_u *qf_last_bufname = NULL; 175 static bufref_T qf_last_bufref = {NULL, 0, 0}; 176 177 static char *e_loc_list_changed = 178 N_("E926: Current location list was changed"); 179 180 /* 181 * Read the errorfile "efile" into memory, line by line, building the error 182 * list. Set the error list's title to qf_title. 183 * Return -1 for error, number of errors for success. 184 */ 185 int 186 qf_init(win_T *wp, 187 char_u *efile, 188 char_u *errorformat, 189 int newlist, /* TRUE: start a new error list */ 190 char_u *qf_title, 191 char_u *enc) 192 { 193 qf_info_T *qi = &ql_info; 194 195 if (wp != NULL) 196 { 197 qi = ll_get_or_alloc_list(wp); 198 if (qi == NULL) 199 return FAIL; 200 } 201 202 return qf_init_ext(qi, qi->qf_curlist, efile, curbuf, NULL, errorformat, 203 newlist, (linenr_T)0, (linenr_T)0, qf_title, enc); 204 } 205 206 /* 207 * Maximum number of bytes allowed per line while reading a errorfile. 208 */ 209 #define LINE_MAXLEN 4096 210 211 static struct fmtpattern 212 { 213 char_u convchar; 214 char *pattern; 215 } fmt_pat[FMT_PATTERNS] = 216 { 217 {'f', ".\\+"}, /* only used when at end */ 218 {'n', "\\d\\+"}, 219 {'l', "\\d\\+"}, 220 {'c', "\\d\\+"}, 221 {'t', "."}, 222 {'m', ".\\+"}, 223 {'r', ".*"}, 224 {'p', "[- .]*"}, 225 {'v', "\\d\\+"}, 226 {'s', ".\\+"}, 227 {'o', ".\\+"} 228 }; 229 230 /* 231 * Converts a 'errorformat' string to regular expression pattern 232 */ 233 static int 234 efm_to_regpat( 235 char_u *efm, 236 int len, 237 efm_T *fmt_ptr, 238 char_u *regpat, 239 char_u *errmsg) 240 { 241 char_u *ptr; 242 char_u *efmp; 243 char_u *srcptr; 244 int round; 245 int idx = 0; 246 247 /* 248 * Build regexp pattern from current 'errorformat' option 249 */ 250 ptr = regpat; 251 *ptr++ = '^'; 252 round = 0; 253 for (efmp = efm; efmp < efm + len; ++efmp) 254 { 255 if (*efmp == '%') 256 { 257 ++efmp; 258 for (idx = 0; idx < FMT_PATTERNS; ++idx) 259 if (fmt_pat[idx].convchar == *efmp) 260 break; 261 if (idx < FMT_PATTERNS) 262 { 263 if (fmt_ptr->addr[idx]) 264 { 265 sprintf((char *)errmsg, 266 _("E372: Too many %%%c in format string"), *efmp); 267 EMSG(errmsg); 268 return -1; 269 } 270 if ((idx 271 && idx < 6 272 && vim_strchr((char_u *)"DXOPQ", 273 fmt_ptr->prefix) != NULL) 274 || (idx == 6 275 && vim_strchr((char_u *)"OPQ", 276 fmt_ptr->prefix) == NULL)) 277 { 278 sprintf((char *)errmsg, 279 _("E373: Unexpected %%%c in format string"), *efmp); 280 EMSG(errmsg); 281 return -1; 282 } 283 fmt_ptr->addr[idx] = (char_u)++round; 284 *ptr++ = '\\'; 285 *ptr++ = '('; 286 #ifdef BACKSLASH_IN_FILENAME 287 if (*efmp == 'f') 288 { 289 /* Also match "c:" in the file name, even when 290 * checking for a colon next: "%f:". 291 * "\%(\a:\)\=" */ 292 STRCPY(ptr, "\\%(\\a:\\)\\="); 293 ptr += 10; 294 } 295 #endif 296 if (*efmp == 'f' && efmp[1] != NUL) 297 { 298 if (efmp[1] != '\\' && efmp[1] != '%') 299 { 300 /* A file name may contain spaces, but this isn't 301 * in "\f". For "%f:%l:%m" there may be a ":" in 302 * the file name. Use ".\{-1,}x" instead (x is 303 * the next character), the requirement that :999: 304 * follows should work. */ 305 STRCPY(ptr, ".\\{-1,}"); 306 ptr += 7; 307 } 308 else 309 { 310 /* File name followed by '\\' or '%': include as 311 * many file name chars as possible. */ 312 STRCPY(ptr, "\\f\\+"); 313 ptr += 4; 314 } 315 } 316 else 317 { 318 srcptr = (char_u *)fmt_pat[idx].pattern; 319 while ((*ptr = *srcptr++) != NUL) 320 ++ptr; 321 } 322 *ptr++ = '\\'; 323 *ptr++ = ')'; 324 } 325 else if (*efmp == '*') 326 { 327 if (*++efmp == '[' || *efmp == '\\') 328 { 329 if ((*ptr++ = *efmp) == '[') /* %*[^a-z0-9] etc. */ 330 { 331 if (efmp[1] == '^') 332 *ptr++ = *++efmp; 333 if (efmp < efm + len) 334 { 335 *ptr++ = *++efmp; /* could be ']' */ 336 while (efmp < efm + len 337 && (*ptr++ = *++efmp) != ']') 338 /* skip */; 339 if (efmp == efm + len) 340 { 341 EMSG(_("E374: Missing ] in format string")); 342 return -1; 343 } 344 } 345 } 346 else if (efmp < efm + len) /* %*\D, %*\s etc. */ 347 *ptr++ = *++efmp; 348 *ptr++ = '\\'; 349 *ptr++ = '+'; 350 } 351 else 352 { 353 /* TODO: scanf()-like: %*ud, %*3c, %*f, ... ? */ 354 sprintf((char *)errmsg, 355 _("E375: Unsupported %%%c in format string"), *efmp); 356 EMSG(errmsg); 357 return -1; 358 } 359 } 360 else if (vim_strchr((char_u *)"%\\.^$~[", *efmp) != NULL) 361 *ptr++ = *efmp; /* regexp magic characters */ 362 else if (*efmp == '#') 363 *ptr++ = '*'; 364 else if (*efmp == '>') 365 fmt_ptr->conthere = TRUE; 366 else if (efmp == efm + 1) /* analyse prefix */ 367 { 368 if (vim_strchr((char_u *)"+-", *efmp) != NULL) 369 fmt_ptr->flags = *efmp++; 370 if (vim_strchr((char_u *)"DXAEWICZGOPQ", *efmp) != NULL) 371 fmt_ptr->prefix = *efmp; 372 else 373 { 374 sprintf((char *)errmsg, 375 _("E376: Invalid %%%c in format string prefix"), *efmp); 376 EMSG(errmsg); 377 return -1; 378 } 379 } 380 else 381 { 382 sprintf((char *)errmsg, 383 _("E377: Invalid %%%c in format string"), *efmp); 384 EMSG(errmsg); 385 return -1; 386 } 387 } 388 else /* copy normal character */ 389 { 390 if (*efmp == '\\' && efmp + 1 < efm + len) 391 ++efmp; 392 else if (vim_strchr((char_u *)".*^$~[", *efmp) != NULL) 393 *ptr++ = '\\'; /* escape regexp atoms */ 394 if (*efmp) 395 *ptr++ = *efmp; 396 } 397 } 398 *ptr++ = '$'; 399 *ptr = NUL; 400 401 return 0; 402 } 403 404 static void 405 free_efm_list(efm_T **efm_first) 406 { 407 efm_T *efm_ptr; 408 409 for (efm_ptr = *efm_first; efm_ptr != NULL; efm_ptr = *efm_first) 410 { 411 *efm_first = efm_ptr->next; 412 vim_regfree(efm_ptr->prog); 413 vim_free(efm_ptr); 414 } 415 fmt_start = NULL; 416 } 417 418 /* Parse 'errorformat' option */ 419 static efm_T * 420 parse_efm_option(char_u *efm) 421 { 422 char_u *errmsg = NULL; 423 int errmsglen; 424 efm_T *fmt_ptr = NULL; 425 efm_T *fmt_first = NULL; 426 efm_T *fmt_last = NULL; 427 char_u *fmtstr = NULL; 428 int len; 429 int i; 430 int round; 431 432 errmsglen = CMDBUFFSIZE + 1; 433 errmsg = alloc_id(errmsglen, aid_qf_errmsg); 434 if (errmsg == NULL) 435 goto parse_efm_end; 436 437 /* 438 * Each part of the format string is copied and modified from errorformat 439 * to regex prog. Only a few % characters are allowed. 440 */ 441 442 /* 443 * Get some space to modify the format string into. 444 */ 445 i = (FMT_PATTERNS * 3) + ((int)STRLEN(efm) << 2); 446 for (round = FMT_PATTERNS; round > 0; ) 447 i += (int)STRLEN(fmt_pat[--round].pattern); 448 #ifdef BACKSLASH_IN_FILENAME 449 i += 12; /* "%f" can become twelve chars longer (see efm_to_regpat) */ 450 #else 451 i += 2; /* "%f" can become two chars longer */ 452 #endif 453 if ((fmtstr = alloc(i)) == NULL) 454 goto parse_efm_error; 455 456 while (efm[0] != NUL) 457 { 458 /* 459 * Allocate a new eformat structure and put it at the end of the list 460 */ 461 fmt_ptr = (efm_T *)alloc_clear((unsigned)sizeof(efm_T)); 462 if (fmt_ptr == NULL) 463 goto parse_efm_error; 464 if (fmt_first == NULL) /* first one */ 465 fmt_first = fmt_ptr; 466 else 467 fmt_last->next = fmt_ptr; 468 fmt_last = fmt_ptr; 469 470 /* 471 * Isolate one part in the 'errorformat' option 472 */ 473 for (len = 0; efm[len] != NUL && efm[len] != ','; ++len) 474 if (efm[len] == '\\' && efm[len + 1] != NUL) 475 ++len; 476 477 if (efm_to_regpat(efm, len, fmt_ptr, fmtstr, errmsg) == -1) 478 goto parse_efm_error; 479 if ((fmt_ptr->prog = vim_regcomp(fmtstr, RE_MAGIC + RE_STRING)) == NULL) 480 goto parse_efm_error; 481 /* 482 * Advance to next part 483 */ 484 efm = skip_to_option_part(efm + len); /* skip comma and spaces */ 485 } 486 487 if (fmt_first == NULL) /* nothing found */ 488 EMSG(_("E378: 'errorformat' contains no pattern")); 489 490 goto parse_efm_end; 491 492 parse_efm_error: 493 free_efm_list(&fmt_first); 494 495 parse_efm_end: 496 vim_free(fmtstr); 497 vim_free(errmsg); 498 499 return fmt_first; 500 } 501 502 enum { 503 QF_FAIL = 0, 504 QF_OK = 1, 505 QF_END_OF_INPUT = 2, 506 QF_NOMEM = 3, 507 QF_IGNORE_LINE = 4 508 }; 509 510 typedef struct { 511 char_u *linebuf; 512 int linelen; 513 char_u *growbuf; 514 int growbufsiz; 515 FILE *fd; 516 typval_T *tv; 517 char_u *p_str; 518 listitem_T *p_li; 519 buf_T *buf; 520 linenr_T buflnum; 521 linenr_T lnumlast; 522 vimconv_T vc; 523 } qfstate_T; 524 525 static char_u * 526 qf_grow_linebuf(qfstate_T *state, int newsz) 527 { 528 /* 529 * If the line exceeds LINE_MAXLEN exclude the last 530 * byte since it's not a NL character. 531 */ 532 state->linelen = newsz > LINE_MAXLEN ? LINE_MAXLEN - 1 : newsz; 533 if (state->growbuf == NULL) 534 { 535 state->growbuf = alloc(state->linelen + 1); 536 if (state->growbuf == NULL) 537 return NULL; 538 state->growbufsiz = state->linelen; 539 } 540 else if (state->linelen > state->growbufsiz) 541 { 542 state->growbuf = vim_realloc(state->growbuf, state->linelen + 1); 543 if (state->growbuf == NULL) 544 return NULL; 545 state->growbufsiz = state->linelen; 546 } 547 return state->growbuf; 548 } 549 550 /* 551 * Get the next string (separated by newline) from state->p_str. 552 */ 553 static int 554 qf_get_next_str_line(qfstate_T *state) 555 { 556 /* Get the next line from the supplied string */ 557 char_u *p_str = state->p_str; 558 char_u *p; 559 int len; 560 561 if (*p_str == NUL) /* Reached the end of the string */ 562 return QF_END_OF_INPUT; 563 564 p = vim_strchr(p_str, '\n'); 565 if (p != NULL) 566 len = (int)(p - p_str) + 1; 567 else 568 len = (int)STRLEN(p_str); 569 570 if (len > IOSIZE - 2) 571 { 572 state->linebuf = qf_grow_linebuf(state, len); 573 if (state->linebuf == NULL) 574 return QF_NOMEM; 575 } 576 else 577 { 578 state->linebuf = IObuff; 579 state->linelen = len; 580 } 581 vim_strncpy(state->linebuf, p_str, state->linelen); 582 583 /* 584 * Increment using len in order to discard the rest of the 585 * line if it exceeds LINE_MAXLEN. 586 */ 587 p_str += len; 588 state->p_str = p_str; 589 590 return QF_OK; 591 } 592 593 /* 594 * Get the next string from state->p_Li. 595 */ 596 static int 597 qf_get_next_list_line(qfstate_T *state) 598 { 599 listitem_T *p_li = state->p_li; 600 int len; 601 602 while (p_li != NULL 603 && (p_li->li_tv.v_type != VAR_STRING 604 || p_li->li_tv.vval.v_string == NULL)) 605 p_li = p_li->li_next; /* Skip non-string items */ 606 607 if (p_li == NULL) /* End of the list */ 608 { 609 state->p_li = NULL; 610 return QF_END_OF_INPUT; 611 } 612 613 len = (int)STRLEN(p_li->li_tv.vval.v_string); 614 if (len > IOSIZE - 2) 615 { 616 state->linebuf = qf_grow_linebuf(state, len); 617 if (state->linebuf == NULL) 618 return QF_NOMEM; 619 } 620 else 621 { 622 state->linebuf = IObuff; 623 state->linelen = len; 624 } 625 626 vim_strncpy(state->linebuf, p_li->li_tv.vval.v_string, state->linelen); 627 628 state->p_li = p_li->li_next; /* next item */ 629 return QF_OK; 630 } 631 632 /* 633 * Get the next string from state->buf. 634 */ 635 static int 636 qf_get_next_buf_line(qfstate_T *state) 637 { 638 char_u *p_buf = NULL; 639 int len; 640 641 /* Get the next line from the supplied buffer */ 642 if (state->buflnum > state->lnumlast) 643 return QF_END_OF_INPUT; 644 645 p_buf = ml_get_buf(state->buf, state->buflnum, FALSE); 646 state->buflnum += 1; 647 648 len = (int)STRLEN(p_buf); 649 if (len > IOSIZE - 2) 650 { 651 state->linebuf = qf_grow_linebuf(state, len); 652 if (state->linebuf == NULL) 653 return QF_NOMEM; 654 } 655 else 656 { 657 state->linebuf = IObuff; 658 state->linelen = len; 659 } 660 vim_strncpy(state->linebuf, p_buf, state->linelen); 661 662 return QF_OK; 663 } 664 665 /* 666 * Get the next string from file state->fd. 667 */ 668 static int 669 qf_get_next_file_line(qfstate_T *state) 670 { 671 int discard; 672 int growbuflen; 673 674 if (fgets((char *)IObuff, IOSIZE, state->fd) == NULL) 675 return QF_END_OF_INPUT; 676 677 discard = FALSE; 678 state->linelen = (int)STRLEN(IObuff); 679 if (state->linelen == IOSIZE - 1 && !(IObuff[state->linelen - 1] == '\n')) 680 { 681 /* 682 * The current line exceeds IObuff, continue reading using 683 * growbuf until EOL or LINE_MAXLEN bytes is read. 684 */ 685 if (state->growbuf == NULL) 686 { 687 state->growbufsiz = 2 * (IOSIZE - 1); 688 state->growbuf = alloc(state->growbufsiz); 689 if (state->growbuf == NULL) 690 return QF_NOMEM; 691 } 692 693 /* Copy the read part of the line, excluding null-terminator */ 694 memcpy(state->growbuf, IObuff, IOSIZE - 1); 695 growbuflen = state->linelen; 696 697 for (;;) 698 { 699 if (fgets((char *)state->growbuf + growbuflen, 700 state->growbufsiz - growbuflen, state->fd) == NULL) 701 break; 702 state->linelen = (int)STRLEN(state->growbuf + growbuflen); 703 growbuflen += state->linelen; 704 if ((state->growbuf)[growbuflen - 1] == '\n') 705 break; 706 if (state->growbufsiz == LINE_MAXLEN) 707 { 708 discard = TRUE; 709 break; 710 } 711 712 state->growbufsiz = 2 * state->growbufsiz < LINE_MAXLEN 713 ? 2 * state->growbufsiz : LINE_MAXLEN; 714 state->growbuf = vim_realloc(state->growbuf, state->growbufsiz); 715 if (state->growbuf == NULL) 716 return QF_NOMEM; 717 } 718 719 while (discard) 720 { 721 /* 722 * The current line is longer than LINE_MAXLEN, continue 723 * reading but discard everything until EOL or EOF is 724 * reached. 725 */ 726 if (fgets((char *)IObuff, IOSIZE, state->fd) == NULL 727 || (int)STRLEN(IObuff) < IOSIZE - 1 728 || IObuff[IOSIZE - 1] == '\n') 729 break; 730 } 731 732 state->linebuf = state->growbuf; 733 state->linelen = growbuflen; 734 } 735 else 736 state->linebuf = IObuff; 737 738 #ifdef FEAT_MBYTE 739 /* Convert a line if it contains a non-ASCII character. */ 740 if (state->vc.vc_type != CONV_NONE && has_non_ascii(state->linebuf)) 741 { 742 char_u *line; 743 744 line = string_convert(&state->vc, state->linebuf, &state->linelen); 745 if (line != NULL) 746 { 747 if (state->linelen < IOSIZE) 748 { 749 STRCPY(state->linebuf, line); 750 vim_free(line); 751 } 752 else 753 { 754 vim_free(state->growbuf); 755 state->linebuf = state->growbuf = line; 756 state->growbufsiz = state->linelen < LINE_MAXLEN 757 ? state->linelen : LINE_MAXLEN; 758 } 759 } 760 } 761 #endif 762 763 return QF_OK; 764 } 765 766 /* 767 * Get the next string from a file/buffer/list/string. 768 */ 769 static int 770 qf_get_nextline(qfstate_T *state) 771 { 772 int status = QF_FAIL; 773 774 if (state->fd == NULL) 775 { 776 if (state->tv != NULL) 777 { 778 if (state->tv->v_type == VAR_STRING) 779 /* Get the next line from the supplied string */ 780 status = qf_get_next_str_line(state); 781 else if (state->tv->v_type == VAR_LIST) 782 /* Get the next line from the supplied list */ 783 status = qf_get_next_list_line(state); 784 } 785 else 786 /* Get the next line from the supplied buffer */ 787 status = qf_get_next_buf_line(state); 788 } 789 else 790 /* Get the next line from the supplied file */ 791 status = qf_get_next_file_line(state); 792 793 if (status != QF_OK) 794 return status; 795 796 /* remove newline/CR from the line */ 797 if (state->linelen > 0 && state->linebuf[state->linelen - 1] == '\n') 798 { 799 state->linebuf[state->linelen - 1] = NUL; 800 #ifdef USE_CRNL 801 if (state->linelen > 1 && state->linebuf[state->linelen - 2] == '\r') 802 state->linebuf[state->linelen - 2] = NUL; 803 #endif 804 } 805 806 #ifdef FEAT_MBYTE 807 remove_bom(state->linebuf); 808 #endif 809 810 return QF_OK; 811 } 812 813 typedef struct { 814 char_u *namebuf; 815 char_u *module; 816 char_u *errmsg; 817 int errmsglen; 818 long lnum; 819 int col; 820 char_u use_viscol; 821 char_u *pattern; 822 int enr; 823 int type; 824 int valid; 825 } qffields_T; 826 827 /* 828 * Parse a line and get the quickfix fields. 829 * Return the QF_ status. 830 */ 831 static int 832 qf_parse_line( 833 qf_info_T *qi, 834 int qf_idx, 835 char_u *linebuf, 836 int linelen, 837 efm_T *fmt_first, 838 qffields_T *fields) 839 { 840 efm_T *fmt_ptr; 841 char_u *ptr; 842 int len; 843 int i; 844 int idx = 0; 845 char_u *tail = NULL; 846 regmatch_T regmatch; 847 qf_list_T *qfl = &qi->qf_lists[qf_idx]; 848 849 /* Always ignore case when looking for a matching error. */ 850 regmatch.rm_ic = TRUE; 851 852 restofline: 853 /* If there was no %> item start at the first pattern */ 854 if (fmt_start == NULL) 855 fmt_ptr = fmt_first; 856 else 857 { 858 fmt_ptr = fmt_start; 859 fmt_start = NULL; 860 } 861 862 /* 863 * Try to match each part of 'errorformat' until we find a complete 864 * match or no match. 865 */ 866 fields->valid = TRUE; 867 for ( ; fmt_ptr != NULL; fmt_ptr = fmt_ptr->next) 868 { 869 int r; 870 871 idx = fmt_ptr->prefix; 872 if (qfl->qf_multiscan && vim_strchr((char_u *)"OPQ", idx) == NULL) 873 continue; 874 fields->namebuf[0] = NUL; 875 fields->module[0] = NUL; 876 fields->pattern[0] = NUL; 877 if (!qfl->qf_multiscan) 878 fields->errmsg[0] = NUL; 879 fields->lnum = 0; 880 fields->col = 0; 881 fields->use_viscol = FALSE; 882 fields->enr = -1; 883 fields->type = 0; 884 tail = NULL; 885 886 regmatch.regprog = fmt_ptr->prog; 887 r = vim_regexec(®match, linebuf, (colnr_T)0); 888 fmt_ptr->prog = regmatch.regprog; 889 if (r) 890 { 891 if ((idx == 'C' || idx == 'Z') && !qfl->qf_multiline) 892 continue; 893 if (vim_strchr((char_u *)"EWI", idx) != NULL) 894 fields->type = idx; 895 else 896 fields->type = 0; 897 /* 898 * Extract error message data from matched line. 899 * We check for an actual submatch, because "\[" and "\]" in 900 * the 'errorformat' may cause the wrong submatch to be used. 901 */ 902 if ((i = (int)fmt_ptr->addr[0]) > 0) /* %f */ 903 { 904 int c; 905 906 if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) 907 continue; 908 909 /* Expand ~/file and $HOME/file to full path. */ 910 c = *regmatch.endp[i]; 911 *regmatch.endp[i] = NUL; 912 expand_env(regmatch.startp[i], fields->namebuf, CMDBUFFSIZE); 913 *regmatch.endp[i] = c; 914 915 if (vim_strchr((char_u *)"OPQ", idx) != NULL 916 && mch_getperm(fields->namebuf) == -1) 917 continue; 918 } 919 if ((i = (int)fmt_ptr->addr[1]) > 0) /* %n */ 920 { 921 if (regmatch.startp[i] == NULL) 922 continue; 923 fields->enr = (int)atol((char *)regmatch.startp[i]); 924 } 925 if ((i = (int)fmt_ptr->addr[2]) > 0) /* %l */ 926 { 927 if (regmatch.startp[i] == NULL) 928 continue; 929 fields->lnum = atol((char *)regmatch.startp[i]); 930 } 931 if ((i = (int)fmt_ptr->addr[3]) > 0) /* %c */ 932 { 933 if (regmatch.startp[i] == NULL) 934 continue; 935 fields->col = (int)atol((char *)regmatch.startp[i]); 936 } 937 if ((i = (int)fmt_ptr->addr[4]) > 0) /* %t */ 938 { 939 if (regmatch.startp[i] == NULL) 940 continue; 941 fields->type = *regmatch.startp[i]; 942 } 943 if (fmt_ptr->flags == '+' && !qfl->qf_multiscan) /* %+ */ 944 { 945 if (linelen >= fields->errmsglen) 946 { 947 /* linelen + null terminator */ 948 if ((fields->errmsg = vim_realloc(fields->errmsg, 949 linelen + 1)) == NULL) 950 return QF_NOMEM; 951 fields->errmsglen = linelen + 1; 952 } 953 vim_strncpy(fields->errmsg, linebuf, linelen); 954 } 955 else if ((i = (int)fmt_ptr->addr[5]) > 0) /* %m */ 956 { 957 if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) 958 continue; 959 len = (int)(regmatch.endp[i] - regmatch.startp[i]); 960 if (len >= fields->errmsglen) 961 { 962 /* len + null terminator */ 963 if ((fields->errmsg = vim_realloc(fields->errmsg, len + 1)) 964 == NULL) 965 return QF_NOMEM; 966 fields->errmsglen = len + 1; 967 } 968 vim_strncpy(fields->errmsg, regmatch.startp[i], len); 969 } 970 if ((i = (int)fmt_ptr->addr[6]) > 0) /* %r */ 971 { 972 if (regmatch.startp[i] == NULL) 973 continue; 974 tail = regmatch.startp[i]; 975 } 976 if ((i = (int)fmt_ptr->addr[7]) > 0) /* %p */ 977 { 978 char_u *match_ptr; 979 980 if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) 981 continue; 982 fields->col = 0; 983 for (match_ptr = regmatch.startp[i]; 984 match_ptr != regmatch.endp[i]; ++match_ptr) 985 { 986 ++fields->col; 987 if (*match_ptr == TAB) 988 { 989 fields->col += 7; 990 fields->col -= fields->col % 8; 991 } 992 } 993 ++fields->col; 994 fields->use_viscol = TRUE; 995 } 996 if ((i = (int)fmt_ptr->addr[8]) > 0) /* %v */ 997 { 998 if (regmatch.startp[i] == NULL) 999 continue; 1000 fields->col = (int)atol((char *)regmatch.startp[i]); 1001 fields->use_viscol = TRUE; 1002 } 1003 if ((i = (int)fmt_ptr->addr[9]) > 0) /* %s */ 1004 { 1005 if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) 1006 continue; 1007 len = (int)(regmatch.endp[i] - regmatch.startp[i]); 1008 if (len > CMDBUFFSIZE - 5) 1009 len = CMDBUFFSIZE - 5; 1010 STRCPY(fields->pattern, "^\\V"); 1011 STRNCAT(fields->pattern, regmatch.startp[i], len); 1012 fields->pattern[len + 3] = '\\'; 1013 fields->pattern[len + 4] = '$'; 1014 fields->pattern[len + 5] = NUL; 1015 } 1016 if ((i = (int)fmt_ptr->addr[10]) > 0) /* %o */ 1017 { 1018 if (regmatch.startp[i] == NULL) 1019 continue; 1020 len = (int)(regmatch.endp[i] - regmatch.startp[i]); 1021 if (len > CMDBUFFSIZE) 1022 len = CMDBUFFSIZE; 1023 STRNCAT(fields->module, regmatch.startp[i], len); 1024 } 1025 break; 1026 } 1027 } 1028 qfl->qf_multiscan = FALSE; 1029 1030 if (fmt_ptr == NULL || idx == 'D' || idx == 'X') 1031 { 1032 if (fmt_ptr != NULL) 1033 { 1034 if (idx == 'D') /* enter directory */ 1035 { 1036 if (*fields->namebuf == NUL) 1037 { 1038 EMSG(_("E379: Missing or empty directory name")); 1039 return QF_FAIL; 1040 } 1041 qfl->qf_directory = 1042 qf_push_dir(fields->namebuf, &qfl->qf_dir_stack, FALSE); 1043 if (qfl->qf_directory == NULL) 1044 return QF_FAIL; 1045 } 1046 else if (idx == 'X') /* leave directory */ 1047 qfl->qf_directory = qf_pop_dir(&qfl->qf_dir_stack); 1048 } 1049 fields->namebuf[0] = NUL; /* no match found, remove file name */ 1050 fields->lnum = 0; /* don't jump to this line */ 1051 fields->valid = FALSE; 1052 if (linelen >= fields->errmsglen) 1053 { 1054 /* linelen + null terminator */ 1055 if ((fields->errmsg = vim_realloc(fields->errmsg, 1056 linelen + 1)) == NULL) 1057 return QF_NOMEM; 1058 fields->errmsglen = linelen + 1; 1059 } 1060 /* copy whole line to error message */ 1061 vim_strncpy(fields->errmsg, linebuf, linelen); 1062 if (fmt_ptr == NULL) 1063 qfl->qf_multiline = qfl->qf_multiignore = FALSE; 1064 } 1065 else if (fmt_ptr != NULL) 1066 { 1067 /* honor %> item */ 1068 if (fmt_ptr->conthere) 1069 fmt_start = fmt_ptr; 1070 1071 if (vim_strchr((char_u *)"AEWI", idx) != NULL) 1072 { 1073 qfl->qf_multiline = TRUE; /* start of a multi-line message */ 1074 qfl->qf_multiignore = FALSE;/* reset continuation */ 1075 } 1076 else if (vim_strchr((char_u *)"CZ", idx) != NULL) 1077 { /* continuation of multi-line msg */ 1078 if (!qfl->qf_multiignore) 1079 { 1080 qfline_T *qfprev = qfl->qf_last; 1081 1082 if (qfprev == NULL) 1083 return QF_FAIL; 1084 if (*fields->errmsg && !qfl->qf_multiignore) 1085 { 1086 len = (int)STRLEN(qfprev->qf_text); 1087 if ((ptr = alloc((unsigned)(len + STRLEN(fields->errmsg) + 2))) 1088 == NULL) 1089 return QF_FAIL; 1090 STRCPY(ptr, qfprev->qf_text); 1091 vim_free(qfprev->qf_text); 1092 qfprev->qf_text = ptr; 1093 *(ptr += len) = '\n'; 1094 STRCPY(++ptr, fields->errmsg); 1095 } 1096 if (qfprev->qf_nr == -1) 1097 qfprev->qf_nr = fields->enr; 1098 if (vim_isprintc(fields->type) && !qfprev->qf_type) 1099 /* only printable chars allowed */ 1100 qfprev->qf_type = fields->type; 1101 1102 if (!qfprev->qf_lnum) 1103 qfprev->qf_lnum = fields->lnum; 1104 if (!qfprev->qf_col) 1105 qfprev->qf_col = fields->col; 1106 qfprev->qf_viscol = fields->use_viscol; 1107 if (!qfprev->qf_fnum) 1108 qfprev->qf_fnum = qf_get_fnum(qi, qf_idx, 1109 qfl->qf_directory, 1110 *fields->namebuf || qfl->qf_directory != NULL 1111 ? fields->namebuf 1112 : qfl->qf_currfile != NULL && fields->valid 1113 ? qfl->qf_currfile : 0); 1114 } 1115 if (idx == 'Z') 1116 qfl->qf_multiline = qfl->qf_multiignore = FALSE; 1117 line_breakcheck(); 1118 return QF_IGNORE_LINE; 1119 } 1120 else if (vim_strchr((char_u *)"OPQ", idx) != NULL) 1121 { 1122 /* global file names */ 1123 fields->valid = FALSE; 1124 if (*fields->namebuf == NUL || mch_getperm(fields->namebuf) >= 0) 1125 { 1126 if (*fields->namebuf && idx == 'P') 1127 qfl->qf_currfile = 1128 qf_push_dir(fields->namebuf, &qfl->qf_file_stack, TRUE); 1129 else if (idx == 'Q') 1130 qfl->qf_currfile = qf_pop_dir(&qfl->qf_file_stack); 1131 *fields->namebuf = NUL; 1132 if (tail && *tail) 1133 { 1134 STRMOVE(IObuff, skipwhite(tail)); 1135 qfl->qf_multiscan = TRUE; 1136 goto restofline; 1137 } 1138 } 1139 } 1140 if (fmt_ptr->flags == '-') /* generally exclude this line */ 1141 { 1142 if (qfl->qf_multiline) 1143 /* also exclude continuation lines */ 1144 qfl->qf_multiignore = TRUE; 1145 return QF_IGNORE_LINE; 1146 } 1147 } 1148 1149 return QF_OK; 1150 } 1151 1152 /* 1153 * Read the errorfile "efile" into memory, line by line, building the error 1154 * list. 1155 * Alternative: when "efile" is NULL read errors from buffer "buf". 1156 * Alternative: when "tv" is not NULL get errors from the string or list. 1157 * Always use 'errorformat' from "buf" if there is a local value. 1158 * Then "lnumfirst" and "lnumlast" specify the range of lines to use. 1159 * Set the title of the list to "qf_title". 1160 * Return -1 for error, number of errors for success. 1161 */ 1162 static int 1163 qf_init_ext( 1164 qf_info_T *qi, 1165 int qf_idx, 1166 char_u *efile, 1167 buf_T *buf, 1168 typval_T *tv, 1169 char_u *errorformat, 1170 int newlist, /* TRUE: start a new error list */ 1171 linenr_T lnumfirst, /* first line number to use */ 1172 linenr_T lnumlast, /* last line number to use */ 1173 char_u *qf_title, 1174 char_u *enc) 1175 { 1176 qf_list_T *qfl; 1177 qfstate_T state; 1178 qffields_T fields; 1179 qfline_T *old_last = NULL; 1180 int adding = FALSE; 1181 static efm_T *fmt_first = NULL; 1182 char_u *efm; 1183 static char_u *last_efm = NULL; 1184 int retval = -1; /* default: return error flag */ 1185 int status; 1186 1187 /* Do not used the cached buffer, it may have been wiped out. */ 1188 VIM_CLEAR(qf_last_bufname); 1189 1190 vim_memset(&state, 0, sizeof(state)); 1191 vim_memset(&fields, 0, sizeof(fields)); 1192 #ifdef FEAT_MBYTE 1193 state.vc.vc_type = CONV_NONE; 1194 if (enc != NULL && *enc != NUL) 1195 convert_setup(&state.vc, enc, p_enc); 1196 #endif 1197 fields.namebuf = alloc_id(CMDBUFFSIZE + 1, aid_qf_namebuf); 1198 fields.module = alloc_id(CMDBUFFSIZE + 1, aid_qf_module); 1199 fields.errmsglen = CMDBUFFSIZE + 1; 1200 fields.errmsg = alloc_id(fields.errmsglen, aid_qf_errmsg); 1201 fields.pattern = alloc_id(CMDBUFFSIZE + 1, aid_qf_pattern); 1202 if (fields.namebuf == NULL || fields.errmsg == NULL 1203 || fields.pattern == NULL || fields.module == NULL) 1204 goto qf_init_end; 1205 1206 if (efile != NULL && (state.fd = mch_fopen((char *)efile, "r")) == NULL) 1207 { 1208 EMSG2(_(e_openerrf), efile); 1209 goto qf_init_end; 1210 } 1211 1212 if (newlist || qf_idx == qi->qf_listcount) 1213 { 1214 /* make place for a new list */ 1215 qf_new_list(qi, qf_title); 1216 qf_idx = qi->qf_curlist; 1217 } 1218 else 1219 { 1220 /* Adding to existing list, use last entry. */ 1221 adding = TRUE; 1222 if (qi->qf_lists[qf_idx].qf_count > 0) 1223 old_last = qi->qf_lists[qf_idx].qf_last; 1224 } 1225 1226 qfl = &qi->qf_lists[qf_idx]; 1227 1228 /* Use the local value of 'errorformat' if it's set. */ 1229 if (errorformat == p_efm && tv == NULL && *buf->b_p_efm != NUL) 1230 efm = buf->b_p_efm; 1231 else 1232 efm = errorformat; 1233 1234 /* 1235 * If the errorformat didn't change between calls, then reuse the 1236 * previously parsed values. 1237 */ 1238 if (last_efm == NULL || (STRCMP(last_efm, efm) != 0)) 1239 { 1240 /* free the previously parsed data */ 1241 VIM_CLEAR(last_efm); 1242 free_efm_list(&fmt_first); 1243 1244 /* parse the current 'efm' */ 1245 fmt_first = parse_efm_option(efm); 1246 if (fmt_first != NULL) 1247 last_efm = vim_strsave(efm); 1248 } 1249 1250 if (fmt_first == NULL) /* nothing found */ 1251 goto error2; 1252 1253 /* 1254 * got_int is reset here, because it was probably set when killing the 1255 * ":make" command, but we still want to read the errorfile then. 1256 */ 1257 got_int = FALSE; 1258 1259 if (tv != NULL) 1260 { 1261 if (tv->v_type == VAR_STRING) 1262 state.p_str = tv->vval.v_string; 1263 else if (tv->v_type == VAR_LIST) 1264 state.p_li = tv->vval.v_list->lv_first; 1265 state.tv = tv; 1266 } 1267 state.buf = buf; 1268 state.buflnum = lnumfirst; 1269 state.lnumlast = lnumlast; 1270 1271 /* 1272 * Read the lines in the error file one by one. 1273 * Try to recognize one of the error formats in each line. 1274 */ 1275 while (!got_int) 1276 { 1277 /* Get the next line from a file/buffer/list/string */ 1278 status = qf_get_nextline(&state); 1279 if (status == QF_NOMEM) /* memory alloc failure */ 1280 goto qf_init_end; 1281 if (status == QF_END_OF_INPUT) /* end of input */ 1282 break; 1283 1284 status = qf_parse_line(qi, qf_idx, state.linebuf, state.linelen, 1285 fmt_first, &fields); 1286 if (status == QF_FAIL) 1287 goto error2; 1288 if (status == QF_NOMEM) 1289 goto qf_init_end; 1290 if (status == QF_IGNORE_LINE) 1291 continue; 1292 1293 if (qf_add_entry(qi, 1294 qf_idx, 1295 qfl->qf_directory, 1296 (*fields.namebuf || qfl->qf_directory != NULL) 1297 ? fields.namebuf 1298 : ((qfl->qf_currfile != NULL && fields.valid) 1299 ? qfl->qf_currfile : (char_u *)NULL), 1300 fields.module, 1301 0, 1302 fields.errmsg, 1303 fields.lnum, 1304 fields.col, 1305 fields.use_viscol, 1306 fields.pattern, 1307 fields.enr, 1308 fields.type, 1309 fields.valid) == FAIL) 1310 goto error2; 1311 line_breakcheck(); 1312 } 1313 if (state.fd == NULL || !ferror(state.fd)) 1314 { 1315 if (qfl->qf_index == 0) 1316 { 1317 /* no valid entry found */ 1318 qfl->qf_ptr = qfl->qf_start; 1319 qfl->qf_index = 1; 1320 qfl->qf_nonevalid = TRUE; 1321 } 1322 else 1323 { 1324 qfl->qf_nonevalid = FALSE; 1325 if (qfl->qf_ptr == NULL) 1326 qfl->qf_ptr = qfl->qf_start; 1327 } 1328 /* return number of matches */ 1329 retval = qfl->qf_count; 1330 goto qf_init_end; 1331 } 1332 EMSG(_(e_readerrf)); 1333 error2: 1334 if (!adding) 1335 { 1336 /* Error when creating a new list. Free the new list */ 1337 qf_free(qi, qi->qf_curlist); 1338 qi->qf_listcount--; 1339 if (qi->qf_curlist > 0) 1340 --qi->qf_curlist; 1341 } 1342 qf_init_end: 1343 if (state.fd != NULL) 1344 fclose(state.fd); 1345 vim_free(fields.namebuf); 1346 vim_free(fields.module); 1347 vim_free(fields.errmsg); 1348 vim_free(fields.pattern); 1349 vim_free(state.growbuf); 1350 1351 if (qf_idx == qi->qf_curlist) 1352 qf_update_buffer(qi, old_last); 1353 #ifdef FEAT_MBYTE 1354 if (state.vc.vc_type != CONV_NONE) 1355 convert_setup(&state.vc, NULL, NULL); 1356 #endif 1357 1358 return retval; 1359 } 1360 1361 static void 1362 qf_store_title(qf_info_T *qi, int qf_idx, char_u *title) 1363 { 1364 VIM_CLEAR(qi->qf_lists[qf_idx].qf_title); 1365 1366 if (title != NULL) 1367 { 1368 char_u *p = alloc((int)STRLEN(title) + 2); 1369 1370 qi->qf_lists[qf_idx].qf_title = p; 1371 if (p != NULL) 1372 sprintf((char *)p, ":%s", (char *)title); 1373 } 1374 } 1375 1376 /* 1377 * Prepare for adding a new quickfix list. If the current list is in the 1378 * middle of the stack, then all the following lists are freed and then 1379 * the new list is added. 1380 */ 1381 static void 1382 qf_new_list(qf_info_T *qi, char_u *qf_title) 1383 { 1384 int i; 1385 1386 /* 1387 * If the current entry is not the last entry, delete entries beyond 1388 * the current entry. This makes it possible to browse in a tree-like 1389 * way with ":grep'. 1390 */ 1391 while (qi->qf_listcount > qi->qf_curlist + 1) 1392 qf_free(qi, --qi->qf_listcount); 1393 1394 /* 1395 * When the stack is full, remove to oldest entry 1396 * Otherwise, add a new entry. 1397 */ 1398 if (qi->qf_listcount == LISTCOUNT) 1399 { 1400 qf_free(qi, 0); 1401 for (i = 1; i < LISTCOUNT; ++i) 1402 qi->qf_lists[i - 1] = qi->qf_lists[i]; 1403 qi->qf_curlist = LISTCOUNT - 1; 1404 } 1405 else 1406 qi->qf_curlist = qi->qf_listcount++; 1407 vim_memset(&qi->qf_lists[qi->qf_curlist], 0, (size_t)(sizeof(qf_list_T))); 1408 qf_store_title(qi, qi->qf_curlist, qf_title); 1409 qi->qf_lists[qi->qf_curlist].qf_id = ++last_qf_id; 1410 } 1411 1412 /* 1413 * Free a location list 1414 */ 1415 static void 1416 ll_free_all(qf_info_T **pqi) 1417 { 1418 int i; 1419 qf_info_T *qi; 1420 1421 qi = *pqi; 1422 if (qi == NULL) 1423 return; 1424 *pqi = NULL; /* Remove reference to this list */ 1425 1426 qi->qf_refcount--; 1427 if (qi->qf_refcount < 1) 1428 { 1429 /* No references to this location list */ 1430 for (i = 0; i < qi->qf_listcount; ++i) 1431 qf_free(qi, i); 1432 vim_free(qi); 1433 } 1434 } 1435 1436 void 1437 qf_free_all(win_T *wp) 1438 { 1439 int i; 1440 qf_info_T *qi = &ql_info; 1441 1442 if (wp != NULL) 1443 { 1444 /* location list */ 1445 ll_free_all(&wp->w_llist); 1446 ll_free_all(&wp->w_llist_ref); 1447 } 1448 else 1449 /* quickfix list */ 1450 for (i = 0; i < qi->qf_listcount; ++i) 1451 qf_free(qi, i); 1452 } 1453 1454 /* 1455 * Add an entry to the end of the list of errors. 1456 * Returns OK or FAIL. 1457 */ 1458 static int 1459 qf_add_entry( 1460 qf_info_T *qi, /* quickfix list */ 1461 int qf_idx, /* list index */ 1462 char_u *dir, /* optional directory name */ 1463 char_u *fname, /* file name or NULL */ 1464 char_u *module, /* module name or NULL */ 1465 int bufnum, /* buffer number or zero */ 1466 char_u *mesg, /* message */ 1467 long lnum, /* line number */ 1468 int col, /* column */ 1469 int vis_col, /* using visual column */ 1470 char_u *pattern, /* search pattern */ 1471 int nr, /* error number */ 1472 int type, /* type character */ 1473 int valid) /* valid entry */ 1474 { 1475 qfline_T *qfp; 1476 qfline_T **lastp; /* pointer to qf_last or NULL */ 1477 1478 if ((qfp = (qfline_T *)alloc((unsigned)sizeof(qfline_T))) == NULL) 1479 return FAIL; 1480 if (bufnum != 0) 1481 { 1482 buf_T *buf = buflist_findnr(bufnum); 1483 1484 qfp->qf_fnum = bufnum; 1485 if (buf != NULL) 1486 buf->b_has_qf_entry |= 1487 (qi == &ql_info) ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY; 1488 } 1489 else 1490 qfp->qf_fnum = qf_get_fnum(qi, qf_idx, dir, fname); 1491 if ((qfp->qf_text = vim_strsave(mesg)) == NULL) 1492 { 1493 vim_free(qfp); 1494 return FAIL; 1495 } 1496 qfp->qf_lnum = lnum; 1497 qfp->qf_col = col; 1498 qfp->qf_viscol = vis_col; 1499 if (pattern == NULL || *pattern == NUL) 1500 qfp->qf_pattern = NULL; 1501 else if ((qfp->qf_pattern = vim_strsave(pattern)) == NULL) 1502 { 1503 vim_free(qfp->qf_text); 1504 vim_free(qfp); 1505 return FAIL; 1506 } 1507 if (module == NULL || *module == NUL) 1508 qfp->qf_module = NULL; 1509 else if ((qfp->qf_module = vim_strsave(module)) == NULL) 1510 { 1511 vim_free(qfp->qf_text); 1512 vim_free(qfp->qf_pattern); 1513 vim_free(qfp); 1514 return FAIL; 1515 } 1516 qfp->qf_nr = nr; 1517 if (type != 1 && !vim_isprintc(type)) /* only printable chars allowed */ 1518 type = 0; 1519 qfp->qf_type = type; 1520 qfp->qf_valid = valid; 1521 1522 lastp = &qi->qf_lists[qf_idx].qf_last; 1523 if (qi->qf_lists[qf_idx].qf_count == 0) 1524 /* first element in the list */ 1525 { 1526 qi->qf_lists[qf_idx].qf_start = qfp; 1527 qi->qf_lists[qf_idx].qf_ptr = qfp; 1528 qi->qf_lists[qf_idx].qf_index = 0; 1529 qfp->qf_prev = NULL; 1530 } 1531 else 1532 { 1533 qfp->qf_prev = *lastp; 1534 (*lastp)->qf_next = qfp; 1535 } 1536 qfp->qf_next = NULL; 1537 qfp->qf_cleared = FALSE; 1538 *lastp = qfp; 1539 ++qi->qf_lists[qf_idx].qf_count; 1540 if (qi->qf_lists[qf_idx].qf_index == 0 && qfp->qf_valid) 1541 /* first valid entry */ 1542 { 1543 qi->qf_lists[qf_idx].qf_index = 1544 qi->qf_lists[qf_idx].qf_count; 1545 qi->qf_lists[qf_idx].qf_ptr = qfp; 1546 } 1547 1548 return OK; 1549 } 1550 1551 /* 1552 * Allocate a new location list 1553 */ 1554 static qf_info_T * 1555 ll_new_list(void) 1556 { 1557 qf_info_T *qi; 1558 1559 qi = (qf_info_T *)alloc((unsigned)sizeof(qf_info_T)); 1560 if (qi != NULL) 1561 { 1562 vim_memset(qi, 0, (size_t)(sizeof(qf_info_T))); 1563 qi->qf_refcount++; 1564 } 1565 1566 return qi; 1567 } 1568 1569 /* 1570 * Return the location list for window 'wp'. 1571 * If not present, allocate a location list 1572 */ 1573 static qf_info_T * 1574 ll_get_or_alloc_list(win_T *wp) 1575 { 1576 if (IS_LL_WINDOW(wp)) 1577 /* For a location list window, use the referenced location list */ 1578 return wp->w_llist_ref; 1579 1580 /* 1581 * For a non-location list window, w_llist_ref should not point to a 1582 * location list. 1583 */ 1584 ll_free_all(&wp->w_llist_ref); 1585 1586 if (wp->w_llist == NULL) 1587 wp->w_llist = ll_new_list(); /* new location list */ 1588 return wp->w_llist; 1589 } 1590 1591 /* 1592 * Copy the location list from window "from" to window "to". 1593 */ 1594 void 1595 copy_loclist(win_T *from, win_T *to) 1596 { 1597 qf_info_T *qi; 1598 int idx; 1599 int i; 1600 1601 /* 1602 * When copying from a location list window, copy the referenced 1603 * location list. For other windows, copy the location list for 1604 * that window. 1605 */ 1606 if (IS_LL_WINDOW(from)) 1607 qi = from->w_llist_ref; 1608 else 1609 qi = from->w_llist; 1610 1611 if (qi == NULL) /* no location list to copy */ 1612 return; 1613 1614 /* allocate a new location list */ 1615 if ((to->w_llist = ll_new_list()) == NULL) 1616 return; 1617 1618 to->w_llist->qf_listcount = qi->qf_listcount; 1619 1620 /* Copy the location lists one at a time */ 1621 for (idx = 0; idx < qi->qf_listcount; idx++) 1622 { 1623 qf_list_T *from_qfl; 1624 qf_list_T *to_qfl; 1625 1626 to->w_llist->qf_curlist = idx; 1627 1628 from_qfl = &qi->qf_lists[idx]; 1629 to_qfl = &to->w_llist->qf_lists[idx]; 1630 1631 /* Some of the fields are populated by qf_add_entry() */ 1632 to_qfl->qf_nonevalid = from_qfl->qf_nonevalid; 1633 to_qfl->qf_count = 0; 1634 to_qfl->qf_index = 0; 1635 to_qfl->qf_start = NULL; 1636 to_qfl->qf_last = NULL; 1637 to_qfl->qf_ptr = NULL; 1638 if (from_qfl->qf_title != NULL) 1639 to_qfl->qf_title = vim_strsave(from_qfl->qf_title); 1640 else 1641 to_qfl->qf_title = NULL; 1642 if (from_qfl->qf_ctx != NULL) 1643 { 1644 to_qfl->qf_ctx = alloc_tv(); 1645 if (to_qfl->qf_ctx != NULL) 1646 copy_tv(from_qfl->qf_ctx, to_qfl->qf_ctx); 1647 } 1648 else 1649 to_qfl->qf_ctx = NULL; 1650 1651 if (from_qfl->qf_count) 1652 { 1653 qfline_T *from_qfp; 1654 qfline_T *prevp; 1655 1656 /* copy all the location entries in this list */ 1657 for (i = 0, from_qfp = from_qfl->qf_start; 1658 i < from_qfl->qf_count && from_qfp != NULL; 1659 ++i, from_qfp = from_qfp->qf_next) 1660 { 1661 if (qf_add_entry(to->w_llist, 1662 to->w_llist->qf_curlist, 1663 NULL, 1664 NULL, 1665 from_qfp->qf_module, 1666 0, 1667 from_qfp->qf_text, 1668 from_qfp->qf_lnum, 1669 from_qfp->qf_col, 1670 from_qfp->qf_viscol, 1671 from_qfp->qf_pattern, 1672 from_qfp->qf_nr, 1673 0, 1674 from_qfp->qf_valid) == FAIL) 1675 { 1676 qf_free_all(to); 1677 return; 1678 } 1679 /* 1680 * qf_add_entry() will not set the qf_num field, as the 1681 * directory and file names are not supplied. So the qf_fnum 1682 * field is copied here. 1683 */ 1684 prevp = to->w_llist->qf_lists[to->w_llist->qf_curlist].qf_last; 1685 prevp->qf_fnum = from_qfp->qf_fnum; /* file number */ 1686 prevp->qf_type = from_qfp->qf_type; /* error type */ 1687 if (from_qfl->qf_ptr == from_qfp) 1688 to_qfl->qf_ptr = prevp; /* current location */ 1689 } 1690 } 1691 1692 to_qfl->qf_index = from_qfl->qf_index; /* current index in the list */ 1693 1694 /* Assign a new ID for the location list */ 1695 to_qfl->qf_id = ++last_qf_id; 1696 to_qfl->qf_changedtick = 0L; 1697 1698 /* When no valid entries are present in the list, qf_ptr points to 1699 * the first item in the list */ 1700 if (to_qfl->qf_nonevalid) 1701 { 1702 to_qfl->qf_ptr = to_qfl->qf_start; 1703 to_qfl->qf_index = 1; 1704 } 1705 } 1706 1707 to->w_llist->qf_curlist = qi->qf_curlist; /* current list */ 1708 } 1709 1710 /* 1711 * Get buffer number for file "directory/fname". 1712 * Also sets the b_has_qf_entry flag. 1713 */ 1714 static int 1715 qf_get_fnum(qf_info_T *qi, int qf_idx, char_u *directory, char_u *fname) 1716 { 1717 char_u *ptr = NULL; 1718 buf_T *buf; 1719 char_u *bufname; 1720 1721 if (fname == NULL || *fname == NUL) /* no file name */ 1722 return 0; 1723 1724 #ifdef VMS 1725 vms_remove_version(fname); 1726 #endif 1727 #ifdef BACKSLASH_IN_FILENAME 1728 if (directory != NULL) 1729 slash_adjust(directory); 1730 slash_adjust(fname); 1731 #endif 1732 if (directory != NULL && !vim_isAbsName(fname) 1733 && (ptr = concat_fnames(directory, fname, TRUE)) != NULL) 1734 { 1735 /* 1736 * Here we check if the file really exists. 1737 * This should normally be true, but if make works without 1738 * "leaving directory"-messages we might have missed a 1739 * directory change. 1740 */ 1741 if (mch_getperm(ptr) < 0) 1742 { 1743 vim_free(ptr); 1744 directory = qf_guess_filepath(qi, qf_idx, fname); 1745 if (directory) 1746 ptr = concat_fnames(directory, fname, TRUE); 1747 else 1748 ptr = vim_strsave(fname); 1749 } 1750 /* Use concatenated directory name and file name */ 1751 bufname = ptr; 1752 } 1753 else 1754 bufname = fname; 1755 1756 if (qf_last_bufname != NULL && STRCMP(bufname, qf_last_bufname) == 0 1757 && bufref_valid(&qf_last_bufref)) 1758 { 1759 buf = qf_last_bufref.br_buf; 1760 vim_free(ptr); 1761 } 1762 else 1763 { 1764 vim_free(qf_last_bufname); 1765 buf = buflist_new(bufname, NULL, (linenr_T)0, BLN_NOOPT); 1766 if (bufname == ptr) 1767 qf_last_bufname = bufname; 1768 else 1769 qf_last_bufname = vim_strsave(bufname); 1770 set_bufref(&qf_last_bufref, buf); 1771 } 1772 if (buf == NULL) 1773 return 0; 1774 1775 buf->b_has_qf_entry = 1776 (qi == &ql_info) ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY; 1777 return buf->b_fnum; 1778 } 1779 1780 /* 1781 * Push dirbuf onto the directory stack and return pointer to actual dir or 1782 * NULL on error. 1783 */ 1784 static char_u * 1785 qf_push_dir(char_u *dirbuf, struct dir_stack_T **stackptr, int is_file_stack) 1786 { 1787 struct dir_stack_T *ds_new; 1788 struct dir_stack_T *ds_ptr; 1789 1790 /* allocate new stack element and hook it in */ 1791 ds_new = (struct dir_stack_T *)alloc((unsigned)sizeof(struct dir_stack_T)); 1792 if (ds_new == NULL) 1793 return NULL; 1794 1795 ds_new->next = *stackptr; 1796 *stackptr = ds_new; 1797 1798 /* store directory on the stack */ 1799 if (vim_isAbsName(dirbuf) 1800 || (*stackptr)->next == NULL 1801 || (*stackptr && is_file_stack)) 1802 (*stackptr)->dirname = vim_strsave(dirbuf); 1803 else 1804 { 1805 /* Okay we don't have an absolute path. 1806 * dirbuf must be a subdir of one of the directories on the stack. 1807 * Let's search... 1808 */ 1809 ds_new = (*stackptr)->next; 1810 (*stackptr)->dirname = NULL; 1811 while (ds_new) 1812 { 1813 vim_free((*stackptr)->dirname); 1814 (*stackptr)->dirname = concat_fnames(ds_new->dirname, dirbuf, 1815 TRUE); 1816 if (mch_isdir((*stackptr)->dirname) == TRUE) 1817 break; 1818 1819 ds_new = ds_new->next; 1820 } 1821 1822 /* clean up all dirs we already left */ 1823 while ((*stackptr)->next != ds_new) 1824 { 1825 ds_ptr = (*stackptr)->next; 1826 (*stackptr)->next = (*stackptr)->next->next; 1827 vim_free(ds_ptr->dirname); 1828 vim_free(ds_ptr); 1829 } 1830 1831 /* Nothing found -> it must be on top level */ 1832 if (ds_new == NULL) 1833 { 1834 vim_free((*stackptr)->dirname); 1835 (*stackptr)->dirname = vim_strsave(dirbuf); 1836 } 1837 } 1838 1839 if ((*stackptr)->dirname != NULL) 1840 return (*stackptr)->dirname; 1841 else 1842 { 1843 ds_ptr = *stackptr; 1844 *stackptr = (*stackptr)->next; 1845 vim_free(ds_ptr); 1846 return NULL; 1847 } 1848 } 1849 1850 /* 1851 * pop dirbuf from the directory stack and return previous directory or NULL if 1852 * stack is empty 1853 */ 1854 static char_u * 1855 qf_pop_dir(struct dir_stack_T **stackptr) 1856 { 1857 struct dir_stack_T *ds_ptr; 1858 1859 /* TODO: Should we check if dirbuf is the directory on top of the stack? 1860 * What to do if it isn't? */ 1861 1862 /* pop top element and free it */ 1863 if (*stackptr != NULL) 1864 { 1865 ds_ptr = *stackptr; 1866 *stackptr = (*stackptr)->next; 1867 vim_free(ds_ptr->dirname); 1868 vim_free(ds_ptr); 1869 } 1870 1871 /* return NEW top element as current dir or NULL if stack is empty*/ 1872 return *stackptr ? (*stackptr)->dirname : NULL; 1873 } 1874 1875 /* 1876 * clean up directory stack 1877 */ 1878 static void 1879 qf_clean_dir_stack(struct dir_stack_T **stackptr) 1880 { 1881 struct dir_stack_T *ds_ptr; 1882 1883 while ((ds_ptr = *stackptr) != NULL) 1884 { 1885 *stackptr = (*stackptr)->next; 1886 vim_free(ds_ptr->dirname); 1887 vim_free(ds_ptr); 1888 } 1889 } 1890 1891 /* 1892 * Check in which directory of the directory stack the given file can be 1893 * found. 1894 * Returns a pointer to the directory name or NULL if not found. 1895 * Cleans up intermediate directory entries. 1896 * 1897 * TODO: How to solve the following problem? 1898 * If we have the this directory tree: 1899 * ./ 1900 * ./aa 1901 * ./aa/bb 1902 * ./bb 1903 * ./bb/x.c 1904 * and make says: 1905 * making all in aa 1906 * making all in bb 1907 * x.c:9: Error 1908 * Then qf_push_dir thinks we are in ./aa/bb, but we are in ./bb. 1909 * qf_guess_filepath will return NULL. 1910 */ 1911 static char_u * 1912 qf_guess_filepath(qf_info_T *qi, int qf_idx, char_u *filename) 1913 { 1914 struct dir_stack_T *ds_ptr; 1915 struct dir_stack_T *ds_tmp; 1916 char_u *fullname; 1917 qf_list_T *qfl = &qi->qf_lists[qf_idx]; 1918 1919 /* no dirs on the stack - there's nothing we can do */ 1920 if (qfl->qf_dir_stack == NULL) 1921 return NULL; 1922 1923 ds_ptr = qfl->qf_dir_stack->next; 1924 fullname = NULL; 1925 while (ds_ptr) 1926 { 1927 vim_free(fullname); 1928 fullname = concat_fnames(ds_ptr->dirname, filename, TRUE); 1929 1930 /* If concat_fnames failed, just go on. The worst thing that can happen 1931 * is that we delete the entire stack. 1932 */ 1933 if ((fullname != NULL) && (mch_getperm(fullname) >= 0)) 1934 break; 1935 1936 ds_ptr = ds_ptr->next; 1937 } 1938 1939 vim_free(fullname); 1940 1941 /* clean up all dirs we already left */ 1942 while (qfl->qf_dir_stack->next != ds_ptr) 1943 { 1944 ds_tmp = qfl->qf_dir_stack->next; 1945 qfl->qf_dir_stack->next = qfl->qf_dir_stack->next->next; 1946 vim_free(ds_tmp->dirname); 1947 vim_free(ds_tmp); 1948 } 1949 1950 return ds_ptr==NULL? NULL: ds_ptr->dirname; 1951 } 1952 1953 /* 1954 * Returns TRUE if a quickfix/location list with the given identifier exists. 1955 */ 1956 static int 1957 qflist_valid (win_T *wp, int_u qf_id) 1958 { 1959 qf_info_T *qi = &ql_info; 1960 int i; 1961 1962 if (wp != NULL) 1963 { 1964 qi = GET_LOC_LIST(wp); /* Location list */ 1965 if (qi == NULL) 1966 return FALSE; 1967 } 1968 1969 for (i = 0; i < qi->qf_listcount; ++i) 1970 if (qi->qf_lists[i].qf_id == qf_id) 1971 return TRUE; 1972 1973 return FALSE; 1974 } 1975 1976 /* 1977 * When loading a file from the quickfix, the auto commands may modify it. 1978 * This may invalidate the current quickfix entry. This function checks 1979 * whether a entry is still present in the quickfix. 1980 * Similar to location list. 1981 */ 1982 static int 1983 is_qf_entry_present(qf_info_T *qi, qfline_T *qf_ptr) 1984 { 1985 qf_list_T *qfl; 1986 qfline_T *qfp; 1987 int i; 1988 1989 qfl = &qi->qf_lists[qi->qf_curlist]; 1990 1991 /* Search for the entry in the current list */ 1992 for (i = 0, qfp = qfl->qf_start; i < qfl->qf_count; 1993 ++i, qfp = qfp->qf_next) 1994 if (qfp == NULL || qfp == qf_ptr) 1995 break; 1996 1997 if (i == qfl->qf_count) /* Entry is not found */ 1998 return FALSE; 1999 2000 return TRUE; 2001 } 2002 2003 /* 2004 * Get the next valid entry in the current quickfix/location list. The search 2005 * starts from the current entry. Returns NULL on failure. 2006 */ 2007 static qfline_T * 2008 get_next_valid_entry( 2009 qf_info_T *qi, 2010 qfline_T *qf_ptr, 2011 int *qf_index, 2012 int dir) 2013 { 2014 int idx; 2015 int old_qf_fnum; 2016 2017 idx = *qf_index; 2018 old_qf_fnum = qf_ptr->qf_fnum; 2019 2020 do 2021 { 2022 if (idx == qi->qf_lists[qi->qf_curlist].qf_count 2023 || qf_ptr->qf_next == NULL) 2024 return NULL; 2025 ++idx; 2026 qf_ptr = qf_ptr->qf_next; 2027 } while ((!qi->qf_lists[qi->qf_curlist].qf_nonevalid 2028 && !qf_ptr->qf_valid) 2029 || (dir == FORWARD_FILE && qf_ptr->qf_fnum == old_qf_fnum)); 2030 2031 *qf_index = idx; 2032 return qf_ptr; 2033 } 2034 2035 /* 2036 * Get the previous valid entry in the current quickfix/location list. The 2037 * search starts from the current entry. Returns NULL on failure. 2038 */ 2039 static qfline_T * 2040 get_prev_valid_entry( 2041 qf_info_T *qi, 2042 qfline_T *qf_ptr, 2043 int *qf_index, 2044 int dir) 2045 { 2046 int idx; 2047 int old_qf_fnum; 2048 2049 idx = *qf_index; 2050 old_qf_fnum = qf_ptr->qf_fnum; 2051 2052 do 2053 { 2054 if (idx == 1 || qf_ptr->qf_prev == NULL) 2055 return NULL; 2056 --idx; 2057 qf_ptr = qf_ptr->qf_prev; 2058 } while ((!qi->qf_lists[qi->qf_curlist].qf_nonevalid 2059 && !qf_ptr->qf_valid) 2060 || (dir == BACKWARD_FILE && qf_ptr->qf_fnum == old_qf_fnum)); 2061 2062 *qf_index = idx; 2063 return qf_ptr; 2064 } 2065 2066 /* 2067 * Get the n'th (errornr) previous/next valid entry from the current entry in 2068 * the quickfix list. 2069 * dir == FORWARD or FORWARD_FILE: next valid entry 2070 * dir == BACKWARD or BACKWARD_FILE: previous valid entry 2071 */ 2072 static qfline_T * 2073 get_nth_valid_entry( 2074 qf_info_T *qi, 2075 int errornr, 2076 qfline_T *qf_ptr, 2077 int *qf_index, 2078 int dir) 2079 { 2080 qfline_T *prev_qf_ptr; 2081 int prev_index; 2082 static char_u *e_no_more_items = (char_u *)N_("E553: No more items"); 2083 char_u *err = e_no_more_items; 2084 2085 while (errornr--) 2086 { 2087 prev_qf_ptr = qf_ptr; 2088 prev_index = *qf_index; 2089 2090 if (dir == FORWARD || dir == FORWARD_FILE) 2091 qf_ptr = get_next_valid_entry(qi, qf_ptr, qf_index, dir); 2092 else 2093 qf_ptr = get_prev_valid_entry(qi, qf_ptr, qf_index, dir); 2094 if (qf_ptr == NULL) 2095 { 2096 qf_ptr = prev_qf_ptr; 2097 *qf_index = prev_index; 2098 if (err != NULL) 2099 { 2100 EMSG(_(err)); 2101 return NULL; 2102 } 2103 break; 2104 } 2105 2106 err = NULL; 2107 } 2108 2109 return qf_ptr; 2110 } 2111 2112 /* 2113 * Get n'th (errornr) quickfix entry 2114 */ 2115 static qfline_T * 2116 get_nth_entry( 2117 qf_info_T *qi, 2118 int errornr, 2119 qfline_T *qf_ptr, 2120 int *cur_qfidx) 2121 { 2122 int qf_idx = *cur_qfidx; 2123 2124 /* New error number is less than the current error number */ 2125 while (errornr < qf_idx && qf_idx > 1 && qf_ptr->qf_prev != NULL) 2126 { 2127 --qf_idx; 2128 qf_ptr = qf_ptr->qf_prev; 2129 } 2130 /* New error number is greater than the current error number */ 2131 while (errornr > qf_idx && 2132 qf_idx < qi->qf_lists[qi->qf_curlist].qf_count && 2133 qf_ptr->qf_next != NULL) 2134 { 2135 ++qf_idx; 2136 qf_ptr = qf_ptr->qf_next; 2137 } 2138 2139 *cur_qfidx = qf_idx; 2140 return qf_ptr; 2141 } 2142 2143 /* 2144 * Find a help window or open one. 2145 */ 2146 static int 2147 jump_to_help_window(qf_info_T *qi, int *opened_window) 2148 { 2149 win_T *wp; 2150 int flags; 2151 2152 if (cmdmod.tab != 0) 2153 wp = NULL; 2154 else 2155 FOR_ALL_WINDOWS(wp) 2156 if (bt_help(wp->w_buffer)) 2157 break; 2158 if (wp != NULL && wp->w_buffer->b_nwindows > 0) 2159 win_enter(wp, TRUE); 2160 else 2161 { 2162 /* 2163 * Split off help window; put it at far top if no position 2164 * specified, the current window is vertically split and narrow. 2165 */ 2166 flags = WSP_HELP; 2167 if (cmdmod.split == 0 && curwin->w_width != Columns 2168 && curwin->w_width < 80) 2169 flags |= WSP_TOP; 2170 if (qi != &ql_info) 2171 flags |= WSP_NEWLOC; /* don't copy the location list */ 2172 2173 if (win_split(0, flags) == FAIL) 2174 return FAIL; 2175 2176 *opened_window = TRUE; 2177 2178 if (curwin->w_height < p_hh) 2179 win_setheight((int)p_hh); 2180 2181 if (qi != &ql_info) /* not a quickfix list */ 2182 { 2183 /* The new window should use the supplied location list */ 2184 curwin->w_llist = qi; 2185 qi->qf_refcount++; 2186 } 2187 } 2188 2189 if (!p_im) 2190 restart_edit = 0; /* don't want insert mode in help file */ 2191 2192 return OK; 2193 } 2194 2195 /* 2196 * Find a suitable window for opening a file (qf_fnum) and jump to it. 2197 * If the file is already opened in a window, jump to it. 2198 */ 2199 static int 2200 qf_jump_to_usable_window(int qf_fnum, int *opened_window) 2201 { 2202 win_T *usable_win_ptr = NULL; 2203 int usable_win; 2204 qf_info_T *ll_ref; 2205 int flags; 2206 win_T *win; 2207 win_T *altwin; 2208 2209 usable_win = 0; 2210 2211 ll_ref = curwin->w_llist_ref; 2212 if (ll_ref != NULL) 2213 { 2214 /* Find a window using the same location list that is not a 2215 * quickfix window. */ 2216 FOR_ALL_WINDOWS(usable_win_ptr) 2217 if (usable_win_ptr->w_llist == ll_ref 2218 && !bt_quickfix(usable_win_ptr->w_buffer)) 2219 { 2220 usable_win = 1; 2221 break; 2222 } 2223 } 2224 2225 if (!usable_win) 2226 { 2227 /* Locate a window showing a normal buffer */ 2228 FOR_ALL_WINDOWS(win) 2229 if (win->w_buffer->b_p_bt[0] == NUL) 2230 { 2231 usable_win = 1; 2232 break; 2233 } 2234 } 2235 2236 /* 2237 * If no usable window is found and 'switchbuf' contains "usetab" 2238 * then search in other tabs. 2239 */ 2240 if (!usable_win && (swb_flags & SWB_USETAB)) 2241 { 2242 tabpage_T *tp; 2243 win_T *wp; 2244 2245 FOR_ALL_TAB_WINDOWS(tp, wp) 2246 { 2247 if (wp->w_buffer->b_fnum == qf_fnum) 2248 { 2249 goto_tabpage_win(tp, wp); 2250 usable_win = 1; 2251 goto win_found; 2252 } 2253 } 2254 } 2255 win_found: 2256 2257 /* 2258 * If there is only one window and it is the quickfix window, create a 2259 * new one above the quickfix window. 2260 */ 2261 if ((ONE_WINDOW && bt_quickfix(curbuf)) || !usable_win) 2262 { 2263 flags = WSP_ABOVE; 2264 if (ll_ref != NULL) 2265 flags |= WSP_NEWLOC; 2266 if (win_split(0, flags) == FAIL) 2267 return FAIL; /* not enough room for window */ 2268 *opened_window = TRUE; /* close it when fail */ 2269 p_swb = empty_option; /* don't split again */ 2270 swb_flags = 0; 2271 RESET_BINDING(curwin); 2272 if (ll_ref != NULL) 2273 { 2274 /* The new window should use the location list from the 2275 * location list window */ 2276 curwin->w_llist = ll_ref; 2277 ll_ref->qf_refcount++; 2278 } 2279 } 2280 else 2281 { 2282 if (curwin->w_llist_ref != NULL) 2283 { 2284 /* In a location window */ 2285 win = usable_win_ptr; 2286 if (win == NULL) 2287 { 2288 /* Find the window showing the selected file */ 2289 FOR_ALL_WINDOWS(win) 2290 if (win->w_buffer->b_fnum == qf_fnum) 2291 break; 2292 if (win == NULL) 2293 { 2294 /* Find a previous usable window */ 2295 win = curwin; 2296 do 2297 { 2298 if (win->w_buffer->b_p_bt[0] == NUL) 2299 break; 2300 if (win->w_prev == NULL) 2301 win = lastwin; /* wrap around the top */ 2302 else 2303 win = win->w_prev; /* go to previous window */ 2304 } while (win != curwin); 2305 } 2306 } 2307 win_goto(win); 2308 2309 /* If the location list for the window is not set, then set it 2310 * to the location list from the location window */ 2311 if (win->w_llist == NULL) 2312 { 2313 win->w_llist = ll_ref; 2314 ll_ref->qf_refcount++; 2315 } 2316 } 2317 else 2318 { 2319 2320 /* 2321 * Try to find a window that shows the right buffer. 2322 * Default to the window just above the quickfix buffer. 2323 */ 2324 win = curwin; 2325 altwin = NULL; 2326 for (;;) 2327 { 2328 if (win->w_buffer->b_fnum == qf_fnum) 2329 break; 2330 if (win->w_prev == NULL) 2331 win = lastwin; /* wrap around the top */ 2332 else 2333 win = win->w_prev; /* go to previous window */ 2334 2335 if (IS_QF_WINDOW(win)) 2336 { 2337 /* Didn't find it, go to the window before the quickfix 2338 * window. */ 2339 if (altwin != NULL) 2340 win = altwin; 2341 else if (curwin->w_prev != NULL) 2342 win = curwin->w_prev; 2343 else 2344 win = curwin->w_next; 2345 break; 2346 } 2347 2348 /* Remember a usable window. */ 2349 if (altwin == NULL && !win->w_p_pvw 2350 && win->w_buffer->b_p_bt[0] == NUL) 2351 altwin = win; 2352 } 2353 2354 win_goto(win); 2355 } 2356 } 2357 2358 return OK; 2359 } 2360 2361 /* 2362 * Edit the selected file or help file. 2363 */ 2364 static int 2365 qf_jump_edit_buffer( 2366 qf_info_T *qi, 2367 qfline_T *qf_ptr, 2368 int forceit, 2369 win_T *oldwin, 2370 int *opened_window, 2371 int *abort) 2372 { 2373 int retval = OK; 2374 2375 if (qf_ptr->qf_type == 1) 2376 { 2377 /* Open help file (do_ecmd() will set b_help flag, readfile() will 2378 * set b_p_ro flag). */ 2379 if (!can_abandon(curbuf, forceit)) 2380 { 2381 no_write_message(); 2382 retval = FAIL; 2383 } 2384 else 2385 retval = do_ecmd(qf_ptr->qf_fnum, NULL, NULL, NULL, (linenr_T)1, 2386 ECMD_HIDE + ECMD_SET_HELP, 2387 oldwin == curwin ? curwin : NULL); 2388 } 2389 else 2390 { 2391 int old_qf_curlist = qi->qf_curlist; 2392 int save_qfid = qi->qf_lists[qi->qf_curlist].qf_id; 2393 2394 retval = buflist_getfile(qf_ptr->qf_fnum, 2395 (linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit); 2396 2397 if (qi != &ql_info) 2398 { 2399 /* 2400 * Location list. Check whether the associated window is still 2401 * present and the list is still valid. 2402 */ 2403 if (!win_valid_any_tab(oldwin)) 2404 { 2405 EMSG(_("E924: Current window was closed")); 2406 *abort = TRUE; 2407 *opened_window = FALSE; 2408 } 2409 else if (!qflist_valid(oldwin, save_qfid)) 2410 { 2411 EMSG(_(e_loc_list_changed)); 2412 *abort = TRUE; 2413 } 2414 } 2415 else if (old_qf_curlist != qi->qf_curlist 2416 || !is_qf_entry_present(qi, qf_ptr)) 2417 { 2418 if (qi == &ql_info) 2419 EMSG(_("E925: Current quickfix was changed")); 2420 else 2421 EMSG(_(e_loc_list_changed)); 2422 *abort = TRUE; 2423 } 2424 2425 if (*abort) 2426 retval = FAIL; 2427 } 2428 2429 return retval; 2430 } 2431 2432 /* 2433 * Goto the error line in the current file using either line/column number or a 2434 * search pattern. 2435 */ 2436 static void 2437 qf_jump_goto_line( 2438 linenr_T qf_lnum, 2439 int qf_col, 2440 char_u qf_viscol, 2441 char_u *qf_pattern) 2442 { 2443 linenr_T i; 2444 char_u *line; 2445 colnr_T screen_col; 2446 colnr_T char_col; 2447 2448 if (qf_pattern == NULL) 2449 { 2450 /* 2451 * Go to line with error, unless qf_lnum is 0. 2452 */ 2453 i = qf_lnum; 2454 if (i > 0) 2455 { 2456 if (i > curbuf->b_ml.ml_line_count) 2457 i = curbuf->b_ml.ml_line_count; 2458 curwin->w_cursor.lnum = i; 2459 } 2460 if (qf_col > 0) 2461 { 2462 curwin->w_cursor.col = qf_col - 1; 2463 #ifdef FEAT_VIRTUALEDIT 2464 curwin->w_cursor.coladd = 0; 2465 #endif 2466 if (qf_viscol == TRUE) 2467 { 2468 /* 2469 * Check each character from the beginning of the error 2470 * line up to the error column. For each tab character 2471 * found, reduce the error column value by the length of 2472 * a tab character. 2473 */ 2474 line = ml_get_curline(); 2475 screen_col = 0; 2476 for (char_col = 0; char_col < curwin->w_cursor.col; ++char_col) 2477 { 2478 if (*line == NUL) 2479 break; 2480 if (*line++ == '\t') 2481 { 2482 curwin->w_cursor.col -= 7 - (screen_col % 8); 2483 screen_col += 8 - (screen_col % 8); 2484 } 2485 else 2486 ++screen_col; 2487 } 2488 } 2489 check_cursor(); 2490 } 2491 else 2492 beginline(BL_WHITE | BL_FIX); 2493 } 2494 else 2495 { 2496 pos_T save_cursor; 2497 2498 /* Move the cursor to the first line in the buffer */ 2499 save_cursor = curwin->w_cursor; 2500 curwin->w_cursor.lnum = 0; 2501 if (!do_search(NULL, '/', qf_pattern, (long)1, 2502 SEARCH_KEEP, NULL, NULL)) 2503 curwin->w_cursor = save_cursor; 2504 } 2505 } 2506 2507 /* 2508 * Display quickfix list index and size message 2509 */ 2510 static void 2511 qf_jump_print_msg( 2512 qf_info_T *qi, 2513 int qf_index, 2514 qfline_T *qf_ptr, 2515 buf_T *old_curbuf, 2516 linenr_T old_lnum) 2517 { 2518 linenr_T i; 2519 int len; 2520 2521 /* Update the screen before showing the message, unless the screen 2522 * scrolled up. */ 2523 if (!msg_scrolled) 2524 update_topline_redraw(); 2525 sprintf((char *)IObuff, _("(%d of %d)%s%s: "), qf_index, 2526 qi->qf_lists[qi->qf_curlist].qf_count, 2527 qf_ptr->qf_cleared ? _(" (line deleted)") : "", 2528 (char *)qf_types(qf_ptr->qf_type, qf_ptr->qf_nr)); 2529 /* Add the message, skipping leading whitespace and newlines. */ 2530 len = (int)STRLEN(IObuff); 2531 qf_fmt_text(skipwhite(qf_ptr->qf_text), IObuff + len, IOSIZE - len); 2532 2533 /* Output the message. Overwrite to avoid scrolling when the 'O' 2534 * flag is present in 'shortmess'; But when not jumping, print the 2535 * whole message. */ 2536 i = msg_scroll; 2537 if (curbuf == old_curbuf && curwin->w_cursor.lnum == old_lnum) 2538 msg_scroll = TRUE; 2539 else if (!msg_scrolled && shortmess(SHM_OVERALL)) 2540 msg_scroll = FALSE; 2541 msg_attr_keep(IObuff, 0, TRUE); 2542 msg_scroll = i; 2543 } 2544 2545 /* 2546 * jump to a quickfix line 2547 * if dir == FORWARD go "errornr" valid entries forward 2548 * if dir == BACKWARD go "errornr" valid entries backward 2549 * if dir == FORWARD_FILE go "errornr" valid entries files backward 2550 * if dir == BACKWARD_FILE go "errornr" valid entries files backward 2551 * else if "errornr" is zero, redisplay the same line 2552 * else go to entry "errornr" 2553 */ 2554 void 2555 qf_jump(qf_info_T *qi, 2556 int dir, 2557 int errornr, 2558 int forceit) 2559 { 2560 qfline_T *qf_ptr; 2561 qfline_T *old_qf_ptr; 2562 int qf_index; 2563 int old_qf_index; 2564 buf_T *old_curbuf; 2565 linenr_T old_lnum; 2566 char_u *old_swb = p_swb; 2567 unsigned old_swb_flags = swb_flags; 2568 int opened_window = FALSE; 2569 win_T *oldwin = curwin; 2570 int print_message = TRUE; 2571 #ifdef FEAT_FOLDING 2572 int old_KeyTyped = KeyTyped; /* getting file may reset it */ 2573 #endif 2574 int retval = OK; 2575 2576 if (qi == NULL) 2577 qi = &ql_info; 2578 2579 if (qi->qf_curlist >= qi->qf_listcount 2580 || qi->qf_lists[qi->qf_curlist].qf_count == 0) 2581 { 2582 EMSG(_(e_quickfix)); 2583 return; 2584 } 2585 2586 qf_ptr = qi->qf_lists[qi->qf_curlist].qf_ptr; 2587 old_qf_ptr = qf_ptr; 2588 qf_index = qi->qf_lists[qi->qf_curlist].qf_index; 2589 old_qf_index = qf_index; 2590 if (dir != 0) /* next/prev valid entry */ 2591 { 2592 qf_ptr = get_nth_valid_entry(qi, errornr, qf_ptr, &qf_index, dir); 2593 if (qf_ptr == NULL) 2594 { 2595 qf_ptr = old_qf_ptr; 2596 qf_index = old_qf_index; 2597 goto theend; 2598 } 2599 } 2600 else if (errornr != 0) /* go to specified number */ 2601 qf_ptr = get_nth_entry(qi, errornr, qf_ptr, &qf_index); 2602 2603 qi->qf_lists[qi->qf_curlist].qf_index = qf_index; 2604 if (qf_win_pos_update(qi, old_qf_index)) 2605 /* No need to print the error message if it's visible in the error 2606 * window */ 2607 print_message = FALSE; 2608 2609 /* 2610 * For ":helpgrep" find a help window or open one. 2611 */ 2612 if (qf_ptr->qf_type == 1 && (!bt_help(curwin->w_buffer) || cmdmod.tab != 0)) 2613 if (jump_to_help_window(qi, &opened_window) == FAIL) 2614 goto theend; 2615 2616 /* 2617 * If currently in the quickfix window, find another window to show the 2618 * file in. 2619 */ 2620 if (bt_quickfix(curbuf) && !opened_window) 2621 { 2622 /* 2623 * If there is no file specified, we don't know where to go. 2624 * But do advance, otherwise ":cn" gets stuck. 2625 */ 2626 if (qf_ptr->qf_fnum == 0) 2627 goto theend; 2628 2629 if (qf_jump_to_usable_window(qf_ptr->qf_fnum, &opened_window) == FAIL) 2630 goto failed; 2631 } 2632 2633 /* 2634 * If there is a file name, 2635 * read the wanted file if needed, and check autowrite etc. 2636 */ 2637 old_curbuf = curbuf; 2638 old_lnum = curwin->w_cursor.lnum; 2639 2640 if (qf_ptr->qf_fnum != 0) 2641 { 2642 int abort = FALSE; 2643 2644 retval = qf_jump_edit_buffer(qi, qf_ptr, forceit, oldwin, 2645 &opened_window, &abort); 2646 if (abort) 2647 { 2648 qi = NULL; 2649 qf_ptr = NULL; 2650 } 2651 } 2652 2653 if (retval == OK) 2654 { 2655 /* When not switched to another buffer, still need to set pc mark */ 2656 if (curbuf == old_curbuf) 2657 setpcmark(); 2658 2659 qf_jump_goto_line(qf_ptr->qf_lnum, qf_ptr->qf_col, qf_ptr->qf_viscol, 2660 qf_ptr->qf_pattern); 2661 2662 #ifdef FEAT_FOLDING 2663 if ((fdo_flags & FDO_QUICKFIX) && old_KeyTyped) 2664 foldOpenCursor(); 2665 #endif 2666 if (print_message) 2667 qf_jump_print_msg(qi, qf_index, qf_ptr, old_curbuf, old_lnum); 2668 } 2669 else 2670 { 2671 if (opened_window) 2672 win_close(curwin, TRUE); /* Close opened window */ 2673 if (qf_ptr != NULL && qf_ptr->qf_fnum != 0) 2674 { 2675 /* 2676 * Couldn't open file, so put index back where it was. This could 2677 * happen if the file was readonly and we changed something. 2678 */ 2679 failed: 2680 qf_ptr = old_qf_ptr; 2681 qf_index = old_qf_index; 2682 } 2683 } 2684 theend: 2685 if (qi != NULL) 2686 { 2687 qi->qf_lists[qi->qf_curlist].qf_ptr = qf_ptr; 2688 qi->qf_lists[qi->qf_curlist].qf_index = qf_index; 2689 } 2690 if (p_swb != old_swb && opened_window) 2691 { 2692 /* Restore old 'switchbuf' value, but not when an autocommand or 2693 * modeline has changed the value. */ 2694 if (p_swb == empty_option) 2695 { 2696 p_swb = old_swb; 2697 swb_flags = old_swb_flags; 2698 } 2699 else 2700 free_string_option(old_swb); 2701 } 2702 } 2703 2704 /* 2705 * ":clist": list all errors 2706 * ":llist": list all locations 2707 */ 2708 void 2709 qf_list(exarg_T *eap) 2710 { 2711 buf_T *buf; 2712 char_u *fname; 2713 qfline_T *qfp; 2714 int i; 2715 int idx1 = 1; 2716 int idx2 = -1; 2717 char_u *arg = eap->arg; 2718 int plus = FALSE; 2719 int qfFileAttr; 2720 int qfSepAttr; 2721 int qfLineAttr; 2722 int all = eap->forceit; /* if not :cl!, only show 2723 recognised errors */ 2724 qf_info_T *qi = &ql_info; 2725 2726 if (eap->cmdidx == CMD_llist) 2727 { 2728 qi = GET_LOC_LIST(curwin); 2729 if (qi == NULL) 2730 { 2731 EMSG(_(e_loclist)); 2732 return; 2733 } 2734 } 2735 2736 if (qi->qf_curlist >= qi->qf_listcount 2737 || qi->qf_lists[qi->qf_curlist].qf_count == 0) 2738 { 2739 EMSG(_(e_quickfix)); 2740 return; 2741 } 2742 if (*arg == '+') 2743 { 2744 ++arg; 2745 plus = TRUE; 2746 } 2747 if (!get_list_range(&arg, &idx1, &idx2) || *arg != NUL) 2748 { 2749 EMSG(_(e_trailing)); 2750 return; 2751 } 2752 if (plus) 2753 { 2754 i = qi->qf_lists[qi->qf_curlist].qf_index; 2755 idx2 = i + idx1; 2756 idx1 = i; 2757 } 2758 else 2759 { 2760 i = qi->qf_lists[qi->qf_curlist].qf_count; 2761 if (idx1 < 0) 2762 idx1 = (-idx1 > i) ? 0 : idx1 + i + 1; 2763 if (idx2 < 0) 2764 idx2 = (-idx2 > i) ? 0 : idx2 + i + 1; 2765 } 2766 2767 /* Shorten all the file names, so that it is easy to read */ 2768 shorten_fnames(FALSE); 2769 2770 /* 2771 * Get the attributes for the different quickfix highlight items. Note 2772 * that this depends on syntax items defined in the qf.vim syntax file 2773 */ 2774 qfFileAttr = syn_name2attr((char_u *)"qfFileName"); 2775 if (qfFileAttr == 0) 2776 qfFileAttr = HL_ATTR(HLF_D); 2777 qfSepAttr = syn_name2attr((char_u *)"qfSeparator"); 2778 if (qfSepAttr == 0) 2779 qfSepAttr = HL_ATTR(HLF_D); 2780 qfLineAttr = syn_name2attr((char_u *)"qfLineNr"); 2781 if (qfLineAttr == 0) 2782 qfLineAttr = HL_ATTR(HLF_N); 2783 2784 if (qi->qf_lists[qi->qf_curlist].qf_nonevalid) 2785 all = TRUE; 2786 qfp = qi->qf_lists[qi->qf_curlist].qf_start; 2787 for (i = 1; !got_int && i <= qi->qf_lists[qi->qf_curlist].qf_count; ) 2788 { 2789 if ((qfp->qf_valid || all) && idx1 <= i && i <= idx2) 2790 { 2791 msg_putchar('\n'); 2792 if (got_int) 2793 break; 2794 2795 fname = NULL; 2796 if (qfp->qf_module != NULL && *qfp->qf_module != NUL) 2797 vim_snprintf((char *)IObuff, IOSIZE, "%2d %s", i, (char *)qfp->qf_module); 2798 else { 2799 if (qfp->qf_fnum != 0 2800 && (buf = buflist_findnr(qfp->qf_fnum)) != NULL) 2801 { 2802 fname = buf->b_fname; 2803 if (qfp->qf_type == 1) /* :helpgrep */ 2804 fname = gettail(fname); 2805 } 2806 if (fname == NULL) 2807 sprintf((char *)IObuff, "%2d", i); 2808 else 2809 vim_snprintf((char *)IObuff, IOSIZE, "%2d %s", 2810 i, (char *)fname); 2811 } 2812 msg_outtrans_attr(IObuff, i == qi->qf_lists[qi->qf_curlist].qf_index 2813 ? HL_ATTR(HLF_QFL) : qfFileAttr); 2814 2815 if (qfp->qf_lnum != 0) 2816 msg_puts_attr((char_u *)":", qfSepAttr); 2817 if (qfp->qf_lnum == 0) 2818 IObuff[0] = NUL; 2819 else if (qfp->qf_col == 0) 2820 sprintf((char *)IObuff, "%ld", qfp->qf_lnum); 2821 else 2822 sprintf((char *)IObuff, "%ld col %d", 2823 qfp->qf_lnum, qfp->qf_col); 2824 sprintf((char *)IObuff + STRLEN(IObuff), "%s", 2825 (char *)qf_types(qfp->qf_type, qfp->qf_nr)); 2826 msg_puts_attr(IObuff, qfLineAttr); 2827 msg_puts_attr((char_u *)":", qfSepAttr); 2828 if (qfp->qf_pattern != NULL) 2829 { 2830 qf_fmt_text(qfp->qf_pattern, IObuff, IOSIZE); 2831 msg_puts(IObuff); 2832 msg_puts_attr((char_u *)":", qfSepAttr); 2833 } 2834 msg_puts((char_u *)" "); 2835 2836 /* Remove newlines and leading whitespace from the text. For an 2837 * unrecognized line keep the indent, the compiler may mark a word 2838 * with ^^^^. */ 2839 qf_fmt_text((fname != NULL || qfp->qf_lnum != 0) 2840 ? skipwhite(qfp->qf_text) : qfp->qf_text, 2841 IObuff, IOSIZE); 2842 msg_prt_line(IObuff, FALSE); 2843 out_flush(); /* show one line at a time */ 2844 } 2845 2846 qfp = qfp->qf_next; 2847 if (qfp == NULL) 2848 break; 2849 ++i; 2850 ui_breakcheck(); 2851 } 2852 } 2853 2854 /* 2855 * Remove newlines and leading whitespace from an error message. 2856 * Put the result in "buf[bufsize]". 2857 */ 2858 static void 2859 qf_fmt_text(char_u *text, char_u *buf, int bufsize) 2860 { 2861 int i; 2862 char_u *p = text; 2863 2864 for (i = 0; *p != NUL && i < bufsize - 1; ++i) 2865 { 2866 if (*p == '\n') 2867 { 2868 buf[i] = ' '; 2869 while (*++p != NUL) 2870 if (!VIM_ISWHITE(*p) && *p != '\n') 2871 break; 2872 } 2873 else 2874 buf[i] = *p++; 2875 } 2876 buf[i] = NUL; 2877 } 2878 2879 static void 2880 qf_msg(qf_info_T *qi, int which, char *lead) 2881 { 2882 char *title = (char *)qi->qf_lists[which].qf_title; 2883 int count = qi->qf_lists[which].qf_count; 2884 char_u buf[IOSIZE]; 2885 2886 vim_snprintf((char *)buf, IOSIZE, _("%serror list %d of %d; %d errors "), 2887 lead, 2888 which + 1, 2889 qi->qf_listcount, 2890 count); 2891 2892 if (title != NULL) 2893 { 2894 size_t len = STRLEN(buf); 2895 2896 if (len < 34) 2897 { 2898 vim_memset(buf + len, ' ', 34 - len); 2899 buf[34] = NUL; 2900 } 2901 vim_strcat(buf, (char_u *)title, IOSIZE); 2902 } 2903 trunc_string(buf, buf, Columns - 1, IOSIZE); 2904 msg(buf); 2905 } 2906 2907 /* 2908 * ":colder [count]": Up in the quickfix stack. 2909 * ":cnewer [count]": Down in the quickfix stack. 2910 * ":lolder [count]": Up in the location list stack. 2911 * ":lnewer [count]": Down in the location list stack. 2912 */ 2913 void 2914 qf_age(exarg_T *eap) 2915 { 2916 qf_info_T *qi = &ql_info; 2917 int count; 2918 2919 if (eap->cmdidx == CMD_lolder || eap->cmdidx == CMD_lnewer) 2920 { 2921 qi = GET_LOC_LIST(curwin); 2922 if (qi == NULL) 2923 { 2924 EMSG(_(e_loclist)); 2925 return; 2926 } 2927 } 2928 2929 if (eap->addr_count != 0) 2930 count = eap->line2; 2931 else 2932 count = 1; 2933 while (count--) 2934 { 2935 if (eap->cmdidx == CMD_colder || eap->cmdidx == CMD_lolder) 2936 { 2937 if (qi->qf_curlist == 0) 2938 { 2939 EMSG(_("E380: At bottom of quickfix stack")); 2940 break; 2941 } 2942 --qi->qf_curlist; 2943 } 2944 else 2945 { 2946 if (qi->qf_curlist >= qi->qf_listcount - 1) 2947 { 2948 EMSG(_("E381: At top of quickfix stack")); 2949 break; 2950 } 2951 ++qi->qf_curlist; 2952 } 2953 } 2954 qf_msg(qi, qi->qf_curlist, ""); 2955 qf_update_buffer(qi, NULL); 2956 } 2957 2958 void 2959 qf_history(exarg_T *eap) 2960 { 2961 qf_info_T *qi = &ql_info; 2962 int i; 2963 2964 if (eap->cmdidx == CMD_lhistory) 2965 qi = GET_LOC_LIST(curwin); 2966 if (qi == NULL || (qi->qf_listcount == 0 2967 && qi->qf_lists[qi->qf_curlist].qf_count == 0)) 2968 MSG(_("No entries")); 2969 else 2970 for (i = 0; i < qi->qf_listcount; ++i) 2971 qf_msg(qi, i, i == qi->qf_curlist ? "> " : " "); 2972 } 2973 2974 /* 2975 * Free all the entries in the error list "idx". Note that other information 2976 * associated with the list like context and title are not freed. 2977 */ 2978 static void 2979 qf_free_items(qf_info_T *qi, int idx) 2980 { 2981 qfline_T *qfp; 2982 qfline_T *qfpnext; 2983 int stop = FALSE; 2984 qf_list_T *qfl = &qi->qf_lists[idx]; 2985 2986 while (qfl->qf_count && qfl->qf_start != NULL) 2987 { 2988 qfp = qfl->qf_start; 2989 qfpnext = qfp->qf_next; 2990 if (!stop) 2991 { 2992 vim_free(qfp->qf_module); 2993 vim_free(qfp->qf_text); 2994 vim_free(qfp->qf_pattern); 2995 stop = (qfp == qfpnext); 2996 vim_free(qfp); 2997 if (stop) 2998 /* Somehow qf_count may have an incorrect value, set it to 1 2999 * to avoid crashing when it's wrong. 3000 * TODO: Avoid qf_count being incorrect. */ 3001 qfl->qf_count = 1; 3002 } 3003 qfl->qf_start = qfpnext; 3004 --qfl->qf_count; 3005 } 3006 3007 qfl->qf_index = 0; 3008 qfl->qf_start = NULL; 3009 qfl->qf_last = NULL; 3010 qfl->qf_ptr = NULL; 3011 qfl->qf_nonevalid = TRUE; 3012 3013 qf_clean_dir_stack(&qfl->qf_dir_stack); 3014 qfl->qf_directory = NULL; 3015 qf_clean_dir_stack(&qfl->qf_file_stack); 3016 qfl->qf_currfile = NULL; 3017 qfl->qf_multiline = FALSE; 3018 qfl->qf_multiignore = FALSE; 3019 qfl->qf_multiscan = FALSE; 3020 } 3021 3022 /* 3023 * Free error list "idx". Frees all the entries in the quickfix list, 3024 * associated context information and the title. 3025 */ 3026 static void 3027 qf_free(qf_info_T *qi, int idx) 3028 { 3029 qf_list_T *qfl = &qi->qf_lists[idx]; 3030 3031 qf_free_items(qi, idx); 3032 3033 VIM_CLEAR(qfl->qf_title); 3034 free_tv(qfl->qf_ctx); 3035 qfl->qf_ctx = NULL; 3036 qfl->qf_id = 0; 3037 qfl->qf_changedtick = 0L; 3038 } 3039 3040 /* 3041 * qf_mark_adjust: adjust marks 3042 */ 3043 void 3044 qf_mark_adjust( 3045 win_T *wp, 3046 linenr_T line1, 3047 linenr_T line2, 3048 long amount, 3049 long amount_after) 3050 { 3051 int i; 3052 qfline_T *qfp; 3053 int idx; 3054 qf_info_T *qi = &ql_info; 3055 int found_one = FALSE; 3056 int buf_has_flag = wp == NULL ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY; 3057 3058 if (!(curbuf->b_has_qf_entry & buf_has_flag)) 3059 return; 3060 if (wp != NULL) 3061 { 3062 if (wp->w_llist == NULL) 3063 return; 3064 qi = wp->w_llist; 3065 } 3066 3067 for (idx = 0; idx < qi->qf_listcount; ++idx) 3068 if (qi->qf_lists[idx].qf_count) 3069 for (i = 0, qfp = qi->qf_lists[idx].qf_start; 3070 i < qi->qf_lists[idx].qf_count && qfp != NULL; 3071 ++i, qfp = qfp->qf_next) 3072 if (qfp->qf_fnum == curbuf->b_fnum) 3073 { 3074 found_one = TRUE; 3075 if (qfp->qf_lnum >= line1 && qfp->qf_lnum <= line2) 3076 { 3077 if (amount == MAXLNUM) 3078 qfp->qf_cleared = TRUE; 3079 else 3080 qfp->qf_lnum += amount; 3081 } 3082 else if (amount_after && qfp->qf_lnum > line2) 3083 qfp->qf_lnum += amount_after; 3084 } 3085 3086 if (!found_one) 3087 curbuf->b_has_qf_entry &= ~buf_has_flag; 3088 } 3089 3090 /* 3091 * Make a nice message out of the error character and the error number: 3092 * char number message 3093 * e or E 0 " error" 3094 * w or W 0 " warning" 3095 * i or I 0 " info" 3096 * 0 0 "" 3097 * other 0 " c" 3098 * e or E n " error n" 3099 * w or W n " warning n" 3100 * i or I n " info n" 3101 * 0 n " error n" 3102 * other n " c n" 3103 * 1 x "" :helpgrep 3104 */ 3105 static char_u * 3106 qf_types(int c, int nr) 3107 { 3108 static char_u buf[20]; 3109 static char_u cc[3]; 3110 char_u *p; 3111 3112 if (c == 'W' || c == 'w') 3113 p = (char_u *)" warning"; 3114 else if (c == 'I' || c == 'i') 3115 p = (char_u *)" info"; 3116 else if (c == 'E' || c == 'e' || (c == 0 && nr > 0)) 3117 p = (char_u *)" error"; 3118 else if (c == 0 || c == 1) 3119 p = (char_u *)""; 3120 else 3121 { 3122 cc[0] = ' '; 3123 cc[1] = c; 3124 cc[2] = NUL; 3125 p = cc; 3126 } 3127 3128 if (nr <= 0) 3129 return p; 3130 3131 sprintf((char *)buf, "%s %3d", (char *)p, nr); 3132 return buf; 3133 } 3134 3135 /* 3136 * ":cwindow": open the quickfix window if we have errors to display, 3137 * close it if not. 3138 * ":lwindow": open the location list window if we have locations to display, 3139 * close it if not. 3140 */ 3141 void 3142 ex_cwindow(exarg_T *eap) 3143 { 3144 qf_info_T *qi = &ql_info; 3145 win_T *win; 3146 3147 if (eap->cmdidx == CMD_lwindow) 3148 { 3149 qi = GET_LOC_LIST(curwin); 3150 if (qi == NULL) 3151 return; 3152 } 3153 3154 /* Look for an existing quickfix window. */ 3155 win = qf_find_win(qi); 3156 3157 /* 3158 * If a quickfix window is open but we have no errors to display, 3159 * close the window. If a quickfix window is not open, then open 3160 * it if we have errors; otherwise, leave it closed. 3161 */ 3162 if (qi->qf_lists[qi->qf_curlist].qf_nonevalid 3163 || qi->qf_lists[qi->qf_curlist].qf_count == 0 3164 || qi->qf_curlist >= qi->qf_listcount) 3165 { 3166 if (win != NULL) 3167 ex_cclose(eap); 3168 } 3169 else if (win == NULL) 3170 ex_copen(eap); 3171 } 3172 3173 /* 3174 * ":cclose": close the window showing the list of errors. 3175 * ":lclose": close the window showing the location list 3176 */ 3177 void 3178 ex_cclose(exarg_T *eap) 3179 { 3180 win_T *win = NULL; 3181 qf_info_T *qi = &ql_info; 3182 3183 if (eap->cmdidx == CMD_lclose || eap->cmdidx == CMD_lwindow) 3184 { 3185 qi = GET_LOC_LIST(curwin); 3186 if (qi == NULL) 3187 return; 3188 } 3189 3190 /* Find existing quickfix window and close it. */ 3191 win = qf_find_win(qi); 3192 if (win != NULL) 3193 win_close(win, FALSE); 3194 } 3195 3196 /* 3197 * ":copen": open a window that shows the list of errors. 3198 * ":lopen": open a window that shows the location list. 3199 */ 3200 void 3201 ex_copen(exarg_T *eap) 3202 { 3203 qf_info_T *qi = &ql_info; 3204 int height; 3205 win_T *win; 3206 tabpage_T *prevtab = curtab; 3207 buf_T *qf_buf; 3208 win_T *oldwin = curwin; 3209 3210 if (eap->cmdidx == CMD_lopen || eap->cmdidx == CMD_lwindow) 3211 { 3212 qi = GET_LOC_LIST(curwin); 3213 if (qi == NULL) 3214 { 3215 EMSG(_(e_loclist)); 3216 return; 3217 } 3218 } 3219 3220 if (eap->addr_count != 0) 3221 height = eap->line2; 3222 else 3223 height = QF_WINHEIGHT; 3224 3225 reset_VIsual_and_resel(); /* stop Visual mode */ 3226 #ifdef FEAT_GUI 3227 need_mouse_correct = TRUE; 3228 #endif 3229 3230 /* 3231 * Find existing quickfix window, or open a new one. 3232 */ 3233 win = qf_find_win(qi); 3234 3235 if (win != NULL && cmdmod.tab == 0) 3236 { 3237 win_goto(win); 3238 if (eap->addr_count != 0) 3239 { 3240 if (cmdmod.split & WSP_VERT) 3241 { 3242 if (height != win->w_width) 3243 win_setwidth(height); 3244 } 3245 else if (height != win->w_height) 3246 win_setheight(height); 3247 } 3248 } 3249 else 3250 { 3251 int flags = 0; 3252 3253 qf_buf = qf_find_buf(qi); 3254 3255 /* The current window becomes the previous window afterwards. */ 3256 win = curwin; 3257 3258 if ((eap->cmdidx == CMD_copen || eap->cmdidx == CMD_cwindow) 3259 && cmdmod.split == 0) 3260 /* Create the new quickfix window at the very bottom, except when 3261 * :belowright or :aboveleft is used. */ 3262 win_goto(lastwin); 3263 /* Default is to open the window below the current window */ 3264 if (cmdmod.split == 0) 3265 flags = WSP_BELOW; 3266 flags |= WSP_NEWLOC; 3267 if (win_split(height, flags) == FAIL) 3268 return; /* not enough room for window */ 3269 RESET_BINDING(curwin); 3270 3271 if (eap->cmdidx == CMD_lopen || eap->cmdidx == CMD_lwindow) 3272 { 3273 /* 3274 * For the location list window, create a reference to the 3275 * location list from the window 'win'. 3276 */ 3277 curwin->w_llist_ref = win->w_llist; 3278 win->w_llist->qf_refcount++; 3279 } 3280 3281 if (oldwin != curwin) 3282 oldwin = NULL; /* don't store info when in another window */ 3283 if (qf_buf != NULL) 3284 /* Use the existing quickfix buffer */ 3285 (void)do_ecmd(qf_buf->b_fnum, NULL, NULL, NULL, ECMD_ONE, 3286 ECMD_HIDE + ECMD_OLDBUF, oldwin); 3287 else 3288 { 3289 /* Create a new quickfix buffer */ 3290 (void)do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, oldwin); 3291 /* switch off 'swapfile' */ 3292 set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL); 3293 set_option_value((char_u *)"bt", 0L, (char_u *)"quickfix", 3294 OPT_LOCAL); 3295 set_option_value((char_u *)"bh", 0L, (char_u *)"wipe", OPT_LOCAL); 3296 RESET_BINDING(curwin); 3297 #ifdef FEAT_DIFF 3298 curwin->w_p_diff = FALSE; 3299 #endif 3300 #ifdef FEAT_FOLDING 3301 set_option_value((char_u *)"fdm", 0L, (char_u *)"manual", 3302 OPT_LOCAL); 3303 #endif 3304 } 3305 3306 /* Only set the height when still in the same tab page and there is no 3307 * window to the side. */ 3308 if (curtab == prevtab && curwin->w_width == Columns) 3309 win_setheight(height); 3310 curwin->w_p_wfh = TRUE; /* set 'winfixheight' */ 3311 if (win_valid(win)) 3312 prevwin = win; 3313 } 3314 3315 qf_set_title_var(qi); 3316 3317 /* 3318 * Fill the buffer with the quickfix list. 3319 */ 3320 qf_fill_buffer(qi, curbuf, NULL); 3321 3322 curwin->w_cursor.lnum = qi->qf_lists[qi->qf_curlist].qf_index; 3323 curwin->w_cursor.col = 0; 3324 check_cursor(); 3325 update_topline(); /* scroll to show the line */ 3326 } 3327 3328 /* 3329 * Move the cursor in the quickfix window to "lnum". 3330 */ 3331 static void 3332 qf_win_goto(win_T *win, linenr_T lnum) 3333 { 3334 win_T *old_curwin = curwin; 3335 3336 curwin = win; 3337 curbuf = win->w_buffer; 3338 curwin->w_cursor.lnum = lnum; 3339 curwin->w_cursor.col = 0; 3340 #ifdef FEAT_VIRTUALEDIT 3341 curwin->w_cursor.coladd = 0; 3342 #endif 3343 curwin->w_curswant = 0; 3344 update_topline(); /* scroll to show the line */ 3345 redraw_later(VALID); 3346 curwin->w_redr_status = TRUE; /* update ruler */ 3347 curwin = old_curwin; 3348 curbuf = curwin->w_buffer; 3349 } 3350 3351 /* 3352 * :cbottom/:lbottom commands. 3353 */ 3354 void 3355 ex_cbottom(exarg_T *eap UNUSED) 3356 { 3357 qf_info_T *qi = &ql_info; 3358 win_T *win; 3359 3360 if (eap->cmdidx == CMD_lbottom) 3361 { 3362 qi = GET_LOC_LIST(curwin); 3363 if (qi == NULL) 3364 { 3365 EMSG(_(e_loclist)); 3366 return; 3367 } 3368 } 3369 3370 win = qf_find_win(qi); 3371 if (win != NULL && win->w_cursor.lnum != win->w_buffer->b_ml.ml_line_count) 3372 qf_win_goto(win, win->w_buffer->b_ml.ml_line_count); 3373 } 3374 3375 /* 3376 * Return the number of the current entry (line number in the quickfix 3377 * window). 3378 */ 3379 linenr_T 3380 qf_current_entry(win_T *wp) 3381 { 3382 qf_info_T *qi = &ql_info; 3383 3384 if (IS_LL_WINDOW(wp)) 3385 /* In the location list window, use the referenced location list */ 3386 qi = wp->w_llist_ref; 3387 3388 return qi->qf_lists[qi->qf_curlist].qf_index; 3389 } 3390 3391 /* 3392 * Update the cursor position in the quickfix window to the current error. 3393 * Return TRUE if there is a quickfix window. 3394 */ 3395 static int 3396 qf_win_pos_update( 3397 qf_info_T *qi, 3398 int old_qf_index) /* previous qf_index or zero */ 3399 { 3400 win_T *win; 3401 int qf_index = qi->qf_lists[qi->qf_curlist].qf_index; 3402 3403 /* 3404 * Put the cursor on the current error in the quickfix window, so that 3405 * it's viewable. 3406 */ 3407 win = qf_find_win(qi); 3408 if (win != NULL 3409 && qf_index <= win->w_buffer->b_ml.ml_line_count 3410 && old_qf_index != qf_index) 3411 { 3412 if (qf_index > old_qf_index) 3413 { 3414 win->w_redraw_top = old_qf_index; 3415 win->w_redraw_bot = qf_index; 3416 } 3417 else 3418 { 3419 win->w_redraw_top = qf_index; 3420 win->w_redraw_bot = old_qf_index; 3421 } 3422 qf_win_goto(win, qf_index); 3423 } 3424 return win != NULL; 3425 } 3426 3427 /* 3428 * Check whether the given window is displaying the specified quickfix/location 3429 * list buffer 3430 */ 3431 static int 3432 is_qf_win(win_T *win, qf_info_T *qi) 3433 { 3434 /* 3435 * A window displaying the quickfix buffer will have the w_llist_ref field 3436 * set to NULL. 3437 * A window displaying a location list buffer will have the w_llist_ref 3438 * pointing to the location list. 3439 */ 3440 if (bt_quickfix(win->w_buffer)) 3441 if ((qi == &ql_info && win->w_llist_ref == NULL) 3442 || (qi != &ql_info && win->w_llist_ref == qi)) 3443 return TRUE; 3444 3445 return FALSE; 3446 } 3447 3448 /* 3449 * Find a window displaying the quickfix/location list 'qi' 3450 * Only searches in the current tabpage. 3451 */ 3452 static win_T * 3453 qf_find_win(qf_info_T *qi) 3454 { 3455 win_T *win; 3456 3457 FOR_ALL_WINDOWS(win) 3458 if (is_qf_win(win, qi)) 3459 return win; 3460 return NULL; 3461 } 3462 3463 /* 3464 * Find a quickfix buffer. 3465 * Searches in windows opened in all the tabs. 3466 */ 3467 static buf_T * 3468 qf_find_buf(qf_info_T *qi) 3469 { 3470 tabpage_T *tp; 3471 win_T *win; 3472 3473 FOR_ALL_TAB_WINDOWS(tp, win) 3474 if (is_qf_win(win, qi)) 3475 return win->w_buffer; 3476 3477 return NULL; 3478 } 3479 3480 /* 3481 * Update the w:quickfix_title variable in the quickfix/location list window 3482 */ 3483 static void 3484 qf_update_win_titlevar(qf_info_T *qi) 3485 { 3486 win_T *win; 3487 win_T *curwin_save; 3488 3489 if ((win = qf_find_win(qi)) != NULL) 3490 { 3491 curwin_save = curwin; 3492 curwin = win; 3493 qf_set_title_var(qi); 3494 curwin = curwin_save; 3495 } 3496 } 3497 3498 /* 3499 * Find the quickfix buffer. If it exists, update the contents. 3500 */ 3501 static void 3502 qf_update_buffer(qf_info_T *qi, qfline_T *old_last) 3503 { 3504 buf_T *buf; 3505 win_T *win; 3506 aco_save_T aco; 3507 3508 /* Check if a buffer for the quickfix list exists. Update it. */ 3509 buf = qf_find_buf(qi); 3510 if (buf != NULL) 3511 { 3512 linenr_T old_line_count = buf->b_ml.ml_line_count; 3513 3514 if (old_last == NULL) 3515 /* set curwin/curbuf to buf and save a few things */ 3516 aucmd_prepbuf(&aco, buf); 3517 3518 qf_update_win_titlevar(qi); 3519 3520 qf_fill_buffer(qi, buf, old_last); 3521 ++CHANGEDTICK(buf); 3522 3523 if (old_last == NULL) 3524 { 3525 (void)qf_win_pos_update(qi, 0); 3526 3527 /* restore curwin/curbuf and a few other things */ 3528 aucmd_restbuf(&aco); 3529 } 3530 3531 /* Only redraw when added lines are visible. This avoids flickering 3532 * when the added lines are not visible. */ 3533 if ((win = qf_find_win(qi)) != NULL && old_line_count < win->w_botline) 3534 redraw_buf_later(buf, NOT_VALID); 3535 } 3536 } 3537 3538 /* 3539 * Set "w:quickfix_title" if "qi" has a title. 3540 */ 3541 static void 3542 qf_set_title_var(qf_info_T *qi) 3543 { 3544 if (qi->qf_lists[qi->qf_curlist].qf_title != NULL) 3545 set_internal_string_var((char_u *)"w:quickfix_title", 3546 qi->qf_lists[qi->qf_curlist].qf_title); 3547 } 3548 3549 /* 3550 * Fill current buffer with quickfix errors, replacing any previous contents. 3551 * curbuf must be the quickfix buffer! 3552 * If "old_last" is not NULL append the items after this one. 3553 * When "old_last" is NULL then "buf" must equal "curbuf"! Because 3554 * ml_delete() is used and autocommands will be triggered. 3555 */ 3556 static void 3557 qf_fill_buffer(qf_info_T *qi, buf_T *buf, qfline_T *old_last) 3558 { 3559 linenr_T lnum; 3560 qfline_T *qfp; 3561 buf_T *errbuf; 3562 int len; 3563 int old_KeyTyped = KeyTyped; 3564 3565 if (old_last == NULL) 3566 { 3567 if (buf != curbuf) 3568 { 3569 internal_error("qf_fill_buffer()"); 3570 return; 3571 } 3572 3573 /* delete all existing lines */ 3574 while ((curbuf->b_ml.ml_flags & ML_EMPTY) == 0) 3575 (void)ml_delete((linenr_T)1, FALSE); 3576 } 3577 3578 /* Check if there is anything to display */ 3579 if (qi->qf_curlist < qi->qf_listcount) 3580 { 3581 char_u dirname[MAXPATHL]; 3582 3583 *dirname = NUL; 3584 3585 /* Add one line for each error */ 3586 if (old_last == NULL) 3587 { 3588 qfp = qi->qf_lists[qi->qf_curlist].qf_start; 3589 lnum = 0; 3590 } 3591 else 3592 { 3593 qfp = old_last->qf_next; 3594 lnum = buf->b_ml.ml_line_count; 3595 } 3596 while (lnum < qi->qf_lists[qi->qf_curlist].qf_count) 3597 { 3598 if (qfp->qf_module != NULL) 3599 { 3600 STRCPY(IObuff, qfp->qf_module); 3601 len = (int)STRLEN(IObuff); 3602 } 3603 else if (qfp->qf_fnum != 0 3604 && (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL 3605 && errbuf->b_fname != NULL) 3606 { 3607 if (qfp->qf_type == 1) /* :helpgrep */ 3608 STRCPY(IObuff, gettail(errbuf->b_fname)); 3609 else 3610 { 3611 /* shorten the file name if not done already */ 3612 if (errbuf->b_sfname == NULL 3613 || mch_isFullName(errbuf->b_sfname)) 3614 { 3615 if (*dirname == NUL) 3616 mch_dirname(dirname, MAXPATHL); 3617 shorten_buf_fname(errbuf, dirname, FALSE); 3618 } 3619 STRCPY(IObuff, errbuf->b_fname); 3620 } 3621 len = (int)STRLEN(IObuff); 3622 } 3623 else 3624 len = 0; 3625 IObuff[len++] = '|'; 3626 3627 if (qfp->qf_lnum > 0) 3628 { 3629 sprintf((char *)IObuff + len, "%ld", qfp->qf_lnum); 3630 len += (int)STRLEN(IObuff + len); 3631 3632 if (qfp->qf_col > 0) 3633 { 3634 sprintf((char *)IObuff + len, " col %d", qfp->qf_col); 3635 len += (int)STRLEN(IObuff + len); 3636 } 3637 3638 sprintf((char *)IObuff + len, "%s", 3639 (char *)qf_types(qfp->qf_type, qfp->qf_nr)); 3640 len += (int)STRLEN(IObuff + len); 3641 } 3642 else if (qfp->qf_pattern != NULL) 3643 { 3644 qf_fmt_text(qfp->qf_pattern, IObuff + len, IOSIZE - len); 3645 len += (int)STRLEN(IObuff + len); 3646 } 3647 IObuff[len++] = '|'; 3648 IObuff[len++] = ' '; 3649 3650 /* Remove newlines and leading whitespace from the text. 3651 * For an unrecognized line keep the indent, the compiler may 3652 * mark a word with ^^^^. */ 3653 qf_fmt_text(len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text, 3654 IObuff + len, IOSIZE - len); 3655 3656 if (ml_append_buf(buf, lnum, IObuff, 3657 (colnr_T)STRLEN(IObuff) + 1, FALSE) == FAIL) 3658 break; 3659 ++lnum; 3660 qfp = qfp->qf_next; 3661 if (qfp == NULL) 3662 break; 3663 } 3664 3665 if (old_last == NULL) 3666 /* Delete the empty line which is now at the end */ 3667 (void)ml_delete(lnum + 1, FALSE); 3668 } 3669 3670 /* correct cursor position */ 3671 check_lnums(TRUE); 3672 3673 if (old_last == NULL) 3674 { 3675 /* Set the 'filetype' to "qf" each time after filling the buffer. 3676 * This resembles reading a file into a buffer, it's more logical when 3677 * using autocommands. */ 3678 ++curbuf_lock; 3679 set_option_value((char_u *)"ft", 0L, (char_u *)"qf", OPT_LOCAL); 3680 curbuf->b_p_ma = FALSE; 3681 3682 keep_filetype = TRUE; /* don't detect 'filetype' */ 3683 apply_autocmds(EVENT_BUFREADPOST, (char_u *)"quickfix", NULL, 3684 FALSE, curbuf); 3685 apply_autocmds(EVENT_BUFWINENTER, (char_u *)"quickfix", NULL, 3686 FALSE, curbuf); 3687 keep_filetype = FALSE; 3688 --curbuf_lock; 3689 3690 /* make sure it will be redrawn */ 3691 redraw_curbuf_later(NOT_VALID); 3692 } 3693 3694 /* Restore KeyTyped, setting 'filetype' may reset it. */ 3695 KeyTyped = old_KeyTyped; 3696 } 3697 3698 static void 3699 qf_list_changed(qf_info_T *qi, int qf_idx) 3700 { 3701 qi->qf_lists[qf_idx].qf_changedtick++; 3702 } 3703 3704 /* 3705 * Return TRUE when using ":vimgrep" for ":grep". 3706 */ 3707 int 3708 grep_internal(cmdidx_T cmdidx) 3709 { 3710 return ((cmdidx == CMD_grep 3711 || cmdidx == CMD_lgrep 3712 || cmdidx == CMD_grepadd 3713 || cmdidx == CMD_lgrepadd) 3714 && STRCMP("internal", 3715 *curbuf->b_p_gp == NUL ? p_gp : curbuf->b_p_gp) == 0); 3716 } 3717 3718 /* 3719 * Used for ":make", ":lmake", ":grep", ":lgrep", ":grepadd", and ":lgrepadd" 3720 */ 3721 void 3722 ex_make(exarg_T *eap) 3723 { 3724 char_u *fname; 3725 char_u *cmd; 3726 char_u *enc = NULL; 3727 unsigned len; 3728 win_T *wp = NULL; 3729 qf_info_T *qi = &ql_info; 3730 int res; 3731 char_u *au_name = NULL; 3732 3733 /* Redirect ":grep" to ":vimgrep" if 'grepprg' is "internal". */ 3734 if (grep_internal(eap->cmdidx)) 3735 { 3736 ex_vimgrep(eap); 3737 return; 3738 } 3739 3740 switch (eap->cmdidx) 3741 { 3742 case CMD_make: au_name = (char_u *)"make"; break; 3743 case CMD_lmake: au_name = (char_u *)"lmake"; break; 3744 case CMD_grep: au_name = (char_u *)"grep"; break; 3745 case CMD_lgrep: au_name = (char_u *)"lgrep"; break; 3746 case CMD_grepadd: au_name = (char_u *)"grepadd"; break; 3747 case CMD_lgrepadd: au_name = (char_u *)"lgrepadd"; break; 3748 default: break; 3749 } 3750 if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, 3751 curbuf->b_fname, TRUE, curbuf)) 3752 { 3753 #ifdef FEAT_EVAL 3754 if (aborting()) 3755 return; 3756 #endif 3757 } 3758 #ifdef FEAT_MBYTE 3759 enc = (*curbuf->b_p_menc != NUL) ? curbuf->b_p_menc : p_menc; 3760 #endif 3761 3762 if (eap->cmdidx == CMD_lmake || eap->cmdidx == CMD_lgrep 3763 || eap->cmdidx == CMD_lgrepadd) 3764 wp = curwin; 3765 3766 autowrite_all(); 3767 fname = get_mef_name(); 3768 if (fname == NULL) 3769 return; 3770 mch_remove(fname); /* in case it's not unique */ 3771 3772 /* 3773 * If 'shellpipe' empty: don't redirect to 'errorfile'. 3774 */ 3775 len = (unsigned)STRLEN(p_shq) * 2 + (unsigned)STRLEN(eap->arg) + 1; 3776 if (*p_sp != NUL) 3777 len += (unsigned)STRLEN(p_sp) + (unsigned)STRLEN(fname) + 3; 3778 cmd = alloc(len); 3779 if (cmd == NULL) 3780 return; 3781 sprintf((char *)cmd, "%s%s%s", (char *)p_shq, (char *)eap->arg, 3782 (char *)p_shq); 3783 if (*p_sp != NUL) 3784 append_redir(cmd, len, p_sp, fname); 3785 /* 3786 * Output a newline if there's something else than the :make command that 3787 * was typed (in which case the cursor is in column 0). 3788 */ 3789 if (msg_col == 0) 3790 msg_didout = FALSE; 3791 msg_start(); 3792 MSG_PUTS(":!"); 3793 msg_outtrans(cmd); /* show what we are doing */ 3794 3795 /* let the shell know if we are redirecting output or not */ 3796 do_shell(cmd, *p_sp != NUL ? SHELL_DOOUT : 0); 3797 3798 #ifdef AMIGA 3799 out_flush(); 3800 /* read window status report and redraw before message */ 3801 (void)char_avail(); 3802 #endif 3803 3804 res = qf_init(wp, fname, (eap->cmdidx != CMD_make 3805 && eap->cmdidx != CMD_lmake) ? p_gefm : p_efm, 3806 (eap->cmdidx != CMD_grepadd 3807 && eap->cmdidx != CMD_lgrepadd), 3808 *eap->cmdlinep, enc); 3809 if (wp != NULL) 3810 qi = GET_LOC_LIST(wp); 3811 if (res >= 0 && qi != NULL) 3812 qf_list_changed(qi, qi->qf_curlist); 3813 if (au_name != NULL) 3814 { 3815 apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, 3816 curbuf->b_fname, TRUE, curbuf); 3817 if (qi != NULL && qi->qf_curlist < qi->qf_listcount) 3818 res = qi->qf_lists[qi->qf_curlist].qf_count; 3819 else 3820 res = 0; 3821 } 3822 if (res > 0 && !eap->forceit) 3823 qf_jump(qi, 0, 0, FALSE); /* display first error */ 3824 3825 mch_remove(fname); 3826 vim_free(fname); 3827 vim_free(cmd); 3828 } 3829 3830 /* 3831 * Return the name for the errorfile, in allocated memory. 3832 * Find a new unique name when 'makeef' contains "##". 3833 * Returns NULL for error. 3834 */ 3835 static char_u * 3836 get_mef_name(void) 3837 { 3838 char_u *p; 3839 char_u *name; 3840 static int start = -1; 3841 static int off = 0; 3842 #ifdef HAVE_LSTAT 3843 stat_T sb; 3844 #endif 3845 3846 if (*p_mef == NUL) 3847 { 3848 name = vim_tempname('e', FALSE); 3849 if (name == NULL) 3850 EMSG(_(e_notmp)); 3851 return name; 3852 } 3853 3854 for (p = p_mef; *p; ++p) 3855 if (p[0] == '#' && p[1] == '#') 3856 break; 3857 3858 if (*p == NUL) 3859 return vim_strsave(p_mef); 3860 3861 /* Keep trying until the name doesn't exist yet. */ 3862 for (;;) 3863 { 3864 if (start == -1) 3865 start = mch_get_pid(); 3866 else 3867 off += 19; 3868 3869 name = alloc((unsigned)STRLEN(p_mef) + 30); 3870 if (name == NULL) 3871 break; 3872 STRCPY(name, p_mef); 3873 sprintf((char *)name + (p - p_mef), "%d%d", start, off); 3874 STRCAT(name, p + 2); 3875 if (mch_getperm(name) < 0 3876 #ifdef HAVE_LSTAT 3877 /* Don't accept a symbolic link, it's a security risk. */ 3878 && mch_lstat((char *)name, &sb) < 0 3879 #endif 3880 ) 3881 break; 3882 vim_free(name); 3883 } 3884 return name; 3885 } 3886 3887 /* 3888 * Returns the number of valid entries in the current quickfix/location list. 3889 */ 3890 int 3891 qf_get_size(exarg_T *eap) 3892 { 3893 qf_info_T *qi = &ql_info; 3894 qfline_T *qfp; 3895 int i, sz = 0; 3896 int prev_fnum = 0; 3897 3898 if (eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo) 3899 { 3900 /* Location list */ 3901 qi = GET_LOC_LIST(curwin); 3902 if (qi == NULL) 3903 return 0; 3904 } 3905 3906 for (i = 0, qfp = qi->qf_lists[qi->qf_curlist].qf_start; 3907 i < qi->qf_lists[qi->qf_curlist].qf_count && qfp != NULL; 3908 ++i, qfp = qfp->qf_next) 3909 { 3910 if (qfp->qf_valid) 3911 { 3912 if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo) 3913 sz++; /* Count all valid entries */ 3914 else if (qfp->qf_fnum > 0 && qfp->qf_fnum != prev_fnum) 3915 { 3916 /* Count the number of files */ 3917 sz++; 3918 prev_fnum = qfp->qf_fnum; 3919 } 3920 } 3921 } 3922 3923 return sz; 3924 } 3925 3926 /* 3927 * Returns the current index of the quickfix/location list. 3928 * Returns 0 if there is an error. 3929 */ 3930 int 3931 qf_get_cur_idx(exarg_T *eap) 3932 { 3933 qf_info_T *qi = &ql_info; 3934 3935 if (eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo) 3936 { 3937 /* Location list */ 3938 qi = GET_LOC_LIST(curwin); 3939 if (qi == NULL) 3940 return 0; 3941 } 3942 3943 return qi->qf_lists[qi->qf_curlist].qf_index; 3944 } 3945 3946 /* 3947 * Returns the current index in the quickfix/location list (counting only valid 3948 * entries). If no valid entries are in the list, then returns 1. 3949 */ 3950 int 3951 qf_get_cur_valid_idx(exarg_T *eap) 3952 { 3953 qf_info_T *qi = &ql_info; 3954 qf_list_T *qfl; 3955 qfline_T *qfp; 3956 int i, eidx = 0; 3957 int prev_fnum = 0; 3958 3959 if (eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo) 3960 { 3961 /* Location list */ 3962 qi = GET_LOC_LIST(curwin); 3963 if (qi == NULL) 3964 return 1; 3965 } 3966 3967 qfl = &qi->qf_lists[qi->qf_curlist]; 3968 qfp = qfl->qf_start; 3969 3970 /* check if the list has valid errors */ 3971 if (qfl->qf_count <= 0 || qfl->qf_nonevalid) 3972 return 1; 3973 3974 for (i = 1; i <= qfl->qf_index && qfp!= NULL; i++, qfp = qfp->qf_next) 3975 { 3976 if (qfp->qf_valid) 3977 { 3978 if (eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) 3979 { 3980 if (qfp->qf_fnum > 0 && qfp->qf_fnum != prev_fnum) 3981 { 3982 /* Count the number of files */ 3983 eidx++; 3984 prev_fnum = qfp->qf_fnum; 3985 } 3986 } 3987 else 3988 eidx++; 3989 } 3990 } 3991 3992 return eidx ? eidx : 1; 3993 } 3994 3995 /* 3996 * Get the 'n'th valid error entry in the quickfix or location list. 3997 * Used by :cdo, :ldo, :cfdo and :lfdo commands. 3998 * For :cdo and :ldo returns the 'n'th valid error entry. 3999 * For :cfdo and :lfdo returns the 'n'th valid file entry. 4000 */ 4001 static int 4002 qf_get_nth_valid_entry(qf_info_T *qi, int n, int fdo) 4003 { 4004 qf_list_T *qfl = &qi->qf_lists[qi->qf_curlist]; 4005 qfline_T *qfp = qfl->qf_start; 4006 int i, eidx; 4007 int prev_fnum = 0; 4008 4009 /* check if the list has valid errors */ 4010 if (qfl->qf_count <= 0 || qfl->qf_nonevalid) 4011 return 1; 4012 4013 for (i = 1, eidx = 0; i <= qfl->qf_count && qfp != NULL; 4014 i++, qfp = qfp->qf_next) 4015 { 4016 if (qfp->qf_valid) 4017 { 4018 if (fdo) 4019 { 4020 if (qfp->qf_fnum > 0 && qfp->qf_fnum != prev_fnum) 4021 { 4022 /* Count the number of files */ 4023 eidx++; 4024 prev_fnum = qfp->qf_fnum; 4025 } 4026 } 4027 else 4028 eidx++; 4029 } 4030 4031 if (eidx == n) 4032 break; 4033 } 4034 4035 if (i <= qfl->qf_count) 4036 return i; 4037 else 4038 return 1; 4039 } 4040 4041 /* 4042 * ":cc", ":crewind", ":cfirst" and ":clast". 4043 * ":ll", ":lrewind", ":lfirst" and ":llast". 4044 * ":cdo", ":ldo", ":cfdo" and ":lfdo" 4045 */ 4046 void 4047 ex_cc(exarg_T *eap) 4048 { 4049 qf_info_T *qi = &ql_info; 4050 int errornr; 4051 4052 if (eap->cmdidx == CMD_ll 4053 || eap->cmdidx == CMD_lrewind 4054 || eap->cmdidx == CMD_lfirst 4055 || eap->cmdidx == CMD_llast 4056 || eap->cmdidx == CMD_ldo 4057 || eap->cmdidx == CMD_lfdo) 4058 { 4059 qi = GET_LOC_LIST(curwin); 4060 if (qi == NULL) 4061 { 4062 EMSG(_(e_loclist)); 4063 return; 4064 } 4065 } 4066 4067 if (eap->addr_count > 0) 4068 errornr = (int)eap->line2; 4069 else 4070 { 4071 if (eap->cmdidx == CMD_cc || eap->cmdidx == CMD_ll) 4072 errornr = 0; 4073 else if (eap->cmdidx == CMD_crewind || eap->cmdidx == CMD_lrewind 4074 || eap->cmdidx == CMD_cfirst || eap->cmdidx == CMD_lfirst) 4075 errornr = 1; 4076 else 4077 errornr = 32767; 4078 } 4079 4080 /* For cdo and ldo commands, jump to the nth valid error. 4081 * For cfdo and lfdo commands, jump to the nth valid file entry. 4082 */ 4083 if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo 4084 || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) 4085 errornr = qf_get_nth_valid_entry(qi, 4086 eap->addr_count > 0 ? (int)eap->line1 : 1, 4087 eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo); 4088 4089 qf_jump(qi, 0, errornr, eap->forceit); 4090 } 4091 4092 /* 4093 * ":cnext", ":cnfile", ":cNext" and ":cprevious". 4094 * ":lnext", ":lNext", ":lprevious", ":lnfile", ":lNfile" and ":lpfile". 4095 * Also, used by ":cdo", ":ldo", ":cfdo" and ":lfdo" commands. 4096 */ 4097 void 4098 ex_cnext(exarg_T *eap) 4099 { 4100 qf_info_T *qi = &ql_info; 4101 int errornr; 4102 4103 if (eap->cmdidx == CMD_lnext 4104 || eap->cmdidx == CMD_lNext 4105 || eap->cmdidx == CMD_lprevious 4106 || eap->cmdidx == CMD_lnfile 4107 || eap->cmdidx == CMD_lNfile 4108 || eap->cmdidx == CMD_lpfile 4109 || eap->cmdidx == CMD_ldo 4110 || eap->cmdidx == CMD_lfdo) 4111 { 4112 qi = GET_LOC_LIST(curwin); 4113 if (qi == NULL) 4114 { 4115 EMSG(_(e_loclist)); 4116 return; 4117 } 4118 } 4119 4120 if (eap->addr_count > 0 4121 && (eap->cmdidx != CMD_cdo && eap->cmdidx != CMD_ldo 4122 && eap->cmdidx != CMD_cfdo && eap->cmdidx != CMD_lfdo)) 4123 errornr = (int)eap->line2; 4124 else 4125 errornr = 1; 4126 4127 qf_jump(qi, (eap->cmdidx == CMD_cnext || eap->cmdidx == CMD_lnext 4128 || eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo) 4129 ? FORWARD 4130 : (eap->cmdidx == CMD_cnfile || eap->cmdidx == CMD_lnfile 4131 || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) 4132 ? FORWARD_FILE 4133 : (eap->cmdidx == CMD_cpfile || eap->cmdidx == CMD_lpfile 4134 || eap->cmdidx == CMD_cNfile || eap->cmdidx == CMD_lNfile) 4135 ? BACKWARD_FILE 4136 : BACKWARD, 4137 errornr, eap->forceit); 4138 } 4139 4140 /* 4141 * ":cfile"/":cgetfile"/":caddfile" commands. 4142 * ":lfile"/":lgetfile"/":laddfile" commands. 4143 */ 4144 void 4145 ex_cfile(exarg_T *eap) 4146 { 4147 char_u *enc = NULL; 4148 win_T *wp = NULL; 4149 qf_info_T *qi = &ql_info; 4150 char_u *au_name = NULL; 4151 int save_qfid = 0; /* init for gcc */ 4152 int res; 4153 4154 switch (eap->cmdidx) 4155 { 4156 case CMD_cfile: au_name = (char_u *)"cfile"; break; 4157 case CMD_cgetfile: au_name = (char_u *)"cgetfile"; break; 4158 case CMD_caddfile: au_name = (char_u *)"caddfile"; break; 4159 case CMD_lfile: au_name = (char_u *)"lfile"; break; 4160 case CMD_lgetfile: au_name = (char_u *)"lgetfile"; break; 4161 case CMD_laddfile: au_name = (char_u *)"laddfile"; break; 4162 default: break; 4163 } 4164 if (au_name != NULL) 4165 apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, NULL, FALSE, curbuf); 4166 #ifdef FEAT_MBYTE 4167 enc = (*curbuf->b_p_menc != NUL) ? curbuf->b_p_menc : p_menc; 4168 #endif 4169 #ifdef FEAT_BROWSE 4170 if (cmdmod.browse) 4171 { 4172 char_u *browse_file = do_browse(0, (char_u *)_("Error file"), eap->arg, 4173 NULL, NULL, 4174 (char_u *)_(BROWSE_FILTER_ALL_FILES), NULL); 4175 if (browse_file == NULL) 4176 return; 4177 set_string_option_direct((char_u *)"ef", -1, browse_file, OPT_FREE, 0); 4178 vim_free(browse_file); 4179 } 4180 else 4181 #endif 4182 if (*eap->arg != NUL) 4183 set_string_option_direct((char_u *)"ef", -1, eap->arg, OPT_FREE, 0); 4184 4185 if (eap->cmdidx == CMD_lfile 4186 || eap->cmdidx == CMD_lgetfile 4187 || eap->cmdidx == CMD_laddfile) 4188 wp = curwin; 4189 4190 /* 4191 * This function is used by the :cfile, :cgetfile and :caddfile 4192 * commands. 4193 * :cfile always creates a new quickfix list and jumps to the 4194 * first error. 4195 * :cgetfile creates a new quickfix list but doesn't jump to the 4196 * first error. 4197 * :caddfile adds to an existing quickfix list. If there is no 4198 * quickfix list then a new list is created. 4199 */ 4200 res = qf_init(wp, p_ef, p_efm, (eap->cmdidx != CMD_caddfile 4201 && eap->cmdidx != CMD_laddfile), *eap->cmdlinep, enc); 4202 if (wp != NULL) 4203 qi = GET_LOC_LIST(wp); 4204 if (res >= 0 && qi != NULL) 4205 qf_list_changed(qi, qi->qf_curlist); 4206 if (qi != NULL) 4207 save_qfid = qi->qf_lists[qi->qf_curlist].qf_id; 4208 if (au_name != NULL) 4209 apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, NULL, FALSE, curbuf); 4210 4211 /* An autocmd might have freed the quickfix/location list. Check whether it 4212 * is still valid. */ 4213 if (qi != NULL && !qflist_valid(wp, save_qfid)) 4214 return; 4215 if (res > 0 && (eap->cmdidx == CMD_cfile || eap->cmdidx == CMD_lfile)) 4216 qf_jump(qi, 0, 0, eap->forceit); /* display first error */ 4217 } 4218 4219 /* 4220 * Return the quickfix/location list number with the given identifier. 4221 * Returns -1 if list is not found. 4222 */ 4223 static int 4224 qf_id2nr(qf_info_T *qi, int_u qfid) 4225 { 4226 int qf_idx; 4227 4228 for (qf_idx = 0; qf_idx < qi->qf_listcount; qf_idx++) 4229 if (qi->qf_lists[qf_idx].qf_id == qfid) 4230 return qf_idx; 4231 return INVALID_QFIDX; 4232 } 4233 4234 /* 4235 * Return the vimgrep autocmd name. 4236 */ 4237 static char_u * 4238 vgr_get_auname(cmdidx_T cmdidx) 4239 { 4240 switch (cmdidx) 4241 { 4242 case CMD_vimgrep: return (char_u *)"vimgrep"; 4243 case CMD_lvimgrep: return (char_u *)"lvimgrep"; 4244 case CMD_vimgrepadd: return (char_u *)"vimgrepadd"; 4245 case CMD_lvimgrepadd: return (char_u *)"lvimgrepadd"; 4246 case CMD_grep: return (char_u *)"grep"; 4247 case CMD_lgrep: return (char_u *)"lgrep"; 4248 case CMD_grepadd: return (char_u *)"grepadd"; 4249 case CMD_lgrepadd: return (char_u *)"lgrepadd"; 4250 default: return NULL; 4251 } 4252 } 4253 4254 /* 4255 * Initialize the regmatch used by vimgrep for pattern "s". 4256 */ 4257 static void 4258 vgr_init_regmatch(regmmatch_T *regmatch, char_u *s) 4259 { 4260 /* Get the search pattern: either white-separated or enclosed in // */ 4261 regmatch->regprog = NULL; 4262 4263 if (s == NULL || *s == NUL) 4264 { 4265 /* Pattern is empty, use last search pattern. */ 4266 if (last_search_pat() == NULL) 4267 { 4268 EMSG(_(e_noprevre)); 4269 return; 4270 } 4271 regmatch->regprog = vim_regcomp(last_search_pat(), RE_MAGIC); 4272 } 4273 else 4274 regmatch->regprog = vim_regcomp(s, RE_MAGIC); 4275 4276 regmatch->rmm_ic = p_ic; 4277 regmatch->rmm_maxcol = 0; 4278 } 4279 4280 /* 4281 * Display a file name when vimgrep is running. 4282 */ 4283 static void 4284 vgr_display_fname(char_u *fname) 4285 { 4286 char_u *p; 4287 4288 msg_start(); 4289 p = msg_strtrunc(fname, TRUE); 4290 if (p == NULL) 4291 msg_outtrans(fname); 4292 else 4293 { 4294 msg_outtrans(p); 4295 vim_free(p); 4296 } 4297 msg_clr_eos(); 4298 msg_didout = FALSE; /* overwrite this message */ 4299 msg_nowait = TRUE; /* don't wait for this message */ 4300 msg_col = 0; 4301 out_flush(); 4302 } 4303 4304 /* 4305 * Load a dummy buffer to search for a pattern using vimgrep. 4306 */ 4307 static buf_T * 4308 vgr_load_dummy_buf( 4309 char_u *fname, 4310 char_u *dirname_start, 4311 char_u *dirname_now) 4312 { 4313 int save_mls; 4314 #if defined(FEAT_SYN_HL) 4315 char_u *save_ei = NULL; 4316 #endif 4317 buf_T *buf; 4318 4319 #if defined(FEAT_SYN_HL) 4320 /* Don't do Filetype autocommands to avoid loading syntax and 4321 * indent scripts, a great speed improvement. */ 4322 save_ei = au_event_disable(",Filetype"); 4323 #endif 4324 /* Don't use modelines here, it's useless. */ 4325 save_mls = p_mls; 4326 p_mls = 0; 4327 4328 /* Load file into a buffer, so that 'fileencoding' is detected, 4329 * autocommands applied, etc. */ 4330 buf = load_dummy_buffer(fname, dirname_start, dirname_now); 4331 4332 p_mls = save_mls; 4333 #if defined(FEAT_SYN_HL) 4334 au_event_restore(save_ei); 4335 #endif 4336 4337 return buf; 4338 } 4339 4340 /* 4341 * Check whether a quickfix/location list valid. Autocmds may remove or change 4342 * a quickfix list when vimgrep is running. If the list is not found, create a 4343 * new list. 4344 */ 4345 static int 4346 vgr_qflist_valid( 4347 win_T *wp, 4348 qf_info_T *qi, 4349 int_u qfid, 4350 char_u *title) 4351 { 4352 /* Verify that the quickfix/location list was not freed by an autocmd */ 4353 if (!qflist_valid(wp, qfid)) 4354 { 4355 if (wp != NULL) 4356 { 4357 /* An autocmd has freed the location list. */ 4358 EMSG(_(e_loc_list_changed)); 4359 return FALSE; 4360 } 4361 else 4362 { 4363 /* Quickfix list is not found, create a new one. */ 4364 qf_new_list(qi, title); 4365 return TRUE; 4366 } 4367 } 4368 4369 if (qi->qf_lists[qi->qf_curlist].qf_id != qfid) 4370 /* Autocommands changed the quickfix list. Find the one we were 4371 * using and restore it. */ 4372 qi->qf_curlist = qf_id2nr(qi, qfid); 4373 4374 return TRUE; 4375 } 4376 4377 /* 4378 * Search for a pattern in all the lines in a buffer and add the matching lines 4379 * to a quickfix list. 4380 */ 4381 static int 4382 vgr_match_buflines( 4383 qf_info_T *qi, 4384 char_u *fname, 4385 buf_T *buf, 4386 regmmatch_T *regmatch, 4387 long tomatch, 4388 int duplicate_name, 4389 int flags) 4390 { 4391 int found_match = FALSE; 4392 long lnum; 4393 colnr_T col; 4394 4395 for (lnum = 1; lnum <= buf->b_ml.ml_line_count && tomatch > 0; ++lnum) 4396 { 4397 col = 0; 4398 while (vim_regexec_multi(regmatch, curwin, buf, lnum, 4399 col, NULL, NULL) > 0) 4400 { 4401 /* Pass the buffer number so that it gets used even for a 4402 * dummy buffer, unless duplicate_name is set, then the 4403 * buffer will be wiped out below. */ 4404 if (qf_add_entry(qi, 4405 qi->qf_curlist, 4406 NULL, /* dir */ 4407 fname, 4408 NULL, 4409 duplicate_name ? 0 : buf->b_fnum, 4410 ml_get_buf(buf, 4411 regmatch->startpos[0].lnum + lnum, FALSE), 4412 regmatch->startpos[0].lnum + lnum, 4413 regmatch->startpos[0].col + 1, 4414 FALSE, /* vis_col */ 4415 NULL, /* search pattern */ 4416 0, /* nr */ 4417 0, /* type */ 4418 TRUE /* valid */ 4419 ) == FAIL) 4420 { 4421 got_int = TRUE; 4422 break; 4423 } 4424 found_match = TRUE; 4425 if (--tomatch == 0) 4426 break; 4427 if ((flags & VGR_GLOBAL) == 0 4428 || regmatch->endpos[0].lnum > 0) 4429 break; 4430 col = regmatch->endpos[0].col 4431 + (col == regmatch->endpos[0].col); 4432 if (col > (colnr_T)STRLEN(ml_get_buf(buf, lnum, FALSE))) 4433 break; 4434 } 4435 line_breakcheck(); 4436 if (got_int) 4437 break; 4438 } 4439 4440 return found_match; 4441 } 4442 4443 /* 4444 * Jump to the first match and update the directory. 4445 */ 4446 static void 4447 vgr_jump_to_match( 4448 qf_info_T *qi, 4449 int forceit, 4450 int *redraw_for_dummy, 4451 buf_T *first_match_buf, 4452 char_u *target_dir) 4453 { 4454 buf_T *buf; 4455 4456 buf = curbuf; 4457 qf_jump(qi, 0, 0, forceit); 4458 if (buf != curbuf) 4459 /* If we jumped to another buffer redrawing will already be 4460 * taken care of. */ 4461 *redraw_for_dummy = FALSE; 4462 4463 /* Jump to the directory used after loading the buffer. */ 4464 if (curbuf == first_match_buf && target_dir != NULL) 4465 { 4466 exarg_T ea; 4467 4468 ea.arg = target_dir; 4469 ea.cmdidx = CMD_lcd; 4470 ex_cd(&ea); 4471 } 4472 } 4473 4474 /* 4475 * ":vimgrep {pattern} file(s)" 4476 * ":vimgrepadd {pattern} file(s)" 4477 * ":lvimgrep {pattern} file(s)" 4478 * ":lvimgrepadd {pattern} file(s)" 4479 */ 4480 void 4481 ex_vimgrep(exarg_T *eap) 4482 { 4483 regmmatch_T regmatch; 4484 int fcount; 4485 char_u **fnames; 4486 char_u *fname; 4487 char_u *title; 4488 char_u *s; 4489 char_u *p; 4490 int fi; 4491 qf_info_T *qi = &ql_info; 4492 int_u save_qfid; 4493 win_T *wp = NULL; 4494 buf_T *buf; 4495 int duplicate_name = FALSE; 4496 int using_dummy; 4497 int redraw_for_dummy = FALSE; 4498 int found_match; 4499 buf_T *first_match_buf = NULL; 4500 time_t seconds = 0; 4501 aco_save_T aco; 4502 int flags = 0; 4503 long tomatch; 4504 char_u *dirname_start = NULL; 4505 char_u *dirname_now = NULL; 4506 char_u *target_dir = NULL; 4507 char_u *au_name = NULL; 4508 4509 au_name = vgr_get_auname(eap->cmdidx); 4510 if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, 4511 curbuf->b_fname, TRUE, curbuf)) 4512 { 4513 #ifdef FEAT_EVAL 4514 if (aborting()) 4515 return; 4516 #endif 4517 } 4518 4519 if (eap->cmdidx == CMD_lgrep 4520 || eap->cmdidx == CMD_lvimgrep 4521 || eap->cmdidx == CMD_lgrepadd 4522 || eap->cmdidx == CMD_lvimgrepadd) 4523 { 4524 qi = ll_get_or_alloc_list(curwin); 4525 if (qi == NULL) 4526 return; 4527 wp = curwin; 4528 } 4529 4530 if (eap->addr_count > 0) 4531 tomatch = eap->line2; 4532 else 4533 tomatch = MAXLNUM; 4534 4535 /* Get the search pattern: either white-separated or enclosed in // */ 4536 regmatch.regprog = NULL; 4537 title = vim_strsave(*eap->cmdlinep); 4538 p = skip_vimgrep_pat(eap->arg, &s, &flags); 4539 if (p == NULL) 4540 { 4541 EMSG(_(e_invalpat)); 4542 goto theend; 4543 } 4544 4545 vgr_init_regmatch(®match, s); 4546 if (regmatch.regprog == NULL) 4547 goto theend; 4548 4549 p = skipwhite(p); 4550 if (*p == NUL) 4551 { 4552 EMSG(_("E683: File name missing or invalid pattern")); 4553 goto theend; 4554 } 4555 4556 if ((eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_lgrepadd 4557 && eap->cmdidx != CMD_vimgrepadd 4558 && eap->cmdidx != CMD_lvimgrepadd) 4559 || qi->qf_curlist == qi->qf_listcount) 4560 /* make place for a new list */ 4561 qf_new_list(qi, title != NULL ? title : *eap->cmdlinep); 4562 4563 /* parse the list of arguments */ 4564 if (get_arglist_exp(p, &fcount, &fnames, TRUE) == FAIL) 4565 goto theend; 4566 if (fcount == 0) 4567 { 4568 EMSG(_(e_nomatch)); 4569 goto theend; 4570 } 4571 4572 dirname_start = alloc_id(MAXPATHL, aid_qf_dirname_start); 4573 dirname_now = alloc_id(MAXPATHL, aid_qf_dirname_now); 4574 if (dirname_start == NULL || dirname_now == NULL) 4575 { 4576 FreeWild(fcount, fnames); 4577 goto theend; 4578 } 4579 4580 /* Remember the current directory, because a BufRead autocommand that does 4581 * ":lcd %:p:h" changes the meaning of short path names. */ 4582 mch_dirname(dirname_start, MAXPATHL); 4583 4584 /* Remember the current quickfix list identifier, so that we can check for 4585 * autocommands changing the current quickfix list. */ 4586 save_qfid = qi->qf_lists[qi->qf_curlist].qf_id; 4587 4588 seconds = (time_t)0; 4589 for (fi = 0; fi < fcount && !got_int && tomatch > 0; ++fi) 4590 { 4591 fname = shorten_fname1(fnames[fi]); 4592 if (time(NULL) > seconds) 4593 { 4594 /* Display the file name every second or so, show the user we are 4595 * working on it. */ 4596 seconds = time(NULL); 4597 vgr_display_fname(fname); 4598 } 4599 4600 buf = buflist_findname_exp(fnames[fi]); 4601 if (buf == NULL || buf->b_ml.ml_mfp == NULL) 4602 { 4603 /* Remember that a buffer with this name already exists. */ 4604 duplicate_name = (buf != NULL); 4605 using_dummy = TRUE; 4606 redraw_for_dummy = TRUE; 4607 4608 buf = vgr_load_dummy_buf(fname, dirname_start, dirname_now); 4609 } 4610 else 4611 /* Use existing, loaded buffer. */ 4612 using_dummy = FALSE; 4613 4614 /* Check whether the quickfix list is still valid. When loading a 4615 * buffer above, autocommands might have changed the quickfix list. */ 4616 if (!vgr_qflist_valid(wp, qi, save_qfid, *eap->cmdlinep)) 4617 { 4618 FreeWild(fcount, fnames); 4619 goto theend; 4620 } 4621 save_qfid = qi->qf_lists[qi->qf_curlist].qf_id; 4622 4623 if (buf == NULL) 4624 { 4625 if (!got_int) 4626 smsg((char_u *)_("Cannot open file \"%s\""), fname); 4627 } 4628 else 4629 { 4630 /* Try for a match in all lines of the buffer. 4631 * For ":1vimgrep" look for first match only. */ 4632 found_match = vgr_match_buflines(qi, fname, buf, ®match, 4633 tomatch, duplicate_name, flags); 4634 4635 if (using_dummy) 4636 { 4637 if (found_match && first_match_buf == NULL) 4638 first_match_buf = buf; 4639 if (duplicate_name) 4640 { 4641 /* Never keep a dummy buffer if there is another buffer 4642 * with the same name. */ 4643 wipe_dummy_buffer(buf, dirname_start); 4644 buf = NULL; 4645 } 4646 else if (!cmdmod.hide 4647 || buf->b_p_bh[0] == 'u' /* "unload" */ 4648 || buf->b_p_bh[0] == 'w' /* "wipe" */ 4649 || buf->b_p_bh[0] == 'd') /* "delete" */ 4650 { 4651 /* When no match was found we don't need to remember the 4652 * buffer, wipe it out. If there was a match and it 4653 * wasn't the first one or we won't jump there: only 4654 * unload the buffer. 4655 * Ignore 'hidden' here, because it may lead to having too 4656 * many swap files. */ 4657 if (!found_match) 4658 { 4659 wipe_dummy_buffer(buf, dirname_start); 4660 buf = NULL; 4661 } 4662 else if (buf != first_match_buf || (flags & VGR_NOJUMP)) 4663 { 4664 unload_dummy_buffer(buf, dirname_start); 4665 /* Keeping the buffer, remove the dummy flag. */ 4666 buf->b_flags &= ~BF_DUMMY; 4667 buf = NULL; 4668 } 4669 } 4670 4671 if (buf != NULL) 4672 { 4673 /* Keeping the buffer, remove the dummy flag. */ 4674 buf->b_flags &= ~BF_DUMMY; 4675 4676 /* If the buffer is still loaded we need to use the 4677 * directory we jumped to below. */ 4678 if (buf == first_match_buf 4679 && target_dir == NULL 4680 && STRCMP(dirname_start, dirname_now) != 0) 4681 target_dir = vim_strsave(dirname_now); 4682 4683 /* The buffer is still loaded, the Filetype autocommands 4684 * need to be done now, in that buffer. And the modelines 4685 * need to be done (again). But not the window-local 4686 * options! */ 4687 aucmd_prepbuf(&aco, buf); 4688 #if defined(FEAT_SYN_HL) 4689 apply_autocmds(EVENT_FILETYPE, buf->b_p_ft, 4690 buf->b_fname, TRUE, buf); 4691 #endif 4692 do_modelines(OPT_NOWIN); 4693 aucmd_restbuf(&aco); 4694 } 4695 } 4696 } 4697 } 4698 4699 FreeWild(fcount, fnames); 4700 4701 qi->qf_lists[qi->qf_curlist].qf_nonevalid = FALSE; 4702 qi->qf_lists[qi->qf_curlist].qf_ptr = qi->qf_lists[qi->qf_curlist].qf_start; 4703 qi->qf_lists[qi->qf_curlist].qf_index = 1; 4704 qf_list_changed(qi, qi->qf_curlist); 4705 4706 qf_update_buffer(qi, NULL); 4707 4708 if (au_name != NULL) 4709 apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, 4710 curbuf->b_fname, TRUE, curbuf); 4711 /* 4712 * The QuickFixCmdPost autocmd may free the quickfix list. Check the list 4713 * is still valid. 4714 */ 4715 if (!qflist_valid(wp, save_qfid)) 4716 goto theend; 4717 4718 /* Jump to first match. */ 4719 if (qi->qf_lists[qi->qf_curlist].qf_count > 0) 4720 { 4721 if ((flags & VGR_NOJUMP) == 0) 4722 vgr_jump_to_match(qi, eap->forceit, &redraw_for_dummy, 4723 first_match_buf, target_dir); 4724 } 4725 else 4726 EMSG2(_(e_nomatch2), s); 4727 4728 /* If we loaded a dummy buffer into the current window, the autocommands 4729 * may have messed up things, need to redraw and recompute folds. */ 4730 if (redraw_for_dummy) 4731 { 4732 #ifdef FEAT_FOLDING 4733 foldUpdateAll(curwin); 4734 #else 4735 redraw_later(NOT_VALID); 4736 #endif 4737 } 4738 4739 theend: 4740 vim_free(title); 4741 vim_free(dirname_now); 4742 vim_free(dirname_start); 4743 vim_free(target_dir); 4744 vim_regfree(regmatch.regprog); 4745 } 4746 4747 /* 4748 * Restore current working directory to "dirname_start" if they differ, taking 4749 * into account whether it is set locally or globally. 4750 */ 4751 static void 4752 restore_start_dir(char_u *dirname_start) 4753 { 4754 char_u *dirname_now = alloc(MAXPATHL); 4755 4756 if (NULL != dirname_now) 4757 { 4758 mch_dirname(dirname_now, MAXPATHL); 4759 if (STRCMP(dirname_start, dirname_now) != 0) 4760 { 4761 /* If the directory has changed, change it back by building up an 4762 * appropriate ex command and executing it. */ 4763 exarg_T ea; 4764 4765 ea.arg = dirname_start; 4766 ea.cmdidx = (curwin->w_localdir == NULL) ? CMD_cd : CMD_lcd; 4767 ex_cd(&ea); 4768 } 4769 vim_free(dirname_now); 4770 } 4771 } 4772 4773 /* 4774 * Load file "fname" into a dummy buffer and return the buffer pointer, 4775 * placing the directory resulting from the buffer load into the 4776 * "resulting_dir" pointer. "resulting_dir" must be allocated by the caller 4777 * prior to calling this function. Restores directory to "dirname_start" prior 4778 * to returning, if autocmds or the 'autochdir' option have changed it. 4779 * 4780 * If creating the dummy buffer does not fail, must call unload_dummy_buffer() 4781 * or wipe_dummy_buffer() later! 4782 * 4783 * Returns NULL if it fails. 4784 */ 4785 static buf_T * 4786 load_dummy_buffer( 4787 char_u *fname, 4788 char_u *dirname_start, /* in: old directory */ 4789 char_u *resulting_dir) /* out: new directory */ 4790 { 4791 buf_T *newbuf; 4792 bufref_T newbufref; 4793 bufref_T newbuf_to_wipe; 4794 int failed = TRUE; 4795 aco_save_T aco; 4796 int readfile_result; 4797 4798 /* Allocate a buffer without putting it in the buffer list. */ 4799 newbuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY); 4800 if (newbuf == NULL) 4801 return NULL; 4802 set_bufref(&newbufref, newbuf); 4803 4804 /* Init the options. */ 4805 buf_copy_options(newbuf, BCO_ENTER | BCO_NOHELP); 4806 4807 /* need to open the memfile before putting the buffer in a window */ 4808 if (ml_open(newbuf) == OK) 4809 { 4810 /* Make sure this buffer isn't wiped out by auto commands. */ 4811 ++newbuf->b_locked; 4812 4813 /* set curwin/curbuf to buf and save a few things */ 4814 aucmd_prepbuf(&aco, newbuf); 4815 4816 /* Need to set the filename for autocommands. */ 4817 (void)setfname(curbuf, fname, NULL, FALSE); 4818 4819 /* Create swap file now to avoid the ATTENTION message. */ 4820 check_need_swap(TRUE); 4821 4822 /* Remove the "dummy" flag, otherwise autocommands may not 4823 * work. */ 4824 curbuf->b_flags &= ~BF_DUMMY; 4825 4826 newbuf_to_wipe.br_buf = NULL; 4827 readfile_result = readfile(fname, NULL, 4828 (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM, 4829 NULL, READ_NEW | READ_DUMMY); 4830 --newbuf->b_locked; 4831 if (readfile_result == OK 4832 && !got_int 4833 && !(curbuf->b_flags & BF_NEW)) 4834 { 4835 failed = FALSE; 4836 if (curbuf != newbuf) 4837 { 4838 /* Bloody autocommands changed the buffer! Can happen when 4839 * using netrw and editing a remote file. Use the current 4840 * buffer instead, delete the dummy one after restoring the 4841 * window stuff. */ 4842 set_bufref(&newbuf_to_wipe, newbuf); 4843 newbuf = curbuf; 4844 } 4845 } 4846 4847 /* restore curwin/curbuf and a few other things */ 4848 aucmd_restbuf(&aco); 4849 if (newbuf_to_wipe.br_buf != NULL && bufref_valid(&newbuf_to_wipe)) 4850 wipe_buffer(newbuf_to_wipe.br_buf, FALSE); 4851 4852 /* Add back the "dummy" flag, otherwise buflist_findname_stat() won't 4853 * skip it. */ 4854 newbuf->b_flags |= BF_DUMMY; 4855 } 4856 4857 /* 4858 * When autocommands/'autochdir' option changed directory: go back. 4859 * Let the caller know what the resulting dir was first, in case it is 4860 * important. 4861 */ 4862 mch_dirname(resulting_dir, MAXPATHL); 4863 restore_start_dir(dirname_start); 4864 4865 if (!bufref_valid(&newbufref)) 4866 return NULL; 4867 if (failed) 4868 { 4869 wipe_dummy_buffer(newbuf, dirname_start); 4870 return NULL; 4871 } 4872 return newbuf; 4873 } 4874 4875 /* 4876 * Wipe out the dummy buffer that load_dummy_buffer() created. Restores 4877 * directory to "dirname_start" prior to returning, if autocmds or the 4878 * 'autochdir' option have changed it. 4879 */ 4880 static void 4881 wipe_dummy_buffer(buf_T *buf, char_u *dirname_start) 4882 { 4883 if (curbuf != buf) /* safety check */ 4884 { 4885 #if defined(FEAT_EVAL) 4886 cleanup_T cs; 4887 4888 /* Reset the error/interrupt/exception state here so that aborting() 4889 * returns FALSE when wiping out the buffer. Otherwise it doesn't 4890 * work when got_int is set. */ 4891 enter_cleanup(&cs); 4892 #endif 4893 4894 wipe_buffer(buf, FALSE); 4895 4896 #if defined(FEAT_EVAL) 4897 /* Restore the error/interrupt/exception state if not discarded by a 4898 * new aborting error, interrupt, or uncaught exception. */ 4899 leave_cleanup(&cs); 4900 #endif 4901 /* When autocommands/'autochdir' option changed directory: go back. */ 4902 restore_start_dir(dirname_start); 4903 } 4904 } 4905 4906 /* 4907 * Unload the dummy buffer that load_dummy_buffer() created. Restores 4908 * directory to "dirname_start" prior to returning, if autocmds or the 4909 * 'autochdir' option have changed it. 4910 */ 4911 static void 4912 unload_dummy_buffer(buf_T *buf, char_u *dirname_start) 4913 { 4914 if (curbuf != buf) /* safety check */ 4915 { 4916 close_buffer(NULL, buf, DOBUF_UNLOAD, FALSE); 4917 4918 /* When autocommands/'autochdir' option changed directory: go back. */ 4919 restore_start_dir(dirname_start); 4920 } 4921 } 4922 4923 #if defined(FEAT_EVAL) || defined(PROTO) 4924 /* 4925 * Add each quickfix error to list "list" as a dictionary. 4926 * If qf_idx is -1, use the current list. Otherwise, use the specified list. 4927 */ 4928 int 4929 get_errorlist(qf_info_T *qi_arg, win_T *wp, int qf_idx, list_T *list) 4930 { 4931 qf_info_T *qi = qi_arg; 4932 dict_T *dict; 4933 char_u buf[2]; 4934 qfline_T *qfp; 4935 int i; 4936 int bufnum; 4937 4938 if (qi == NULL) 4939 { 4940 qi = &ql_info; 4941 if (wp != NULL) 4942 { 4943 qi = GET_LOC_LIST(wp); 4944 if (qi == NULL) 4945 return FAIL; 4946 } 4947 } 4948 4949 if (qf_idx == INVALID_QFIDX) 4950 qf_idx = qi->qf_curlist; 4951 4952 if (qf_idx >= qi->qf_listcount 4953 || qi->qf_lists[qf_idx].qf_count == 0) 4954 return FAIL; 4955 4956 qfp = qi->qf_lists[qf_idx].qf_start; 4957 for (i = 1; !got_int && i <= qi->qf_lists[qf_idx].qf_count; ++i) 4958 { 4959 /* Handle entries with a non-existing buffer number. */ 4960 bufnum = qfp->qf_fnum; 4961 if (bufnum != 0 && (buflist_findnr(bufnum) == NULL)) 4962 bufnum = 0; 4963 4964 if ((dict = dict_alloc()) == NULL) 4965 return FAIL; 4966 if (list_append_dict(list, dict) == FAIL) 4967 return FAIL; 4968 4969 buf[0] = qfp->qf_type; 4970 buf[1] = NUL; 4971 if ( dict_add_nr_str(dict, "bufnr", (long)bufnum, NULL) == FAIL 4972 || dict_add_nr_str(dict, "lnum", (long)qfp->qf_lnum, NULL) == FAIL 4973 || dict_add_nr_str(dict, "col", (long)qfp->qf_col, NULL) == FAIL 4974 || dict_add_nr_str(dict, "vcol", (long)qfp->qf_viscol, NULL) == FAIL 4975 || dict_add_nr_str(dict, "nr", (long)qfp->qf_nr, NULL) == FAIL 4976 || dict_add_nr_str(dict, "module", 0L, 4977 qfp->qf_module == NULL ? (char_u *)"" : qfp->qf_module) == FAIL 4978 || dict_add_nr_str(dict, "pattern", 0L, 4979 qfp->qf_pattern == NULL ? (char_u *)"" : qfp->qf_pattern) == FAIL 4980 || dict_add_nr_str(dict, "text", 0L, 4981 qfp->qf_text == NULL ? (char_u *)"" : qfp->qf_text) == FAIL 4982 || dict_add_nr_str(dict, "type", 0L, buf) == FAIL 4983 || dict_add_nr_str(dict, "valid", (long)qfp->qf_valid, NULL) == FAIL) 4984 return FAIL; 4985 4986 qfp = qfp->qf_next; 4987 if (qfp == NULL) 4988 break; 4989 } 4990 return OK; 4991 } 4992 4993 /* 4994 * Flags used by getqflist()/getloclist() to determine which fields to return. 4995 */ 4996 enum { 4997 QF_GETLIST_NONE = 0x0, 4998 QF_GETLIST_TITLE = 0x1, 4999 QF_GETLIST_ITEMS = 0x2, 5000 QF_GETLIST_NR = 0x4, 5001 QF_GETLIST_WINID = 0x8, 5002 QF_GETLIST_CONTEXT = 0x10, 5003 QF_GETLIST_ID = 0x20, 5004 QF_GETLIST_IDX = 0x40, 5005 QF_GETLIST_SIZE = 0x80, 5006 QF_GETLIST_TICK = 0x100, 5007 QF_GETLIST_ALL = 0x1FF 5008 }; 5009 5010 /* 5011 * Parse text from 'di' and return the quickfix list items. 5012 * Existing quickfix lists are not modified. 5013 */ 5014 static int 5015 qf_get_list_from_lines(dict_T *what, dictitem_T *di, dict_T *retdict) 5016 { 5017 int status = FAIL; 5018 qf_info_T *qi; 5019 char_u *errorformat = p_efm; 5020 dictitem_T *efm_di; 5021 list_T *l; 5022 5023 /* Only a List value is supported */ 5024 if (di->di_tv.v_type == VAR_LIST && di->di_tv.vval.v_list != NULL) 5025 { 5026 /* If errorformat is supplied then use it, otherwise use the 'efm' 5027 * option setting 5028 */ 5029 if ((efm_di = dict_find(what, (char_u *)"efm", -1)) != NULL) 5030 { 5031 if (efm_di->di_tv.v_type != VAR_STRING || 5032 efm_di->di_tv.vval.v_string == NULL) 5033 return FAIL; 5034 errorformat = efm_di->di_tv.vval.v_string; 5035 } 5036 5037 l = list_alloc(); 5038 if (l == NULL) 5039 return FAIL; 5040 5041 qi = (qf_info_T *)alloc((unsigned)sizeof(qf_info_T)); 5042 if (qi != NULL) 5043 { 5044 vim_memset(qi, 0, (size_t)(sizeof(qf_info_T))); 5045 qi->qf_refcount++; 5046 5047 if (qf_init_ext(qi, 0, NULL, NULL, &di->di_tv, errorformat, 5048 TRUE, (linenr_T)0, (linenr_T)0, NULL, NULL) > 0) 5049 { 5050 (void)get_errorlist(qi, NULL, 0, l); 5051 qf_free(qi, 0); 5052 } 5053 free(qi); 5054 } 5055 dict_add_list(retdict, "items", l); 5056 status = OK; 5057 } 5058 5059 return status; 5060 } 5061 5062 /* 5063 * Return the quickfix/location list window identifier in the current tabpage. 5064 */ 5065 static int 5066 qf_winid(qf_info_T *qi) 5067 { 5068 win_T *win; 5069 5070 /* The quickfix window can be opened even if the quickfix list is not set 5071 * using ":copen". This is not true for location lists. */ 5072 if (qi == NULL) 5073 return 0; 5074 win = qf_find_win(qi); 5075 if (win != NULL) 5076 return win->w_id; 5077 return 0; 5078 } 5079 5080 /* 5081 * Convert the keys in 'what' to quickfix list property flags. 5082 */ 5083 static int 5084 qf_getprop_keys2flags(dict_T *what) 5085 { 5086 int flags = QF_GETLIST_NONE; 5087 5088 if (dict_find(what, (char_u *)"all", -1) != NULL) 5089 flags |= QF_GETLIST_ALL; 5090 5091 if (dict_find(what, (char_u *)"title", -1) != NULL) 5092 flags |= QF_GETLIST_TITLE; 5093 5094 if (dict_find(what, (char_u *)"nr", -1) != NULL) 5095 flags |= QF_GETLIST_NR; 5096 5097 if (dict_find(what, (char_u *)"winid", -1) != NULL) 5098 flags |= QF_GETLIST_WINID; 5099 5100 if (dict_find(what, (char_u *)"context", -1) != NULL) 5101 flags |= QF_GETLIST_CONTEXT; 5102 5103 if (dict_find(what, (char_u *)"id", -1) != NULL) 5104 flags |= QF_GETLIST_ID; 5105 5106 if (dict_find(what, (char_u *)"items", -1) != NULL) 5107 flags |= QF_GETLIST_ITEMS; 5108 5109 if (dict_find(what, (char_u *)"idx", -1) != NULL) 5110 flags |= QF_GETLIST_IDX; 5111 5112 if (dict_find(what, (char_u *)"size", -1) != NULL) 5113 flags |= QF_GETLIST_SIZE; 5114 5115 if (dict_find(what, (char_u *)"changedtick", -1) != NULL) 5116 flags |= QF_GETLIST_TICK; 5117 5118 return flags; 5119 } 5120 5121 /* 5122 * Return the quickfix list index based on 'nr' or 'id' in 'what'. 5123 * If 'nr' and 'id' are not present in 'what' then return the current 5124 * quickfix list index. 5125 * If 'nr' is zero then return the current quickfix list index. 5126 * If 'nr' is '$' then return the last quickfix list index. 5127 * If 'id' is present then return the index of the quickfix list with that id. 5128 * If 'id' is zero then return the quickfix list index specified by 'nr'. 5129 * Return -1, if quickfix list is not present or if the stack is empty. 5130 */ 5131 static int 5132 qf_getprop_qfidx(qf_info_T *qi, dict_T *what) 5133 { 5134 int qf_idx; 5135 dictitem_T *di; 5136 5137 qf_idx = qi->qf_curlist; /* default is the current list */ 5138 if ((di = dict_find(what, (char_u *)"nr", -1)) != NULL) 5139 { 5140 /* Use the specified quickfix/location list */ 5141 if (di->di_tv.v_type == VAR_NUMBER) 5142 { 5143 /* for zero use the current list */ 5144 if (di->di_tv.vval.v_number != 0) 5145 { 5146 qf_idx = di->di_tv.vval.v_number - 1; 5147 if (qf_idx < 0 || qf_idx >= qi->qf_listcount) 5148 qf_idx = INVALID_QFIDX; 5149 } 5150 } 5151 else if (di->di_tv.v_type == VAR_STRING 5152 && di->di_tv.vval.v_string != NULL 5153 && STRCMP(di->di_tv.vval.v_string, "$") == 0) 5154 /* Get the last quickfix list number */ 5155 qf_idx = qi->qf_listcount - 1; 5156 else 5157 qf_idx = INVALID_QFIDX; 5158 } 5159 5160 if ((di = dict_find(what, (char_u *)"id", -1)) != NULL) 5161 { 5162 /* Look for a list with the specified id */ 5163 if (di->di_tv.v_type == VAR_NUMBER) 5164 { 5165 /* 5166 * For zero, use the current list or the list specified by 'nr' 5167 */ 5168 if (di->di_tv.vval.v_number != 0) 5169 qf_idx = qf_id2nr(qi, di->di_tv.vval.v_number); 5170 } 5171 else 5172 qf_idx = INVALID_QFIDX; 5173 } 5174 5175 return qf_idx; 5176 } 5177 5178 /* 5179 * Return default values for quickfix list properties in retdict. 5180 */ 5181 static int 5182 qf_getprop_defaults(qf_info_T *qi, int flags, dict_T *retdict) 5183 { 5184 int status = OK; 5185 5186 if (flags & QF_GETLIST_TITLE) 5187 status = dict_add_nr_str(retdict, "title", 0L, (char_u *)""); 5188 if ((status == OK) && (flags & QF_GETLIST_ITEMS)) 5189 { 5190 list_T *l = list_alloc(); 5191 if (l != NULL) 5192 status = dict_add_list(retdict, "items", l); 5193 else 5194 status = FAIL; 5195 } 5196 if ((status == OK) && (flags & QF_GETLIST_NR)) 5197 status = dict_add_nr_str(retdict, "nr", 0L, NULL); 5198 if ((status == OK) && (flags & QF_GETLIST_WINID)) 5199 status = dict_add_nr_str(retdict, "winid", qf_winid(qi), NULL); 5200 if ((status == OK) && (flags & QF_GETLIST_CONTEXT)) 5201 status = dict_add_nr_str(retdict, "context", 0L, (char_u *)""); 5202 if ((status == OK) && (flags & QF_GETLIST_ID)) 5203 status = dict_add_nr_str(retdict, "id", 0L, NULL); 5204 if ((status == OK) && (flags & QF_GETLIST_IDX)) 5205 status = dict_add_nr_str(retdict, "idx", 0L, NULL); 5206 if ((status == OK) && (flags & QF_GETLIST_SIZE)) 5207 status = dict_add_nr_str(retdict, "size", 0L, NULL); 5208 if ((status == OK) && (flags & QF_GETLIST_TICK)) 5209 status = dict_add_nr_str(retdict, "changedtick", 0L, NULL); 5210 5211 return status; 5212 } 5213 5214 /* 5215 * Return the quickfix list title as 'title' in retdict 5216 */ 5217 static int 5218 qf_getprop_title(qf_info_T *qi, int qf_idx, dict_T *retdict) 5219 { 5220 char_u *t; 5221 5222 t = qi->qf_lists[qf_idx].qf_title; 5223 if (t == NULL) 5224 t = (char_u *)""; 5225 return dict_add_nr_str(retdict, "title", 0L, t); 5226 } 5227 5228 /* 5229 * Return the quickfix list items/entries as 'items' in retdict 5230 */ 5231 static int 5232 qf_getprop_items(qf_info_T *qi, int qf_idx, dict_T *retdict) 5233 { 5234 int status = OK; 5235 list_T *l = list_alloc(); 5236 if (l != NULL) 5237 { 5238 (void)get_errorlist(qi, NULL, qf_idx, l); 5239 dict_add_list(retdict, "items", l); 5240 } 5241 else 5242 status = FAIL; 5243 5244 return status; 5245 } 5246 5247 /* 5248 * Return the quickfix list context (if any) as 'context' in retdict. 5249 */ 5250 static int 5251 qf_getprop_ctx(qf_info_T *qi, int qf_idx, dict_T *retdict) 5252 { 5253 int status; 5254 dictitem_T *di; 5255 5256 if (qi->qf_lists[qf_idx].qf_ctx != NULL) 5257 { 5258 di = dictitem_alloc((char_u *)"context"); 5259 if (di != NULL) 5260 { 5261 copy_tv(qi->qf_lists[qf_idx].qf_ctx, &di->di_tv); 5262 status = dict_add(retdict, di); 5263 if (status == FAIL) 5264 dictitem_free(di); 5265 } 5266 else 5267 status = FAIL; 5268 } 5269 else 5270 status = dict_add_nr_str(retdict, "context", 0L, (char_u *)""); 5271 5272 return status; 5273 } 5274 5275 /* 5276 * Return the quickfix list index as 'idx' in retdict 5277 */ 5278 static int 5279 qf_getprop_idx(qf_info_T *qi, int qf_idx, dict_T *retdict) 5280 { 5281 int idx = qi->qf_lists[qf_idx].qf_index; 5282 if (qi->qf_lists[qf_idx].qf_count == 0) 5283 /* For empty lists, qf_index is set to 1 */ 5284 idx = 0; 5285 return dict_add_nr_str(retdict, "idx", idx, NULL); 5286 } 5287 5288 /* 5289 * Return quickfix/location list details (title) as a 5290 * dictionary. 'what' contains the details to return. If 'list_idx' is -1, 5291 * then current list is used. Otherwise the specified list is used. 5292 */ 5293 int 5294 qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict) 5295 { 5296 qf_info_T *qi = &ql_info; 5297 int status = OK; 5298 int qf_idx; 5299 dictitem_T *di; 5300 int flags = QF_GETLIST_NONE; 5301 5302 if ((di = dict_find(what, (char_u *)"lines", -1)) != NULL) 5303 return qf_get_list_from_lines(what, di, retdict); 5304 5305 if (wp != NULL) 5306 qi = GET_LOC_LIST(wp); 5307 5308 flags = qf_getprop_keys2flags(what); 5309 5310 if (qi != NULL && qi->qf_listcount != 0) 5311 qf_idx = qf_getprop_qfidx(qi, what); 5312 5313 /* List is not present or is empty */ 5314 if (qi == NULL || qi->qf_listcount == 0 || qf_idx == INVALID_QFIDX) 5315 return qf_getprop_defaults(qi, flags, retdict); 5316 5317 if (flags & QF_GETLIST_TITLE) 5318 status = qf_getprop_title(qi, qf_idx, retdict); 5319 if ((status == OK) && (flags & QF_GETLIST_NR)) 5320 status = dict_add_nr_str(retdict, "nr", qf_idx + 1, NULL); 5321 if ((status == OK) && (flags & QF_GETLIST_WINID)) 5322 status = dict_add_nr_str(retdict, "winid", qf_winid(qi), NULL); 5323 if ((status == OK) && (flags & QF_GETLIST_ITEMS)) 5324 status = qf_getprop_items(qi, qf_idx, retdict); 5325 if ((status == OK) && (flags & QF_GETLIST_CONTEXT)) 5326 status = qf_getprop_ctx(qi, qf_idx, retdict); 5327 if ((status == OK) && (flags & QF_GETLIST_ID)) 5328 status = dict_add_nr_str(retdict, "id", qi->qf_lists[qf_idx].qf_id, 5329 NULL); 5330 if ((status == OK) && (flags & QF_GETLIST_IDX)) 5331 status = qf_getprop_idx(qi, qf_idx, retdict); 5332 if ((status == OK) && (flags & QF_GETLIST_SIZE)) 5333 status = dict_add_nr_str(retdict, "size", 5334 qi->qf_lists[qf_idx].qf_count, NULL); 5335 if ((status == OK) && (flags & QF_GETLIST_TICK)) 5336 status = dict_add_nr_str(retdict, "changedtick", 5337 qi->qf_lists[qf_idx].qf_changedtick, NULL); 5338 5339 return status; 5340 } 5341 5342 /* 5343 * Add list of entries to quickfix/location list. Each list entry is 5344 * a dictionary with item information. 5345 */ 5346 static int 5347 qf_add_entries( 5348 qf_info_T *qi, 5349 int qf_idx, 5350 list_T *list, 5351 char_u *title, 5352 int action) 5353 { 5354 listitem_T *li; 5355 dict_T *d; 5356 char_u *filename, *module, *pattern, *text, *type; 5357 int bufnum; 5358 long lnum; 5359 int col, nr; 5360 int vcol; 5361 qfline_T *old_last = NULL; 5362 int valid, status; 5363 int retval = OK; 5364 int did_bufnr_emsg = FALSE; 5365 5366 if (action == ' ' || qf_idx == qi->qf_listcount) 5367 { 5368 /* make place for a new list */ 5369 qf_new_list(qi, title); 5370 qf_idx = qi->qf_curlist; 5371 } 5372 else if (action == 'a' && qi->qf_lists[qf_idx].qf_count > 0) 5373 /* Adding to existing list, use last entry. */ 5374 old_last = qi->qf_lists[qf_idx].qf_last; 5375 else if (action == 'r') 5376 { 5377 qf_free_items(qi, qf_idx); 5378 qf_store_title(qi, qf_idx, title); 5379 } 5380 5381 for (li = list->lv_first; li != NULL; li = li->li_next) 5382 { 5383 if (li->li_tv.v_type != VAR_DICT) 5384 continue; /* Skip non-dict items */ 5385 5386 d = li->li_tv.vval.v_dict; 5387 if (d == NULL) 5388 continue; 5389 5390 filename = get_dict_string(d, (char_u *)"filename", TRUE); 5391 module = get_dict_string(d, (char_u *)"module", TRUE); 5392 bufnum = (int)get_dict_number(d, (char_u *)"bufnr"); 5393 lnum = (int)get_dict_number(d, (char_u *)"lnum"); 5394 col = (int)get_dict_number(d, (char_u *)"col"); 5395 vcol = (int)get_dict_number(d, (char_u *)"vcol"); 5396 nr = (int)get_dict_number(d, (char_u *)"nr"); 5397 type = get_dict_string(d, (char_u *)"type", TRUE); 5398 pattern = get_dict_string(d, (char_u *)"pattern", TRUE); 5399 text = get_dict_string(d, (char_u *)"text", TRUE); 5400 if (text == NULL) 5401 text = vim_strsave((char_u *)""); 5402 5403 valid = TRUE; 5404 if ((filename == NULL && bufnum == 0) || (lnum == 0 && pattern == NULL)) 5405 valid = FALSE; 5406 5407 /* Mark entries with non-existing buffer number as not valid. Give the 5408 * error message only once. */ 5409 if (bufnum != 0 && (buflist_findnr(bufnum) == NULL)) 5410 { 5411 if (!did_bufnr_emsg) 5412 { 5413 did_bufnr_emsg = TRUE; 5414 EMSGN(_("E92: Buffer %ld not found"), bufnum); 5415 } 5416 valid = FALSE; 5417 bufnum = 0; 5418 } 5419 5420 /* If the 'valid' field is present it overrules the detected value. */ 5421 if ((dict_find(d, (char_u *)"valid", -1)) != NULL) 5422 valid = (int)get_dict_number(d, (char_u *)"valid"); 5423 5424 status = qf_add_entry(qi, 5425 qf_idx, 5426 NULL, /* dir */ 5427 filename, 5428 module, 5429 bufnum, 5430 text, 5431 lnum, 5432 col, 5433 vcol, /* vis_col */ 5434 pattern, /* search pattern */ 5435 nr, 5436 type == NULL ? NUL : *type, 5437 valid); 5438 5439 vim_free(filename); 5440 vim_free(module); 5441 vim_free(pattern); 5442 vim_free(text); 5443 vim_free(type); 5444 5445 if (status == FAIL) 5446 { 5447 retval = FAIL; 5448 break; 5449 } 5450 } 5451 5452 if (qi->qf_lists[qf_idx].qf_index == 0) 5453 /* no valid entry */ 5454 qi->qf_lists[qf_idx].qf_nonevalid = TRUE; 5455 else 5456 qi->qf_lists[qf_idx].qf_nonevalid = FALSE; 5457 if (action != 'a') 5458 { 5459 qi->qf_lists[qf_idx].qf_ptr = 5460 qi->qf_lists[qf_idx].qf_start; 5461 if (qi->qf_lists[qf_idx].qf_count > 0) 5462 qi->qf_lists[qf_idx].qf_index = 1; 5463 } 5464 5465 /* Don't update the cursor in quickfix window when appending entries */ 5466 qf_update_buffer(qi, old_last); 5467 5468 return retval; 5469 } 5470 5471 /* 5472 * Get the quickfix list index from 'nr' or 'id' 5473 */ 5474 static int 5475 qf_setprop_get_qfidx( 5476 qf_info_T *qi, 5477 dict_T *what, 5478 int action, 5479 int *newlist) 5480 { 5481 dictitem_T *di; 5482 int qf_idx = qi->qf_curlist; /* default is the current list */ 5483 5484 if ((di = dict_find(what, (char_u *)"nr", -1)) != NULL) 5485 { 5486 /* Use the specified quickfix/location list */ 5487 if (di->di_tv.v_type == VAR_NUMBER) 5488 { 5489 /* for zero use the current list */ 5490 if (di->di_tv.vval.v_number != 0) 5491 qf_idx = di->di_tv.vval.v_number - 1; 5492 5493 if ((action == ' ' || action == 'a') && qf_idx == qi->qf_listcount) 5494 { 5495 /* 5496 * When creating a new list, accept qf_idx pointing to the next 5497 * non-available list and add the new list at the end of the 5498 * stack. 5499 */ 5500 *newlist = TRUE; 5501 qf_idx = qi->qf_listcount > 0 ? qi->qf_listcount - 1 : 0; 5502 } 5503 else if (qf_idx < 0 || qf_idx >= qi->qf_listcount) 5504 return INVALID_QFIDX; 5505 else if (action != ' ') 5506 *newlist = FALSE; /* use the specified list */ 5507 } 5508 else if (di->di_tv.v_type == VAR_STRING 5509 && di->di_tv.vval.v_string != NULL 5510 && STRCMP(di->di_tv.vval.v_string, "$") == 0) 5511 { 5512 if (qi->qf_listcount > 0) 5513 qf_idx = qi->qf_listcount - 1; 5514 else if (*newlist) 5515 qf_idx = 0; 5516 else 5517 return INVALID_QFIDX; 5518 } 5519 else 5520 return INVALID_QFIDX; 5521 } 5522 5523 if (!*newlist && (di = dict_find(what, (char_u *)"id", -1)) != NULL) 5524 { 5525 /* Use the quickfix/location list with the specified id */ 5526 if (di->di_tv.v_type != VAR_NUMBER) 5527 return INVALID_QFIDX; 5528 5529 return qf_id2nr(qi, di->di_tv.vval.v_number); 5530 } 5531 5532 return qf_idx; 5533 } 5534 5535 /* 5536 * Set the quickfix list title. 5537 */ 5538 static int 5539 qf_setprop_title(qf_info_T *qi, int qf_idx, dict_T *what, dictitem_T *di) 5540 { 5541 if (di->di_tv.v_type != VAR_STRING) 5542 return FAIL; 5543 5544 vim_free(qi->qf_lists[qf_idx].qf_title); 5545 qi->qf_lists[qf_idx].qf_title = 5546 get_dict_string(what, (char_u *)"title", TRUE); 5547 if (qf_idx == qi->qf_curlist) 5548 qf_update_win_titlevar(qi); 5549 5550 return OK; 5551 } 5552 5553 /* 5554 * Set quickfix list items/entries. 5555 */ 5556 static int 5557 qf_setprop_items(qf_info_T *qi, int qf_idx, dictitem_T *di, int action) 5558 { 5559 int retval = FAIL; 5560 char_u *title_save; 5561 5562 if (di->di_tv.v_type != VAR_LIST) 5563 return FAIL; 5564 5565 title_save = vim_strsave(qi->qf_lists[qf_idx].qf_title); 5566 retval = qf_add_entries(qi, qf_idx, di->di_tv.vval.v_list, 5567 title_save, action == ' ' ? 'a' : action); 5568 if (action == 'r') 5569 { 5570 /* 5571 * When replacing the quickfix list entries using 5572 * qf_add_entries(), the title is set with a ':' prefix. 5573 * Restore the title with the saved title. 5574 */ 5575 vim_free(qi->qf_lists[qf_idx].qf_title); 5576 qi->qf_lists[qf_idx].qf_title = vim_strsave(title_save); 5577 } 5578 vim_free(title_save); 5579 5580 return retval; 5581 } 5582 5583 /* 5584 * Set quickfix list items/entries from a list of lines. 5585 */ 5586 static int 5587 qf_setprop_items_from_lines( 5588 qf_info_T *qi, 5589 int qf_idx, 5590 dict_T *what, 5591 dictitem_T *di, 5592 int action) 5593 { 5594 char_u *errorformat = p_efm; 5595 dictitem_T *efm_di; 5596 int retval = FAIL; 5597 5598 /* Use the user supplied errorformat settings (if present) */ 5599 if ((efm_di = dict_find(what, (char_u *)"efm", -1)) != NULL) 5600 { 5601 if (efm_di->di_tv.v_type != VAR_STRING || 5602 efm_di->di_tv.vval.v_string == NULL) 5603 return FAIL; 5604 errorformat = efm_di->di_tv.vval.v_string; 5605 } 5606 5607 /* Only a List value is supported */ 5608 if (di->di_tv.v_type != VAR_LIST || di->di_tv.vval.v_list == NULL) 5609 return FAIL; 5610 5611 if (action == 'r') 5612 qf_free_items(qi, qf_idx); 5613 if (qf_init_ext(qi, qf_idx, NULL, NULL, &di->di_tv, errorformat, 5614 FALSE, (linenr_T)0, (linenr_T)0, NULL, NULL) > 0) 5615 retval = OK; 5616 5617 return retval; 5618 } 5619 5620 /* 5621 * Set quickfix list context. 5622 */ 5623 static int 5624 qf_setprop_context(qf_info_T *qi, int qf_idx, dictitem_T *di) 5625 { 5626 typval_T *ctx; 5627 5628 free_tv(qi->qf_lists[qf_idx].qf_ctx); 5629 ctx = alloc_tv(); 5630 if (ctx != NULL) 5631 copy_tv(&di->di_tv, ctx); 5632 qi->qf_lists[qf_idx].qf_ctx = ctx; 5633 5634 return OK; 5635 } 5636 5637 /* 5638 * Set quickfix/location list properties (title, items, context). 5639 * Also used to add items from parsing a list of lines. 5640 * Used by the setqflist() and setloclist() VimL functions. 5641 */ 5642 static int 5643 qf_set_properties(qf_info_T *qi, dict_T *what, int action, char_u *title) 5644 { 5645 dictitem_T *di; 5646 int retval = FAIL; 5647 int qf_idx; 5648 int newlist = FALSE; 5649 5650 if (action == ' ' || qi->qf_curlist == qi->qf_listcount) 5651 newlist = TRUE; 5652 5653 qf_idx = qf_setprop_get_qfidx(qi, what, action, &newlist); 5654 if (qf_idx == INVALID_QFIDX) /* List not found */ 5655 return FAIL; 5656 5657 if (newlist) 5658 { 5659 qi->qf_curlist = qf_idx; 5660 qf_new_list(qi, title); 5661 qf_idx = qi->qf_curlist; 5662 } 5663 5664 if ((di = dict_find(what, (char_u *)"title", -1)) != NULL) 5665 retval = qf_setprop_title(qi, qf_idx, what, di); 5666 if ((di = dict_find(what, (char_u *)"items", -1)) != NULL) 5667 retval = qf_setprop_items(qi, qf_idx, di, action); 5668 if ((di = dict_find(what, (char_u *)"lines", -1)) != NULL) 5669 retval = qf_setprop_items_from_lines(qi, qf_idx, what, di, action); 5670 if ((di = dict_find(what, (char_u *)"context", -1)) != NULL) 5671 retval = qf_setprop_context(qi, qf_idx, di); 5672 5673 if (retval == OK) 5674 qf_list_changed(qi, qf_idx); 5675 5676 return retval; 5677 } 5678 5679 /* 5680 * Find the non-location list window with the specified location list. 5681 */ 5682 static win_T * 5683 find_win_with_ll(qf_info_T *qi) 5684 { 5685 win_T *wp = NULL; 5686 5687 FOR_ALL_WINDOWS(wp) 5688 if ((wp->w_llist == qi) && !bt_quickfix(wp->w_buffer)) 5689 return wp; 5690 5691 return NULL; 5692 } 5693 5694 /* 5695 * Free the entire quickfix/location list stack. 5696 * If the quickfix/location list window is open, then clear it. 5697 */ 5698 static void 5699 qf_free_stack(win_T *wp, qf_info_T *qi) 5700 { 5701 win_T *qfwin = qf_find_win(qi); 5702 win_T *llwin = NULL; 5703 win_T *orig_wp = wp; 5704 5705 if (qfwin != NULL) 5706 { 5707 /* If the quickfix/location list window is open, then clear it */ 5708 if (qi->qf_curlist < qi->qf_listcount) 5709 qf_free(qi, qi->qf_curlist); 5710 qf_update_buffer(qi, NULL); 5711 } 5712 5713 if (wp != NULL && IS_LL_WINDOW(wp)) 5714 { 5715 /* If in the location list window, then use the non-location list 5716 * window with this location list (if present) 5717 */ 5718 llwin = find_win_with_ll(qi); 5719 if (llwin != NULL) 5720 wp = llwin; 5721 } 5722 5723 qf_free_all(wp); 5724 if (wp == NULL) 5725 { 5726 /* quickfix list */ 5727 qi->qf_curlist = 0; 5728 qi->qf_listcount = 0; 5729 } 5730 else if (IS_LL_WINDOW(orig_wp)) 5731 { 5732 /* If the location list window is open, then create a new empty 5733 * location list */ 5734 qf_info_T *new_ll = ll_new_list(); 5735 5736 /* first free the list reference in the location list window */ 5737 ll_free_all(&orig_wp->w_llist_ref); 5738 5739 orig_wp->w_llist_ref = new_ll; 5740 if (llwin != NULL) 5741 { 5742 llwin->w_llist = new_ll; 5743 new_ll->qf_refcount++; 5744 } 5745 } 5746 } 5747 5748 /* 5749 * Populate the quickfix list with the items supplied in the list 5750 * of dictionaries. "title" will be copied to w:quickfix_title. 5751 * "action" is 'a' for add, 'r' for replace. Otherwise create a new list. 5752 */ 5753 int 5754 set_errorlist( 5755 win_T *wp, 5756 list_T *list, 5757 int action, 5758 char_u *title, 5759 dict_T *what) 5760 { 5761 qf_info_T *qi = &ql_info; 5762 int retval = OK; 5763 5764 if (wp != NULL) 5765 { 5766 qi = ll_get_or_alloc_list(wp); 5767 if (qi == NULL) 5768 return FAIL; 5769 } 5770 5771 if (action == 'f') 5772 { 5773 /* Free the entire quickfix or location list stack */ 5774 qf_free_stack(wp, qi); 5775 } 5776 else if (what != NULL) 5777 retval = qf_set_properties(qi, what, action, title); 5778 else 5779 { 5780 retval = qf_add_entries(qi, qi->qf_curlist, list, title, action); 5781 if (retval == OK) 5782 qf_list_changed(qi, qi->qf_curlist); 5783 } 5784 5785 return retval; 5786 } 5787 5788 static int 5789 mark_quickfix_ctx(qf_info_T *qi, int copyID) 5790 { 5791 int i; 5792 int abort = FALSE; 5793 typval_T *ctx; 5794 5795 for (i = 0; i < LISTCOUNT && !abort; ++i) 5796 { 5797 ctx = qi->qf_lists[i].qf_ctx; 5798 if (ctx != NULL && ctx->v_type != VAR_NUMBER 5799 && ctx->v_type != VAR_STRING && ctx->v_type != VAR_FLOAT) 5800 abort = set_ref_in_item(ctx, copyID, NULL, NULL); 5801 } 5802 5803 return abort; 5804 } 5805 5806 /* 5807 * Mark the context of the quickfix list and the location lists (if present) as 5808 * "in use". So that garbage collection doesn't free the context. 5809 */ 5810 int 5811 set_ref_in_quickfix(int copyID) 5812 { 5813 int abort = FALSE; 5814 tabpage_T *tp; 5815 win_T *win; 5816 5817 abort = mark_quickfix_ctx(&ql_info, copyID); 5818 if (abort) 5819 return abort; 5820 5821 FOR_ALL_TAB_WINDOWS(tp, win) 5822 { 5823 if (win->w_llist != NULL) 5824 { 5825 abort = mark_quickfix_ctx(win->w_llist, copyID); 5826 if (abort) 5827 return abort; 5828 } 5829 if (IS_LL_WINDOW(win) && (win->w_llist_ref->qf_refcount == 1)) 5830 { 5831 /* In a location list window and none of the other windows is 5832 * referring to this location list. Mark the location list 5833 * context as still in use. 5834 */ 5835 abort = mark_quickfix_ctx(win->w_llist_ref, copyID); 5836 if (abort) 5837 return abort; 5838 } 5839 } 5840 5841 return abort; 5842 } 5843 #endif 5844 5845 /* 5846 * ":[range]cbuffer [bufnr]" command. 5847 * ":[range]caddbuffer [bufnr]" command. 5848 * ":[range]cgetbuffer [bufnr]" command. 5849 * ":[range]lbuffer [bufnr]" command. 5850 * ":[range]laddbuffer [bufnr]" command. 5851 * ":[range]lgetbuffer [bufnr]" command. 5852 */ 5853 void 5854 ex_cbuffer(exarg_T *eap) 5855 { 5856 buf_T *buf = NULL; 5857 qf_info_T *qi = &ql_info; 5858 char_u *au_name = NULL; 5859 int res; 5860 5861 switch (eap->cmdidx) 5862 { 5863 case CMD_cbuffer: au_name = (char_u *)"cbuffer"; break; 5864 case CMD_cgetbuffer: au_name = (char_u *)"cgetbuffer"; break; 5865 case CMD_caddbuffer: au_name = (char_u *)"caddbuffer"; break; 5866 case CMD_lbuffer: au_name = (char_u *)"lbuffer"; break; 5867 case CMD_lgetbuffer: au_name = (char_u *)"lgetbuffer"; break; 5868 case CMD_laddbuffer: au_name = (char_u *)"laddbuffer"; break; 5869 default: break; 5870 } 5871 if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, 5872 curbuf->b_fname, TRUE, curbuf)) 5873 { 5874 #ifdef FEAT_EVAL 5875 if (aborting()) 5876 return; 5877 #endif 5878 } 5879 5880 /* Must come after autocommands. */ 5881 if (eap->cmdidx == CMD_lbuffer 5882 || eap->cmdidx == CMD_lgetbuffer 5883 || eap->cmdidx == CMD_laddbuffer) 5884 { 5885 qi = ll_get_or_alloc_list(curwin); 5886 if (qi == NULL) 5887 return; 5888 } 5889 5890 if (*eap->arg == NUL) 5891 buf = curbuf; 5892 else if (*skipwhite(skipdigits(eap->arg)) == NUL) 5893 buf = buflist_findnr(atoi((char *)eap->arg)); 5894 if (buf == NULL) 5895 EMSG(_(e_invarg)); 5896 else if (buf->b_ml.ml_mfp == NULL) 5897 EMSG(_("E681: Buffer is not loaded")); 5898 else 5899 { 5900 if (eap->addr_count == 0) 5901 { 5902 eap->line1 = 1; 5903 eap->line2 = buf->b_ml.ml_line_count; 5904 } 5905 if (eap->line1 < 1 || eap->line1 > buf->b_ml.ml_line_count 5906 || eap->line2 < 1 || eap->line2 > buf->b_ml.ml_line_count) 5907 EMSG(_(e_invrange)); 5908 else 5909 { 5910 char_u *qf_title = *eap->cmdlinep; 5911 5912 if (buf->b_sfname) 5913 { 5914 vim_snprintf((char *)IObuff, IOSIZE, "%s (%s)", 5915 (char *)qf_title, (char *)buf->b_sfname); 5916 qf_title = IObuff; 5917 } 5918 5919 res = qf_init_ext(qi, qi->qf_curlist, NULL, buf, NULL, p_efm, 5920 (eap->cmdidx != CMD_caddbuffer 5921 && eap->cmdidx != CMD_laddbuffer), 5922 eap->line1, eap->line2, 5923 qf_title, NULL); 5924 if (res >= 0) 5925 qf_list_changed(qi, qi->qf_curlist); 5926 if (au_name != NULL) 5927 apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, 5928 curbuf->b_fname, TRUE, curbuf); 5929 if (res > 0 && (eap->cmdidx == CMD_cbuffer || 5930 eap->cmdidx == CMD_lbuffer)) 5931 qf_jump(qi, 0, 0, eap->forceit); /* display first error */ 5932 } 5933 } 5934 } 5935 5936 #if defined(FEAT_EVAL) || defined(PROTO) 5937 /* 5938 * ":cexpr {expr}", ":cgetexpr {expr}", ":caddexpr {expr}" command. 5939 * ":lexpr {expr}", ":lgetexpr {expr}", ":laddexpr {expr}" command. 5940 */ 5941 void 5942 ex_cexpr(exarg_T *eap) 5943 { 5944 typval_T *tv; 5945 qf_info_T *qi = &ql_info; 5946 char_u *au_name = NULL; 5947 int res; 5948 5949 switch (eap->cmdidx) 5950 { 5951 case CMD_cexpr: au_name = (char_u *)"cexpr"; break; 5952 case CMD_cgetexpr: au_name = (char_u *)"cgetexpr"; break; 5953 case CMD_caddexpr: au_name = (char_u *)"caddexpr"; break; 5954 case CMD_lexpr: au_name = (char_u *)"lexpr"; break; 5955 case CMD_lgetexpr: au_name = (char_u *)"lgetexpr"; break; 5956 case CMD_laddexpr: au_name = (char_u *)"laddexpr"; break; 5957 default: break; 5958 } 5959 if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, 5960 curbuf->b_fname, TRUE, curbuf)) 5961 { 5962 #ifdef FEAT_EVAL 5963 if (aborting()) 5964 return; 5965 #endif 5966 } 5967 5968 if (eap->cmdidx == CMD_lexpr 5969 || eap->cmdidx == CMD_lgetexpr 5970 || eap->cmdidx == CMD_laddexpr) 5971 { 5972 qi = ll_get_or_alloc_list(curwin); 5973 if (qi == NULL) 5974 return; 5975 } 5976 5977 /* Evaluate the expression. When the result is a string or a list we can 5978 * use it to fill the errorlist. */ 5979 tv = eval_expr(eap->arg, NULL); 5980 if (tv != NULL) 5981 { 5982 if ((tv->v_type == VAR_STRING && tv->vval.v_string != NULL) 5983 || (tv->v_type == VAR_LIST && tv->vval.v_list != NULL)) 5984 { 5985 res = qf_init_ext(qi, qi->qf_curlist, NULL, NULL, tv, p_efm, 5986 (eap->cmdidx != CMD_caddexpr 5987 && eap->cmdidx != CMD_laddexpr), 5988 (linenr_T)0, (linenr_T)0, *eap->cmdlinep, 5989 NULL); 5990 if (res >= 0) 5991 qf_list_changed(qi, qi->qf_curlist); 5992 if (au_name != NULL) 5993 apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, 5994 curbuf->b_fname, TRUE, curbuf); 5995 if (res > 0 && (eap->cmdidx == CMD_cexpr || 5996 eap->cmdidx == CMD_lexpr)) 5997 qf_jump(qi, 0, 0, eap->forceit); /* display first error */ 5998 } 5999 else 6000 EMSG(_("E777: String or List expected")); 6001 free_tv(tv); 6002 } 6003 } 6004 #endif 6005 6006 /* 6007 * Get the location list for ":lhelpgrep" 6008 */ 6009 static qf_info_T * 6010 hgr_get_ll(int *new_ll) 6011 { 6012 win_T *wp; 6013 qf_info_T *qi; 6014 6015 /* If the current window is a help window, then use it */ 6016 if (bt_help(curwin->w_buffer)) 6017 wp = curwin; 6018 else 6019 /* Find an existing help window */ 6020 FOR_ALL_WINDOWS(wp) 6021 if (bt_help(wp->w_buffer)) 6022 break; 6023 6024 if (wp == NULL) /* Help window not found */ 6025 qi = NULL; 6026 else 6027 qi = wp->w_llist; 6028 6029 if (qi == NULL) 6030 { 6031 /* Allocate a new location list for help text matches */ 6032 if ((qi = ll_new_list()) == NULL) 6033 return NULL; 6034 *new_ll = TRUE; 6035 } 6036 6037 return qi; 6038 } 6039 6040 /* 6041 * Search for a pattern in a help file. 6042 */ 6043 static void 6044 hgr_search_file( 6045 qf_info_T *qi, 6046 char_u *fname, 6047 #ifdef FEAT_MBYTE 6048 vimconv_T *p_vc, 6049 #endif 6050 regmatch_T *p_regmatch) 6051 { 6052 FILE *fd; 6053 long lnum; 6054 6055 fd = mch_fopen((char *)fname, "r"); 6056 if (fd == NULL) 6057 return; 6058 6059 lnum = 1; 6060 while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int) 6061 { 6062 char_u *line = IObuff; 6063 #ifdef FEAT_MBYTE 6064 /* Convert a line if 'encoding' is not utf-8 and 6065 * the line contains a non-ASCII character. */ 6066 if (p_vc->vc_type != CONV_NONE 6067 && has_non_ascii(IObuff)) 6068 { 6069 line = string_convert(p_vc, IObuff, NULL); 6070 if (line == NULL) 6071 line = IObuff; 6072 } 6073 #endif 6074 6075 if (vim_regexec(p_regmatch, line, (colnr_T)0)) 6076 { 6077 int l = (int)STRLEN(line); 6078 6079 /* remove trailing CR, LF, spaces, etc. */ 6080 while (l > 0 && line[l - 1] <= ' ') 6081 line[--l] = NUL; 6082 6083 if (qf_add_entry(qi, 6084 qi->qf_curlist, 6085 NULL, /* dir */ 6086 fname, 6087 NULL, 6088 0, 6089 line, 6090 lnum, 6091 (int)(p_regmatch->startp[0] - line) 6092 + 1, /* col */ 6093 FALSE, /* vis_col */ 6094 NULL, /* search pattern */ 6095 0, /* nr */ 6096 1, /* type */ 6097 TRUE /* valid */ 6098 ) == FAIL) 6099 { 6100 got_int = TRUE; 6101 #ifdef FEAT_MBYTE 6102 if (line != IObuff) 6103 vim_free(line); 6104 #endif 6105 break; 6106 } 6107 } 6108 #ifdef FEAT_MBYTE 6109 if (line != IObuff) 6110 vim_free(line); 6111 #endif 6112 ++lnum; 6113 line_breakcheck(); 6114 } 6115 fclose(fd); 6116 } 6117 6118 /* 6119 * Search for a pattern in all the help files in the doc directory under 6120 * the given directory. 6121 */ 6122 static void 6123 hgr_search_files_in_dir( 6124 qf_info_T *qi, 6125 char_u *dirname, 6126 regmatch_T *p_regmatch 6127 #ifdef FEAT_MBYTE 6128 , vimconv_T *p_vc 6129 #endif 6130 #ifdef FEAT_MULTI_LANG 6131 , char_u *lang 6132 #endif 6133 ) 6134 { 6135 int fcount; 6136 char_u **fnames; 6137 int fi; 6138 6139 /* Find all "*.txt" and "*.??x" files in the "doc" directory. */ 6140 add_pathsep(dirname); 6141 STRCAT(dirname, "doc/*.\\(txt\\|??x\\)"); 6142 if (gen_expand_wildcards(1, &dirname, &fcount, 6143 &fnames, EW_FILE|EW_SILENT) == OK 6144 && fcount > 0) 6145 { 6146 for (fi = 0; fi < fcount && !got_int; ++fi) 6147 { 6148 #ifdef FEAT_MULTI_LANG 6149 /* Skip files for a different language. */ 6150 if (lang != NULL 6151 && STRNICMP(lang, fnames[fi] 6152 + STRLEN(fnames[fi]) - 3, 2) != 0 6153 && !(STRNICMP(lang, "en", 2) == 0 6154 && STRNICMP("txt", fnames[fi] 6155 + STRLEN(fnames[fi]) - 3, 3) == 0)) 6156 continue; 6157 #endif 6158 6159 hgr_search_file(qi, fnames[fi], 6160 #ifdef FEAT_MBYTE 6161 p_vc, 6162 #endif 6163 p_regmatch); 6164 } 6165 FreeWild(fcount, fnames); 6166 } 6167 } 6168 6169 /* 6170 * Search for a pattern in all the help files in the 'runtimepath'. 6171 */ 6172 static void 6173 hgr_search_in_rtp(qf_info_T *qi, regmatch_T *p_regmatch, char_u *arg) 6174 { 6175 char_u *p; 6176 #ifdef FEAT_MULTI_LANG 6177 char_u *lang; 6178 #endif 6179 6180 #ifdef FEAT_MBYTE 6181 vimconv_T vc; 6182 6183 /* Help files are in utf-8 or latin1, convert lines when 'encoding' 6184 * differs. */ 6185 vc.vc_type = CONV_NONE; 6186 if (!enc_utf8) 6187 convert_setup(&vc, (char_u *)"utf-8", p_enc); 6188 #endif 6189 6190 #ifdef FEAT_MULTI_LANG 6191 /* Check for a specified language */ 6192 lang = check_help_lang(arg); 6193 #endif 6194 6195 /* Go through all directories in 'runtimepath' */ 6196 p = p_rtp; 6197 while (*p != NUL && !got_int) 6198 { 6199 copy_option_part(&p, NameBuff, MAXPATHL, ","); 6200 6201 hgr_search_files_in_dir(qi, NameBuff, p_regmatch 6202 #ifdef FEAT_MBYTE 6203 , &vc 6204 #endif 6205 #ifdef FEAT_MULTI_LANG 6206 , lang 6207 #endif 6208 ); 6209 } 6210 6211 #ifdef FEAT_MBYTE 6212 if (vc.vc_type != CONV_NONE) 6213 convert_setup(&vc, NULL, NULL); 6214 #endif 6215 } 6216 6217 /* 6218 * ":helpgrep {pattern}" 6219 */ 6220 void 6221 ex_helpgrep(exarg_T *eap) 6222 { 6223 regmatch_T regmatch; 6224 char_u *save_cpo; 6225 qf_info_T *qi = &ql_info; 6226 int new_qi = FALSE; 6227 char_u *au_name = NULL; 6228 6229 switch (eap->cmdidx) 6230 { 6231 case CMD_helpgrep: au_name = (char_u *)"helpgrep"; break; 6232 case CMD_lhelpgrep: au_name = (char_u *)"lhelpgrep"; break; 6233 default: break; 6234 } 6235 if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, 6236 curbuf->b_fname, TRUE, curbuf)) 6237 { 6238 #ifdef FEAT_EVAL 6239 if (aborting()) 6240 return; 6241 #endif 6242 } 6243 6244 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */ 6245 save_cpo = p_cpo; 6246 p_cpo = empty_option; 6247 6248 if (eap->cmdidx == CMD_lhelpgrep) 6249 { 6250 qi = hgr_get_ll(&new_qi); 6251 if (qi == NULL) 6252 return; 6253 } 6254 6255 regmatch.regprog = vim_regcomp(eap->arg, RE_MAGIC + RE_STRING); 6256 regmatch.rm_ic = FALSE; 6257 if (regmatch.regprog != NULL) 6258 { 6259 /* create a new quickfix list */ 6260 qf_new_list(qi, *eap->cmdlinep); 6261 6262 hgr_search_in_rtp(qi, ®match, eap->arg); 6263 6264 vim_regfree(regmatch.regprog); 6265 6266 qi->qf_lists[qi->qf_curlist].qf_nonevalid = FALSE; 6267 qi->qf_lists[qi->qf_curlist].qf_ptr = 6268 qi->qf_lists[qi->qf_curlist].qf_start; 6269 qi->qf_lists[qi->qf_curlist].qf_index = 1; 6270 } 6271 6272 if (p_cpo == empty_option) 6273 p_cpo = save_cpo; 6274 else 6275 /* Darn, some plugin changed the value. */ 6276 free_string_option(save_cpo); 6277 6278 qf_list_changed(qi, qi->qf_curlist); 6279 qf_update_buffer(qi, NULL); 6280 6281 if (au_name != NULL) 6282 { 6283 apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, 6284 curbuf->b_fname, TRUE, curbuf); 6285 if (!new_qi && qi != &ql_info && qf_find_buf(qi) == NULL) 6286 /* autocommands made "qi" invalid */ 6287 return; 6288 } 6289 6290 /* Jump to first match. */ 6291 if (qi->qf_lists[qi->qf_curlist].qf_count > 0) 6292 qf_jump(qi, 0, 0, FALSE); 6293 else 6294 EMSG2(_(e_nomatch2), eap->arg); 6295 6296 if (eap->cmdidx == CMD_lhelpgrep) 6297 { 6298 /* If the help window is not opened or if it already points to the 6299 * correct location list, then free the new location list. */ 6300 if (!bt_help(curwin->w_buffer) || curwin->w_llist == qi) 6301 { 6302 if (new_qi) 6303 ll_free_all(&qi); 6304 } 6305 else if (curwin->w_llist == NULL) 6306 curwin->w_llist = qi; 6307 } 6308 } 6309 6310 #endif /* FEAT_QUICKFIX */ 6311