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