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