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