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