neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

quickfix.c (228145B)


      1 // quickfix.c: functions for quickfix mode, using a file with error messages
      2 
      3 #include <assert.h>
      4 #include <errno.h>
      5 #include <inttypes.h>
      6 #include <limits.h>
      7 #include <stdbool.h>
      8 #include <stdio.h>
      9 #include <stdlib.h>
     10 #include <string.h>
     11 #include <time.h>
     12 
     13 #include "nvim/arglist.h"
     14 #include "nvim/ascii_defs.h"
     15 #include "nvim/autocmd.h"
     16 #include "nvim/autocmd_defs.h"
     17 #include "nvim/buffer.h"
     18 #include "nvim/buffer_defs.h"
     19 #include "nvim/change.h"
     20 #include "nvim/charset.h"
     21 #include "nvim/cursor.h"
     22 #include "nvim/drawscreen.h"
     23 #include "nvim/edit.h"
     24 #include "nvim/errors.h"
     25 #include "nvim/eval.h"
     26 #include "nvim/eval/typval.h"
     27 #include "nvim/eval/vars.h"
     28 #include "nvim/eval/window.h"
     29 #include "nvim/ex_cmds.h"
     30 #include "nvim/ex_cmds2.h"
     31 #include "nvim/ex_cmds_defs.h"
     32 #include "nvim/ex_docmd.h"
     33 #include "nvim/ex_eval.h"
     34 #include "nvim/ex_eval_defs.h"
     35 #include "nvim/ex_getln.h"
     36 #include "nvim/extmark.h"
     37 #include "nvim/fileio.h"
     38 #include "nvim/fold.h"
     39 #include "nvim/fuzzy.h"
     40 #include "nvim/garray.h"
     41 #include "nvim/garray_defs.h"
     42 #include "nvim/gettext_defs.h"
     43 #include "nvim/globals.h"
     44 #include "nvim/help.h"
     45 #include "nvim/highlight_defs.h"
     46 #include "nvim/highlight_group.h"
     47 #include "nvim/macros_defs.h"
     48 #include "nvim/mark.h"
     49 #include "nvim/mbyte.h"
     50 #include "nvim/mbyte_defs.h"
     51 #include "nvim/memline.h"
     52 #include "nvim/memline_defs.h"
     53 #include "nvim/memory.h"
     54 #include "nvim/message.h"
     55 #include "nvim/move.h"
     56 #include "nvim/normal.h"
     57 #include "nvim/ops.h"
     58 #include "nvim/option.h"
     59 #include "nvim/option_defs.h"
     60 #include "nvim/option_vars.h"
     61 #include "nvim/optionstr.h"
     62 #include "nvim/os/fs.h"
     63 #include "nvim/os/fs_defs.h"
     64 #include "nvim/os/input.h"
     65 #include "nvim/os/os.h"
     66 #include "nvim/os/os_defs.h"
     67 #include "nvim/path.h"
     68 #include "nvim/pos_defs.h"
     69 #include "nvim/quickfix.h"
     70 #include "nvim/regexp.h"
     71 #include "nvim/regexp_defs.h"
     72 #include "nvim/search.h"
     73 #include "nvim/strings.h"
     74 #include "nvim/types_defs.h"
     75 #include "nvim/ui.h"
     76 #include "nvim/undo.h"
     77 #include "nvim/vim_defs.h"
     78 #include "nvim/window.h"
     79 
     80 struct dir_stack_T {
     81  struct dir_stack_T *next;
     82  char *dirname;
     83 };
     84 
     85 // For each error the next struct is allocated and linked in a list.
     86 typedef struct qfline_S qfline_T;
     87 struct qfline_S {
     88  qfline_T *qf_next;      ///< pointer to next error in the list
     89  qfline_T *qf_prev;      ///< pointer to previous error in the list
     90  linenr_T qf_lnum;       ///< line number where the error occurred
     91  linenr_T qf_end_lnum;   ///< line number when the error has range or zero
     92 
     93  int qf_fnum;            ///< file number for the line
     94  int qf_col;             ///< column where the error occurred
     95  int qf_end_col;         ///< column when the error has range or zero
     96  int qf_nr;              ///< error number
     97  char *qf_module;        ///< module name for this error
     98  char *qf_fname;         ///< different filename if there're hard links
     99  char *qf_pattern;       ///< search pattern for the error
    100  char *qf_text;          ///< description of the error
    101  char qf_viscol;         ///< set to true if qf_col and qf_end_col is screen column
    102  char qf_cleared;        ///< set to true if line has been deleted
    103  char qf_type;           ///< type of the error (mostly 'E'); 1 for :helpgrep
    104  typval_T qf_user_data;  ///< custom user data associated with this item
    105  char qf_valid;          ///< valid error message detected
    106 };
    107 
    108 // There is a stack of error lists.
    109 #define INVALID_QFIDX (-1)
    110 #define INVALID_QFBUFNR (0)
    111 
    112 /// Quickfix list type.
    113 typedef enum {
    114  QFLT_QUICKFIX,  ///< Quickfix list - global list
    115  QFLT_LOCATION,  ///< Location list - per window list
    116  QFLT_INTERNAL,  ///< Internal - Temporary list used by
    117  //   getqflist()/getloclist()
    118 } qfltype_T;
    119 
    120 /// Quickfix/Location list definition
    121 ///
    122 /// Usually the list contains one or more entries. But an empty list can be
    123 /// created using setqflist()/setloclist() with a title and/or user context
    124 /// information and entries can be added later using setqflist()/setloclist().
    125 typedef struct {
    126  unsigned qf_id;         ///< Unique identifier for this list
    127  qfltype_T qfl_type;
    128  qfline_T *qf_start;     ///< pointer to the first error
    129  qfline_T *qf_last;      ///< pointer to the last error
    130  qfline_T *qf_ptr;       ///< pointer to the current error
    131  int qf_count;           ///< number of errors (0 means empty list)
    132  int qf_index;           ///< current index in the error list
    133  bool qf_nonevalid;      ///< true if not a single valid entry found
    134  bool qf_has_user_data;  ///< true if at least one item has user_data attached
    135  char *qf_title;         ///< title derived from the command that created
    136                          ///< the error list or set by setqflist
    137  typval_T *qf_ctx;       ///< context set by setqflist/setloclist
    138  Callback qf_qftf_cb;    ///< 'quickfixtextfunc' callback function
    139 
    140  struct dir_stack_T *qf_dir_stack;
    141  char *qf_directory;
    142  struct dir_stack_T *qf_file_stack;
    143  char *qf_currfile;
    144  bool qf_multiline;
    145  bool qf_multiignore;
    146  bool qf_multiscan;
    147  int qf_changedtick;
    148 } qf_list_T;
    149 
    150 /// Quickfix/Location list stack definition
    151 /// Contains a list of quickfix/location lists (qf_list_T)
    152 struct qf_info_S {
    153  // Count of references to this list. Used only for location lists.
    154  // When a location list window reference this list, qf_refcount
    155  // will be 2. Otherwise, qf_refcount will be 1. When qf_refcount
    156  // reaches 0, the list is freed.
    157  int qf_refcount;
    158  int qf_listcount;                 // current number of lists
    159  int qf_curlist;                   // current error list
    160  int qf_maxcount;                  // maximum number of lists
    161  qf_list_T *qf_lists;
    162  qfltype_T qfl_type;  // type of list
    163  int qf_bufnr;                     // quickfix window buffer number
    164 };
    165 
    166 static qf_info_T ql_info_actual;  // global quickfix list
    167 static qf_info_T *ql_info;        // points to ql_info_actual after allocation
    168 static unsigned last_qf_id = 0;   // Last Used quickfix list id
    169 
    170 #define FMT_PATTERNS 14           // maximum number of % recognized
    171 
    172 // Structure used to hold the info of one part of 'errorformat'
    173 typedef struct efm_S efm_T;
    174 struct efm_S {
    175  regprog_T *prog;        // pre-formatted part of 'errorformat'
    176  efm_T *next;        // pointer to next (NULL if last)
    177  char addr[FMT_PATTERNS];    // indices of used % patterns
    178  char prefix;                // prefix of this format line:
    179                              // 'D' enter directory
    180                              // 'X' leave directory
    181                              // 'A' start of multi-line message
    182                              // 'E' error message
    183                              // 'W' warning message
    184                              // 'I' informational message
    185                              // 'N' note message
    186                              // 'C' continuation line
    187                              // 'Z' end of multi-line message
    188                              // 'G' general, unspecific message
    189                              // 'P' push file (partial) message
    190                              // 'Q' pop/quit file (partial) message
    191                              // 'O' overread (partial) message
    192  char flags;                 // additional flags given in prefix
    193                              // '-' do not include this line
    194                              // '+' include whole line in message
    195  int conthere;                 // %> used
    196 };
    197 
    198 /// List of location lists to be deleted.
    199 /// Used to delay the deletion of locations lists by autocmds.
    200 typedef struct qf_delq_S {
    201  struct qf_delq_S *next;
    202  qf_info_T *qi;
    203 } qf_delq_T;
    204 
    205 enum {
    206  QF_FAIL = 0,
    207  QF_OK = 1,
    208  QF_END_OF_INPUT = 2,
    209  QF_NOMEM = 3,
    210  QF_IGNORE_LINE = 4,
    211  QF_MULTISCAN = 5,
    212  QF_ABORT = 6,
    213 };
    214 
    215 /// State information used to parse lines and add entries to a quickfix/location
    216 /// list.
    217 typedef struct {
    218  char *linebuf;
    219  size_t linelen;
    220  char *growbuf;
    221  size_t growbufsiz;
    222  FILE *fd;
    223  typval_T *tv;
    224  char *p_str;
    225  list_T *p_list;
    226  listitem_T *p_li;
    227  buf_T *buf;
    228  linenr_T buflnum;
    229  linenr_T lnumlast;
    230  vimconv_T vc;
    231 } qfstate_T;
    232 
    233 typedef struct {
    234  char *namebuf;
    235  int bnr;
    236  char *module;
    237  char *errmsg;
    238  size_t errmsglen;
    239  linenr_T lnum;
    240  linenr_T end_lnum;
    241  int col;
    242  int end_col;
    243  bool use_viscol;
    244  char *pattern;
    245  int enr;
    246  char type;
    247  typval_T *user_data;
    248  bool valid;
    249 } qffields_T;
    250 
    251 /// :vimgrep command arguments
    252 typedef struct {
    253  int tomatch;          ///< maximum number of matches to find
    254  char *spat;          ///< search pattern
    255  int flags;             ///< search modifier
    256  char **fnames;       ///< list of files to search
    257  int fcount;            ///< number of files
    258  regmmatch_T regmatch;  ///< compiled search pattern
    259  char *qf_title;      ///< quickfix list title
    260 } vgr_args_T;
    261 
    262 #include "quickfix.c.generated.h"
    263 
    264 static const char *e_no_more_items = N_("E553: No more items");
    265 static const char *e_current_quickfix_list_was_changed =
    266  N_("E925: Current quickfix list was changed");
    267 static const char *e_current_location_list_was_changed =
    268  N_("E926: Current location list was changed");
    269 
    270 enum { QF_WINHEIGHT = 10, };  ///< default height for quickfix window
    271 
    272 // Quickfix window check helper macro
    273 #define IS_QF_WINDOW(wp) (bt_quickfix((wp)->w_buffer) && (wp)->w_llist_ref == NULL)
    274 // Location list window check helper macro
    275 #define IS_LL_WINDOW(wp) (bt_quickfix((wp)->w_buffer) && (wp)->w_llist_ref != NULL)
    276 
    277 // Quickfix and location list stack check helper macros
    278 #define IS_QF_STACK(qi)       ((qi)->qfl_type == QFLT_QUICKFIX)
    279 #define IS_LL_STACK(qi)       ((qi)->qfl_type == QFLT_LOCATION)
    280 #define IS_QF_LIST(qfl)       ((qfl)->qfl_type == QFLT_QUICKFIX)
    281 #define IS_LL_LIST(qfl)       ((qfl)->qfl_type == QFLT_LOCATION)
    282 
    283 // Return location list for window 'wp'
    284 // For location list window, return the referenced location list
    285 #define GET_LOC_LIST(wp) (IS_LL_WINDOW(wp) ? (wp)->w_llist_ref : (wp)->w_llist)
    286 
    287 // Macro to loop through all the items in a quickfix list
    288 // Quickfix item index starts from 1, so i below starts at 1
    289 #define FOR_ALL_QFL_ITEMS(qfl, qfp, i) \
    290  for ((i) = 1, (qfp) = (qfl)->qf_start; \
    291       !got_int && (i) <= (qfl)->qf_count && (qfp) != NULL; \
    292       (i)++, (qfp) = (qfp)->qf_next)
    293 
    294 // Looking up a buffer can be slow if there are many.  Remember the last one
    295 // to make this a lot faster if there are multiple matches in the same file.
    296 static char *qf_last_bufname = NULL;
    297 static bufref_T qf_last_bufref = { NULL, 0, 0 };
    298 
    299 static garray_T qfga;
    300 
    301 /// Get a growarray to buffer text in.  Shared between various commands to avoid
    302 /// many alloc/free calls.
    303 static garray_T *qfga_get(void)
    304 {
    305  static bool initialized = false;
    306 
    307  if (!initialized) {
    308    initialized = true;
    309    ga_init(&qfga, 1, 256);
    310  }
    311 
    312  // Reset the length to zero.  Retain ga_data from previous use to avoid
    313  // many alloc/free calls.
    314  qfga.ga_len = 0;
    315 
    316  return &qfga;
    317 }
    318 
    319 /// The "qfga" grow array buffer is reused across multiple quickfix commands as
    320 /// a temporary buffer to reduce the number of alloc/free calls.  But if the
    321 /// buffer size is large, then to avoid holding on to that memory, clear the
    322 /// grow array.  Otherwise just reset the grow array length.
    323 static void qfga_clear(void)
    324 {
    325  if (qfga.ga_maxlen > 1000) {
    326    ga_clear(&qfga);
    327  } else {
    328    qfga.ga_len = 0;
    329  }
    330 }
    331 
    332 // Counter to prevent autocmds from freeing up location lists when they are
    333 // still being used.
    334 static int quickfix_busy = 0;
    335 static qf_delq_T *qf_delq_head = NULL;
    336 
    337 /// Process the next line from a file/buffer/list/string and add it
    338 /// to the quickfix list 'qfl'.
    339 static int qf_init_process_nextline(qf_list_T *qfl, efm_T *fmt_first, qfstate_T *state,
    340                                    qffields_T *fields)
    341 {
    342  // Get the next line from a file/buffer/list/string
    343  int status = qf_get_nextline(state);
    344  if (status != QF_OK) {
    345    return status;
    346  }
    347 
    348  status = qf_parse_line(qfl, state->linebuf, state->linelen,
    349                         fmt_first, fields);
    350  if (status != QF_OK) {
    351    return status;
    352  }
    353 
    354  return qf_add_entry(qfl,
    355                      qfl->qf_directory,
    356                      (*fields->namebuf || qfl->qf_directory != NULL)
    357                      ? fields->namebuf
    358                      : ((qfl->qf_currfile != NULL && fields->valid)
    359                         ? qfl->qf_currfile : NULL),
    360                      fields->module,
    361                      fields->bnr,
    362                      fields->errmsg,
    363                      fields->lnum,
    364                      fields->end_lnum,
    365                      fields->col,
    366                      fields->end_col,
    367                      fields->use_viscol,
    368                      fields->pattern,
    369                      fields->enr,
    370                      fields->type,
    371                      fields->user_data,
    372                      fields->valid);
    373 }
    374 
    375 /// Read the errorfile "efile" into memory, line by line, building the error
    376 /// list. Set the error list's title to qf_title.
    377 ///
    378 /// @params  wp  If non-NULL, make a location list
    379 /// @params  efile  If non-NULL, errorfile to parse
    380 /// @params  errorformat  'errorformat' string used to parse the error lines
    381 /// @params  newlist  If true, create a new error list
    382 /// @params  qf_title  If non-NULL, title of the error list
    383 /// @params  enc  If non-NULL, encoding used to parse errors
    384 ///
    385 /// @returns -1 for error, number of errors for success.
    386 int qf_init(win_T *wp, const char *restrict efile, char *restrict errorformat, int newlist,
    387            const char *restrict qf_title, char *restrict enc)
    388 {
    389  qf_info_T *qi = wp == NULL ? ql_info : ll_get_or_alloc_list(wp);
    390  assert(qi != NULL);
    391 
    392  return qf_init_ext(qi, qi->qf_curlist, efile, curbuf, NULL, errorformat,
    393                     newlist, 0, 0, qf_title, enc);
    394 }
    395 
    396 // Maximum number of bytes allowed per line while reading an errorfile.
    397 static const size_t LINE_MAXLEN = 4096;
    398 
    399 /// Patterns used.  Keep in sync with qf_parse_fmt[].
    400 static struct fmtpattern {
    401  char convchar;
    402  char *pattern;
    403 } fmt_pat[FMT_PATTERNS] = {
    404  { 'f', ".\\+" },      // only used when at end
    405  { 'b', "\\d\\+" },    // 1
    406  { 'n', "\\d\\+" },    // 2
    407  { 'l', "\\d\\+" },    // 3
    408  { 'e', "\\d\\+" },    // 4
    409  { 'c', "\\d\\+" },    // 5
    410  { 'k', "\\d\\+" },    // 6
    411  { 't', "." },         // 7
    412 #define FMT_PATTERN_M 8
    413  { 'm', ".\\+" },      // 8
    414 #define FMT_PATTERN_R 9
    415  { 'r', ".*" },        // 9
    416  { 'p', "[-\t .]*" },  // 10
    417  { 'v', "\\d\\+" },    // 11
    418  { 's', ".\\+" },      // 12
    419  { 'o', ".\\+" }       // 13
    420 };
    421 
    422 /// Convert an errorformat pattern to a regular expression pattern.
    423 /// See fmt_pat definition above for the list of supported patterns.  The
    424 /// pattern specifier is supplied in "efmpat".  The converted pattern is stored
    425 /// in "regpat".  Returns a pointer to the location after the pattern.
    426 static char *efmpat_to_regpat(const char *efmpat, char *regpat, efm_T *efminfo, int idx, int round)
    427  FUNC_ATTR_NONNULL_ALL
    428 {
    429  if (efminfo->addr[idx]) {
    430    // Each errorformat pattern can occur only once
    431    semsg(_("E372: Too many %%%c in format string"), *efmpat);
    432    return NULL;
    433  }
    434  if ((idx && idx < FMT_PATTERN_R
    435       && vim_strchr("DXOPQ", (uint8_t)efminfo->prefix) != NULL)
    436      || (idx == FMT_PATTERN_R
    437          && vim_strchr("OPQ", (uint8_t)efminfo->prefix) == NULL)) {
    438    semsg(_("E373: Unexpected %%%c in format string"), *efmpat);
    439    return NULL;
    440  }
    441  efminfo->addr[idx] = (char)++round;
    442  *regpat++ = '\\';
    443  *regpat++ = '(';
    444 #ifdef BACKSLASH_IN_FILENAME
    445  if (*efmpat == 'f') {
    446    // Also match "c:" in the file name, even when
    447    // checking for a colon next: "%f:".
    448    // "\%(\a:\)\="
    449    STRCPY(regpat, "\\%(\\a:\\)\\=");
    450    regpat += 10;
    451  }
    452 #endif
    453  if (*efmpat == 'f' && efmpat[1] != NUL) {
    454    if (efmpat[1] != '\\' && efmpat[1] != '%') {
    455      // A file name may contain spaces, but this isn't
    456      // in "\f".  For "%f:%l:%m" there may be a ":" in
    457      // the file name.  Use ".\{-1,}x" instead (x is
    458      // the next character), the requirement that :999:
    459      // follows should work.
    460      STRCPY(regpat, ".\\{-1,}");
    461      regpat += 7;
    462    } else {
    463      // File name followed by '\\' or '%': include as
    464      // many file name chars as possible.
    465      STRCPY(regpat, "\\f\\+");
    466      regpat += 4;
    467    }
    468  } else {
    469    char *srcptr = fmt_pat[idx].pattern;
    470    while ((*regpat = *srcptr++) != NUL) {
    471      regpat++;
    472    }
    473  }
    474  *regpat++ = '\\';
    475  *regpat++ = ')';
    476 
    477  return regpat;
    478 }
    479 
    480 /// Convert a scanf like format in 'errorformat' to a regular expression.
    481 /// Returns a pointer to the location after the pattern.
    482 static char *scanf_fmt_to_regpat(const char **pefmp, const char *efm, int len, char *regpat)
    483  FUNC_ATTR_NONNULL_ALL
    484 {
    485  const char *efmp = *pefmp;
    486 
    487  if (*efmp == '[' || *efmp == '\\') {
    488    if ((*regpat++ = *efmp) == '[') {  // %*[^a-z0-9] etc.
    489      if (efmp[1] == '^') {
    490        *regpat++ = *++efmp;
    491      }
    492      if (efmp < efm + len) {
    493        *regpat++ = *++efmp;  // could be ']'
    494        while (efmp < efm + len && (*regpat++ = *++efmp) != ']') {}
    495        if (efmp == efm + len) {
    496          emsg(_("E374: Missing ] in format string"));
    497          return NULL;
    498        }
    499      }
    500    } else if (efmp < efm + len) {  // %*\D, %*\s etc.
    501      *regpat++ = *++efmp;
    502    }
    503    *regpat++ = '\\';
    504    *regpat++ = '+';
    505  } else {
    506    semsg(_("E375: Unsupported %%%c in format string"), *efmp);
    507    return NULL;
    508  }
    509 
    510  *pefmp = efmp;
    511 
    512  return regpat;
    513 }
    514 
    515 /// Analyze/parse an errorformat prefix.
    516 static const char *efm_analyze_prefix(const char *efmp, efm_T *efminfo)
    517  FUNC_ATTR_NONNULL_ALL
    518 {
    519  if (vim_strchr("+-", (uint8_t)(*efmp)) != NULL) {
    520    efminfo->flags = *efmp++;
    521  }
    522  if (vim_strchr("DXAEWINCZGOPQ", (uint8_t)(*efmp)) != NULL) {
    523    efminfo->prefix = *efmp;
    524  } else {
    525    semsg(_("E376: Invalid %%%c in format string prefix"), *efmp);
    526    return NULL;
    527  }
    528 
    529  return efmp;
    530 }
    531 
    532 // Converts a 'errorformat' string to regular expression pattern
    533 static int efm_to_regpat(const char *efm, int len, efm_T *fmt_ptr, char *regpat)
    534  FUNC_ATTR_NONNULL_ALL
    535 {
    536  // Build regexp pattern from current 'errorformat' option
    537  char *ptr = regpat;
    538  *ptr++ = '^';
    539  int round = 0;
    540  for (const char *efmp = efm; efmp < efm + len; efmp++) {
    541    if (*efmp == '%') {
    542      efmp++;
    543      int idx;
    544      for (idx = 0; idx < FMT_PATTERNS; idx++) {
    545        if (fmt_pat[idx].convchar == *efmp) {
    546          break;
    547        }
    548      }
    549      if (idx < FMT_PATTERNS) {
    550        ptr = efmpat_to_regpat(efmp, ptr, fmt_ptr, idx, round);
    551        if (ptr == NULL) {
    552          return FAIL;
    553        }
    554        round++;
    555      } else if (*efmp == '*') {
    556        efmp++;
    557        ptr = scanf_fmt_to_regpat(&efmp, efm, len, ptr);
    558        if (ptr == NULL) {
    559          return FAIL;
    560        }
    561      } else if (vim_strchr("%\\.^$~[", (uint8_t)(*efmp)) != NULL) {
    562        *ptr++ = *efmp;  // regexp magic characters
    563      } else if (*efmp == '#') {
    564        *ptr++ = '*';
    565      } else if (*efmp == '>') {
    566        fmt_ptr->conthere = true;
    567      } else if (efmp == efm + 1) {             // analyse prefix
    568        // prefix is allowed only at the beginning of the errorformat
    569        // option part
    570        efmp = efm_analyze_prefix(efmp, fmt_ptr);
    571        if (efmp == NULL) {
    572          return FAIL;
    573        }
    574      } else {
    575        semsg(_("E377: Invalid %%%c in format string"), *efmp);
    576        return FAIL;
    577      }
    578    } else {                    // copy normal character
    579      if (*efmp == '\\' && efmp + 1 < efm + len) {
    580        efmp++;
    581      } else if (vim_strchr(".*^$~[", (uint8_t)(*efmp)) != NULL) {
    582        *ptr++ = '\\';  // escape regexp atoms
    583      }
    584      if (*efmp) {
    585        *ptr++ = *efmp;
    586      }
    587    }
    588  }
    589  *ptr++ = '$';
    590  *ptr = NUL;
    591 
    592  return OK;
    593 }
    594 
    595 static efm_T *fmt_start = NULL;  // cached across qf_parse_line() calls
    596 
    597 // callback function for 'quickfixtextfunc'
    598 static Callback qftf_cb;
    599 
    600 static void free_efm_list(efm_T **efm_first)
    601 {
    602  for (efm_T *efm_ptr = *efm_first; efm_ptr != NULL; efm_ptr = *efm_first) {
    603    *efm_first = efm_ptr->next;
    604    vim_regfree(efm_ptr->prog);
    605    xfree(efm_ptr);
    606  }
    607 
    608  fmt_start = NULL;
    609 }
    610 
    611 /// Compute the size of the buffer used to convert a 'errorformat' pattern into
    612 /// a regular expression pattern.
    613 static size_t efm_regpat_bufsz(char *efm)
    614 {
    615  size_t sz = (FMT_PATTERNS * 3) + (strlen(efm) << 2);
    616  for (int i = FMT_PATTERNS - 1; i >= 0;) {
    617    sz += strlen(fmt_pat[i--].pattern);
    618  }
    619 #ifdef BACKSLASH_IN_FILENAME
    620  sz += 12;  // "%f" can become twelve chars longer (see efm_to_regpat)
    621 #else
    622  sz += 2;  // "%f" can become two chars longer
    623 #endif
    624 
    625  return sz;
    626 }
    627 
    628 /// Return the length of a 'errorformat' option part (separated by ",").
    629 static int efm_option_part_len(const char *efm)
    630 {
    631  int len;
    632 
    633  for (len = 0; efm[len] != NUL && efm[len] != ','; len++) {
    634    if (efm[len] == '\\' && efm[len + 1] != NUL) {
    635      len++;
    636    }
    637  }
    638 
    639  return len;
    640 }
    641 
    642 /// Parse the 'errorformat' option. Multiple parts in the 'errorformat' option
    643 /// are parsed and converted to regular expressions. Returns information about
    644 /// the parsed 'errorformat' option.
    645 static efm_T *parse_efm_option(char *efm)
    646 {
    647  efm_T *fmt_first = NULL;
    648  efm_T *fmt_last = NULL;
    649 
    650  // Get some space to modify the format string into.
    651  size_t sz = efm_regpat_bufsz(efm);
    652  char *fmtstr = xmalloc(sz);
    653 
    654  while (efm[0] != NUL) {
    655    // Allocate a new eformat structure and put it at the end of the list
    656    efm_T *fmt_ptr = (efm_T *)xcalloc(1, sizeof(efm_T));
    657    if (fmt_first == NULL) {        // first one
    658      fmt_first = fmt_ptr;
    659    } else {
    660      fmt_last->next = fmt_ptr;
    661    }
    662    fmt_last = fmt_ptr;
    663 
    664    // Isolate one part in the 'errorformat' option
    665    int len = efm_option_part_len(efm);
    666 
    667    if (efm_to_regpat(efm, len, fmt_ptr, fmtstr) == FAIL) {
    668      goto parse_efm_error;
    669    }
    670    if ((fmt_ptr->prog = vim_regcomp(fmtstr, RE_MAGIC + RE_STRING)) == NULL) {
    671      goto parse_efm_error;
    672    }
    673    // Advance to next part
    674    efm = skip_to_option_part(efm + len);       // skip comma and spaces
    675  }
    676 
    677  if (fmt_first == NULL) {      // nothing found
    678    emsg(_("E378: 'errorformat' contains no pattern"));
    679  }
    680 
    681  goto parse_efm_end;
    682 
    683 parse_efm_error:
    684  free_efm_list(&fmt_first);
    685 
    686 parse_efm_end:
    687  xfree(fmtstr);
    688 
    689  return fmt_first;
    690 }
    691 
    692 /// Allocate more memory for the line buffer used for parsing lines.
    693 static char *qf_grow_linebuf(qfstate_T *state, size_t newsz)
    694 {
    695  // If the line exceeds LINE_MAXLEN exclude the last
    696  // byte since it's not a NL character.
    697  state->linelen = newsz > LINE_MAXLEN ? LINE_MAXLEN - 1 : newsz;
    698  if (state->growbuf == NULL) {
    699    state->growbuf = xmalloc(state->linelen + 1);
    700    state->growbufsiz = state->linelen;
    701  } else if (state->linelen > state->growbufsiz) {
    702    state->growbuf = xrealloc(state->growbuf, state->linelen + 1);
    703    state->growbufsiz = state->linelen;
    704  }
    705  return state->growbuf;
    706 }
    707 
    708 /// Get the next string (separated by newline) from state->p_str.
    709 static int qf_get_next_str_line(qfstate_T *state)
    710 {
    711  // Get the next line from the supplied string
    712  char *p_str = state->p_str;
    713 
    714  if (*p_str == NUL) {  // Reached the end of the string
    715    return QF_END_OF_INPUT;
    716  }
    717 
    718  char *p = vim_strchr(p_str, '\n');
    719  size_t len = (p != NULL) ? (size_t)(p - p_str) + 1 : strlen(p_str);
    720 
    721  if (len > IOSIZE - 2) {
    722    state->linebuf = qf_grow_linebuf(state, len);
    723  } else {
    724    state->linebuf = IObuff;
    725    state->linelen = len;
    726  }
    727  memcpy(state->linebuf, p_str, state->linelen);
    728  state->linebuf[state->linelen] = NUL;
    729 
    730  // Increment using len in order to discard the rest of the line if it
    731  // exceeds LINE_MAXLEN.
    732  p_str += len;
    733  state->p_str = p_str;
    734 
    735  return QF_OK;
    736 }
    737 
    738 /// Get the next string from the List item state->p_li.
    739 static int qf_get_next_list_line(qfstate_T *state)
    740 {
    741  listitem_T *p_li = state->p_li;
    742 
    743  // Get the next line from the supplied list
    744  while (p_li != NULL
    745         && (TV_LIST_ITEM_TV(p_li)->v_type != VAR_STRING
    746             || TV_LIST_ITEM_TV(p_li)->vval.v_string == NULL)) {
    747    p_li = TV_LIST_ITEM_NEXT(state->p_list, p_li);  // Skip non-string items.
    748  }
    749 
    750  if (p_li == NULL) {  // End of the list.
    751    state->p_li = NULL;
    752    return QF_END_OF_INPUT;
    753  }
    754 
    755  size_t len = strlen(TV_LIST_ITEM_TV(p_li)->vval.v_string);
    756  if (len > IOSIZE - 2) {
    757    state->linebuf = qf_grow_linebuf(state, len);
    758  } else {
    759    state->linebuf = IObuff;
    760    state->linelen = len;
    761  }
    762 
    763  xstrlcpy(state->linebuf, TV_LIST_ITEM_TV(p_li)->vval.v_string,
    764           state->linelen + 1);
    765 
    766  state->p_li = TV_LIST_ITEM_NEXT(state->p_list, p_li);
    767  return QF_OK;
    768 }
    769 
    770 /// Get the next string from state->buf.
    771 static int qf_get_next_buf_line(qfstate_T *state)
    772 {
    773  // Get the next line from the supplied buffer
    774  if (state->buflnum > state->lnumlast) {
    775    return QF_END_OF_INPUT;
    776  }
    777  char *p_buf = ml_get_buf(state->buf, state->buflnum);
    778  size_t len = (size_t)ml_get_buf_len(state->buf, state->buflnum);
    779  state->buflnum += 1;
    780 
    781  if (len > IOSIZE - 2) {
    782    state->linebuf = qf_grow_linebuf(state, len);
    783  } else {
    784    state->linebuf = IObuff;
    785    state->linelen = len;
    786  }
    787  xstrlcpy(state->linebuf, p_buf, state->linelen + 1);
    788 
    789  return QF_OK;
    790 }
    791 
    792 /// Get the next string from file state->fd.
    793 static int qf_get_next_file_line(qfstate_T *state)
    794 {
    795 retry:
    796  errno = 0;
    797  if (fgets(IObuff, IOSIZE, state->fd) == NULL) {
    798    if (errno == EINTR) {
    799      goto retry;
    800    }
    801    return QF_END_OF_INPUT;
    802  }
    803 
    804  bool discard = false;
    805  state->linelen = strlen(IObuff);
    806  if (state->linelen == IOSIZE - 1
    807      && !(IObuff[state->linelen - 1] == '\n')) {
    808    // The current line exceeds IObuff, continue reading using growbuf
    809    // until EOL or LINE_MAXLEN bytes is read.
    810    if (state->growbuf == NULL) {
    811      state->growbufsiz = 2 * (IOSIZE - 1);
    812      state->growbuf = xmalloc(state->growbufsiz);
    813    }
    814 
    815    // Copy the read part of the line, excluding null-terminator
    816    memcpy(state->growbuf, IObuff, IOSIZE - 1);
    817    size_t growbuflen = state->linelen;
    818 
    819    while (true) {
    820      errno = 0;
    821      if (fgets(state->growbuf + growbuflen,
    822                (int)(state->growbufsiz - growbuflen), state->fd) == NULL) {
    823        if (errno == EINTR) {
    824          continue;
    825        }
    826        break;
    827      }
    828      state->linelen = strlen(state->growbuf + growbuflen);
    829      growbuflen += state->linelen;
    830      if (state->growbuf[growbuflen - 1] == '\n') {
    831        break;
    832      }
    833      if (state->growbufsiz == LINE_MAXLEN) {
    834        discard = true;
    835        break;
    836      }
    837 
    838      state->growbufsiz = MIN(2 * state->growbufsiz, LINE_MAXLEN);
    839      state->growbuf = xrealloc(state->growbuf, state->growbufsiz);
    840    }
    841 
    842    while (discard) {
    843      // The current line is longer than LINE_MAXLEN, continue reading but
    844      // discard everything until EOL or EOF is reached.
    845      errno = 0;
    846      if (fgets(IObuff, IOSIZE, state->fd) == NULL) {
    847        if (errno == EINTR) {
    848          continue;
    849        }
    850        break;
    851      }
    852      if (strlen(IObuff) < IOSIZE - 1 || IObuff[IOSIZE - 2] == '\n') {
    853        break;
    854      }
    855    }
    856 
    857    state->linebuf = state->growbuf;
    858    state->linelen = growbuflen;
    859  } else {
    860    state->linebuf = IObuff;
    861  }
    862 
    863  // Convert a line if it contains a non-ASCII character
    864  if (state->vc.vc_type != CONV_NONE && has_non_ascii(state->linebuf)) {
    865    char *line = string_convert(&state->vc, state->linebuf, &state->linelen);
    866    if (line != NULL) {
    867      if (state->linelen < IOSIZE) {
    868        xstrlcpy(state->linebuf, line, state->linelen + 1);
    869        xfree(line);
    870      } else {
    871        xfree(state->growbuf);
    872        state->linebuf = line;
    873        state->growbuf = line;
    874        state->growbufsiz = MIN(state->linelen, LINE_MAXLEN);
    875      }
    876    }
    877  }
    878  return QF_OK;
    879 }
    880 
    881 /// Get the next string from a file/buffer/list/string.
    882 static int qf_get_nextline(qfstate_T *state)
    883 {
    884  int status = QF_FAIL;
    885 
    886  if (state->fd == NULL) {
    887    if (state->tv != NULL) {
    888      if (state->tv->v_type == VAR_STRING) {
    889        // Get the next line from the supplied string
    890        status = qf_get_next_str_line(state);
    891      } else if (state->tv->v_type == VAR_LIST) {
    892        // Get the next line from the supplied list
    893        status = qf_get_next_list_line(state);
    894      }
    895    } else {
    896      // Get the next line from the supplied buffer
    897      status = qf_get_next_buf_line(state);
    898    }
    899  } else {
    900    // Get the next line from the supplied file
    901    status = qf_get_next_file_line(state);
    902  }
    903 
    904  if (status != QF_OK) {
    905    return status;
    906  }
    907 
    908  if (state->linelen > 0 && state->linebuf[state->linelen - 1] == '\n') {
    909    state->linebuf[state->linelen - 1] = NUL;
    910 #ifdef USE_CRNL
    911    if (state->linelen > 1 && state->linebuf[state->linelen - 2] == '\r') {
    912      state->linebuf[state->linelen - 2] = NUL;
    913    }
    914 #endif
    915  }
    916 
    917  remove_bom(state->linebuf);
    918 
    919  return QF_OK;
    920 }
    921 
    922 /// Returns true if the specified quickfix/location stack is empty
    923 static bool qf_stack_empty(const qf_info_T *qi)
    924  FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
    925 {
    926  return qi == NULL || qi->qf_listcount <= 0;
    927 }
    928 
    929 /// Returns true if the specified quickfix/location list is empty.
    930 static bool qf_list_empty(qf_list_T *qfl)
    931  FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
    932 {
    933  return qfl == NULL || qfl->qf_count <= 0;
    934 }
    935 
    936 /// Returns true if the specified quickfix/location list is not empty and
    937 /// has valid entries.
    938 static bool qf_list_has_valid_entries(qf_list_T *qfl)
    939 {
    940  return !qf_list_empty(qfl) && !qfl->qf_nonevalid;
    941 }
    942 
    943 /// Return a pointer to a list in the specified quickfix stack
    944 static qf_list_T *qf_get_list(qf_info_T *qi, int idx)
    945  FUNC_ATTR_NONNULL_ALL
    946 {
    947  return &qi->qf_lists[idx];
    948 }
    949 
    950 /// Parse a line and get the quickfix fields.
    951 /// Return the QF_ status.
    952 static int qf_parse_line(qf_list_T *qfl, char *linebuf, size_t linelen, efm_T *fmt_first,
    953                         qffields_T *fields)
    954 {
    955  efm_T *fmt_ptr;
    956  int idx = 0;
    957  char *tail = NULL;
    958  int status;
    959 
    960 restofline:
    961  // If there was no %> item start at the first pattern
    962  if (fmt_start == NULL) {
    963    fmt_ptr = fmt_first;
    964  } else {
    965    // Otherwise start from the last used pattern.
    966    fmt_ptr = fmt_start;
    967    fmt_start = NULL;
    968  }
    969 
    970  // Try to match each part of 'errorformat' until we find a complete
    971  // match or no match.
    972  fields->valid = true;
    973  for (; fmt_ptr != NULL; fmt_ptr = fmt_ptr->next) {
    974    idx = (uint8_t)fmt_ptr->prefix;
    975    status = qf_parse_get_fields(linebuf, linelen, fmt_ptr, fields,
    976                                 qfl->qf_multiline, qfl->qf_multiscan,
    977                                 &tail);
    978    if (status == QF_NOMEM) {
    979      return status;
    980    }
    981    if (status == QF_OK) {
    982      break;
    983    }
    984  }
    985  qfl->qf_multiscan = false;
    986 
    987  if (fmt_ptr == NULL || idx == 'D' || idx == 'X') {
    988    if (fmt_ptr != NULL) {
    989      // 'D' and 'X' directory specifiers.
    990      status = qf_parse_dir_pfx(idx, fields, qfl);
    991      if (status != QF_OK) {
    992        return status;
    993      }
    994    }
    995    status = qf_parse_line_nomatch(linebuf, linelen, fields);
    996    if (status != QF_OK) {
    997      return status;
    998    }
    999    if (fmt_ptr == NULL) {
   1000      qfl->qf_multiline = qfl->qf_multiignore = false;
   1001    }
   1002  } else {
   1003    // honor %> item
   1004    if (fmt_ptr->conthere) {
   1005      fmt_start = fmt_ptr;
   1006    }
   1007 
   1008    if (vim_strchr("AEWIN", idx) != NULL) {
   1009      qfl->qf_multiline = true;     // start of a multi-line message
   1010      qfl->qf_multiignore = false;  // reset continuation
   1011    } else if (vim_strchr("CZ", idx) != NULL) {
   1012      // continuation of multi-line msg
   1013      status = qf_parse_multiline_pfx(idx, qfl, fields);
   1014      if (status != QF_OK) {
   1015        return status;
   1016      }
   1017    } else if (vim_strchr("OPQ", idx) != NULL) {
   1018      // global file names
   1019      status = qf_parse_file_pfx(idx, fields, qfl, tail);
   1020      if (status == QF_MULTISCAN) {
   1021        goto restofline;
   1022      }
   1023    }
   1024    if (fmt_ptr->flags == '-') {  // generally exclude this line
   1025      if (qfl->qf_multiline) {
   1026        // also exclude continuation lines
   1027        qfl->qf_multiignore = true;
   1028      }
   1029      return QF_IGNORE_LINE;
   1030    }
   1031  }
   1032 
   1033  return QF_OK;
   1034 }
   1035 
   1036 // Allocate the fields used for parsing lines and populating a quickfix list.
   1037 static void qf_alloc_fields(qffields_T *pfields)
   1038  FUNC_ATTR_NONNULL_ALL
   1039 {
   1040  pfields->namebuf = xmalloc(CMDBUFFSIZE + 1);
   1041  pfields->module = xmalloc(CMDBUFFSIZE + 1);
   1042  pfields->errmsglen = CMDBUFFSIZE + 1;
   1043  pfields->errmsg = xmalloc(pfields->errmsglen);
   1044  pfields->pattern = xmalloc(CMDBUFFSIZE + 1);
   1045 }
   1046 
   1047 // Free the fields used for parsing lines and populating a quickfix list.
   1048 static void qf_free_fields(qffields_T *pfields)
   1049  FUNC_ATTR_NONNULL_ALL
   1050 {
   1051  xfree(pfields->namebuf);
   1052  xfree(pfields->module);
   1053  xfree(pfields->errmsg);
   1054  xfree(pfields->pattern);
   1055 }
   1056 
   1057 // Setup the state information used for parsing lines and populating a
   1058 // quickfix list.
   1059 static int qf_setup_state(qfstate_T *pstate, char *restrict enc, const char *restrict efile,
   1060                          typval_T *tv, buf_T *buf, linenr_T lnumfirst, linenr_T lnumlast)
   1061  FUNC_ATTR_NONNULL_ARG(1)
   1062 {
   1063  pstate->vc.vc_type = CONV_NONE;
   1064  if (enc != NULL && *enc != NUL) {
   1065    convert_setup(&pstate->vc, enc, p_enc);
   1066  }
   1067 
   1068  if (efile != NULL
   1069      && (pstate->fd = (strequal(efile, "-")
   1070                        ? fdopen(os_open_stdin_fd(), "r")
   1071                        : os_fopen(efile, "r"))) == NULL) {
   1072    semsg(_(e_openerrf), efile);
   1073    return FAIL;
   1074  }
   1075 
   1076  if (tv != NULL) {
   1077    if (tv->v_type == VAR_STRING) {
   1078      pstate->p_str = tv->vval.v_string;
   1079    } else if (tv->v_type == VAR_LIST) {
   1080      pstate->p_li = tv_list_first(tv->vval.v_list);
   1081    }
   1082    pstate->tv = tv;
   1083  }
   1084  pstate->buf = buf;
   1085  pstate->buflnum = lnumfirst;
   1086  pstate->lnumlast = lnumlast;
   1087 
   1088  return OK;
   1089 }
   1090 
   1091 // Cleanup the state information used for parsing lines and populating a
   1092 // quickfix list.
   1093 static void qf_cleanup_state(qfstate_T *pstate)
   1094  FUNC_ATTR_NONNULL_ALL
   1095 {
   1096  if (pstate->fd != NULL) {
   1097    fclose(pstate->fd);
   1098  }
   1099  xfree(pstate->growbuf);
   1100  if (pstate->vc.vc_type != CONV_NONE) {
   1101    convert_setup(&pstate->vc, NULL, NULL);
   1102  }
   1103 }
   1104 
   1105 /// Read the errorfile "efile" into memory, line by line, building the error
   1106 /// list.
   1107 /// Alternative: when "efile" is NULL read errors from buffer "buf".
   1108 /// Alternative: when "tv" is not NULL get errors from the string or list.
   1109 /// Always use 'errorformat' from "buf" if there is a local value.
   1110 /// Then "lnumfirst" and "lnumlast" specify the range of lines to use.
   1111 /// Set the title of the list to "qf_title".
   1112 ///
   1113 /// @param newlist  true: start a new error list
   1114 /// @param lnumfirst  first line number to use
   1115 /// @param lnumlast  last line number to use
   1116 ///
   1117 /// @return  -1 for error, number of errors for success.
   1118 static int qf_init_ext(qf_info_T *qi, int qf_idx, const char *restrict efile, buf_T *buf,
   1119                       typval_T *tv, char *restrict errorformat, bool newlist, linenr_T lnumfirst,
   1120                       linenr_T lnumlast, const char *restrict qf_title, char *restrict enc)
   1121  FUNC_ATTR_NONNULL_ARG(1)
   1122 {
   1123  qfstate_T state = { 0 };
   1124  qffields_T fields = { 0 };
   1125  qfline_T *old_last = NULL;
   1126  static efm_T *fmt_first = NULL;
   1127  static char *last_efm = NULL;
   1128  int retval = -1;                      // default: return error flag
   1129 
   1130  // Do not used the cached buffer, it may have been wiped out.
   1131  XFREE_CLEAR(qf_last_bufname);
   1132 
   1133  qf_alloc_fields(&fields);
   1134  if (qf_setup_state(&state, enc, efile, tv, buf, lnumfirst, lnumlast) == FAIL) {
   1135    goto qf_init_end;
   1136  }
   1137 
   1138  qf_list_T *qfl;
   1139  bool adding = false;
   1140  if (newlist || qf_idx == qi->qf_listcount) {
   1141    // make place for a new list
   1142    qf_new_list(qi, qf_title);
   1143    qf_idx = qi->qf_curlist;
   1144    qfl = qf_get_list(qi, qf_idx);
   1145  } else {
   1146    // Adding to existing list, use last entry.
   1147    adding = true;
   1148    qfl = qf_get_list(qi, qf_idx);
   1149    if (!qf_list_empty(qfl)) {
   1150      old_last = qfl->qf_last;
   1151    }
   1152  }
   1153 
   1154  // Use the local value of 'errorformat' if it's set.
   1155  char *efm = (errorformat == p_efm && tv == NULL && buf && *buf->b_p_efm != NUL)
   1156              ? buf->b_p_efm
   1157              : errorformat;
   1158 
   1159  // If the errorformat didn't change between calls, then reuse the previously
   1160  // parsed values.
   1161  if (last_efm == NULL || (strcmp(last_efm, efm) != 0)) {
   1162    // free the previously parsed data
   1163    XFREE_CLEAR(last_efm);
   1164    free_efm_list(&fmt_first);
   1165 
   1166    // parse the current 'efm'
   1167    fmt_first = parse_efm_option(efm);
   1168    if (fmt_first != NULL) {
   1169      last_efm = xstrdup(efm);
   1170    }
   1171  }
   1172 
   1173  if (fmt_first == NULL) {      // nothing found
   1174    goto error2;
   1175  }
   1176 
   1177  // got_int is reset here, because it was probably set when killing the
   1178  // ":make" command, but we still want to read the errorfile then.
   1179  got_int = false;
   1180 
   1181  // Read the lines in the error file one by one.
   1182  // Try to recognize one of the error formats in each line.
   1183  while (!got_int) {
   1184    int status = qf_init_process_nextline(qfl, fmt_first, &state, &fields);
   1185    if (status == QF_END_OF_INPUT) {  // end of input
   1186      break;
   1187    }
   1188    if (status == QF_FAIL) {
   1189      goto error2;
   1190    }
   1191 
   1192    line_breakcheck();
   1193  }
   1194  if (state.fd == NULL || !ferror(state.fd)) {
   1195    if (qfl->qf_index == 0) {
   1196      // no valid entry found
   1197      qfl->qf_ptr = qfl->qf_start;
   1198      qfl->qf_index = 1;
   1199      qfl->qf_nonevalid = true;
   1200    } else {
   1201      qfl->qf_nonevalid = false;
   1202      if (qfl->qf_ptr == NULL) {
   1203        qfl->qf_ptr = qfl->qf_start;
   1204      }
   1205    }
   1206    // return number of matches
   1207    retval = qfl->qf_count;
   1208    goto qf_init_end;
   1209  }
   1210  emsg(_(e_readerrf));
   1211 error2:
   1212  if (!adding) {
   1213    // Error when creating a new list. Free the new list
   1214    qf_free(qfl);
   1215    qi->qf_listcount--;
   1216    if (qi->qf_curlist > 0) {
   1217      qi->qf_curlist--;
   1218    }
   1219  }
   1220 qf_init_end:
   1221  if (qf_idx == qi->qf_curlist) {
   1222    qf_update_buffer(qi, old_last);
   1223  }
   1224  qf_cleanup_state(&state);
   1225  qf_free_fields(&fields);
   1226 
   1227  return retval;
   1228 }
   1229 
   1230 /// Set the title of the specified quickfix list. Frees the previous title.
   1231 /// Prepends ':' to the title.
   1232 static void qf_store_title(qf_list_T *qfl, const char *title)
   1233  FUNC_ATTR_NONNULL_ARG(1)
   1234 {
   1235  XFREE_CLEAR(qfl->qf_title);
   1236 
   1237  if (title == NULL) {
   1238    return;
   1239  }
   1240 
   1241  size_t len = strlen(title) + 1;
   1242  char *p = xmallocz(len);
   1243 
   1244  qfl->qf_title = p;
   1245  xstrlcpy(p, title, len + 1);
   1246 }
   1247 
   1248 /// The title of a quickfix/location list is set, by default, to the command
   1249 /// that created the quickfix list with the ":" prefix.
   1250 /// Create a quickfix list title string by prepending ":" to a user command.
   1251 /// Returns a pointer to a static buffer with the title.
   1252 static char *qf_cmdtitle(const char *cmd)
   1253  FUNC_ATTR_NONNULL_ALL
   1254 {
   1255  static char qftitle_str[IOSIZE];
   1256 
   1257  snprintf(qftitle_str, IOSIZE, ":%s", cmd);
   1258 
   1259  return qftitle_str;
   1260 }
   1261 
   1262 /// Return a pointer to the current list in the specified quickfix stack
   1263 static qf_list_T *qf_get_curlist(qf_info_T *qi)
   1264  FUNC_ATTR_NONNULL_ALL
   1265 {
   1266  return qf_get_list(qi, qi->qf_curlist);
   1267 }
   1268 
   1269 /// Pop a quickfix list from the quickfix/location list stack
   1270 /// Automatically adjust qf_curlist so that it stays pointed
   1271 /// to the same list, unless it is deleted, if so then use the
   1272 /// newest created list instead. qf_listcount will be set correctly.
   1273 /// The above will only happen if <adjust> is true.
   1274 static void qf_pop_stack(qf_info_T *qi, bool adjust)
   1275 {
   1276  qf_free(&qi->qf_lists[0]);
   1277  for (int i = 1; i < qi->qf_listcount; i++) {
   1278    qi->qf_lists[i - 1] = qi->qf_lists[i];
   1279  }
   1280 
   1281  // fill with zeroes now unused list at the top
   1282  memset(qi->qf_lists + qi->qf_listcount - 1, 0, sizeof(*qi->qf_lists));
   1283 
   1284  if (adjust) {
   1285    qi->qf_listcount--;
   1286    if (qi->qf_curlist == 0) {
   1287      qi->qf_curlist = qi->qf_listcount - 1;
   1288    } else {
   1289      qi->qf_curlist--;
   1290    }
   1291  }
   1292 }
   1293 
   1294 /// Prepare for adding a new quickfix list. If the current list is in the
   1295 /// middle of the stack, then all the following lists are freed and then
   1296 /// the new list is added.
   1297 static void qf_new_list(qf_info_T *qi, const char *qf_title)
   1298 {
   1299  // If the current entry is not the last entry, delete entries beyond
   1300  // the current entry.  This makes it possible to browse in a tree-like
   1301  // way with ":grep".
   1302  while (qi->qf_listcount > qi->qf_curlist + 1) {
   1303    qf_free(&qi->qf_lists[--qi->qf_listcount]);
   1304  }
   1305 
   1306  // When the stack is full, remove to oldest entry
   1307  // Otherwise, add a new entry.
   1308  if (qi->qf_listcount == qi->qf_maxcount) {
   1309    qf_pop_stack(qi, false);
   1310    qi->qf_curlist = qi->qf_listcount - 1;  // point to new empty list
   1311  } else {
   1312    qi->qf_curlist = qi->qf_listcount++;
   1313  }
   1314 
   1315  qf_list_T *qfl = qf_get_curlist(qi);
   1316  CLEAR_POINTER(qfl);
   1317  qf_store_title(qfl, qf_title);
   1318  qfl->qfl_type = qi->qfl_type;
   1319  qfl->qf_id = ++last_qf_id;
   1320  qfl->qf_has_user_data = false;
   1321 }
   1322 
   1323 /// Parse the match for filename ('%f') pattern in regmatch.
   1324 /// Return the matched value in "fields->namebuf".
   1325 static int qf_parse_fmt_f(regmatch_T *rmp, int midx, qffields_T *fields, int prefix)
   1326 {
   1327  if (rmp->startp[midx] == NULL || rmp->endp[midx] == NULL) {
   1328    return QF_FAIL;
   1329  }
   1330 
   1331  // Expand ~/file and $HOME/file to full path.
   1332  char c = *rmp->endp[midx];
   1333  *rmp->endp[midx] = NUL;
   1334  expand_env(rmp->startp[midx], fields->namebuf, CMDBUFFSIZE);
   1335  *rmp->endp[midx] = c;
   1336 
   1337  // For separate filename patterns (%O, %P and %Q), the specified file
   1338  // should exist.
   1339  if (vim_strchr("OPQ", prefix) != NULL
   1340      && !os_path_exists(fields->namebuf)) {
   1341    return QF_FAIL;
   1342  }
   1343 
   1344  return QF_OK;
   1345 }
   1346 
   1347 /// Parse the match for buffer number ('%b') pattern in regmatch.
   1348 /// Return the matched value in "fields->bnr".
   1349 static int qf_parse_fmt_b(regmatch_T *rmp, int midx, qffields_T *fields)
   1350 {
   1351  if (rmp->startp[midx] == NULL) {
   1352    return QF_FAIL;
   1353  }
   1354  int bnr = (int)atol(rmp->startp[midx]);
   1355  if (buflist_findnr(bnr) == NULL) {
   1356    return QF_FAIL;
   1357  }
   1358  fields->bnr = bnr;
   1359  return QF_OK;
   1360 }
   1361 
   1362 /// Parse the match for error number ('%n') pattern in regmatch.
   1363 /// Return the matched value in "fields->enr".
   1364 static int qf_parse_fmt_n(regmatch_T *rmp, int midx, qffields_T *fields)
   1365 {
   1366  if (rmp->startp[midx] == NULL) {
   1367    return QF_FAIL;
   1368  }
   1369  fields->enr = (int)atol(rmp->startp[midx]);
   1370  return QF_OK;
   1371 }
   1372 
   1373 /// Parse the match for line number ('%l') pattern in regmatch.
   1374 /// Return the matched value in "fields->lnum".
   1375 static int qf_parse_fmt_l(regmatch_T *rmp, int midx, qffields_T *fields)
   1376 {
   1377  if (rmp->startp[midx] == NULL) {
   1378    return QF_FAIL;
   1379  }
   1380  fields->lnum = (linenr_T)atol(rmp->startp[midx]);
   1381  return QF_OK;
   1382 }
   1383 
   1384 /// Parse the match for end line number ('%e') pattern in regmatch.
   1385 /// Return the matched value in "fields->end_lnum".
   1386 static int qf_parse_fmt_e(regmatch_T *rmp, int midx, qffields_T *fields)
   1387 {
   1388  if (rmp->startp[midx] == NULL) {
   1389    return QF_FAIL;
   1390  }
   1391  fields->end_lnum = (linenr_T)atol(rmp->startp[midx]);
   1392  return QF_OK;
   1393 }
   1394 
   1395 /// Parse the match for column number ('%c') pattern in regmatch.
   1396 /// Return the matched value in "fields->col".
   1397 static int qf_parse_fmt_c(regmatch_T *rmp, int midx, qffields_T *fields)
   1398 {
   1399  if (rmp->startp[midx] == NULL) {
   1400    return QF_FAIL;
   1401  }
   1402  fields->col = (int)atol(rmp->startp[midx]);
   1403  return QF_OK;
   1404 }
   1405 
   1406 /// Parse the match for end line number ('%e') pattern in regmatch.
   1407 /// Return the matched value in "fields->end_lnum".
   1408 static int qf_parse_fmt_k(regmatch_T *rmp, int midx, qffields_T *fields)
   1409 {
   1410  if (rmp->startp[midx] == NULL) {
   1411    return QF_FAIL;
   1412  }
   1413  fields->end_col = (int)atol(rmp->startp[midx]);
   1414  return QF_OK;
   1415 }
   1416 
   1417 /// Parse the match for error type ('%t') pattern in regmatch.
   1418 /// Return the matched value in "fields->type".
   1419 static int qf_parse_fmt_t(regmatch_T *rmp, int midx, qffields_T *fields)
   1420 {
   1421  if (rmp->startp[midx] == NULL) {
   1422    return QF_FAIL;
   1423  }
   1424  fields->type = *rmp->startp[midx];
   1425  return QF_OK;
   1426 }
   1427 
   1428 /// Copy a non-error line into the error string.  Return the matched line in
   1429 /// "fields->errmsg".
   1430 static int copy_nonerror_line(const char *linebuf, size_t linelen, qffields_T *fields)
   1431  FUNC_ATTR_NONNULL_ALL
   1432 {
   1433  if (linelen >= fields->errmsglen) {
   1434    // linelen + null terminator
   1435    fields->errmsg = xrealloc(fields->errmsg, linelen + 1);
   1436    fields->errmsglen = linelen + 1;
   1437  }
   1438  // copy whole line to error message
   1439  xstrlcpy(fields->errmsg, linebuf, linelen + 1);
   1440 
   1441  return QF_OK;
   1442 }
   1443 
   1444 /// Parse the match for error message ('%m') pattern in regmatch.
   1445 /// Return the matched value in "fields->errmsg".
   1446 static int qf_parse_fmt_m(regmatch_T *rmp, int midx, qffields_T *fields)
   1447 {
   1448  if (rmp->startp[midx] == NULL || rmp->endp[midx] == NULL) {
   1449    return QF_FAIL;
   1450  }
   1451  size_t len = (size_t)(rmp->endp[midx] - rmp->startp[midx]);
   1452  if (len >= fields->errmsglen) {
   1453    // len + null terminator
   1454    fields->errmsg = xrealloc(fields->errmsg, len + 1);
   1455    fields->errmsglen = len + 1;
   1456  }
   1457  xstrlcpy(fields->errmsg, rmp->startp[midx], len + 1);
   1458  return QF_OK;
   1459 }
   1460 
   1461 /// Parse the match for rest of a single-line file message ('%r') pattern.
   1462 /// Return the matched value in "tail".
   1463 static int qf_parse_fmt_r(regmatch_T *rmp, int midx, char **tail)
   1464 {
   1465  if (rmp->startp[midx] == NULL) {
   1466    return QF_FAIL;
   1467  }
   1468  *tail = rmp->startp[midx];
   1469  return QF_OK;
   1470 }
   1471 
   1472 /// Parse the match for the pointer line ('%p') pattern in regmatch.
   1473 /// Return the matched value in "fields->col".
   1474 static int qf_parse_fmt_p(regmatch_T *rmp, int midx, qffields_T *fields)
   1475 {
   1476  if (rmp->startp[midx] == NULL || rmp->endp[midx] == NULL) {
   1477    return QF_FAIL;
   1478  }
   1479  fields->col = 0;
   1480  for (char *match_ptr = rmp->startp[midx]; match_ptr != rmp->endp[midx];
   1481       match_ptr++) {
   1482    fields->col++;
   1483    if (*match_ptr == TAB) {
   1484      fields->col += 7;
   1485      fields->col -= fields->col % 8;
   1486    }
   1487  }
   1488  fields->col++;
   1489  fields->use_viscol = true;
   1490  return QF_OK;
   1491 }
   1492 
   1493 /// Parse the match for the virtual column number ('%v') pattern in regmatch.
   1494 /// Return the matched value in "fields->col".
   1495 static int qf_parse_fmt_v(regmatch_T *rmp, int midx, qffields_T *fields)
   1496 {
   1497  if (rmp->startp[midx] == NULL) {
   1498    return QF_FAIL;
   1499  }
   1500  fields->col = (int)atol(rmp->startp[midx]);
   1501  fields->use_viscol = true;
   1502  return QF_OK;
   1503 }
   1504 
   1505 /// Parse the match for the search text ('%s') pattern in regmatch.
   1506 /// Return the matched value in "fields->pattern".
   1507 static int qf_parse_fmt_s(regmatch_T *rmp, int midx, qffields_T *fields)
   1508 {
   1509  if (rmp->startp[midx] == NULL || rmp->endp[midx] == NULL) {
   1510    return QF_FAIL;
   1511  }
   1512  size_t len = (size_t)(rmp->endp[midx] - rmp->startp[midx]);
   1513  len = MIN(len, CMDBUFFSIZE - 5);
   1514  STRCPY(fields->pattern, "^\\V");
   1515  xstrlcat(fields->pattern, rmp->startp[midx], len + 4);
   1516  fields->pattern[len + 3] = '\\';
   1517  fields->pattern[len + 4] = '$';
   1518  fields->pattern[len + 5] = NUL;
   1519  return QF_OK;
   1520 }
   1521 
   1522 /// Parse the match for the module ('%o') pattern in regmatch.
   1523 /// Return the matched value in "fields->module".
   1524 static int qf_parse_fmt_o(regmatch_T *rmp, int midx, qffields_T *fields)
   1525 {
   1526  if (rmp->startp[midx] == NULL || rmp->endp[midx] == NULL) {
   1527    return QF_FAIL;
   1528  }
   1529  size_t len = (size_t)(rmp->endp[midx] - rmp->startp[midx]);
   1530  size_t dsize = strlen(fields->module) + len + 1;
   1531  dsize = MIN(dsize, CMDBUFFSIZE);
   1532  xstrlcat(fields->module, rmp->startp[midx], dsize);
   1533  return QF_OK;
   1534 }
   1535 
   1536 /// 'errorformat' format pattern parser functions.
   1537 /// The '%f' and '%r' formats are parsed differently from other formats.
   1538 /// See qf_parse_match() for details.
   1539 /// Keep in sync with fmt_pat[].
   1540 static int (*qf_parse_fmt[FMT_PATTERNS])(regmatch_T *, int, qffields_T *) = {
   1541  NULL,  // %f
   1542  qf_parse_fmt_b,
   1543  qf_parse_fmt_n,
   1544  qf_parse_fmt_l,
   1545  qf_parse_fmt_e,
   1546  qf_parse_fmt_c,
   1547  qf_parse_fmt_k,
   1548  qf_parse_fmt_t,
   1549  qf_parse_fmt_m,
   1550  NULL,  // %r
   1551  qf_parse_fmt_p,
   1552  qf_parse_fmt_v,
   1553  qf_parse_fmt_s,
   1554  qf_parse_fmt_o
   1555 };
   1556 
   1557 /// Parse the error format matches in 'regmatch' and set the values in 'fields'.
   1558 /// fmt_ptr contains the 'efm' format specifiers/prefixes that have a match.
   1559 /// Returns QF_OK if all the matches are successfully parsed. On failure,
   1560 /// returns QF_FAIL or QF_NOMEM.
   1561 static int qf_parse_match(char *linebuf, size_t linelen, efm_T *fmt_ptr, regmatch_T *regmatch,
   1562                          qffields_T *fields, int qf_multiline, int qf_multiscan, char **tail)
   1563 {
   1564  char idx = fmt_ptr->prefix;
   1565 
   1566  if ((idx == 'C' || idx == 'Z') && !qf_multiline) {
   1567    return QF_FAIL;
   1568  }
   1569  if (vim_strchr("EWIN", (uint8_t)idx) != NULL) {
   1570    fields->type = idx;
   1571  } else {
   1572    fields->type = 0;
   1573  }
   1574 
   1575  // Extract error message data from matched line.
   1576  // We check for an actual submatch, because "\[" and "\]" in
   1577  // the 'errorformat' may cause the wrong submatch to be used.
   1578  for (int i = 0; i < FMT_PATTERNS; i++) {
   1579    int status = QF_OK;
   1580    int midx = (int)fmt_ptr->addr[i];
   1581    if (i == 0 && midx > 0) {  // %f
   1582      status = qf_parse_fmt_f(regmatch, midx, fields, idx);
   1583    } else if (i == FMT_PATTERN_M) {
   1584      if (fmt_ptr->flags == '+' && !qf_multiscan) {  // %+
   1585        status = copy_nonerror_line(linebuf, linelen, fields);
   1586      } else if (midx > 0) {  // %m
   1587        status = qf_parse_fmt_m(regmatch, midx, fields);
   1588      }
   1589    } else if (i == FMT_PATTERN_R && midx > 0) {  // %r
   1590      status = qf_parse_fmt_r(regmatch, midx, tail);
   1591    } else if (midx > 0) {  // others
   1592      status = (qf_parse_fmt[i])(regmatch, midx, fields);
   1593    }
   1594 
   1595    if (status != QF_OK) {
   1596      return status;
   1597    }
   1598  }
   1599 
   1600  return QF_OK;
   1601 }
   1602 
   1603 /// Parse an error line in 'linebuf' using a single error format string in
   1604 /// 'fmt_ptr->prog' and return the matching values in 'fields'.
   1605 /// Returns QF_OK if the efm format matches completely and the fields are
   1606 /// successfully copied. Otherwise returns QF_FAIL or QF_NOMEM.
   1607 static int qf_parse_get_fields(char *linebuf, size_t linelen, efm_T *fmt_ptr, qffields_T *fields,
   1608                               int qf_multiline, int qf_multiscan, char **tail)
   1609 {
   1610  if (qf_multiscan && vim_strchr("OPQ", (uint8_t)fmt_ptr->prefix) == NULL) {
   1611    return QF_FAIL;
   1612  }
   1613 
   1614  fields->namebuf[0] = NUL;
   1615  fields->bnr = 0;
   1616  fields->module[0] = NUL;
   1617  fields->pattern[0] = NUL;
   1618  if (!qf_multiscan) {
   1619    fields->errmsg[0] = NUL;
   1620  }
   1621  fields->lnum = 0;
   1622  fields->end_lnum = 0;
   1623  fields->col = 0;
   1624  fields->end_col = 0;
   1625  fields->use_viscol = false;
   1626  fields->enr = -1;
   1627  fields->type = 0;
   1628  *tail = NULL;
   1629 
   1630  regmatch_T regmatch;
   1631  // Always ignore case when looking for a matching error.
   1632  regmatch.rm_ic = true;
   1633  regmatch.regprog = fmt_ptr->prog;
   1634  bool r = vim_regexec(&regmatch, linebuf, 0);
   1635  fmt_ptr->prog = regmatch.regprog;
   1636  int status = QF_FAIL;
   1637  if (r) {
   1638    status = qf_parse_match(linebuf, linelen, fmt_ptr, &regmatch, fields,
   1639                            qf_multiline, qf_multiscan, tail);
   1640  }
   1641 
   1642  return status;
   1643 }
   1644 
   1645 /// Parse directory error format prefixes (%D and %X).
   1646 /// Push and pop directories from the directory stack when scanning directory
   1647 /// names.
   1648 static int qf_parse_dir_pfx(int idx, qffields_T *fields, qf_list_T *qfl)
   1649 {
   1650  if (idx == 'D') {  // enter directory
   1651    if (*fields->namebuf == NUL) {
   1652      emsg(_("E379: Missing or empty directory name"));
   1653      return QF_FAIL;
   1654    }
   1655    qfl->qf_directory = qf_push_dir(fields->namebuf, &qfl->qf_dir_stack, false);
   1656    if (qfl->qf_directory == NULL) {
   1657      return QF_FAIL;
   1658    }
   1659  } else if (idx == 'X') {  // leave directory
   1660    qfl->qf_directory = qf_pop_dir(&qfl->qf_dir_stack);
   1661  }
   1662 
   1663  return QF_OK;
   1664 }
   1665 
   1666 /// Parse global file name error format prefixes (%O, %P and %Q).
   1667 static int qf_parse_file_pfx(int idx, qffields_T *fields, qf_list_T *qfl, char *tail)
   1668 {
   1669  fields->valid = false;
   1670  if (*fields->namebuf == NUL || os_path_exists(fields->namebuf)) {
   1671    if (*fields->namebuf && idx == 'P') {
   1672      qfl->qf_currfile = qf_push_dir(fields->namebuf, &qfl->qf_file_stack, true);
   1673    } else if (idx == 'Q') {
   1674      qfl->qf_currfile = qf_pop_dir(&qfl->qf_file_stack);
   1675    }
   1676    *fields->namebuf = NUL;
   1677    if (tail && *tail) {
   1678      STRMOVE(IObuff, skipwhite(tail));
   1679      qfl->qf_multiscan = true;
   1680      return QF_MULTISCAN;
   1681    }
   1682  }
   1683 
   1684  return QF_OK;
   1685 }
   1686 
   1687 /// Parse a non-error line (a line which doesn't match any of the error
   1688 /// format in 'efm').
   1689 static int qf_parse_line_nomatch(char *linebuf, size_t linelen, qffields_T *fields)
   1690 {
   1691  fields->namebuf[0] = NUL;   // no match found, remove file name
   1692  fields->lnum = 0;           // don't jump to this line
   1693  fields->valid = false;
   1694 
   1695  return copy_nonerror_line(linebuf, linelen, fields);
   1696 }
   1697 
   1698 /// Parse multi-line error format prefixes (%C and %Z)
   1699 static int qf_parse_multiline_pfx(int idx, qf_list_T *qfl, qffields_T *fields)
   1700 {
   1701  if (!qfl->qf_multiignore) {
   1702    qfline_T *qfprev = qfl->qf_last;
   1703 
   1704    if (qfprev == NULL) {
   1705      return QF_FAIL;
   1706    }
   1707    if (*fields->errmsg) {
   1708      size_t textlen = strlen(qfprev->qf_text);
   1709      size_t errlen = strlen(fields->errmsg);
   1710      qfprev->qf_text = xrealloc(qfprev->qf_text, textlen + errlen + 2);
   1711      qfprev->qf_text[textlen] = '\n';
   1712      STRCPY(qfprev->qf_text + textlen + 1, fields->errmsg);
   1713    }
   1714    if (qfprev->qf_nr == -1) {
   1715      qfprev->qf_nr = fields->enr;
   1716    }
   1717    if (vim_isprintc(fields->type) && !qfprev->qf_type) {
   1718      // only printable chars allowed
   1719      qfprev->qf_type = fields->type;
   1720    }
   1721 
   1722    if (!qfprev->qf_lnum) {
   1723      qfprev->qf_lnum = fields->lnum;
   1724    }
   1725    if (!qfprev->qf_end_lnum) {
   1726      qfprev->qf_end_lnum = fields->end_lnum;
   1727    }
   1728    if (!qfprev->qf_col) {
   1729      qfprev->qf_col = fields->col;
   1730      qfprev->qf_viscol = fields->use_viscol;
   1731    }
   1732    if (!qfprev->qf_end_col) {
   1733      qfprev->qf_end_col = fields->end_col;
   1734    }
   1735    if (!qfprev->qf_fnum) {
   1736      qfprev->qf_fnum = qf_get_fnum(qfl, qfl->qf_directory,
   1737                                    *fields->namebuf || qfl->qf_directory
   1738                                    ? fields->namebuf
   1739                                    : qfl->qf_currfile && fields->valid
   1740                                    ? qfl->qf_currfile : 0);
   1741    }
   1742  }
   1743  if (idx == 'Z') {
   1744    qfl->qf_multiline = qfl->qf_multiignore = false;
   1745  }
   1746  line_breakcheck();
   1747 
   1748  return QF_IGNORE_LINE;
   1749 }
   1750 
   1751 /// Queue location list stack delete request.
   1752 static void locstack_queue_delreq(qf_info_T *qi)
   1753 {
   1754  qf_delq_T *q = xmalloc(sizeof(qf_delq_T));
   1755  q->qi = qi;
   1756  q->next = qf_delq_head;
   1757  qf_delq_head = q;
   1758 }
   1759 
   1760 /// Return the global quickfix stack window buffer number.
   1761 int qf_stack_get_bufnr(void)
   1762 {
   1763  assert(ql_info != NULL);
   1764  return ql_info->qf_bufnr;
   1765 }
   1766 
   1767 /// Wipe the quickfix window buffer (if present) for the specified
   1768 /// quickfix/location list.
   1769 static void wipe_qf_buffer(qf_info_T *qi)
   1770  FUNC_ATTR_NONNULL_ALL
   1771 {
   1772  if (qi->qf_bufnr == INVALID_QFBUFNR) {
   1773    return;
   1774  }
   1775 
   1776  buf_T *const qfbuf = buflist_findnr(qi->qf_bufnr);
   1777  if (qfbuf != NULL && qfbuf->b_nwindows == 0) {
   1778    bool buf_was_null = false;
   1779    // can happen when curwin is going to be closed e.g. curwin->w_buffer
   1780    // was already closed in win_close(), and we are now closing the
   1781    // window related location list buffer from win_free_mem()
   1782    // but close_buffer() calls CHECK_CURBUF() macro and requires
   1783    // curwin->w_buffer == curbuf
   1784    if (curwin->w_buffer == NULL) {
   1785      curwin->w_buffer = curbuf;
   1786      buf_was_null = true;
   1787    }
   1788 
   1789    // If the quickfix buffer is not loaded in any window, then
   1790    // wipe the buffer.
   1791    close_buffer(NULL, qfbuf, DOBUF_WIPE, false, false);
   1792    qi->qf_bufnr = INVALID_QFBUFNR;
   1793    if (buf_was_null) {
   1794      curwin->w_buffer = NULL;
   1795    }
   1796  }
   1797 }
   1798 
   1799 /// Free all lists in the stack (not including the stack)
   1800 static void qf_free_list_stack_items(qf_info_T *qi)
   1801 {
   1802  for (int i = 0; i < qi->qf_listcount; i++) {
   1803    qf_free(qf_get_list(qi, i));
   1804  }
   1805 }
   1806 
   1807 /// Free a qf_info_T struct completely
   1808 static void qf_free_lists(qf_info_T *qi)
   1809 {
   1810  qf_free_list_stack_items(qi);
   1811 
   1812  xfree(qi->qf_lists);
   1813  xfree(qi);
   1814 }
   1815 
   1816 /// Free a location list stack
   1817 static void ll_free_all(qf_info_T **pqi)
   1818 {
   1819  qf_info_T *qi = *pqi;
   1820  if (qi == NULL) {
   1821    return;
   1822  }
   1823  *pqi = NULL;          // Remove reference to this list
   1824 
   1825  // If the location list is still in use, then queue the delete request
   1826  // to be processed later.
   1827  if (quickfix_busy > 0) {
   1828    locstack_queue_delreq(qi);
   1829    return;
   1830  }
   1831 
   1832  qi->qf_refcount--;
   1833  if (qi->qf_refcount < 1) {
   1834    // No references to this location list.
   1835    // If the quickfix window buffer is loaded, then wipe it
   1836    wipe_qf_buffer(qi);
   1837 
   1838    qf_free_lists(qi);
   1839  }
   1840 }
   1841 
   1842 /// Free all the quickfix/location lists in the stack.
   1843 void qf_free_all(win_T *wp)
   1844 {
   1845  qf_info_T *qi = ql_info;
   1846 
   1847  if (wp != NULL) {
   1848    // location list
   1849    ll_free_all(&wp->w_llist);
   1850    ll_free_all(&wp->w_llist_ref);
   1851  } else if (qi != NULL) {
   1852    qf_free_list_stack_items(qi);  // quickfix list
   1853  }
   1854 }
   1855 
   1856 /// Delay freeing of location list stacks when the quickfix code is running.
   1857 /// Used to avoid problems with autocmds freeing location list stacks when the
   1858 /// quickfix code is still referencing the stack.
   1859 /// Must always call decr_quickfix_busy() exactly once after this.
   1860 static void incr_quickfix_busy(void)
   1861 {
   1862  quickfix_busy++;
   1863 }
   1864 
   1865 /// Safe to free location list stacks. Process any delayed delete requests.
   1866 static void decr_quickfix_busy(void)
   1867 {
   1868  quickfix_busy--;
   1869  if (quickfix_busy == 0) {
   1870    // No longer referencing the location lists. Process all the pending
   1871    // delete requests.
   1872    while (qf_delq_head != NULL) {
   1873      qf_delq_T *q = qf_delq_head;
   1874 
   1875      qf_delq_head = q->next;
   1876      ll_free_all(&q->qi);
   1877      xfree(q);
   1878    }
   1879  }
   1880 #ifdef ABORT_ON_INTERNAL_ERROR
   1881  if (quickfix_busy < 0) {
   1882    emsg("quickfix_busy has become negative");
   1883    abort();
   1884  }
   1885 #endif
   1886 }
   1887 
   1888 #if defined(EXITFREE)
   1889 void check_quickfix_busy(void)
   1890 {
   1891  if (quickfix_busy != 0) {
   1892    semsg("quickfix_busy not zero on exit: %" PRId64, (int64_t)quickfix_busy);
   1893 # ifdef ABORT_ON_INTERNAL_ERROR
   1894    abort();
   1895 # endif
   1896  }
   1897 }
   1898 #endif
   1899 
   1900 /// Add an entry to the end of the list of errors.
   1901 ///
   1902 /// @param  qfl      quickfix list entry
   1903 /// @param  dir      optional directory name
   1904 /// @param  fname    file name or NULL
   1905 /// @param  module   module name or NULL
   1906 /// @param  bufnum   buffer number or zero
   1907 /// @param  mesg     message
   1908 /// @param  lnum     line number
   1909 /// @param  end_lnum  line number for end
   1910 /// @param  col      column
   1911 /// @param  end_col  column for end
   1912 /// @param  vis_col  using visual column
   1913 /// @param  pattern  search pattern
   1914 /// @param  nr       error number
   1915 /// @param  type     type character
   1916 /// @param  user_data  custom user data or NULL
   1917 /// @param  valid    valid entry
   1918 ///
   1919 /// @return  QF_OK on success or QF_FAIL on failure.
   1920 static int qf_add_entry(qf_list_T *qfl, char *dir, char *fname, char *module, int bufnum,
   1921                        char *mesg, linenr_T lnum, linenr_T end_lnum, int col, int end_col,
   1922                        char vis_col, char *pattern, int nr, char type, typval_T *user_data,
   1923                        char valid)
   1924 {
   1925  buf_T *buf;
   1926  qfline_T *qfp = xmalloc(sizeof(qfline_T));
   1927  char *fullname = NULL;
   1928  char *p = NULL;
   1929 
   1930  if (bufnum != 0) {
   1931    buf = buflist_findnr(bufnum);
   1932    qfp->qf_fnum = bufnum;
   1933    if (buf != NULL) {
   1934      buf->b_has_qf_entry |=
   1935        IS_QF_LIST(qfl) ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY;
   1936    }
   1937  } else {
   1938    qfp->qf_fnum = qf_get_fnum(qfl, dir, fname);
   1939    buf = buflist_findnr(qfp->qf_fnum);
   1940  }
   1941  if (fname != NULL) {
   1942    fullname = fix_fname(fname);
   1943  }
   1944  qfp->qf_fname = NULL;
   1945  if (buf != NULL && buf->b_ffname != NULL && fullname != NULL) {
   1946    if (path_fnamecmp(fullname, buf->b_ffname) != 0) {
   1947      p = path_try_shorten_fname(fullname);
   1948      if (p != NULL) {
   1949        qfp->qf_fname = xstrdup(p);
   1950      }
   1951    }
   1952  }
   1953  xfree(fullname);
   1954  qfp->qf_text = xstrdup(mesg);
   1955  qfp->qf_lnum = lnum;
   1956  qfp->qf_end_lnum = end_lnum;
   1957  qfp->qf_col = col;
   1958  qfp->qf_end_col = end_col;
   1959  qfp->qf_viscol = vis_col;
   1960  if (user_data == NULL || user_data->v_type == VAR_UNKNOWN) {
   1961    qfp->qf_user_data.v_type = VAR_UNKNOWN;
   1962  } else {
   1963    tv_copy(user_data, &qfp->qf_user_data);
   1964    qfl->qf_has_user_data = true;
   1965  }
   1966  if (pattern == NULL || *pattern == NUL) {
   1967    qfp->qf_pattern = NULL;
   1968  } else {
   1969    qfp->qf_pattern = xstrdup(pattern);
   1970  }
   1971  if (module == NULL || *module == NUL) {
   1972    qfp->qf_module = NULL;
   1973  } else {
   1974    qfp->qf_module = xstrdup(module);
   1975  }
   1976  qfp->qf_nr = nr;
   1977  if (type != 1 && !vim_isprintc(type)) {  // only printable chars allowed
   1978    type = 0;
   1979  }
   1980  qfp->qf_type = type;
   1981  qfp->qf_valid = valid;
   1982 
   1983  qfline_T **lastp = &qfl->qf_last;
   1984  if (qf_list_empty(qfl)) {
   1985    // first element in the list
   1986    qfl->qf_start = qfp;
   1987    qfl->qf_ptr = qfp;
   1988    qfl->qf_index = 0;
   1989    qfp->qf_prev = NULL;
   1990  } else {
   1991    assert(*lastp);
   1992    qfp->qf_prev = *lastp;
   1993    (*lastp)->qf_next = qfp;
   1994  }
   1995  qfp->qf_next = NULL;
   1996  qfp->qf_cleared = false;
   1997  *lastp = qfp;
   1998  qfl->qf_count++;
   1999  if (qfl->qf_index == 0 && qfp->qf_valid) {
   2000    // first valid entry
   2001    qfl->qf_index = qfl->qf_count;
   2002    qfl->qf_ptr = qfp;
   2003  }
   2004 
   2005  return QF_OK;
   2006 }
   2007 
   2008 /// Resize quickfix stack to be able to hold n amount of lists.
   2009 void qf_resize_stack(int n)
   2010 {
   2011  assert(ql_info != NULL);
   2012  qf_resize_stack_base(ql_info, n);
   2013 }
   2014 
   2015 /// Resize location list stack for window 'wp' to be able to hold n amount of lists.
   2016 void ll_resize_stack(win_T *wp, int n)
   2017 {
   2018  // check if given window is a location list window;
   2019  // if so then sync its 'lhistory' to the parent window or vice versa
   2020  if (IS_LL_WINDOW(wp)) {
   2021    qf_sync_llw_to_win(wp);
   2022  } else {
   2023    qf_sync_win_to_llw(wp);
   2024  }
   2025 
   2026  qf_info_T *qi = ll_get_or_alloc_list(wp);
   2027  qf_resize_stack_base(qi, n);
   2028 }
   2029 
   2030 /// Resize quickfix/location lists stack to be able to hold n amount of lists.
   2031 static void qf_resize_stack_base(qf_info_T *qi, int n)
   2032  FUNC_ATTR_NONNULL_ALL
   2033 {
   2034  int amount_to_rm = 0;
   2035  size_t lsz = sizeof(*qi->qf_lists);
   2036 
   2037  if (n == qi->qf_maxcount) {
   2038    return;
   2039  } else if (n < qi->qf_maxcount && n < qi->qf_listcount) {
   2040    // We have too many lists to store them all in the new stack,
   2041    // pop lists until we can fit them all in the newly resized stack
   2042    amount_to_rm = qi->qf_listcount - n;
   2043 
   2044    for (int i = 0; i < amount_to_rm; i++) {
   2045      qf_pop_stack(qi, true);
   2046    }
   2047  }
   2048 
   2049  qf_list_T *new = xrealloc(qi->qf_lists, lsz * (size_t)n);
   2050 
   2051  // fill with zeroes any newly allocated memory
   2052  if (n > qi->qf_maxcount) {
   2053    memset(new + qi->qf_maxcount, 0, lsz * (size_t)(n - qi->qf_maxcount));
   2054  }
   2055 
   2056  qi->qf_lists = new;
   2057  qi->qf_maxcount = n;
   2058 
   2059  qf_update_buffer(qi, NULL);
   2060 }
   2061 
   2062 /// Initialize quickfix list, should only be called once.
   2063 void qf_init_stack(void)
   2064 {
   2065  ql_info = qf_alloc_stack(QFLT_QUICKFIX, (int)p_chi);
   2066 }
   2067 
   2068 /// Sync a location list window's 'lhistory' value to the parent window
   2069 static void qf_sync_llw_to_win(win_T *llw)
   2070 {
   2071  win_T *wp = qf_find_win_with_loclist(llw->w_llist_ref);
   2072 
   2073  if (wp != NULL) {
   2074    wp->w_p_lhi = llw->w_p_lhi;
   2075  }
   2076 }
   2077 
   2078 /// Sync a window's 'lhistory' value to its location list window, if any
   2079 static void qf_sync_win_to_llw(win_T *pwp)
   2080 {
   2081  qf_info_T *llw = pwp->w_llist;
   2082 
   2083  if (llw != NULL) {
   2084    FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
   2085      if (wp->w_llist_ref == llw && bt_quickfix(wp->w_buffer)) {
   2086        wp->w_p_lhi = pwp->w_p_lhi;
   2087        return;
   2088      }
   2089    }
   2090  }
   2091 }
   2092 
   2093 /// Allocate a new quickfix/location list stack that is able to hold
   2094 /// up to n amount of lists
   2095 static qf_info_T *qf_alloc_stack(qfltype_T qfltype, int n)
   2096  FUNC_ATTR_NONNULL_RET
   2097 {
   2098  qf_info_T *qi;
   2099  if (qfltype == QFLT_QUICKFIX) {
   2100    qi = &ql_info_actual;
   2101  } else {
   2102    qi = xcalloc(1, sizeof(qf_info_T));
   2103    qi->qf_refcount++;
   2104  }
   2105  qi->qfl_type = qfltype;
   2106  qi->qf_bufnr = INVALID_QFBUFNR;
   2107  qi->qf_lists = qf_alloc_list_stack(n);
   2108  qi->qf_maxcount = n;
   2109 
   2110  return qi;
   2111 }
   2112 
   2113 /// Allocate memory for qf_lists member of qf_info_T struct.
   2114 static qf_list_T *qf_alloc_list_stack(int n)
   2115  FUNC_ATTR_NONNULL_RET
   2116 {
   2117  return xcalloc((size_t)n, sizeof(qf_list_T));
   2118 }
   2119 
   2120 /// Return the location list stack for window 'wp'.
   2121 /// If not present, allocate a location list stack
   2122 static qf_info_T *ll_get_or_alloc_list(win_T *wp)
   2123  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
   2124 {
   2125  if (IS_LL_WINDOW(wp)) {
   2126    // For a location list window, use the referenced location list
   2127    return wp->w_llist_ref;
   2128  }
   2129 
   2130  // For a non-location list window, w_llist_ref should not point to a
   2131  // location list.
   2132  ll_free_all(&wp->w_llist_ref);
   2133 
   2134  if (wp->w_llist == NULL) {
   2135    // new location list
   2136    wp->w_llist = qf_alloc_stack(QFLT_LOCATION, (int)wp->w_p_lhi);
   2137  }
   2138 
   2139  return wp->w_llist;
   2140 }
   2141 
   2142 /// Get the quickfix/location list stack to use for the specified Ex command.
   2143 /// For a location list command, returns the stack for the current window.  If
   2144 /// the location list is not found, then returns NULL and prints an error
   2145 /// message if 'print_emsg' is true.
   2146 static qf_info_T *qf_cmd_get_stack(exarg_T *eap, bool print_emsg)
   2147 {
   2148  qf_info_T *qi = ql_info;
   2149  assert(qi != NULL);
   2150 
   2151  if (is_loclist_cmd(eap->cmdidx)) {
   2152    qi = GET_LOC_LIST(curwin);
   2153    if (qi == NULL) {
   2154      if (print_emsg) {
   2155        emsg(_(e_loclist));
   2156      }
   2157      return NULL;
   2158    }
   2159  }
   2160 
   2161  return qi;
   2162 }
   2163 
   2164 /// Get the quickfix/location list stack to use for the specified Ex command.
   2165 /// For a location list command, returns the stack for the current window.
   2166 /// If the location list is not present, then allocates a new one.
   2167 /// For a location list command, sets 'pwinp' to curwin.
   2168 static qf_info_T *qf_cmd_get_or_alloc_stack(const exarg_T *eap, win_T **pwinp)
   2169  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
   2170 {
   2171  qf_info_T *qi = ql_info;
   2172 
   2173  if (is_loclist_cmd(eap->cmdidx)) {
   2174    qi = ll_get_or_alloc_list(curwin);
   2175    *pwinp = curwin;
   2176  }
   2177 
   2178  return qi;
   2179 }
   2180 
   2181 /// Copy location list entries from 'from_qfl' to 'to_qfl'.
   2182 static int copy_loclist_entries(const qf_list_T *from_qfl, qf_list_T *to_qfl)
   2183  FUNC_ATTR_NONNULL_ALL
   2184 {
   2185  int i;
   2186  qfline_T *from_qfp;
   2187 
   2188  // copy all the location entries in this list
   2189  FOR_ALL_QFL_ITEMS(from_qfl, from_qfp, i) {
   2190    if (qf_add_entry(to_qfl,
   2191                     NULL,
   2192                     NULL,
   2193                     from_qfp->qf_module,
   2194                     0,
   2195                     from_qfp->qf_text,
   2196                     from_qfp->qf_lnum,
   2197                     from_qfp->qf_end_lnum,
   2198                     from_qfp->qf_col,
   2199                     from_qfp->qf_end_col,
   2200                     from_qfp->qf_viscol,
   2201                     from_qfp->qf_pattern,
   2202                     from_qfp->qf_nr,
   2203                     0,
   2204                     &from_qfp->qf_user_data,
   2205                     from_qfp->qf_valid) == QF_FAIL) {
   2206      return FAIL;
   2207    }
   2208 
   2209    // qf_add_entry() will not set the qf_num field, as the
   2210    // directory and file names are not supplied. So the qf_fnum
   2211    // field is copied here.
   2212    qfline_T *const prevp = to_qfl->qf_last;
   2213    prevp->qf_fnum = from_qfp->qf_fnum;  // file number
   2214    prevp->qf_type = from_qfp->qf_type;  // error type
   2215    if (from_qfl->qf_ptr == from_qfp) {
   2216      to_qfl->qf_ptr = prevp;  // current location
   2217    }
   2218  }
   2219 
   2220  return OK;
   2221 }
   2222 
   2223 /// Copy the specified location list 'from_qfl' to 'to_qfl'.
   2224 static int copy_loclist(qf_list_T *from_qfl, qf_list_T *to_qfl)
   2225  FUNC_ATTR_NONNULL_ALL
   2226 {
   2227  // Some of the fields are populated by qf_add_entry()
   2228  to_qfl->qfl_type = from_qfl->qfl_type;
   2229  to_qfl->qf_nonevalid = from_qfl->qf_nonevalid;
   2230  to_qfl->qf_has_user_data = from_qfl->qf_has_user_data;
   2231  to_qfl->qf_count = 0;
   2232  to_qfl->qf_index = 0;
   2233  to_qfl->qf_start = NULL;
   2234  to_qfl->qf_last = NULL;
   2235  to_qfl->qf_ptr = NULL;
   2236  if (from_qfl->qf_title != NULL) {
   2237    to_qfl->qf_title = xstrdup(from_qfl->qf_title);
   2238  } else {
   2239    to_qfl->qf_title = NULL;
   2240  }
   2241  if (from_qfl->qf_ctx != NULL) {
   2242    to_qfl->qf_ctx = xcalloc(1, sizeof(*to_qfl->qf_ctx));
   2243    tv_copy(from_qfl->qf_ctx, to_qfl->qf_ctx);
   2244  } else {
   2245    to_qfl->qf_ctx = NULL;
   2246  }
   2247  callback_copy(&to_qfl->qf_qftf_cb, &from_qfl->qf_qftf_cb);
   2248 
   2249  if (from_qfl->qf_count) {
   2250    if (copy_loclist_entries(from_qfl, to_qfl) == FAIL) {
   2251      return FAIL;
   2252    }
   2253  }
   2254 
   2255  to_qfl->qf_index = from_qfl->qf_index;  // current index in the list
   2256 
   2257  // Assign a new ID for the location list
   2258  to_qfl->qf_id = ++last_qf_id;
   2259  to_qfl->qf_changedtick = 0;
   2260 
   2261  // When no valid entries are present in the list, qf_ptr points to
   2262  // the first item in the list
   2263  if (to_qfl->qf_nonevalid) {
   2264    to_qfl->qf_ptr = to_qfl->qf_start;
   2265    to_qfl->qf_index = 1;
   2266  }
   2267 
   2268  return OK;
   2269 }
   2270 
   2271 // Copy the location list stack 'from' window to 'to' window.
   2272 void copy_loclist_stack(win_T *from, win_T *to)
   2273  FUNC_ATTR_NONNULL_ALL
   2274 {
   2275  // When copying from a location list window, copy the referenced
   2276  // location list. For other windows, copy the location list for
   2277  // that window.
   2278  qf_info_T *qi = IS_LL_WINDOW(from) ? from->w_llist_ref : from->w_llist;
   2279 
   2280  if (qi == NULL) {                 // no location list to copy
   2281    return;
   2282  }
   2283 
   2284  // allocate a new location list, set size of stack to 'from' window value
   2285  to->w_llist = qf_alloc_stack(QFLT_LOCATION, (int)from->w_p_lhi);
   2286  // set 'to' lhi to reflect new value
   2287  to->w_p_lhi = to->w_llist->qf_maxcount;
   2288 
   2289  to->w_llist->qf_listcount = qi->qf_listcount;
   2290 
   2291  // Copy the location lists one at a time
   2292  for (int idx = 0; idx < qi->qf_listcount; idx++) {
   2293    to->w_llist->qf_curlist = idx;
   2294 
   2295    if (copy_loclist(qf_get_list(qi, idx),
   2296                     qf_get_list(to->w_llist, idx)) == FAIL) {
   2297      qf_free_all(to);
   2298      return;
   2299    }
   2300  }
   2301 
   2302  to->w_llist->qf_curlist = qi->qf_curlist;  // current list
   2303 }
   2304 
   2305 /// Get buffer number for file "directory/fname".
   2306 /// Also sets the b_has_qf_entry flag.
   2307 static int qf_get_fnum(qf_list_T *qfl, char *directory, char *fname)
   2308 {
   2309  char *ptr = NULL;
   2310  char *bufname;
   2311  buf_T *buf;
   2312  if (fname == NULL || *fname == NUL) {         // no file name
   2313    return 0;
   2314  }
   2315 
   2316 #ifdef BACKSLASH_IN_FILENAME
   2317  if (directory != NULL) {
   2318    slash_adjust(directory);
   2319  }
   2320  slash_adjust(fname);
   2321 #endif
   2322  if (directory != NULL && !vim_isAbsName(fname)) {
   2323    ptr = concat_fnames(directory, fname, true);
   2324    // Here we check if the file really exists.
   2325    // This should normally be true, but if make works without
   2326    // "leaving directory"-messages we might have missed a
   2327    // directory change.
   2328    if (!os_path_exists(ptr)) {
   2329      xfree(ptr);
   2330      directory = qf_guess_filepath(qfl, fname);
   2331      if (directory) {
   2332        ptr = concat_fnames(directory, fname, true);
   2333      } else {
   2334        ptr = xstrdup(fname);
   2335      }
   2336    }
   2337    // Use concatenated directory name and file name.
   2338    bufname = ptr;
   2339  } else {
   2340    bufname = fname;
   2341  }
   2342 
   2343  if (qf_last_bufname != NULL
   2344      && strcmp(bufname, qf_last_bufname) == 0
   2345      && bufref_valid(&qf_last_bufref)) {
   2346    buf = qf_last_bufref.br_buf;
   2347    xfree(ptr);
   2348  } else {
   2349    xfree(qf_last_bufname);
   2350    buf = buflist_new(bufname, NULL, 0, BLN_NOOPT);
   2351    qf_last_bufname = (bufname == ptr) ? bufname : xstrdup(bufname);
   2352    set_bufref(&qf_last_bufref, buf);
   2353  }
   2354  if (buf == NULL) {
   2355    return 0;
   2356  }
   2357  buf->b_has_qf_entry =
   2358    IS_QF_LIST(qfl) ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY;
   2359  return buf->b_fnum;
   2360 }
   2361 
   2362 // Push dirbuf onto the directory stack and return pointer to actual dir or
   2363 // NULL on error.
   2364 static char *qf_push_dir(char *dirbuf, struct dir_stack_T **stackptr, bool is_file_stack)
   2365 {
   2366  struct dir_stack_T *ds_ptr;
   2367 
   2368  // allocate new stack element and hook it in
   2369  struct dir_stack_T *ds_new = xmalloc(sizeof(struct dir_stack_T));
   2370 
   2371  ds_new->next = *stackptr;
   2372  *stackptr = ds_new;
   2373 
   2374  // store directory on the stack
   2375  if (vim_isAbsName(dirbuf)
   2376      || (*stackptr)->next == NULL
   2377      || is_file_stack) {
   2378    (*stackptr)->dirname = xstrdup(dirbuf);
   2379  } else {
   2380    // Okay we don't have an absolute path.
   2381    // dirbuf must be a subdir of one of the directories on the stack.
   2382    // Let's search...
   2383    ds_new = (*stackptr)->next;
   2384    (*stackptr)->dirname = NULL;
   2385    while (ds_new) {
   2386      xfree((*stackptr)->dirname);
   2387      (*stackptr)->dirname = concat_fnames(ds_new->dirname, dirbuf, true);
   2388      if (os_isdir((*stackptr)->dirname)) {
   2389        break;
   2390      }
   2391 
   2392      ds_new = ds_new->next;
   2393    }
   2394 
   2395    // clean up all dirs we already left
   2396    while ((*stackptr)->next != ds_new) {
   2397      ds_ptr = (*stackptr)->next;
   2398      (*stackptr)->next = (*stackptr)->next->next;
   2399      xfree(ds_ptr->dirname);
   2400      xfree(ds_ptr);
   2401    }
   2402 
   2403    // Nothing found -> it must be on top level
   2404    if (ds_new == NULL) {
   2405      xfree((*stackptr)->dirname);
   2406      (*stackptr)->dirname = xstrdup(dirbuf);
   2407    }
   2408  }
   2409 
   2410  if ((*stackptr)->dirname != NULL) {
   2411    return (*stackptr)->dirname;
   2412  }
   2413  ds_ptr = *stackptr;
   2414  *stackptr = (*stackptr)->next;
   2415  xfree(ds_ptr);
   2416  return NULL;
   2417 }
   2418 
   2419 // pop dirbuf from the directory stack and return previous directory or NULL if
   2420 // stack is empty
   2421 static char *qf_pop_dir(struct dir_stack_T **stackptr)
   2422 {
   2423  // TODO(vim): Should we check if dirbuf is the directory on top of the stack?
   2424  // What to do if it isn't?
   2425 
   2426  // pop top element and free it
   2427  if (*stackptr != NULL) {
   2428    struct dir_stack_T *ds_ptr = *stackptr;
   2429    *stackptr = (*stackptr)->next;
   2430    xfree(ds_ptr->dirname);
   2431    xfree(ds_ptr);
   2432  }
   2433 
   2434  // return NEW top element as current dir or NULL if stack is empty
   2435  return *stackptr ? (*stackptr)->dirname : NULL;
   2436 }
   2437 
   2438 // clean up directory stack
   2439 static void qf_clean_dir_stack(struct dir_stack_T **stackptr)
   2440 {
   2441  struct dir_stack_T *ds_ptr;
   2442 
   2443  while ((ds_ptr = *stackptr) != NULL) {
   2444    *stackptr = (*stackptr)->next;
   2445    xfree(ds_ptr->dirname);
   2446    xfree(ds_ptr);
   2447  }
   2448 }
   2449 
   2450 /// Check in which directory of the directory stack the given file can be
   2451 /// found.
   2452 /// Returns a pointer to the directory name or NULL if not found.
   2453 /// Cleans up intermediate directory entries.
   2454 ///
   2455 /// TODO(vim): How to solve the following problem?
   2456 /// If we have this directory tree:
   2457 ///     ./
   2458 ///     ./aa
   2459 ///     ./aa/bb
   2460 ///     ./bb
   2461 ///     ./bb/x.c
   2462 /// and make says:
   2463 ///     making all in aa
   2464 ///     making all in bb
   2465 ///     x.c:9: Error
   2466 /// Then qf_push_dir thinks we are in ./aa/bb, but we are in ./bb.
   2467 /// qf_guess_filepath will return NULL.
   2468 static char *qf_guess_filepath(qf_list_T *qfl, char *filename)
   2469 {
   2470  // no dirs on the stack - there's nothing we can do
   2471  if (qfl->qf_dir_stack == NULL) {
   2472    return NULL;
   2473  }
   2474 
   2475  struct dir_stack_T *ds_ptr = qfl->qf_dir_stack->next;
   2476  char *fullname = NULL;
   2477  while (ds_ptr) {
   2478    xfree(fullname);
   2479    fullname = concat_fnames(ds_ptr->dirname, filename, true);
   2480 
   2481    if (os_path_exists(fullname)) {
   2482      break;
   2483    }
   2484 
   2485    ds_ptr = ds_ptr->next;
   2486  }
   2487 
   2488  xfree(fullname);
   2489 
   2490  // clean up all dirs we already left
   2491  while (qfl->qf_dir_stack->next != ds_ptr) {
   2492    struct dir_stack_T *ds_tmp = qfl->qf_dir_stack->next;
   2493    qfl->qf_dir_stack->next = qfl->qf_dir_stack->next->next;
   2494    xfree(ds_tmp->dirname);
   2495    xfree(ds_tmp);
   2496  }
   2497 
   2498  return ds_ptr == NULL ? NULL : ds_ptr->dirname;
   2499 }
   2500 
   2501 /// Returns true, if a quickfix/location list with the given identifier exists.
   2502 static bool qflist_valid(win_T *wp, unsigned qf_id)
   2503 {
   2504  qf_info_T *qi = ql_info;
   2505 
   2506  if (wp) {
   2507    if (!win_valid(wp)) {
   2508      return false;
   2509    }
   2510    qi = GET_LOC_LIST(wp);  // Location list
   2511  }
   2512  if (!qi) {
   2513    return false;
   2514  }
   2515 
   2516  for (int i = 0; i < qi->qf_listcount; i++) {
   2517    if (qi->qf_lists[i].qf_id == qf_id) {
   2518      return true;
   2519    }
   2520  }
   2521 
   2522  return false;
   2523 }
   2524 
   2525 /// When loading a file from the quickfix, the autocommands may modify it.
   2526 /// This may invalidate the current quickfix entry.  This function checks
   2527 /// whether an entry is still present in the quickfix list.
   2528 /// Similar to location list.
   2529 static bool is_qf_entry_present(qf_list_T *qfl, qfline_T *qf_ptr)
   2530 {
   2531  qfline_T *qfp;
   2532  int i;
   2533 
   2534  // Search for the entry in the current list
   2535  FOR_ALL_QFL_ITEMS(qfl, qfp, i) {
   2536    if (qfp == qf_ptr) {
   2537      break;
   2538    }
   2539  }
   2540 
   2541  if (i > qfl->qf_count) {  // Entry is not found
   2542    return false;
   2543  }
   2544 
   2545  return true;
   2546 }
   2547 
   2548 /// Get the next valid entry in the current quickfix/location list. The search
   2549 /// starts from the current entry. Returns NULL on failure.
   2550 static qfline_T *get_next_valid_entry(qf_list_T *qfl, qfline_T *qf_ptr, int *qf_index, int dir)
   2551 {
   2552  int idx = *qf_index;
   2553  int old_qf_fnum = qf_ptr->qf_fnum;
   2554 
   2555  do {
   2556    if (idx == qfl->qf_count || qf_ptr->qf_next == NULL) {
   2557      return NULL;
   2558    }
   2559    idx++;
   2560    qf_ptr = qf_ptr->qf_next;
   2561  } while ((!qfl->qf_nonevalid && !qf_ptr->qf_valid)
   2562           || (dir == FORWARD_FILE && qf_ptr->qf_fnum == old_qf_fnum));
   2563 
   2564  *qf_index = idx;
   2565  return qf_ptr;
   2566 }
   2567 
   2568 /// Get the previous valid entry in the current quickfix/location list. The
   2569 /// search starts from the current entry. Returns NULL on failure.
   2570 static qfline_T *get_prev_valid_entry(qf_list_T *qfl, qfline_T *qf_ptr, int *qf_index, int dir)
   2571 {
   2572  int idx = *qf_index;
   2573  int old_qf_fnum = qf_ptr->qf_fnum;
   2574 
   2575  do {
   2576    if (idx == 1 || qf_ptr->qf_prev == NULL) {
   2577      return NULL;
   2578    }
   2579    idx--;
   2580    qf_ptr = qf_ptr->qf_prev;
   2581  } while ((!qfl->qf_nonevalid && !qf_ptr->qf_valid)
   2582           || (dir == BACKWARD_FILE && qf_ptr->qf_fnum == old_qf_fnum));
   2583 
   2584  *qf_index = idx;
   2585  return qf_ptr;
   2586 }
   2587 
   2588 /// Get the n'th (errornr) previous/next valid entry from the current entry in
   2589 /// the quickfix list.
   2590 ///   dir == FORWARD or FORWARD_FILE: next valid entry
   2591 ///   dir == BACKWARD or BACKWARD_FILE: previous valid entry
   2592 static qfline_T *get_nth_valid_entry(qf_list_T *qfl, int errornr, int dir, int *new_qfidx)
   2593 {
   2594  qfline_T *qf_ptr = qfl->qf_ptr;
   2595  int qf_idx = qfl->qf_index;
   2596  const char *err = e_no_more_items;
   2597 
   2598  while (errornr--) {
   2599    qfline_T *prev_qf_ptr = qf_ptr;
   2600    int prev_index = qf_idx;
   2601 
   2602    if (dir == FORWARD || dir == FORWARD_FILE) {
   2603      qf_ptr = get_next_valid_entry(qfl, qf_ptr, &qf_idx, dir);
   2604    } else {
   2605      qf_ptr = get_prev_valid_entry(qfl, qf_ptr, &qf_idx, dir);
   2606    }
   2607 
   2608    if (qf_ptr == NULL) {
   2609      qf_ptr = prev_qf_ptr;
   2610      qf_idx = prev_index;
   2611      if (err != NULL) {
   2612        emsg(_(err));
   2613        return NULL;
   2614      }
   2615      break;
   2616    }
   2617 
   2618    err = NULL;
   2619  }
   2620 
   2621  *new_qfidx = qf_idx;
   2622  return qf_ptr;
   2623 }
   2624 
   2625 /// Get n'th (errornr) quickfix entry from the current entry in the quickfix
   2626 /// list 'qfl'. Returns a pointer to the new entry and the index in 'new_qfidx'
   2627 static qfline_T *get_nth_entry(qf_list_T *qfl, int errornr, int *new_qfidx)
   2628 {
   2629  qfline_T *qf_ptr = qfl->qf_ptr;
   2630  int qf_idx = qfl->qf_index;
   2631 
   2632  // New error number is less than the current error number
   2633  while (errornr < qf_idx && qf_idx > 1 && qf_ptr->qf_prev != NULL) {
   2634    qf_idx--;
   2635    qf_ptr = qf_ptr->qf_prev;
   2636  }
   2637 
   2638  // New error number is greater than the current error number
   2639  while (errornr > qf_idx
   2640         && qf_idx < qfl->qf_count
   2641         && qf_ptr->qf_next != NULL) {
   2642    qf_idx++;
   2643    qf_ptr = qf_ptr->qf_next;
   2644  }
   2645 
   2646  *new_qfidx = qf_idx;
   2647  return qf_ptr;
   2648 }
   2649 
   2650 /// Get a entry specified by 'errornr' and 'dir' from the current
   2651 /// quickfix/location list. 'errornr' specifies the index of the entry and 'dir'
   2652 /// specifies the direction (FORWARD/BACKWARD/FORWARD_FILE/BACKWARD_FILE).
   2653 /// Returns a pointer to the entry and the index of the new entry is stored in
   2654 /// 'new_qfidx'.
   2655 static qfline_T *qf_get_entry(qf_list_T *qfl, int errornr, int dir, int *new_qfidx)
   2656 {
   2657  qfline_T *qf_ptr = qfl->qf_ptr;
   2658  int qfidx = qfl->qf_index;
   2659 
   2660  if (dir != 0) {  // next/prev valid entry
   2661    qf_ptr = get_nth_valid_entry(qfl, errornr, dir, &qfidx);
   2662  } else if (errornr != 0) {  // go to specified number
   2663    qf_ptr = get_nth_entry(qfl, errornr, &qfidx);
   2664  }
   2665 
   2666  *new_qfidx = qfidx;
   2667  return qf_ptr;
   2668 }
   2669 
   2670 // Find a window displaying a Vim help file in the current tab page.
   2671 static win_T *qf_find_help_win(void)
   2672  FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
   2673 {
   2674  FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
   2675    if (bt_help(wp->w_buffer) && !wp->w_config.hide && wp->w_config.focusable) {
   2676      return wp;
   2677    }
   2678  }
   2679  return NULL;
   2680 }
   2681 
   2682 /// Set the location list for the specified window to 'qi'.
   2683 static void win_set_loclist(win_T *wp, qf_info_T *qi)
   2684 {
   2685  wp->w_llist = qi;
   2686  qi->qf_refcount++;
   2687 }
   2688 
   2689 /// Find a help window or open one. If 'newwin' is true, then open a new help
   2690 /// window.
   2691 static int jump_to_help_window(qf_info_T *qi, bool newwin, bool *opened_window)
   2692 {
   2693  win_T *wp = (cmdmod.cmod_tab != 0 || newwin) ? NULL : qf_find_help_win();
   2694 
   2695  if (wp != NULL && wp->w_buffer->b_nwindows > 0) {
   2696    win_enter(wp, true);
   2697  } else {
   2698    // Split off help window; put it at far top if no position
   2699    // specified, the current window is vertically split and narrow.
   2700    int flags = WSP_HELP;
   2701    if (cmdmod.cmod_split == 0
   2702        && curwin->w_width != Columns
   2703        && curwin->w_width < 80) {
   2704      flags |= WSP_TOP;
   2705    }
   2706 
   2707    // If the user asks to open a new window, then copy the location list.
   2708    // Otherwise, don't copy the location list.
   2709    if (IS_LL_STACK(qi) && !newwin) {
   2710      flags |= WSP_NEWLOC;
   2711    }
   2712 
   2713    if (win_split(0, flags) == FAIL) {
   2714      return FAIL;
   2715    }
   2716 
   2717    *opened_window = true;
   2718 
   2719    if (curwin->w_height < p_hh) {
   2720      win_setheight((int)p_hh);
   2721    }
   2722 
   2723    // When using location list, the new window should use the supplied
   2724    // location list. If the user asks to open a new window, then the new
   2725    // window will get a copy of the location list.
   2726    if (IS_LL_STACK(qi) && !newwin) {
   2727      win_set_loclist(curwin, qi);
   2728    }
   2729  }
   2730 
   2731  restart_edit = 0;  // don't want insert mode in help file
   2732 
   2733  return OK;
   2734 }
   2735 
   2736 /// Find a non-quickfix window using the given location list stack in the
   2737 /// current tabpage.
   2738 /// Returns NULL if a matching window is not found.
   2739 static win_T *qf_find_win_with_loclist(const qf_info_T *ll)
   2740  FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
   2741 {
   2742  FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
   2743    if (wp->w_llist == ll && !bt_quickfix(wp->w_buffer)) {
   2744      return wp;
   2745    }
   2746  }
   2747  return NULL;
   2748 }
   2749 
   2750 /// Find a window containing a normal buffer in the current tab page.
   2751 static win_T *qf_find_win_with_normal_buf(void)
   2752  FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
   2753 {
   2754  FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
   2755    if (bt_normal(wp->w_buffer)) {
   2756      return wp;
   2757    }
   2758  }
   2759  return NULL;
   2760 }
   2761 
   2762 // Go to a window in any tabpage containing the specified file.  Returns true
   2763 // if successfully jumped to the window. Otherwise returns false.
   2764 static bool qf_goto_tabwin_with_file(int fnum)
   2765 {
   2766  FOR_ALL_TAB_WINDOWS(tp, wp) {
   2767    if (wp->w_buffer->b_fnum == fnum) {
   2768      goto_tabpage_win(tp, wp);
   2769      return true;
   2770    }
   2771  }
   2772  return false;
   2773 }
   2774 
   2775 // Create a new window to show a file above the quickfix window. Called when
   2776 // only the quickfix window is present.
   2777 static int qf_open_new_file_win(qf_info_T *ll_ref)
   2778 {
   2779  int flags = WSP_ABOVE;
   2780  if (ll_ref != NULL) {
   2781    flags |= WSP_NEWLOC;
   2782  }
   2783  if (win_split(0, flags) == FAIL) {
   2784    return FAIL;  // not enough room for window
   2785  }
   2786  p_swb = empty_string_option;  // don't split again
   2787  swb_flags = 0;
   2788  RESET_BINDING(curwin);
   2789  if (ll_ref != NULL) {
   2790    // The new window should use the location list from the
   2791    // location list window
   2792    win_set_loclist(curwin, ll_ref);
   2793  }
   2794  return OK;
   2795 }
   2796 
   2797 // Go to a window that shows the right buffer. If the window is not found, go
   2798 // to the window just above the location list window. This is used for opening
   2799 // a file from a location window and not from a quickfix window. If some usable
   2800 // window is previously found, then it is supplied in 'use_win'.
   2801 static void qf_goto_win_with_ll_file(win_T *use_win, int qf_fnum, qf_info_T *ll_ref)
   2802 {
   2803  win_T *win = use_win;
   2804 
   2805  if (win == NULL) {
   2806    // Find the window showing the selected file in the current tab page.
   2807    FOR_ALL_WINDOWS_IN_TAB(win2, curtab) {
   2808      if (win2->w_buffer->b_fnum == qf_fnum) {
   2809        win = win2;
   2810        break;
   2811      }
   2812    }
   2813    if (win == NULL) {
   2814      // Find a previous usable window
   2815      win = curwin;
   2816      do {
   2817        if (bt_normal(win->w_buffer)) {
   2818          break;
   2819        }
   2820        if (win->w_prev == NULL) {
   2821          win = lastwin;      // wrap around the top
   2822        } else {
   2823          win = win->w_prev;  // go to previous window
   2824        }
   2825      } while (win != curwin);
   2826    }
   2827  }
   2828  win_goto(win);
   2829 
   2830  // If the location list for the window is not set, then set it
   2831  // to the location list from the location window
   2832  if (win->w_llist == NULL && ll_ref != NULL) {
   2833    // The new window should use the location list from the
   2834    // location list window
   2835    win_set_loclist(win, ll_ref);
   2836  }
   2837 }
   2838 
   2839 // Go to a window that shows the specified file. If a window is not found, go
   2840 // to the window just above the quickfix window. This is used for opening a
   2841 // file from a quickfix window and not from a location window.
   2842 static void qf_goto_win_with_qfl_file(int qf_fnum)
   2843 {
   2844  win_T *win = curwin;
   2845  win_T *altwin = NULL;
   2846  while (true) {
   2847    if (win->w_buffer->b_fnum == qf_fnum) {
   2848      break;
   2849    }
   2850    if (win->w_prev == NULL) {
   2851      win = lastwin;      // wrap around the top
   2852    } else {
   2853      win = win->w_prev;  // go to previous window
   2854    }
   2855 
   2856    if (IS_QF_WINDOW(win)) {
   2857      // Didn't find it, go to the window before the quickfix
   2858      // window, unless 'switchbuf' contains 'uselast': in this case we
   2859      // try to jump to the previously used window first.
   2860      if ((swb_flags & kOptSwbFlagUselast) && win_valid(prevwin)
   2861          && !prevwin->w_p_wfb) {
   2862        win = prevwin;
   2863      } else if (altwin != NULL) {
   2864        win = altwin;
   2865      } else if (curwin->w_prev != NULL) {
   2866        win = curwin->w_prev;
   2867      } else {
   2868        win = curwin->w_next;
   2869      }
   2870      break;
   2871    }
   2872 
   2873    // Remember a usable window.
   2874    if (altwin == NULL
   2875        && !win->w_p_pvw
   2876        && !win->w_p_wfb
   2877        && bt_normal(win->w_buffer)) {
   2878      altwin = win;
   2879    }
   2880  }
   2881 
   2882  win_goto(win);
   2883 }
   2884 
   2885 // Find a suitable window for opening a file (qf_fnum) from the
   2886 // quickfix/location list and jump to it.  If the file is already opened in a
   2887 // window, jump to it. Otherwise open a new window to display the file. If
   2888 // 'newwin' is true, then always open a new window. This is called from either
   2889 // a quickfix or a location list window.
   2890 static int qf_jump_to_usable_window(int qf_fnum, bool newwin, bool *opened_window)
   2891 {
   2892  win_T *usable_wp = NULL;
   2893  bool usable_win = false;
   2894 
   2895  // If opening a new window, then don't use the location list referred by
   2896  // the current window.  Otherwise two windows will refer to the same
   2897  // location list.
   2898  qf_info_T *ll_ref = newwin ? NULL : curwin->w_llist_ref;
   2899  if (ll_ref != NULL) {
   2900    // Find a non-quickfix window with this location list
   2901    usable_wp = qf_find_win_with_loclist(ll_ref);
   2902    if (usable_wp != NULL) {
   2903      usable_win = true;
   2904    }
   2905  }
   2906 
   2907  if (!usable_win) {
   2908    // Locate a window showing a normal buffer
   2909    win_T *win = qf_find_win_with_normal_buf();
   2910    if (win != NULL) {
   2911      usable_win = true;
   2912    }
   2913  }
   2914 
   2915  // If no usable window is found and 'switchbuf' contains "usetab"
   2916  // then search in other tabs.
   2917  if (!usable_win && (swb_flags & kOptSwbFlagUsetab)) {
   2918    usable_win = qf_goto_tabwin_with_file(qf_fnum);
   2919  }
   2920 
   2921  // If there is only one window and it is the quickfix window, create a
   2922  // new one above the quickfix window.
   2923  if ((ONE_WINDOW && bt_quickfix(curbuf)) || !usable_win || newwin) {
   2924    if (qf_open_new_file_win(ll_ref) != OK) {
   2925      return FAIL;
   2926    }
   2927    *opened_window = true;  // close it when fail
   2928  } else {
   2929    if (curwin->w_llist_ref != NULL) {  // In a location window
   2930      qf_goto_win_with_ll_file(usable_wp, qf_fnum, ll_ref);
   2931    } else {  // In a quickfix window
   2932      qf_goto_win_with_qfl_file(qf_fnum);
   2933    }
   2934  }
   2935 
   2936  return OK;
   2937 }
   2938 
   2939 /// Edit the selected file or help file.
   2940 /// @return  OK if successfully edited the file.
   2941 ///          FAIL on failing to open the buffer.
   2942 ///          QF_ABORT if the quickfix/location list was freed by an autocmd
   2943 ///          when opening the buffer.
   2944 static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit, int prev_winid,
   2945                               bool *opened_window)
   2946 {
   2947  qf_list_T *qfl = qf_get_curlist(qi);
   2948  int old_changetick = qfl->qf_changedtick;
   2949  int old_qf_curlist = qi->qf_curlist;
   2950  qfltype_T qfl_type = qfl->qfl_type;
   2951  int retval = OK;
   2952  unsigned save_qfid = qfl->qf_id;
   2953 
   2954  if (qf_ptr->qf_type == 1) {
   2955    // Open help file (do_ecmd() will set b_help flag, readfile() will
   2956    // set b_p_ro flag).
   2957    if (!can_abandon(curbuf, forceit)) {
   2958      no_write_message();
   2959      return FAIL;
   2960    }
   2961    retval = do_ecmd(qf_ptr->qf_fnum, NULL, NULL, NULL, 1,
   2962                     ECMD_HIDE + ECMD_SET_HELP,
   2963                     prev_winid == curwin->handle ? curwin : NULL);
   2964  } else {
   2965    int fnum = qf_ptr->qf_fnum;
   2966 
   2967    if (!forceit && curwin->w_p_wfb && curbuf->b_fnum != fnum) {
   2968      if (qi->qfl_type == QFLT_LOCATION) {
   2969        // Location lists cannot split or reassign their window
   2970        // so 'winfixbuf' windows must fail
   2971        emsg(_(e_winfixbuf_cannot_go_to_buffer));
   2972        return FAIL;
   2973      }
   2974 
   2975      if (win_valid(prevwin) && !prevwin->w_p_wfb
   2976          && !bt_quickfix(prevwin->w_buffer)) {
   2977        // 'winfixbuf' is set; attempt to change to a window without it
   2978        // that isn't a quickfix/location list window.
   2979        win_goto(prevwin);
   2980      }
   2981      if (curwin->w_p_wfb) {
   2982        // Split the window, which will be 'nowinfixbuf', and set curwin
   2983        // to that
   2984        if (win_split(0, 0) == OK) {
   2985          *opened_window = true;
   2986        }
   2987        if (curwin->w_p_wfb) {
   2988          // Autocommands set 'winfixbuf' or sent us to another window
   2989          // with it set, or we failed to split the window.  Give up,
   2990          // but don't return immediately, as they may have messed
   2991          // with the list.
   2992          emsg(_(e_winfixbuf_cannot_go_to_buffer));
   2993          retval = FAIL;
   2994        }
   2995      }
   2996    }
   2997 
   2998    if (retval == OK) {
   2999      retval = buflist_getfile(fnum, 1,
   3000                               GETF_SETMARK | GETF_SWITCH, forceit);
   3001    }
   3002  }
   3003  // If a location list, check whether the associated window is still
   3004  // present.
   3005  if (qfl_type == QFLT_LOCATION) {
   3006    win_T *wp = win_id2wp(prev_winid);
   3007 
   3008    if (wp == NULL && curwin->w_llist != qi) {
   3009      emsg(_("E924: Current window was closed"));
   3010      *opened_window = false;
   3011      return QF_ABORT;
   3012    }
   3013  }
   3014 
   3015  if (qfl_type == QFLT_QUICKFIX && !qflist_valid(NULL, save_qfid)) {
   3016    emsg(_(e_current_quickfix_list_was_changed));
   3017    return QF_ABORT;
   3018  }
   3019 
   3020  if (old_qf_curlist != qi->qf_curlist
   3021      || old_changetick != qfl->qf_changedtick
   3022      || !is_qf_entry_present(qfl, qf_ptr)) {
   3023    if (qfl_type == QFLT_QUICKFIX) {
   3024      emsg(_(e_current_quickfix_list_was_changed));
   3025    } else {
   3026      emsg(_(e_current_location_list_was_changed));
   3027    }
   3028    return QF_ABORT;
   3029  }
   3030 
   3031  return retval;
   3032 }
   3033 
   3034 /// Go to the error line in the current file using either line/column number or
   3035 /// a search pattern.
   3036 static void qf_jump_goto_line(linenr_T qf_lnum, int qf_col, char qf_viscol, char *qf_pattern)
   3037 {
   3038  if (qf_pattern == NULL) {
   3039    // Go to line with error, unless qf_lnum is 0.
   3040    linenr_T i = qf_lnum;
   3041    if (i > 0) {
   3042      i = MIN(i, curbuf->b_ml.ml_line_count);
   3043      curwin->w_cursor.lnum = i;
   3044    }
   3045    if (qf_col > 0) {
   3046      curwin->w_cursor.coladd = 0;
   3047      if (qf_viscol == true) {
   3048        coladvance(curwin, qf_col - 1);
   3049      } else {
   3050        curwin->w_cursor.col = qf_col - 1;
   3051      }
   3052      curwin->w_set_curswant = true;
   3053      check_cursor(curwin);
   3054    } else {
   3055      beginline(BL_WHITE | BL_FIX);
   3056    }
   3057  } else {
   3058    // Move the cursor to the first line in the buffer
   3059    pos_T save_cursor = curwin->w_cursor;
   3060    curwin->w_cursor.lnum = 0;
   3061    if (!do_search(NULL, '/', '/', qf_pattern, strlen(qf_pattern), 1, SEARCH_KEEP, NULL)) {
   3062      curwin->w_cursor = save_cursor;
   3063    }
   3064  }
   3065 }
   3066 
   3067 /// Display quickfix list index and size message
   3068 static void qf_jump_print_msg(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, buf_T *old_curbuf,
   3069                              linenr_T old_lnum)
   3070 {
   3071  garray_T *const gap = qfga_get();
   3072 
   3073  // Update the screen before showing the message, unless messages scrolled.
   3074  if (!msg_scrolled) {
   3075    update_topline(curwin);
   3076    if (must_redraw) {
   3077      update_screen();
   3078    }
   3079  }
   3080  size_t IObufflen = vim_snprintf_safelen(IObuff, IOSIZE,
   3081                                          _("(%d of %d)%s%s: "), qf_index,
   3082                                          qf_get_curlist(qi)->qf_count,
   3083                                          qf_ptr->qf_cleared ? _(" (line deleted)") : "",
   3084                                          qf_types(qf_ptr->qf_type, qf_ptr->qf_nr));
   3085  // Add the message, skipping leading whitespace and newlines.
   3086  ga_concat_len(gap, IObuff, IObufflen);
   3087  qf_fmt_text(gap, skipwhite(qf_ptr->qf_text));
   3088  ga_append(gap, NUL);
   3089 
   3090  // Output the message.  Overwrite to avoid scrolling when the 'O'
   3091  // flag is present in 'shortmess'; But when not jumping, print the
   3092  // whole message.
   3093  linenr_T i = msg_scroll;
   3094  if (curbuf == old_curbuf && curwin->w_cursor.lnum == old_lnum) {
   3095    msg_scroll = true;
   3096  } else if ((msg_scrolled == 0 || (p_ch == 0 && msg_scrolled == 1))
   3097             && shortmess(SHM_OVERALL)) {
   3098    msg_scroll = false;
   3099  }
   3100  msg_ext_set_kind("quickfix");
   3101  msg_keep(gap->ga_data, 0, true, false);
   3102  msg_scroll = (int)i;
   3103 
   3104  qfga_clear();
   3105 }
   3106 
   3107 /// Find a usable window for opening a file from the quickfix/location list. If
   3108 /// a window is not found then open a new window. If 'newwin' is true, then open
   3109 /// a new window.
   3110 /// @return  OK if successfully jumped or opened a window.
   3111 ///          FAIL if not able to jump/open a window.
   3112 ///          NOTDONE if a file is not associated with the entry.
   3113 ///          QF_ABORT if the quickfix/location list was modified by an autocmd.
   3114 static int qf_jump_open_window(qf_info_T *qi, qfline_T *qf_ptr, bool newwin, bool *opened_window)
   3115 {
   3116  qf_list_T *qfl = qf_get_curlist(qi);
   3117  int old_changetick = qfl->qf_changedtick;
   3118  int old_qf_curlist = qi->qf_curlist;
   3119  qfltype_T qfl_type = qfl->qfl_type;
   3120 
   3121  // For ":helpgrep" find a help window or open one.
   3122  if (qf_ptr->qf_type == 1 && (!bt_help(curwin->w_buffer) || cmdmod.cmod_tab != 0)) {
   3123    if (jump_to_help_window(qi, newwin, opened_window) == FAIL) {
   3124      return FAIL;
   3125    }
   3126  }
   3127  if (old_qf_curlist != qi->qf_curlist
   3128      || old_changetick != qfl->qf_changedtick
   3129      || !is_qf_entry_present(qfl, qf_ptr)) {
   3130    if (qfl_type == QFLT_QUICKFIX) {
   3131      emsg(_(e_current_quickfix_list_was_changed));
   3132    } else {
   3133      emsg(_(e_current_location_list_was_changed));
   3134    }
   3135    return QF_ABORT;
   3136  }
   3137 
   3138  // If currently in the quickfix window, find another window to show the
   3139  // file in.
   3140  if (bt_quickfix(curbuf) && !*opened_window) {
   3141    // If there is no file specified, we don't know where to go.
   3142    // But do advance, otherwise ":cn" gets stuck.
   3143    if (qf_ptr->qf_fnum == 0) {
   3144      return NOTDONE;
   3145    }
   3146 
   3147    if (qf_jump_to_usable_window(qf_ptr->qf_fnum, newwin, opened_window)
   3148        == FAIL) {
   3149      return FAIL;
   3150    }
   3151  }
   3152  if (old_qf_curlist != qi->qf_curlist
   3153      || old_changetick != qfl->qf_changedtick
   3154      || !is_qf_entry_present(qfl, qf_ptr)) {
   3155    if (qfl_type == QFLT_QUICKFIX) {
   3156      emsg(_(e_current_quickfix_list_was_changed));
   3157    } else {
   3158      emsg(_(e_current_location_list_was_changed));
   3159    }
   3160    return QF_ABORT;
   3161  }
   3162 
   3163  return OK;
   3164 }
   3165 
   3166 /// Edit a selected file from the quickfix/location list and jump to a
   3167 /// particular line/column, adjust the folds and display a message about the
   3168 /// jump.
   3169 /// @return  OK on success and FAIL on failing to open the file/buffer.
   3170 ///          QF_ABORT if the quickfix/location list is freed by an autocmd when opening
   3171 ///          the file.
   3172 static int qf_jump_to_buffer(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, int forceit,
   3173                             int prev_winid, bool *opened_window, int openfold, bool print_message)
   3174 {
   3175  // If there is a file name, read the wanted file if needed, and check
   3176  // autowrite etc.
   3177  buf_T *old_curbuf = curbuf;
   3178  linenr_T old_lnum = curwin->w_cursor.lnum;
   3179  int retval = OK;
   3180 
   3181  if (qf_ptr->qf_fnum != 0) {
   3182    retval = qf_jump_edit_buffer(qi, qf_ptr, forceit, prev_winid,
   3183                                 opened_window);
   3184    if (retval != OK) {
   3185      return retval;
   3186    }
   3187  }
   3188 
   3189  // When not switched to another buffer, still need to set pc mark
   3190  if (curbuf == old_curbuf) {
   3191    setpcmark();
   3192  }
   3193 
   3194  qf_jump_goto_line(qf_ptr->qf_lnum, qf_ptr->qf_col, qf_ptr->qf_viscol, qf_ptr->qf_pattern);
   3195 
   3196  if ((fdo_flags & kOptFdoFlagQuickfix) && openfold) {
   3197    foldOpenCursor();
   3198  }
   3199  if (print_message) {
   3200    qf_jump_print_msg(qi, qf_index, qf_ptr, old_curbuf, old_lnum);
   3201  }
   3202 
   3203  return retval;
   3204 }
   3205 
   3206 /// Jump to a quickfix line and try to use an existing window.
   3207 void qf_jump(qf_info_T *qi, int dir, int errornr, int forceit)
   3208 {
   3209  qf_jump_newwin(qi, dir, errornr, forceit, false);
   3210 }
   3211 
   3212 // Jump to a quickfix line.
   3213 // If dir == 0 go to entry "errornr".
   3214 // If dir == FORWARD go "errornr" valid entries forward.
   3215 // If dir == BACKWARD go "errornr" valid entries backward.
   3216 // If dir == FORWARD_FILE go "errornr" valid entries files backward.
   3217 // If dir == BACKWARD_FILE go "errornr" valid entries files backward
   3218 // else if "errornr" is zero, redisplay the same line
   3219 // If 'forceit' is true, then can discard changes to the current buffer.
   3220 // If 'newwin' is true, then open the file in a new window.
   3221 static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, bool newwin)
   3222 {
   3223  char *old_swb = p_swb;
   3224  unsigned old_swb_flags = swb_flags;
   3225  const bool old_KeyTyped = KeyTyped;           // getting file may reset it
   3226 
   3227  if (qi == NULL) {
   3228    assert(ql_info != NULL);
   3229    qi = ql_info;
   3230  }
   3231 
   3232  if (qf_stack_empty(qi) || qf_list_empty(qf_get_curlist(qi))) {
   3233    emsg(_(e_no_errors));
   3234    return;
   3235  }
   3236 
   3237  incr_quickfix_busy();
   3238 
   3239  qf_list_T *qfl = qf_get_curlist(qi);
   3240 
   3241  qfline_T *qf_ptr = qfl->qf_ptr;
   3242  qfline_T *old_qf_ptr = qf_ptr;
   3243  int qf_index = qfl->qf_index;
   3244  int old_qf_index = qf_index;
   3245 
   3246  qf_ptr = qf_get_entry(qfl, errornr, dir, &qf_index);
   3247  if (qf_ptr == NULL) {
   3248    qf_ptr = old_qf_ptr;
   3249    qf_index = old_qf_index;
   3250    goto theend;
   3251  }
   3252 
   3253  qfl->qf_index = qf_index;
   3254  qfl->qf_ptr = qf_ptr;
   3255 
   3256  // No need to print the error message if it's visible in the error window
   3257  bool print_message = !qf_win_pos_update(qi, old_qf_index);
   3258 
   3259  int prev_winid = curwin->handle;
   3260 
   3261  bool opened_window = false;
   3262  int retval = qf_jump_open_window(qi, qf_ptr, newwin, &opened_window);
   3263  if (retval == FAIL) {
   3264    goto failed;
   3265  }
   3266  if (retval == QF_ABORT) {
   3267    qi = NULL;
   3268    qf_ptr = NULL;
   3269    goto theend;
   3270  }
   3271  if (retval == NOTDONE) {
   3272    goto theend;
   3273  }
   3274 
   3275  retval = qf_jump_to_buffer(qi, qf_index, qf_ptr, forceit, prev_winid,
   3276                             &opened_window, old_KeyTyped, print_message);
   3277  if (retval == QF_ABORT) {
   3278    // Quickfix/location list was modified by an autocmd
   3279    qi = NULL;
   3280    qf_ptr = NULL;
   3281  }
   3282 
   3283  if (retval != OK) {
   3284    if (opened_window) {
   3285      win_close(curwin, true, false);          // Close opened window
   3286    }
   3287    if (qf_ptr != NULL && qf_ptr->qf_fnum != 0) {
   3288      // Couldn't open file, so put index back where it was.  This could
   3289      // happen if the file was readonly and we changed something.
   3290 failed:
   3291      qf_ptr = old_qf_ptr;
   3292      qf_index = old_qf_index;
   3293    }
   3294  }
   3295 theend:
   3296  if (qi != NULL) {
   3297    qfl->qf_ptr = qf_ptr;
   3298    qfl->qf_index = qf_index;
   3299  }
   3300  if (p_swb != old_swb && p_swb == empty_string_option) {
   3301    // Restore old 'switchbuf' value, but not when an autocommand or
   3302    // modeline has changed the value.
   3303    p_swb = old_swb;
   3304    swb_flags = old_swb_flags;
   3305  }
   3306  decr_quickfix_busy();
   3307 }
   3308 
   3309 // Highlight ids used for displaying entries from the quickfix list.
   3310 static int qfFile_hl_id;
   3311 static int qfSep_hl_id;
   3312 static int qfLine_hl_id;
   3313 
   3314 /// Display information about a single entry from the quickfix/location list.
   3315 /// Used by ":clist/:llist" commands.
   3316 /// 'cursel' will be set to true for the currently selected entry in the
   3317 /// quickfix list.
   3318 static void qf_list_entry(qfline_T *qfp, int qf_idx, bool cursel)
   3319 {
   3320  char *fname = NULL;
   3321  if (qfp->qf_module != NULL && *qfp->qf_module != NUL) {
   3322    vim_snprintf(IObuff, IOSIZE, "%2d %s", qf_idx, qfp->qf_module);
   3323  } else {
   3324    buf_T *buf;
   3325    if (qfp->qf_fnum != 0
   3326        && (buf = buflist_findnr(qfp->qf_fnum)) != NULL) {
   3327      fname = qfp->qf_fname == NULL ? buf->b_fname : qfp->qf_fname;
   3328      if (qfp->qf_type == 1) {  // :helpgrep
   3329        fname = path_tail(fname);
   3330      }
   3331    }
   3332    if (fname == NULL) {
   3333      snprintf(IObuff, IOSIZE, "%2d", qf_idx);
   3334    } else {
   3335      vim_snprintf(IObuff, IOSIZE, "%2d %s", qf_idx, fname);
   3336    }
   3337  }
   3338 
   3339  // Support for filtering entries using :filter /pat/ clist
   3340  // Match against the module name, file name, search pattern and
   3341  // text of the entry.
   3342  bool filter_entry = true;
   3343  if (qfp->qf_module != NULL && *qfp->qf_module != NUL) {
   3344    filter_entry &= message_filtered(qfp->qf_module);
   3345  }
   3346  if (filter_entry && fname != NULL) {
   3347    filter_entry &= message_filtered(fname);
   3348  }
   3349  if (filter_entry && qfp->qf_pattern != NULL) {
   3350    filter_entry &= message_filtered(qfp->qf_pattern);
   3351  }
   3352  if (filter_entry) {
   3353    filter_entry &= message_filtered(qfp->qf_text);
   3354  }
   3355  if (filter_entry) {
   3356    return;
   3357  }
   3358 
   3359  if (msg_col > 0) {
   3360    msg_putchar('\n');
   3361  }
   3362  msg_outtrans(IObuff, cursel ? HLF_QFL : qfFile_hl_id, false);
   3363 
   3364  if (qfp->qf_lnum != 0) {
   3365    msg_puts_hl(":", qfSep_hl_id, false);
   3366  }
   3367  garray_T *gap = qfga_get();
   3368  if (qfp->qf_lnum != 0) {
   3369    qf_range_text(gap, qfp);
   3370  }
   3371  ga_concat(gap, qf_types(qfp->qf_type, qfp->qf_nr));
   3372  ga_append(gap, NUL);
   3373  if (*(char *)gap->ga_data != NUL) {
   3374    msg_puts_hl(gap->ga_data, qfLine_hl_id, false);
   3375  }
   3376  msg_puts_hl(":", qfSep_hl_id, false);
   3377  if (qfp->qf_pattern != NULL) {
   3378    gap = qfga_get();
   3379    qf_fmt_text(gap, qfp->qf_pattern);
   3380    ga_append(gap, NUL);
   3381    msg_puts(gap->ga_data);
   3382    msg_puts_hl(":", qfSep_hl_id, false);
   3383  }
   3384  msg_puts(" ");
   3385 
   3386  // Remove newlines and leading whitespace from the text.  For an
   3387  // unrecognized line keep the indent, the compiler may mark a word
   3388  // with ^^^^.
   3389  gap = qfga_get();
   3390  qf_fmt_text(gap, (fname != NULL || qfp->qf_lnum != 0) ? skipwhite(qfp->qf_text) : qfp->qf_text);
   3391  ga_append(gap, NUL);
   3392  msg_prt_line(gap->ga_data, false);
   3393 }
   3394 
   3395 // ":clist": list all errors
   3396 // ":llist": list all locations
   3397 void qf_list(exarg_T *eap)
   3398 {
   3399  char *arg = eap->arg;
   3400  int all = eap->forceit;     // if not :cl!, only show recognised errors
   3401  qf_info_T *qi = qf_cmd_get_stack(eap, true);
   3402 
   3403  if (qi == NULL) {
   3404    return;
   3405  }
   3406 
   3407  if (qf_stack_empty(qi) || qf_list_empty(qf_get_curlist(qi))) {
   3408    emsg(_(e_no_errors));
   3409    return;
   3410  }
   3411 
   3412  bool plus = false;
   3413  if (*arg == '+') {
   3414    arg++;
   3415    plus = true;
   3416  }
   3417  int idx1 = 1;
   3418  int idx2 = -1;
   3419  if (!get_list_range(&arg, &idx1, &idx2) || *arg != NUL) {
   3420    semsg(_(e_trailing_arg), arg);
   3421    return;
   3422  }
   3423  qf_list_T *qfl = qf_get_curlist(qi);
   3424  int i;
   3425  if (plus) {
   3426    i = qfl->qf_index;
   3427    idx2 = i + idx1;
   3428    idx1 = i;
   3429  } else {
   3430    i = qfl->qf_count;
   3431    if (idx1 < 0) {
   3432      idx1 = (-idx1 > i) ? 0 : idx1 + i + 1;
   3433    }
   3434    if (idx2 < 0) {
   3435      idx2 = (-idx2 > i) ? 0 : idx2 + i + 1;
   3436    }
   3437  }
   3438 
   3439  // Shorten all the file names, so that it is easy to read.
   3440  shorten_fnames(false);
   3441 
   3442  // Get the attributes for the different quickfix highlight items.  Note
   3443  // that this depends on syntax items defined in the qf.vim syntax file
   3444  qfFile_hl_id = syn_name2id("qfFileName");
   3445  if (qfFile_hl_id == 0) {
   3446    qfFile_hl_id = HLF_D;
   3447  }
   3448  qfSep_hl_id = syn_name2id("qfSeparator");
   3449  if (qfSep_hl_id == 0) {
   3450    qfSep_hl_id = HLF_D;
   3451  }
   3452  qfLine_hl_id = syn_name2id("qfLineNr");
   3453  if (qfLine_hl_id == 0) {
   3454    qfLine_hl_id = HLF_N;
   3455  }
   3456 
   3457  if (qfl->qf_nonevalid) {
   3458    all = true;
   3459  }
   3460  msg_ext_set_kind("list_cmd");
   3461  qfline_T *qfp;
   3462  FOR_ALL_QFL_ITEMS(qfl, qfp, i) {
   3463    if ((qfp->qf_valid || all) && idx1 <= i && i <= idx2) {
   3464      qf_list_entry(qfp, i, i == qfl->qf_index);
   3465    }
   3466    os_breakcheck();
   3467  }
   3468  qfga_clear();
   3469 }
   3470 
   3471 /// Remove newlines and leading whitespace from an error message.
   3472 /// Add the result to the grow array "gap".
   3473 static void qf_fmt_text(garray_T *gap, const char *restrict text)
   3474  FUNC_ATTR_NONNULL_ALL
   3475 {
   3476  const char *p = text;
   3477  while (*p != NUL) {
   3478    if (*p == '\n') {
   3479      ga_append(gap, ' ');
   3480      while (*++p != NUL) {
   3481        if (!ascii_iswhite(*p) && *p != '\n') {
   3482          break;
   3483        }
   3484      }
   3485    } else {
   3486      ga_append(gap, (uint8_t)(*p++));
   3487    }
   3488  }
   3489 }
   3490 
   3491 /// Add the range information from the lnum, col, end_lnum, and end_col values
   3492 /// of a quickfix entry to the grow array "gap".
   3493 static void qf_range_text(garray_T *gap, const qfline_T *qfp)
   3494 {
   3495  String buf = cbuf_as_string(IObuff, 0);
   3496 
   3497  buf.size = vim_snprintf_safelen(buf.data, IOSIZE, "%" PRIdLINENR, qfp->qf_lnum);
   3498 
   3499  if (qfp->qf_end_lnum > 0 && qfp->qf_lnum != qfp->qf_end_lnum) {
   3500    buf.size += vim_snprintf_safelen(buf.data + buf.size, IOSIZE - buf.size,
   3501                                     "-%" PRIdLINENR, qfp->qf_end_lnum);
   3502  }
   3503  if (qfp->qf_col > 0) {
   3504    buf.size += vim_snprintf_safelen(buf.data + buf.size, IOSIZE - buf.size,
   3505                                     " col %d", qfp->qf_col);
   3506    if (qfp->qf_end_col > 0 && qfp->qf_col != qfp->qf_end_col) {
   3507      buf.size += vim_snprintf_safelen(buf.data + buf.size, IOSIZE - buf.size,
   3508                                       "-%d", qfp->qf_end_col);
   3509    }
   3510  }
   3511 
   3512  ga_concat_len(gap, buf.data, buf.size);
   3513 }
   3514 
   3515 /// Display information (list number, list size and the title) about a
   3516 /// quickfix/location list.
   3517 static void qf_msg(qf_info_T *qi, int which, char *lead)
   3518 {
   3519  char *title = qi->qf_lists[which].qf_title;
   3520  int count = qi->qf_lists[which].qf_count;
   3521  char buf[IOSIZE];
   3522 
   3523  vim_snprintf(buf, IOSIZE, _("%serror list %d of %d; %d errors "),
   3524               lead,
   3525               which + 1,
   3526               qi->qf_listcount,
   3527               count);
   3528 
   3529  if (title != NULL) {
   3530    size_t len = strlen(buf);
   3531 
   3532    if (len < 34) {
   3533      memset(buf + len, ' ', 34 - len);
   3534      buf[34] = NUL;
   3535    }
   3536    xstrlcat(buf, title, IOSIZE);
   3537  }
   3538  trunc_string(buf, buf, Columns - 1, IOSIZE);
   3539  msg(buf, 0);
   3540 }
   3541 
   3542 /// ":colder [count]": Up in the quickfix stack.
   3543 /// ":cnewer [count]": Down in the quickfix stack.
   3544 /// ":lolder [count]": Up in the location list stack.
   3545 /// ":lnewer [count]": Down in the location list stack.
   3546 void qf_age(exarg_T *eap)
   3547 {
   3548  qf_info_T *qi;
   3549 
   3550  if ((qi = qf_cmd_get_stack(eap, true)) == NULL) {
   3551    return;
   3552  }
   3553 
   3554  int count = (eap->addr_count != 0) ? (int)eap->line2 : 1;
   3555  while (count--) {
   3556    if (eap->cmdidx == CMD_colder || eap->cmdidx == CMD_lolder) {
   3557      if (qi->qf_curlist == 0) {
   3558        emsg(_("E380: At bottom of quickfix stack"));
   3559        break;
   3560      }
   3561      qi->qf_curlist--;
   3562    } else {
   3563      if (qi->qf_curlist >= qi->qf_listcount - 1) {
   3564        emsg(_("E381: At top of quickfix stack"));
   3565        break;
   3566      }
   3567      qi->qf_curlist++;
   3568    }
   3569  }
   3570  qf_msg(qi, qi->qf_curlist, "");
   3571  qf_update_buffer(qi, NULL);
   3572 }
   3573 
   3574 /// Display the information about all the quickfix/location lists in the stack.
   3575 void qf_history(exarg_T *eap)
   3576 {
   3577  qf_info_T *qi = qf_cmd_get_stack(eap, false);
   3578 
   3579  if (eap->addr_count > 0) {
   3580    if (qi == NULL) {
   3581      emsg(_(e_loclist));
   3582      return;
   3583    }
   3584 
   3585    // Jump to the specified quickfix list
   3586    if (eap->line2 > 0 && eap->line2 <= qi->qf_listcount) {
   3587      qi->qf_curlist = eap->line2 - 1;
   3588      qf_msg(qi, qi->qf_curlist, "");
   3589      qf_update_buffer(qi, NULL);
   3590    } else {
   3591      emsg(_(e_invrange));
   3592    }
   3593 
   3594    return;
   3595  }
   3596 
   3597  if (qf_stack_empty(qi)) {
   3598    msg(_("No entries"), 0);
   3599  } else {
   3600    for (int i = 0; i < qi->qf_listcount; i++) {
   3601      qf_msg(qi, i, i == qi->qf_curlist ? "> " : "  ");
   3602    }
   3603  }
   3604 }
   3605 
   3606 /// Free all the entries in the error list "idx". Note that other information
   3607 /// associated with the list like context and title are not freed.
   3608 static void qf_free_items(qf_list_T *qfl)
   3609 {
   3610  bool stop = false;
   3611 
   3612  while (qfl->qf_count && qfl->qf_start != NULL) {
   3613    qfline_T *qfp = qfl->qf_start;
   3614    qfline_T *qfpnext = qfp->qf_next;
   3615    if (!stop) {
   3616      xfree(qfp->qf_fname);
   3617      xfree(qfp->qf_module);
   3618      xfree(qfp->qf_text);
   3619      xfree(qfp->qf_pattern);
   3620      tv_clear(&qfp->qf_user_data);
   3621      stop = (qfp == qfpnext);
   3622      xfree(qfp);
   3623      if (stop) {
   3624        // Somehow qf_count may have an incorrect value, set it to 1
   3625        // to avoid crashing when it's wrong.
   3626        // TODO(vim): Avoid qf_count being incorrect.
   3627        qfl->qf_count = 1;
   3628      } else {
   3629        qfl->qf_start = qfpnext;
   3630      }
   3631    }
   3632    qfl->qf_count--;
   3633  }
   3634 
   3635  qfl->qf_start = NULL;
   3636  qfl->qf_ptr = NULL;
   3637  qfl->qf_index = 0;
   3638  qfl->qf_start = NULL;
   3639  qfl->qf_last = NULL;
   3640  qfl->qf_ptr = NULL;
   3641  qfl->qf_nonevalid = true;
   3642 
   3643  qf_clean_dir_stack(&qfl->qf_dir_stack);
   3644  qfl->qf_directory = NULL;
   3645  qf_clean_dir_stack(&qfl->qf_file_stack);
   3646  qfl->qf_currfile = NULL;
   3647  qfl->qf_multiline = false;
   3648  qfl->qf_multiignore = false;
   3649  qfl->qf_multiscan = false;
   3650 }
   3651 
   3652 /// Free error list "idx". Frees all the entries in the quickfix list,
   3653 /// associated context information and the title.
   3654 static void qf_free(qf_list_T *qfl)
   3655 {
   3656  qf_free_items(qfl);
   3657 
   3658  XFREE_CLEAR(qfl->qf_title);
   3659  tv_free(qfl->qf_ctx);
   3660  qfl->qf_ctx = NULL;
   3661  callback_free(&qfl->qf_qftf_cb);
   3662  qfl->qf_id = 0;
   3663  qfl->qf_changedtick = 0;
   3664 }
   3665 
   3666 /// Adjust error list entries for changed line numbers
   3667 ///
   3668 /// Note: `buf` is the changed buffer, but `wp` is a potential location list
   3669 /// into that buffer, or NULL to check the quickfix list.
   3670 bool qf_mark_adjust(buf_T *buf, win_T *wp, linenr_T line1, linenr_T line2, linenr_T amount,
   3671                    linenr_T amount_after)
   3672 {
   3673  qf_info_T *qi = ql_info;
   3674  assert(qi != NULL);
   3675  int buf_has_flag = wp == NULL ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY;
   3676 
   3677  if (!(buf->b_has_qf_entry & buf_has_flag)) {
   3678    return false;
   3679  }
   3680  if (wp != NULL) {
   3681    if (wp->w_llist == NULL) {
   3682      return false;
   3683    }
   3684    qi = wp->w_llist;
   3685  }
   3686 
   3687  int i;
   3688  qfline_T *qfp;
   3689  bool found_one = false;
   3690  for (int idx = 0; idx < qi->qf_listcount; idx++) {
   3691    qf_list_T *qfl = qf_get_list(qi, idx);
   3692    if (!qf_list_empty(qfl)) {
   3693      FOR_ALL_QFL_ITEMS(qfl, qfp, i) {
   3694        if (qfp->qf_fnum == buf->b_fnum) {
   3695          found_one = true;
   3696          if (qfp->qf_lnum >= line1 && qfp->qf_lnum <= line2) {
   3697            if (amount == MAXLNUM) {
   3698              qfp->qf_cleared = true;
   3699            } else {
   3700              qfp->qf_lnum += amount;
   3701            }
   3702          } else if (amount_after && qfp->qf_lnum > line2) {
   3703            qfp->qf_lnum += amount_after;
   3704          }
   3705        }
   3706      }
   3707    }
   3708  }
   3709 
   3710  return found_one;
   3711 }
   3712 
   3713 // Make a nice message out of the error character and the error number:
   3714 //  char    number  message
   3715 //  e or E    0     " error"
   3716 //  w or W    0     " warning"
   3717 //  i or I    0     " info"
   3718 //  n or N    0     " note"
   3719 //  0         0     ""
   3720 //  other     0     " c"
   3721 //  e or E    n     " error n"
   3722 //  w or W    n     " warning n"
   3723 //  i or I    n     " info n"
   3724 //  n or N    n     " note n"
   3725 //  0         n     " error n"
   3726 //  other     n     " c n"
   3727 //  1         x     ""          :helpgrep
   3728 static char *qf_types(int c, int nr)
   3729 {
   3730  static char cc[3];
   3731  char *p;
   3732 
   3733  if (c == 'W' || c == 'w') {
   3734    p = " warning";
   3735  } else if (c == 'I' || c == 'i') {
   3736    p = " info";
   3737  } else if (c == 'N' || c == 'n') {
   3738    p = " note";
   3739  } else if (c == 'E' || c == 'e' || (c == 0 && nr > 0)) {
   3740    p = " error";
   3741  } else if (c == 0 || c == 1) {
   3742    p = "";
   3743  } else {
   3744    cc[0] = ' ';
   3745    cc[1] = (char)c;
   3746    cc[2] = NUL;
   3747    p = cc;
   3748  }
   3749 
   3750  if (nr <= 0) {
   3751    return p;
   3752  }
   3753 
   3754  static char buf[20];
   3755  snprintf(buf, sizeof(buf), "%s %3d", p, nr);
   3756  return buf;
   3757 }
   3758 
   3759 // When "split" is false: Open the entry/result under the cursor.
   3760 // When "split" is true: Open the entry/result under the cursor in a new window.
   3761 void qf_view_result(bool split)
   3762 {
   3763  qf_info_T *qi = ql_info;
   3764  assert(qi != NULL);
   3765 
   3766  if (IS_LL_WINDOW(curwin)) {
   3767    qi = GET_LOC_LIST(curwin);
   3768  }
   3769 
   3770  if (qf_list_empty(qf_get_curlist(qi))) {
   3771    emsg(_(e_no_errors));
   3772    return;
   3773  }
   3774 
   3775  if (split) {
   3776    // Open the selected entry in a new window
   3777    qf_jump_newwin(qi, 0, (int)curwin->w_cursor.lnum, false, true);
   3778    do_cmdline_cmd("clearjumps");
   3779    return;
   3780  }
   3781 
   3782  do_cmdline_cmd((IS_LL_WINDOW(curwin) ? ".ll" : ".cc"));
   3783 }
   3784 
   3785 // ":cwindow": open the quickfix window if we have errors to display,
   3786 //             close it if not.
   3787 // ":lwindow": open the location list window if we have locations to display,
   3788 //             close it if not.
   3789 void ex_cwindow(exarg_T *eap)
   3790 {
   3791  qf_info_T *qi;
   3792 
   3793  if ((qi = qf_cmd_get_stack(eap, true)) == NULL) {
   3794    return;
   3795  }
   3796 
   3797  qf_list_T *qfl = qf_get_curlist(qi);
   3798 
   3799  // Look for an existing quickfix window.
   3800  win_T *win = qf_find_win(qi);
   3801 
   3802  // If a quickfix window is open but we have no errors to display,
   3803  // close the window.  If a quickfix window is not open, then open
   3804  // it if we have errors; otherwise, leave it closed.
   3805  if (qf_stack_empty(qi)
   3806      || qfl->qf_nonevalid
   3807      || qf_list_empty(qfl)) {
   3808    if (win != NULL) {
   3809      ex_cclose(eap);
   3810    }
   3811  } else if (win == NULL) {
   3812    ex_copen(eap);
   3813  }
   3814 }
   3815 
   3816 // ":cclose": close the window showing the list of errors.
   3817 // ":lclose": close the window showing the location list
   3818 void ex_cclose(exarg_T *eap)
   3819 {
   3820  qf_info_T *qi;
   3821 
   3822  if ((qi = qf_cmd_get_stack(eap, false)) == NULL) {
   3823    return;
   3824  }
   3825 
   3826  // Find existing quickfix window and close it.
   3827  win_T *win = qf_find_win(qi);
   3828  if (win != NULL) {
   3829    win_close(win, false, false);
   3830  }
   3831 }
   3832 
   3833 // Goto a quickfix or location list window (if present).
   3834 // Returns OK if the window is found, FAIL otherwise.
   3835 static int qf_goto_cwindow(const qf_info_T *qi, bool resize, int sz, bool vertsplit)
   3836 {
   3837  win_T *const win = qf_find_win(qi);
   3838  if (win == NULL) {
   3839    return FAIL;
   3840  }
   3841 
   3842  win_goto(win);
   3843  if (resize) {
   3844    if (vertsplit) {
   3845      if (sz != win->w_width) {
   3846        win_setwidth(sz);
   3847      }
   3848    } else if (sz != win->w_height
   3849               && (win->w_height + win->w_hsep_height + win->w_status_height + tabline_height()
   3850                   < cmdline_row)) {
   3851      win_setheight(sz);
   3852    }
   3853  }
   3854 
   3855  return OK;
   3856 }
   3857 
   3858 // Set options for the buffer in the quickfix or location list window.
   3859 static void qf_set_cwindow_options(void)
   3860 {
   3861  // switch off 'swapfile'
   3862  set_option_value_give_err(kOptSwapfile, BOOLEAN_OPTVAL(false), OPT_LOCAL);
   3863  set_option_value_give_err(kOptBuftype, STATIC_CSTR_AS_OPTVAL("quickfix"), OPT_LOCAL);
   3864  set_option_value_give_err(kOptBufhidden, STATIC_CSTR_AS_OPTVAL("hide"), OPT_LOCAL);
   3865  RESET_BINDING(curwin);
   3866  curwin->w_p_diff = false;
   3867  set_option_value_give_err(kOptFoldmethod, STATIC_CSTR_AS_OPTVAL("manual"), OPT_LOCAL);
   3868 }
   3869 
   3870 // Open a new quickfix or location list window, load the quickfix buffer and
   3871 // set the appropriate options for the window.
   3872 // Returns FAIL if the window could not be opened.
   3873 static int qf_open_new_cwindow(qf_info_T *qi, int height)
   3874  FUNC_ATTR_NONNULL_ALL
   3875 {
   3876  win_T *oldwin = curwin;
   3877  const tabpage_T *const prevtab = curtab;
   3878  int flags = 0;
   3879 
   3880  const buf_T *const qf_buf = qf_find_buf(qi);
   3881 
   3882  // The current window becomes the previous window afterwards.
   3883  win_T *const win = curwin;
   3884 
   3885  // Default is to open the window below the current window or at the bottom,
   3886  // except when :belowright or :aboveleft is used.
   3887  if (cmdmod.cmod_split == 0) {
   3888    flags = IS_QF_STACK(qi) ? WSP_BOT : WSP_BELOW;
   3889  }
   3890  flags |= WSP_NEWLOC;
   3891 
   3892  // Create a snapshot for quickfix window (not for location list)
   3893  // so that when closing it, we can restore to the previous window
   3894  if (IS_QF_STACK(qi)) {
   3895    flags |= WSP_QUICKFIX;
   3896  }
   3897 
   3898  if (win_split(height, flags) == FAIL) {
   3899    return FAIL;  // not enough room for window
   3900  }
   3901  RESET_BINDING(curwin);
   3902 
   3903  if (IS_LL_STACK(qi)) {
   3904    // For the location list window, create a reference to the
   3905    // location list stack from the window 'win'.
   3906    curwin->w_llist_ref = qi;
   3907    qi->qf_refcount++;
   3908  }
   3909 
   3910  if (oldwin != curwin) {
   3911    oldwin = NULL;  // don't store info when in another window
   3912  }
   3913  if (qf_buf != NULL) {
   3914    // Use the existing quickfix buffer
   3915    if (do_ecmd(qf_buf->b_fnum, NULL, NULL, NULL, ECMD_ONE,
   3916                ECMD_HIDE + ECMD_OLDBUF + ECMD_NOWINENTER, oldwin) == FAIL) {
   3917      return FAIL;
   3918    }
   3919  } else {
   3920    // Create a new quickfix buffer
   3921    if (do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE + ECMD_NOWINENTER, oldwin) == FAIL) {
   3922      return FAIL;
   3923    }
   3924    // save the number of the new buffer
   3925    qi->qf_bufnr = curbuf->b_fnum;
   3926  }
   3927 
   3928  // Set the options for the quickfix buffer/window (if not already done)
   3929  // Do this even if the quickfix buffer was already present, as an autocmd
   3930  // might have previously deleted (:bdelete) the quickfix buffer.
   3931  if (!bt_quickfix(curbuf)) {
   3932    qf_set_cwindow_options();
   3933  }
   3934 
   3935  // Only set the height when still in the same tab page and there is no
   3936  // window to the side.
   3937  if (curtab == prevtab && curwin->w_width == Columns) {
   3938    win_setheight(height);
   3939  }
   3940  curwin->w_p_wfh = true;  // set 'winfixheight'
   3941  if (win_valid(win)) {
   3942    prevwin = win;
   3943  }
   3944  return OK;
   3945 }
   3946 
   3947 /// Set "w:quickfix_title" if "qi" has a title.
   3948 static void qf_set_title_var(qf_list_T *qfl)
   3949 {
   3950  if (qfl->qf_title != NULL) {
   3951    set_internal_string_var("w:quickfix_title", qfl->qf_title);
   3952  }
   3953 }
   3954 
   3955 /// ":copen": open a window that shows the list of errors.
   3956 /// ":lopen": open a window that shows the location list.
   3957 void ex_copen(exarg_T *eap)
   3958 {
   3959  qf_info_T *qi;
   3960 
   3961  if ((qi = qf_cmd_get_stack(eap, true)) == NULL) {
   3962    return;
   3963  }
   3964 
   3965  incr_quickfix_busy();
   3966 
   3967  int height;
   3968  if (eap->addr_count != 0) {
   3969    height = (int)eap->line2;
   3970  } else {
   3971    height = QF_WINHEIGHT;
   3972  }
   3973  reset_VIsual_and_resel();  // stop Visual mode
   3974 
   3975  // Find an existing quickfix window, or open a new one.
   3976  int status = FAIL;
   3977  if (cmdmod.cmod_tab == 0) {
   3978    status = qf_goto_cwindow(qi, eap->addr_count != 0, height,
   3979                             cmdmod.cmod_split & WSP_VERT);
   3980  }
   3981  if (status == FAIL) {
   3982    if (qf_open_new_cwindow(qi, height) == FAIL) {
   3983      decr_quickfix_busy();
   3984      return;
   3985    }
   3986  }
   3987 
   3988  qf_list_T *qfl = qf_get_curlist(qi);
   3989  qf_set_title_var(qfl);
   3990  // Save the current index here, as updating the quickfix buffer may free
   3991  // the quickfix list
   3992  int lnum = qfl->qf_index;
   3993 
   3994  // Fill the buffer with the quickfix list.
   3995  qf_fill_buffer(qfl, curbuf, NULL, curwin->handle);
   3996 
   3997  decr_quickfix_busy();
   3998 
   3999  curwin->w_cursor.lnum = lnum;
   4000  curwin->w_cursor.col = 0;
   4001  check_cursor(curwin);
   4002  update_topline(curwin);             // scroll to show the line
   4003 }
   4004 
   4005 // Move the cursor in the quickfix window to "lnum".
   4006 static void qf_win_goto(win_T *win, linenr_T lnum)
   4007 {
   4008  win_T *old_curwin = curwin;
   4009 
   4010  curwin = win;
   4011  curbuf = win->w_buffer;
   4012  curwin->w_cursor.lnum = lnum;
   4013  curwin->w_cursor.col = 0;
   4014  curwin->w_cursor.coladd = 0;
   4015  curwin->w_curswant = 0;
   4016  update_topline(curwin);              // scroll to show the line
   4017  redraw_later(curwin, UPD_VALID);
   4018  curwin->w_redr_status = true;  // update ruler
   4019  curwin = old_curwin;
   4020  curbuf = curwin->w_buffer;
   4021 }
   4022 
   4023 /// :cbottom/:lbottom command.
   4024 void ex_cbottom(exarg_T *eap)
   4025 {
   4026  qf_info_T *qi;
   4027 
   4028  if ((qi = qf_cmd_get_stack(eap, true)) == NULL) {
   4029    return;
   4030  }
   4031 
   4032  win_T *win = qf_find_win(qi);
   4033 
   4034  if (win != NULL && win->w_cursor.lnum != win->w_buffer->b_ml.ml_line_count) {
   4035    qf_win_goto(win, win->w_buffer->b_ml.ml_line_count);
   4036  }
   4037 }
   4038 
   4039 // Return the number of the current entry (line number in the quickfix
   4040 // window).
   4041 linenr_T qf_current_entry(win_T *wp)
   4042 {
   4043  qf_info_T *qi = ql_info;
   4044  assert(qi != NULL);
   4045 
   4046  if (IS_LL_WINDOW(wp)) {
   4047    // In the location list window, use the referenced location list
   4048    qi = wp->w_llist_ref;
   4049  }
   4050 
   4051  return qf_get_curlist(qi)->qf_index;
   4052 }
   4053 
   4054 /// Update the cursor position in the quickfix window to the current error.
   4055 /// Return true if there is a quickfix window.
   4056 ///
   4057 /// @param old_qf_index  previous qf_index or zero
   4058 static bool qf_win_pos_update(qf_info_T *qi, int old_qf_index)
   4059 {
   4060  int qf_index = qf_get_curlist(qi)->qf_index;
   4061 
   4062  // Put the cursor on the current error in the quickfix window, so that
   4063  // it's viewable.
   4064  win_T *win = qf_find_win(qi);
   4065  if (win != NULL
   4066      && qf_index <= win->w_buffer->b_ml.ml_line_count
   4067      && old_qf_index != qf_index) {
   4068    win->w_redraw_top = MIN(old_qf_index, qf_index);
   4069    win->w_redraw_bot = MAX(old_qf_index, qf_index);
   4070    qf_win_goto(win, qf_index);
   4071  }
   4072  return win != NULL;
   4073 }
   4074 
   4075 /// Checks whether the given window is displaying the specified
   4076 /// quickfix/location stack.
   4077 static int is_qf_win(const win_T *win, const qf_info_T *qi)
   4078  FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
   4079 {
   4080  // A window displaying the quickfix buffer will have the w_llist_ref field
   4081  // set to NULL.
   4082  // A window displaying a location list buffer will have the w_llist_ref
   4083  // pointing to the location list.
   4084  if (buf_valid(win->w_buffer) && bt_quickfix(win->w_buffer)) {
   4085    if ((IS_QF_STACK(qi) && win->w_llist_ref == NULL)
   4086        || (IS_LL_STACK(qi) && win->w_llist_ref == qi)) {
   4087      return true;
   4088    }
   4089  }
   4090 
   4091  return false;
   4092 }
   4093 
   4094 /// Find a window displaying the quickfix/location stack 'qi' in the current tab
   4095 /// page.
   4096 static win_T *qf_find_win(const qf_info_T *qi)
   4097  FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
   4098 {
   4099  FOR_ALL_WINDOWS_IN_TAB(win, curtab) {
   4100    if (is_qf_win(win, qi)) {
   4101      return win;
   4102    }
   4103  }
   4104 
   4105  return NULL;
   4106 }
   4107 
   4108 /// Find a quickfix buffer.
   4109 /// Searches in windows opened in all the tab pages.
   4110 static buf_T *qf_find_buf(qf_info_T *qi)
   4111  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
   4112 {
   4113  if (qi->qf_bufnr != INVALID_QFBUFNR) {
   4114    buf_T *const qfbuf = buflist_findnr(qi->qf_bufnr);
   4115    if (qfbuf != NULL) {
   4116      return qfbuf;
   4117    }
   4118    // buffer is no longer present
   4119    qi->qf_bufnr = INVALID_QFBUFNR;
   4120  }
   4121 
   4122  FOR_ALL_TAB_WINDOWS(tp, win) {
   4123    if (is_qf_win(win, qi)) {
   4124      return win->w_buffer;
   4125    }
   4126  }
   4127 
   4128  return NULL;
   4129 }
   4130 
   4131 /// Process the 'quickfixtextfunc' option value.
   4132 const char *did_set_quickfixtextfunc(optset_T *args FUNC_ATTR_UNUSED)
   4133 {
   4134  if (option_set_callback_func(p_qftf, &qftf_cb) == FAIL) {
   4135    return e_invarg;
   4136  }
   4137  return NULL;
   4138 }
   4139 
   4140 /// Update the w:quickfix_title variable in the quickfix/location list window in
   4141 /// all the tab pages.
   4142 static void qf_update_win_titlevar(qf_info_T *qi)
   4143  FUNC_ATTR_NONNULL_ALL
   4144 {
   4145  qf_list_T *const qfl = qf_get_curlist(qi);
   4146  win_T *const save_curwin = curwin;
   4147 
   4148  FOR_ALL_TAB_WINDOWS(tp, win) {
   4149    if (is_qf_win(win, qi)) {
   4150      curwin = win;
   4151      qf_set_title_var(qfl);
   4152    }
   4153  }
   4154  curwin = save_curwin;
   4155 }
   4156 
   4157 // Find the quickfix buffer.  If it exists, update the contents.
   4158 static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last)
   4159 {
   4160  // Check if a buffer for the quickfix list exists.  Update it.
   4161  buf_T *buf = qf_find_buf(qi);
   4162  if (buf == NULL) {
   4163    return;
   4164  }
   4165 
   4166  linenr_T old_line_count = buf->b_ml.ml_line_count;
   4167  colnr_T old_endcol = ml_get_buf_len(buf, old_line_count);
   4168  bcount_t old_bytecount = get_region_bytecount(buf, 1, old_line_count, 0, old_endcol);
   4169  int qf_winid = 0;
   4170 
   4171  win_T *win;
   4172  if (IS_LL_STACK(qi)) {
   4173    if (curwin->w_llist == qi) {
   4174      win = curwin;
   4175    } else {
   4176      // Find the file window (non-quickfix) with this location list
   4177      win = qf_find_win_with_loclist(qi);
   4178      if (win == NULL) {
   4179        // File window is not found. Find the location list window.
   4180        win = qf_find_win(qi);
   4181      }
   4182      if (win == NULL) {
   4183        return;
   4184      }
   4185    }
   4186    qf_winid = (int)win->handle;
   4187  }
   4188 
   4189  // autocommands may cause trouble
   4190  incr_quickfix_busy();
   4191 
   4192  aco_save_T aco;
   4193 
   4194  if (old_last == NULL) {
   4195    // set curwin/curbuf to buf and save a few things
   4196    aucmd_prepbuf(&aco, buf);
   4197  }
   4198 
   4199  qf_update_win_titlevar(qi);
   4200 
   4201  qf_fill_buffer(qf_get_curlist(qi), buf, old_last, qf_winid);
   4202 
   4203  linenr_T new_line_count = buf->b_ml.ml_line_count;
   4204  colnr_T new_endcol = ml_get_buf_len(buf, new_line_count);
   4205  bcount_t new_byte_count = 0;
   4206  linenr_T delta = new_line_count - old_line_count;
   4207 
   4208  if (old_last == NULL) {
   4209    new_byte_count = get_region_bytecount(buf, 1, new_line_count, 0, new_endcol);
   4210    extmark_splice(buf, 0, 0, old_line_count - 1, 0, old_bytecount, new_line_count - 1, new_endcol,
   4211                   new_byte_count, kExtmarkNoUndo);
   4212    changed_lines(buf, 1, 0, old_line_count > 0 ? old_line_count + 1 : 1, delta, true);
   4213  } else if (delta > 0) {
   4214    linenr_T start_lnum = old_line_count + 1;
   4215    new_byte_count = get_region_bytecount(buf, start_lnum, new_line_count, 0, new_endcol);
   4216    extmark_splice(buf, old_line_count - 1, old_endcol, 0, 0, 0, delta, new_endcol, new_byte_count,
   4217                   kExtmarkNoUndo);
   4218    changed_lines(buf, start_lnum, 0, start_lnum, delta, true);
   4219  }
   4220  buf->b_changed = false;
   4221 
   4222  if (old_last == NULL) {
   4223    qf_win_pos_update(qi, 0);
   4224 
   4225    // restore curwin/curbuf and a few other things
   4226    aucmd_restbuf(&aco);
   4227  }
   4228 
   4229  // Only redraw when added lines are visible.  This avoids flickering when
   4230  // the added lines are not visible.
   4231  if ((win = qf_find_win(qi)) != NULL && old_line_count < win->w_botline) {
   4232    redraw_buf_later(buf, UPD_NOT_VALID);
   4233  }
   4234 
   4235  // always called after incr_quickfix_busy()
   4236  decr_quickfix_busy();
   4237 }
   4238 
   4239 // Add an error line to the quickfix buffer.
   4240 static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum, const qfline_T *qfp,
   4241                           char *dirname, char *qftf_str, bool first_bufline)
   4242  FUNC_ATTR_NONNULL_ARG(1, 2, 4, 5)
   4243 {
   4244  garray_T *gap = qfga_get();
   4245 
   4246  // If the 'quickfixtextfunc' function returned a non-empty custom string
   4247  // for this entry, then use it.
   4248  if (qftf_str != NULL && *qftf_str != NUL) {
   4249    ga_concat(gap, qftf_str);
   4250  } else {
   4251    buf_T *errbuf;
   4252    if (qfp->qf_module != NULL) {
   4253      ga_concat(gap, qfp->qf_module);
   4254    } else if (qfp->qf_fnum != 0
   4255               && (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL
   4256               && errbuf->b_fname != NULL) {
   4257      if (qfp->qf_type == 1) {  // :helpgrep
   4258        ga_concat(gap, path_tail(errbuf->b_fname));
   4259      } else {
   4260        // Shorten the file name if not done already.
   4261        // For optimization, do this only for the first entry in a
   4262        // buffer.
   4263        if (first_bufline
   4264            && (errbuf->b_sfname == NULL
   4265                || path_is_absolute(errbuf->b_sfname))) {
   4266          if (*dirname == NUL) {
   4267            os_dirname(dirname, MAXPATHL);
   4268          }
   4269          shorten_buf_fname(errbuf, dirname, false);
   4270        }
   4271        ga_concat(gap, qfp->qf_fname == NULL ? errbuf->b_fname : qfp->qf_fname);
   4272      }
   4273    }
   4274 
   4275    ga_append(gap, '|');
   4276 
   4277    if (qfp->qf_lnum > 0) {
   4278      qf_range_text(gap, qfp);
   4279      ga_concat(gap, qf_types(qfp->qf_type, qfp->qf_nr));
   4280    } else if (qfp->qf_pattern != NULL) {
   4281      qf_fmt_text(gap, qfp->qf_pattern);
   4282    }
   4283    ga_append(gap, '|');
   4284    ga_append(gap, ' ');
   4285 
   4286    // Remove newlines and leading whitespace from the text.
   4287    // For an unrecognized line keep the indent, the compiler may
   4288    // mark a word with ^^^^.
   4289    qf_fmt_text(gap, gap->ga_len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text);
   4290  }
   4291 
   4292  ga_append(gap, NUL);
   4293  if (ml_append_buf(buf, lnum, gap->ga_data, gap->ga_len, false) == FAIL) {
   4294    return FAIL;
   4295  }
   4296 
   4297  return OK;
   4298 }
   4299 
   4300 // Call the 'quickfixtextfunc' function to get the list of lines to display in
   4301 // the quickfix window for the entries 'start_idx' to 'end_idx'.
   4302 static list_T *call_qftf_func(qf_list_T *qfl, int qf_winid, int start_idx, int end_idx)
   4303 {
   4304  Callback *cb = &qftf_cb;
   4305  list_T *qftf_list = NULL;
   4306  static bool recursive = false;
   4307 
   4308  if (recursive) {
   4309    return NULL;  // this doesn't work properly recursively
   4310  }
   4311  recursive = true;
   4312 
   4313  // If 'quickfixtextfunc' is set, then use the user-supplied function to get
   4314  // the text to display. Use the local value of 'quickfixtextfunc' if it is
   4315  // set.
   4316  if (qfl->qf_qftf_cb.type != kCallbackNone) {
   4317    cb = &qfl->qf_qftf_cb;
   4318  }
   4319  if (cb->type != kCallbackNone) {
   4320    typval_T args[1];
   4321    typval_T rettv;
   4322 
   4323    // create the dict argument
   4324    dict_T *const dict = tv_dict_alloc_lock(VAR_FIXED);
   4325 
   4326    tv_dict_add_nr(dict, S_LEN("quickfix"), IS_QF_LIST(qfl));
   4327    tv_dict_add_nr(dict, S_LEN("winid"), qf_winid);
   4328    tv_dict_add_nr(dict, S_LEN("id"), qfl->qf_id);
   4329    tv_dict_add_nr(dict, S_LEN("start_idx"), start_idx);
   4330    tv_dict_add_nr(dict, S_LEN("end_idx"), end_idx);
   4331    dict->dv_refcount++;
   4332    args[0].v_type = VAR_DICT;
   4333    args[0].vval.v_dict = dict;
   4334 
   4335    textlock++;
   4336    if (callback_call(cb, 1, args, &rettv)) {
   4337      if (rettv.v_type == VAR_LIST) {
   4338        qftf_list = rettv.vval.v_list;
   4339        tv_list_ref(qftf_list);
   4340      }
   4341      tv_clear(&rettv);
   4342    }
   4343    textlock--;
   4344    tv_dict_unref(dict);
   4345  }
   4346 
   4347  recursive = false;
   4348  return qftf_list;
   4349 }
   4350 
   4351 /// Fill current buffer with quickfix errors, replacing any previous contents.
   4352 /// curbuf must be the quickfix buffer!
   4353 /// If "old_last" is not NULL append the items after this one.
   4354 /// When "old_last" is NULL then "buf" must equal "curbuf"!  Because ml_delete()
   4355 /// is used and autocommands will be triggered.
   4356 static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int qf_winid)
   4357  FUNC_ATTR_NONNULL_ARG(2)
   4358 {
   4359  const bool old_KeyTyped = KeyTyped;
   4360 
   4361  if (old_last == NULL) {
   4362    if (buf != curbuf) {
   4363      internal_error("qf_fill_buffer()");
   4364      return;
   4365    }
   4366 
   4367    // delete all existing lines
   4368    //
   4369    // Note: we cannot store undo information, because
   4370    // qf buffer is usually not allowed to be modified.
   4371    //
   4372    // So we need to clean up undo information
   4373    // otherwise autocommands may invalidate the undo stack
   4374    while ((curbuf->b_ml.ml_flags & ML_EMPTY) == 0) {
   4375      // If deletion fails, this loop may run forever, so
   4376      // signal error and return.
   4377      if (ml_delete(1) == FAIL) {
   4378        internal_error("qf_fill_buffer()");
   4379        return;
   4380      }
   4381    }
   4382 
   4383    FOR_ALL_TAB_WINDOWS(tp, wp) {
   4384      if (wp->w_buffer == curbuf) {
   4385        wp->w_skipcol = 0;
   4386      }
   4387    }
   4388 
   4389    // Remove all undo information
   4390    u_clearallandblockfree(curbuf);
   4391  }
   4392 
   4393  // Check if there is anything to display
   4394  if (qfl != NULL && qfl->qf_start != NULL) {
   4395    char dirname[MAXPATHL];
   4396 
   4397    *dirname = NUL;
   4398 
   4399    linenr_T lnum;
   4400    qfline_T *qfp;
   4401 
   4402    // Add one line for each error
   4403    if (old_last == NULL) {
   4404      qfp = qfl->qf_start;
   4405      lnum = 0;
   4406    } else {
   4407      qfp = old_last->qf_next != NULL ? old_last->qf_next : old_last;
   4408      lnum = buf->b_ml.ml_line_count;
   4409    }
   4410 
   4411    list_T *qftf_list = call_qftf_func(qfl, qf_winid, lnum + 1, qfl->qf_count);
   4412    listitem_T *qftf_li = tv_list_first(qftf_list);
   4413 
   4414    int prev_bufnr = -1;
   4415    bool invalid_val = false;
   4416 
   4417    while (lnum < qfl->qf_count) {
   4418      char *qftf_str = NULL;
   4419 
   4420      // Use the text supplied by the user defined function (if any).
   4421      // If the returned value is not string, then ignore the rest
   4422      // of the returned values and use the default.
   4423      if (qftf_li != NULL && !invalid_val) {
   4424        qftf_str = (char *)tv_get_string_chk(TV_LIST_ITEM_TV(qftf_li));
   4425        if (qftf_str == NULL) {
   4426          invalid_val = true;
   4427        }
   4428      }
   4429 
   4430      if (qf_buf_add_line(qfl, buf, lnum, qfp, dirname, qftf_str,
   4431                          prev_bufnr != qfp->qf_fnum) == FAIL) {
   4432        break;
   4433      }
   4434      prev_bufnr = qfp->qf_fnum;
   4435      lnum++;
   4436      qfp = qfp->qf_next;
   4437      if (qfp == NULL) {
   4438        break;
   4439      }
   4440 
   4441      if (qftf_li != NULL) {
   4442        qftf_li = TV_LIST_ITEM_NEXT(qftf_list, qftf_li);
   4443      }
   4444    }
   4445    if (old_last == NULL) {
   4446      // Delete the empty line which is now at the end
   4447      ml_delete(lnum + 1);
   4448    }
   4449 
   4450    qfga_clear();
   4451  }
   4452 
   4453  // Correct cursor position.
   4454  check_lnums(true);
   4455 
   4456  if (old_last == NULL) {
   4457    // Set the 'filetype' to "qf" each time after filling the buffer.  This
   4458    // resembles reading a file into a buffer, it's more logical when using
   4459    // autocommands.
   4460    curbuf->b_ro_locked++;
   4461    set_option_value_give_err(kOptFiletype, STATIC_CSTR_AS_OPTVAL("qf"), OPT_LOCAL);
   4462    curbuf->b_p_ma = false;
   4463 
   4464    curbuf->b_keep_filetype = true;  // don't detect 'filetype'
   4465    apply_autocmds(EVENT_BUFREADPOST, "quickfix", NULL, false, curbuf);
   4466    apply_autocmds(EVENT_BUFWINENTER, "quickfix", NULL, false, curbuf);
   4467    curbuf->b_keep_filetype = false;
   4468    curbuf->b_ro_locked--;
   4469 
   4470    // make sure it will be redrawn
   4471    redraw_curbuf_later(UPD_NOT_VALID);
   4472  }
   4473 
   4474  // Restore KeyTyped, setting 'filetype' may reset it.
   4475  KeyTyped = old_KeyTyped;
   4476 }
   4477 
   4478 static void qf_list_changed(qf_list_T *qfl)
   4479 {
   4480  qfl->qf_changedtick++;
   4481 }
   4482 
   4483 /// Return the quickfix/location list number with the given identifier.
   4484 ///
   4485 /// @returns -1 if list is not found.
   4486 static int qf_id2nr(const qf_info_T *const qi, const unsigned qfid)
   4487 {
   4488  for (int qf_idx = 0; qf_idx < qi->qf_listcount; qf_idx++) {
   4489    if (qi->qf_lists[qf_idx].qf_id == qfid) {
   4490      return qf_idx;
   4491    }
   4492  }
   4493  return INVALID_QFIDX;
   4494 }
   4495 
   4496 /// If the current list is not "save_qfid" and we can find the list with that ID
   4497 /// then make it the current list.
   4498 /// This is used when autocommands may have changed the current list.
   4499 /// Returns OK if successfully restored the list. Returns FAIL if the list with
   4500 /// the specified identifier (save_qfid) is not found in the stack.
   4501 static int qf_restore_list(qf_info_T *qi, unsigned save_qfid)
   4502  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
   4503 {
   4504  if (qf_get_curlist(qi)->qf_id == save_qfid) {
   4505    return OK;
   4506  }
   4507 
   4508  const int curlist = qf_id2nr(qi, save_qfid);
   4509  if (curlist < 0) {
   4510    // list is not present
   4511    return FAIL;
   4512  }
   4513  qi->qf_curlist = curlist;
   4514  return OK;
   4515 }
   4516 
   4517 // Jump to the first entry if there is one.
   4518 static void qf_jump_first(qf_info_T *qi, unsigned save_qfid, int forceit)
   4519  FUNC_ATTR_NONNULL_ALL
   4520 {
   4521  if (qf_restore_list(qi, save_qfid) == FAIL) {
   4522    return;
   4523  }
   4524 
   4525  if (!check_can_set_curbuf_forceit(forceit)) {
   4526    return;
   4527  }
   4528 
   4529  // Autocommands might have cleared the list, check for that
   4530  if (!qf_list_empty(qf_get_curlist(qi))) {
   4531    qf_jump(qi, 0, 0, forceit);
   4532  }
   4533 }
   4534 
   4535 // Return true when using ":vimgrep" for ":grep".
   4536 int grep_internal(cmdidx_T cmdidx)
   4537 {
   4538  return (cmdidx == CMD_grep
   4539          || cmdidx == CMD_lgrep
   4540          || cmdidx == CMD_grepadd
   4541          || cmdidx == CMD_lgrepadd)
   4542         && strcmp("internal", *curbuf->b_p_gp == NUL ? p_gp : curbuf->b_p_gp) == 0;
   4543 }
   4544 
   4545 // Return the make/grep autocmd name.
   4546 static char *make_get_auname(cmdidx_T cmdidx)
   4547  FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
   4548 {
   4549  switch (cmdidx) {
   4550  case CMD_make:
   4551    return "make";
   4552  case CMD_lmake:
   4553    return "lmake";
   4554  case CMD_grep:
   4555    return "grep";
   4556  case CMD_lgrep:
   4557    return "lgrep";
   4558  case CMD_grepadd:
   4559    return "grepadd";
   4560  case CMD_lgrepadd:
   4561    return "lgrepadd";
   4562  default:
   4563    return NULL;
   4564  }
   4565 }
   4566 
   4567 // Form the complete command line to invoke 'make'/'grep'. Quote the command
   4568 // using 'shellquote' and append 'shellpipe'. Echo the fully formed command.
   4569 static char *make_get_fullcmd(const char *makecmd, const char *fname)
   4570  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
   4571 {
   4572  size_t len = strlen(p_shq) * 2 + strlen(makecmd) + 1;
   4573  if (*p_sp != NUL) {
   4574    len += strlen(p_sp) + strlen(fname) + 3;
   4575  }
   4576  char *const cmd = xmalloc(len);
   4577  snprintf(cmd, len, "%s%s%s", p_shq, makecmd, p_shq);
   4578 
   4579  // If 'shellpipe' empty: don't redirect to 'errorfile'.
   4580  if (*p_sp != NUL) {
   4581    append_redir(cmd, len, p_sp, fname);
   4582  }
   4583 
   4584  // Display the fully formed command.  Output a newline if there's something
   4585  // else than the :make command that was typed (in which case the cursor is
   4586  // in column 0).
   4587  if (msg_col == 0) {
   4588    msg_didout = false;
   4589  }
   4590  msg_start();
   4591  msg_puts(":!");
   4592  msg_outtrans(cmd, 0, false);  // show what we are doing
   4593 
   4594  return cmd;
   4595 }
   4596 
   4597 // Used for ":make", ":lmake", ":grep", ":lgrep", ":grepadd", and ":lgrepadd"
   4598 void ex_make(exarg_T *eap)
   4599 {
   4600  char *enc = (*curbuf->b_p_menc != NUL) ? curbuf->b_p_menc : p_menc;
   4601 
   4602  // Redirect ":grep" to ":vimgrep" if 'grepprg' is "internal".
   4603  if (grep_internal(eap->cmdidx)) {
   4604    ex_vimgrep(eap);
   4605    return;
   4606  }
   4607 
   4608  char *const au_name = make_get_auname(eap->cmdidx);
   4609  if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
   4610                                        curbuf->b_fname, true, curbuf)) {
   4611    if (aborting()) {
   4612      return;
   4613    }
   4614  }
   4615 
   4616  win_T *wp = NULL;
   4617  if (is_loclist_cmd(eap->cmdidx)) {
   4618    wp = curwin;
   4619  }
   4620 
   4621  autowrite_all();
   4622  char *fname = get_mef_name();
   4623  if (fname == NULL) {
   4624    return;
   4625  }
   4626  os_remove(fname);  // in case it's not unique
   4627 
   4628  char *const cmd = make_get_fullcmd(eap->arg, fname);
   4629 
   4630  do_shell(cmd, 0);
   4631 
   4632  incr_quickfix_busy();
   4633 
   4634  char *errorformat = (eap->cmdidx != CMD_make && eap->cmdidx != CMD_lmake)
   4635                      ? *curbuf->b_p_gefm != NUL ? curbuf->b_p_gefm : p_gefm
   4636                      : p_efm;
   4637 
   4638  bool newlist = eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_lgrepadd;
   4639 
   4640  int res = qf_init(wp, fname, errorformat, newlist, qf_cmdtitle(*eap->cmdlinep), enc);
   4641 
   4642  qf_info_T *qi = ql_info;
   4643  assert(qi != NULL);
   4644  if (wp != NULL) {
   4645    qi = GET_LOC_LIST(wp);
   4646    if (qi == NULL) {
   4647      goto cleanup;
   4648    }
   4649  }
   4650  if (res >= 0) {
   4651    qf_list_changed(qf_get_curlist(qi));
   4652  }
   4653  // Remember the current quickfix list identifier, so that we can
   4654  // check for autocommands changing the current quickfix list.
   4655  unsigned save_qfid = qf_get_curlist(qi)->qf_id;
   4656  if (au_name != NULL) {
   4657    apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, curbuf->b_fname, true,
   4658                   curbuf);
   4659  }
   4660  if (res > 0 && !eap->forceit && qflist_valid(wp, save_qfid)) {
   4661    // display the first error
   4662    qf_jump_first(qi, save_qfid, false);
   4663  }
   4664 
   4665 cleanup:
   4666  decr_quickfix_busy();
   4667  os_remove(fname);
   4668  xfree(fname);
   4669  xfree(cmd);
   4670 }
   4671 
   4672 // Return the name for the errorfile, in allocated memory.
   4673 // Find a new unique name when 'makeef' contains "##".
   4674 // Returns NULL for error.
   4675 static char *get_mef_name(void)
   4676 {
   4677  char *name;
   4678  static int start = -1;
   4679  static int off = 0;
   4680 
   4681  if (*p_mef == NUL) {
   4682    name = vim_tempname();
   4683    if (name == NULL) {
   4684      emsg(_(e_notmp));
   4685    }
   4686    return name;
   4687  }
   4688 
   4689  char *p;
   4690 
   4691  for (p = p_mef; *p; p++) {
   4692    if (p[0] == '#' && p[1] == '#') {
   4693      break;
   4694    }
   4695  }
   4696 
   4697  if (*p == NUL) {
   4698    return xstrdup(p_mef);
   4699  }
   4700 
   4701  // Keep trying until the name doesn't exist yet.
   4702  while (true) {
   4703    if (start == -1) {
   4704      start = (int)os_get_pid();
   4705    } else {
   4706      off += 19;
   4707    }
   4708    name = xmalloc(strlen(p_mef) + 30);
   4709    STRCPY(name, p_mef);
   4710    snprintf(name + (p - p_mef), strlen(name), "%d%d", start, off);
   4711    strcat(name, p + 2);
   4712    // Don't accept a symbolic link, it's a security risk.
   4713    FileInfo file_info;
   4714    bool file_or_link_found = os_fileinfo_link(name, &file_info);
   4715    if (!file_or_link_found) {
   4716      break;
   4717    }
   4718    xfree(name);
   4719  }
   4720  return name;
   4721 }
   4722 
   4723 /// Returns the number of entries in the current quickfix/location list.
   4724 size_t qf_get_size(exarg_T *eap)
   4725  FUNC_ATTR_NONNULL_ALL
   4726 {
   4727  qf_info_T *qi;
   4728 
   4729  if ((qi = qf_cmd_get_stack(eap, false)) == NULL) {
   4730    return 0;
   4731  }
   4732  return (size_t)qf_get_curlist(qi)->qf_count;
   4733 }
   4734 
   4735 /// Returns the number of valid entries in the current quickfix/location list.
   4736 size_t qf_get_valid_size(exarg_T *eap)
   4737 {
   4738  qf_info_T *qi;
   4739 
   4740  if ((qi = qf_cmd_get_stack(eap, false)) == NULL) {
   4741    return 0;
   4742  }
   4743 
   4744  int prev_fnum = 0;
   4745  size_t sz = 0;
   4746  qfline_T *qfp;
   4747  int i;
   4748  assert(qf_get_curlist(qi)->qf_count >= 0);
   4749  qf_list_T *qfl = qf_get_curlist(qi);
   4750  FOR_ALL_QFL_ITEMS(qfl, qfp, i) {
   4751    if (!qfp->qf_valid) {
   4752      continue;
   4753    }
   4754 
   4755    if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo) {
   4756      // Count all valid entries.
   4757      sz++;
   4758    } else if (qfp->qf_fnum > 0 && qfp->qf_fnum != prev_fnum) {
   4759      // Count the number of files.
   4760      sz++;
   4761      prev_fnum = qfp->qf_fnum;
   4762    }
   4763  }
   4764 
   4765  return sz;
   4766 }
   4767 
   4768 /// Returns the current index of the quickfix/location list.
   4769 /// Returns 0 if there is an error.
   4770 size_t qf_get_cur_idx(exarg_T *eap)
   4771  FUNC_ATTR_NONNULL_ALL
   4772 {
   4773  qf_info_T *qi;
   4774 
   4775  if ((qi = qf_cmd_get_stack(eap, false)) == NULL) {
   4776    return 0;
   4777  }
   4778 
   4779  assert(qf_get_curlist(qi)->qf_index >= 0);
   4780  return (size_t)qf_get_curlist(qi)->qf_index;
   4781 }
   4782 
   4783 /// Returns the current index in the quickfix/location list,
   4784 /// counting only valid entries.
   4785 /// Returns 1 if there are no valid entries.
   4786 int qf_get_cur_valid_idx(exarg_T *eap)
   4787  FUNC_ATTR_NONNULL_ALL
   4788 {
   4789  qf_info_T *qi;
   4790 
   4791  if ((qi = qf_cmd_get_stack(eap, false)) == NULL) {
   4792    return 1;
   4793  }
   4794 
   4795  qf_list_T *qfl = qf_get_curlist(qi);
   4796 
   4797  // Check if the list has valid errors.
   4798  if (!qf_list_has_valid_entries(qfl)) {
   4799    return 1;
   4800  }
   4801 
   4802  int prev_fnum = 0;
   4803  int eidx = 0;
   4804  qfline_T *qfp;
   4805  size_t i;
   4806  assert(qfl->qf_index >= 0);
   4807  for (i = 1, qfp = qfl->qf_start;
   4808       i <= (size_t)qfl->qf_index && qfp != NULL;
   4809       i++, qfp = qfp->qf_next) {
   4810    if (!qfp->qf_valid) {
   4811      continue;
   4812    }
   4813 
   4814    if (eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) {
   4815      if (qfp->qf_fnum > 0 && qfp->qf_fnum != prev_fnum) {
   4816        // Count the number of files.
   4817        eidx++;
   4818        prev_fnum = qfp->qf_fnum;
   4819      }
   4820    } else {
   4821      eidx++;
   4822    }
   4823  }
   4824 
   4825  return eidx != 0 ? eidx : 1;
   4826 }
   4827 
   4828 /// Get the 'n'th valid error entry in the quickfix or location list.
   4829 ///
   4830 /// Used by :cdo, :ldo, :cfdo and :lfdo commands.
   4831 /// For :cdo and :ldo, returns the 'n'th valid error entry.
   4832 /// For :cfdo and :lfdo, returns the 'n'th valid file entry.
   4833 static size_t qf_get_nth_valid_entry(qf_list_T *qfl, size_t n, bool fdo)
   4834  FUNC_ATTR_NONNULL_ALL
   4835 {
   4836  // Check if the list has valid errors.
   4837  if (!qf_list_has_valid_entries(qfl)) {
   4838    return 1;
   4839  }
   4840 
   4841  int prev_fnum = 0;
   4842  size_t eidx = 0;
   4843  int i;
   4844  qfline_T *qfp;
   4845  assert(qfl->qf_count >= 0);
   4846  FOR_ALL_QFL_ITEMS(qfl, qfp, i) {
   4847    if (qfp->qf_valid) {
   4848      if (fdo) {
   4849        if (qfp->qf_fnum > 0 && qfp->qf_fnum != prev_fnum) {
   4850          // Count the number of files.
   4851          eidx++;
   4852          prev_fnum = qfp->qf_fnum;
   4853        }
   4854      } else {
   4855        eidx++;
   4856      }
   4857    }
   4858 
   4859    if (eidx == n) {
   4860      break;
   4861    }
   4862  }
   4863 
   4864  return i <= qfl->qf_count ? (size_t)i : 1;
   4865 }
   4866 
   4867 /// ":cc", ":crewind", ":cfirst" and ":clast".
   4868 /// ":ll", ":lrewind", ":lfirst" and ":llast".
   4869 /// ":cdo", ":ldo", ":cfdo" and ":lfdo".
   4870 void ex_cc(exarg_T *eap)
   4871 {
   4872  qf_info_T *qi;
   4873 
   4874  if ((qi = qf_cmd_get_stack(eap, true)) == NULL) {
   4875    return;
   4876  }
   4877 
   4878  int errornr;
   4879  if (eap->addr_count > 0) {
   4880    errornr = (int)eap->line2;
   4881  } else {
   4882    switch (eap->cmdidx) {
   4883    case CMD_cc:
   4884    case CMD_ll:
   4885      errornr = 0;
   4886      break;
   4887    case CMD_crewind:
   4888    case CMD_lrewind:
   4889    case CMD_cfirst:
   4890    case CMD_lfirst:
   4891      errornr = 1;
   4892      break;
   4893    default:
   4894      errornr = 32767;
   4895      break;
   4896    }
   4897  }
   4898 
   4899  // For cdo and ldo commands, jump to the nth valid error.
   4900  // For cfdo and lfdo commands, jump to the nth valid file entry.
   4901  if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo
   4902      || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) {
   4903    size_t n;
   4904    if (eap->addr_count > 0) {
   4905      assert(eap->line1 >= 0);
   4906      n = (size_t)eap->line1;
   4907    } else {
   4908      n = 1;
   4909    }
   4910    size_t valid_entry = qf_get_nth_valid_entry(qf_get_curlist(qi), n,
   4911                                                eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo);
   4912    assert(valid_entry <= INT_MAX);
   4913    errornr = (int)valid_entry;
   4914  }
   4915 
   4916  qf_jump(qi, 0, errornr, eap->forceit);
   4917 }
   4918 
   4919 /// ":cnext", ":cnfile", ":cNext" and ":cprevious".
   4920 /// ":lnext", ":lNext", ":lprevious", ":lnfile", ":lNfile" and ":lpfile".
   4921 /// ":cdo", ":ldo", ":cfdo" and ":lfdo".
   4922 void ex_cnext(exarg_T *eap)
   4923 {
   4924  qf_info_T *qi;
   4925 
   4926  if ((qi = qf_cmd_get_stack(eap, true)) == NULL) {
   4927    return;
   4928  }
   4929 
   4930  int errornr;
   4931  if (eap->addr_count > 0
   4932      && (eap->cmdidx != CMD_cdo && eap->cmdidx != CMD_ldo
   4933          && eap->cmdidx != CMD_cfdo && eap->cmdidx != CMD_lfdo)) {
   4934    errornr = (int)eap->line2;
   4935  } else {
   4936    errornr = 1;
   4937  }
   4938 
   4939  // Depending on the command jump to either next or previous entry/file.
   4940  Direction dir;
   4941  switch (eap->cmdidx) {
   4942  case CMD_cprevious:
   4943  case CMD_lprevious:
   4944  case CMD_cNext:
   4945  case CMD_lNext:
   4946    dir = BACKWARD;
   4947    break;
   4948  case CMD_cnfile:
   4949  case CMD_lnfile:
   4950  case CMD_cfdo:
   4951  case CMD_lfdo:
   4952    dir = FORWARD_FILE;
   4953    break;
   4954  case CMD_cpfile:
   4955  case CMD_lpfile:
   4956  case CMD_cNfile:
   4957  case CMD_lNfile:
   4958    dir = BACKWARD_FILE;
   4959    break;
   4960  case CMD_cnext:
   4961  case CMD_lnext:
   4962  case CMD_cdo:
   4963  case CMD_ldo:
   4964  default:
   4965    dir = FORWARD;
   4966    break;
   4967  }
   4968 
   4969  qf_jump(qi, dir, errornr, eap->forceit);
   4970 }
   4971 
   4972 /// Find the first entry in the quickfix list 'qfl' from buffer 'bnr'.
   4973 /// The index of the entry is stored in 'errornr'.
   4974 /// Returns NULL if an entry is not found.
   4975 static qfline_T *qf_find_first_entry_in_buf(qf_list_T *qfl, int bnr, int *errornr)
   4976 {
   4977  qfline_T *qfp = NULL;
   4978  int idx = 0;
   4979 
   4980  // Find the first entry in this file
   4981  FOR_ALL_QFL_ITEMS(qfl, qfp, idx) {
   4982    if (qfp->qf_fnum == bnr) {
   4983      break;
   4984    }
   4985  }
   4986 
   4987  *errornr = idx;
   4988  return qfp;
   4989 }
   4990 
   4991 /// Find the first quickfix entry on the same line as 'entry'. Updates 'errornr'
   4992 /// with the error number for the first entry. Assumes the entries are sorted in
   4993 /// the quickfix list by line number.
   4994 static qfline_T *qf_find_first_entry_on_line(qfline_T *entry, int *errornr)
   4995 {
   4996  while (!got_int
   4997         && entry->qf_prev != NULL
   4998         && entry->qf_fnum == entry->qf_prev->qf_fnum
   4999         && entry->qf_lnum == entry->qf_prev->qf_lnum) {
   5000    entry = entry->qf_prev;
   5001    (*errornr)--;
   5002  }
   5003 
   5004  return entry;
   5005 }
   5006 
   5007 /// Find the last quickfix entry on the same line as 'entry'. Updates 'errornr'
   5008 /// with the error number for the last entry. Assumes the entries are sorted in
   5009 /// the quickfix list by line number.
   5010 static qfline_T *qf_find_last_entry_on_line(qfline_T *entry, int *errornr)
   5011 {
   5012  while (!got_int
   5013         && entry->qf_next != NULL
   5014         && entry->qf_fnum == entry->qf_next->qf_fnum
   5015         && entry->qf_lnum == entry->qf_next->qf_lnum) {
   5016    entry = entry->qf_next;
   5017    (*errornr)++;
   5018  }
   5019 
   5020  return entry;
   5021 }
   5022 
   5023 // Returns true if the specified quickfix entry is
   5024 // after the given line (linewise is true)
   5025 // or after the line and column.
   5026 static bool qf_entry_after_pos(const qfline_T *qfp, const pos_T *pos, bool linewise)
   5027  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
   5028 {
   5029  if (linewise) {
   5030    return qfp->qf_lnum > pos->lnum;
   5031  }
   5032  return qfp->qf_lnum > pos->lnum
   5033         || (qfp->qf_lnum == pos->lnum && qfp->qf_col > pos->col);
   5034 }
   5035 
   5036 // Returns true if the specified quickfix entry is
   5037 // before the given line (linewise is true)
   5038 // or before the line and column.
   5039 static bool qf_entry_before_pos(const qfline_T *qfp, const pos_T *pos, bool linewise)
   5040  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
   5041 {
   5042  if (linewise) {
   5043    return qfp->qf_lnum < pos->lnum;
   5044  }
   5045  return qfp->qf_lnum < pos->lnum
   5046         || (qfp->qf_lnum == pos->lnum && qfp->qf_col < pos->col);
   5047 }
   5048 
   5049 // Returns true if the specified quickfix entry is
   5050 // on or after the given line (linewise is true)
   5051 // or on or after the line and column.
   5052 static bool qf_entry_on_or_after_pos(const qfline_T *qfp, const pos_T *pos, bool linewise)
   5053  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
   5054 {
   5055  if (linewise) {
   5056    return qfp->qf_lnum >= pos->lnum;
   5057  }
   5058  return qfp->qf_lnum > pos->lnum
   5059         || (qfp->qf_lnum == pos->lnum && qfp->qf_col >= pos->col);
   5060 }
   5061 
   5062 // Returns true if the specified quickfix entry is
   5063 // on or before the given line (linewise is true)
   5064 // or on or before the line and column.
   5065 static bool qf_entry_on_or_before_pos(const qfline_T *qfp, const pos_T *pos, bool linewise)
   5066  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
   5067 {
   5068  if (linewise) {
   5069    return qfp->qf_lnum <= pos->lnum;
   5070  }
   5071  return qfp->qf_lnum < pos->lnum
   5072         || (qfp->qf_lnum == pos->lnum && qfp->qf_col <= pos->col);
   5073 }
   5074 
   5075 /// Find the first quickfix entry after position 'pos' in buffer 'bnr'.
   5076 /// If 'linewise' is true, returns the entry after the specified line and treats
   5077 /// multiple entries on a single line as one. Otherwise returns the entry after
   5078 /// the specified line and column.
   5079 /// 'qfp' points to the very first entry in the buffer and 'errornr' is the
   5080 /// index of the very first entry in the quickfix list.
   5081 /// Returns NULL if an entry is not found after 'pos'.
   5082 static qfline_T *qf_find_entry_after_pos(int bnr, const pos_T *pos, bool linewise, qfline_T *qfp,
   5083                                         int *errornr)
   5084  FUNC_ATTR_NONNULL_ALL
   5085 {
   5086  if (qf_entry_after_pos(qfp, pos, linewise)) {
   5087    // First entry is after position 'pos'
   5088    return qfp;
   5089  }
   5090 
   5091  // Find the entry just before or at the position 'pos'
   5092  while (qfp->qf_next != NULL
   5093         && qfp->qf_next->qf_fnum == bnr
   5094         && qf_entry_on_or_before_pos(qfp->qf_next, pos, linewise)) {
   5095    qfp = qfp->qf_next;
   5096    (*errornr)++;
   5097  }
   5098 
   5099  if (qfp->qf_next == NULL || qfp->qf_next->qf_fnum != bnr) {
   5100    // No entries found after position 'pos'
   5101    return NULL;
   5102  }
   5103 
   5104  // Use the entry just after position 'pos'
   5105  qfp = qfp->qf_next;
   5106  (*errornr)++;
   5107 
   5108  return qfp;
   5109 }
   5110 
   5111 /// Find the first quickfix entry before position 'pos' in buffer 'bnr'.
   5112 /// If 'linewise' is true, returns the entry before the specified line and
   5113 /// treats multiple entries on a single line as one. Otherwise returns the entry
   5114 /// before the specified line and column.
   5115 /// 'qfp' points to the very first entry in the buffer and 'errornr' is the
   5116 /// index of the very first entry in the quickfix list.
   5117 /// Returns NULL if an entry is not found before 'pos'.
   5118 static qfline_T *qf_find_entry_before_pos(int bnr, const pos_T *pos, bool linewise, qfline_T *qfp,
   5119                                          int *errornr)
   5120  FUNC_ATTR_NONNULL_ALL
   5121 {
   5122  // Find the entry just before the position 'pos'
   5123  while (qfp->qf_next != NULL
   5124         && qfp->qf_next->qf_fnum == bnr
   5125         && qf_entry_before_pos(qfp->qf_next, pos, linewise)) {
   5126    qfp = qfp->qf_next;
   5127    (*errornr)++;
   5128  }
   5129 
   5130  if (qf_entry_on_or_after_pos(qfp, pos, linewise)) {
   5131    return NULL;
   5132  }
   5133 
   5134  if (linewise) {
   5135    // If multiple entries are on the same line, then use the first entry
   5136    qfp = qf_find_first_entry_on_line(qfp, errornr);
   5137  }
   5138 
   5139  return qfp;
   5140 }
   5141 
   5142 /// Find a quickfix entry in 'qfl' closest to position 'pos' in buffer 'bnr' in
   5143 /// the direction 'dir'.
   5144 static qfline_T *qf_find_closest_entry(qf_list_T *qfl, int bnr, const pos_T *pos, Direction dir,
   5145                                       bool linewise, int *errornr)
   5146  FUNC_ATTR_NONNULL_ALL
   5147 {
   5148  *errornr = 0;
   5149 
   5150  // Find the first entry in this file
   5151  qfline_T *qfp = qf_find_first_entry_in_buf(qfl, bnr, errornr);
   5152  if (qfp == NULL) {
   5153    return NULL;  // no entry in this file
   5154  }
   5155 
   5156  if (dir == FORWARD) {
   5157    qfp = qf_find_entry_after_pos(bnr, pos, linewise, qfp, errornr);
   5158  } else {
   5159    qfp = qf_find_entry_before_pos(bnr, pos, linewise, qfp, errornr);
   5160  }
   5161 
   5162  return qfp;
   5163 }
   5164 
   5165 /// Get the nth quickfix entry below the specified entry.  Searches forward in
   5166 /// the list. If linewise is true, then treat multiple entries on a single line
   5167 /// as one.
   5168 static void qf_get_nth_below_entry(qfline_T *entry_arg, linenr_T n, bool linewise, int *errornr)
   5169  FUNC_ATTR_NONNULL_ALL
   5170 {
   5171  qfline_T *entry = entry_arg;
   5172 
   5173  while (n-- > 0 && !got_int) {
   5174    int first_errornr = *errornr;
   5175 
   5176    if (linewise) {
   5177      // Treat all the entries on the same line in this file as one
   5178      entry = qf_find_last_entry_on_line(entry, errornr);
   5179    }
   5180 
   5181    if (entry->qf_next == NULL
   5182        || entry->qf_next->qf_fnum != entry->qf_fnum) {
   5183      if (linewise) {
   5184        *errornr = first_errornr;
   5185      }
   5186      break;
   5187    }
   5188 
   5189    entry = entry->qf_next;
   5190    (*errornr)++;
   5191  }
   5192 }
   5193 
   5194 /// Get the nth quickfix entry above the specified entry.  Searches backwards in
   5195 /// the list. If linewise is true, then treat multiple entries on a single line
   5196 /// as one.
   5197 static void qf_get_nth_above_entry(qfline_T *entry, linenr_T n, bool linewise, int *errornr)
   5198  FUNC_ATTR_NONNULL_ALL
   5199 {
   5200  while (n-- > 0 && !got_int) {
   5201    if (entry->qf_prev == NULL
   5202        || entry->qf_prev->qf_fnum != entry->qf_fnum) {
   5203      break;
   5204    }
   5205 
   5206    entry = entry->qf_prev;
   5207    (*errornr)--;
   5208 
   5209    if (linewise) {
   5210      entry = qf_find_first_entry_on_line(entry, errornr);
   5211    }
   5212  }
   5213 }
   5214 
   5215 /// Find the n'th quickfix entry adjacent to position 'pos' in buffer 'bnr' in
   5216 /// the specified direction.  Returns the error number in the quickfix list or 0
   5217 /// if an entry is not found.
   5218 static int qf_find_nth_adj_entry(qf_list_T *qfl, int bnr, pos_T *pos, linenr_T n, Direction dir,
   5219                                 bool linewise)
   5220  FUNC_ATTR_NONNULL_ALL
   5221 {
   5222  int errornr;
   5223 
   5224  // Find an entry closest to the specified position
   5225  qfline_T *const adj_entry = qf_find_closest_entry(qfl, bnr, pos, dir,
   5226                                                    linewise, &errornr);
   5227  if (adj_entry == NULL) {
   5228    return 0;
   5229  }
   5230 
   5231  if (--n > 0) {
   5232    // Go to the n'th entry in the current buffer
   5233    if (dir == FORWARD) {
   5234      qf_get_nth_below_entry(adj_entry, n, linewise, &errornr);
   5235    } else {
   5236      qf_get_nth_above_entry(adj_entry, n, linewise, &errornr);
   5237    }
   5238  }
   5239 
   5240  return errornr;
   5241 }
   5242 
   5243 /// Jump to a quickfix entry in the current file nearest to the current line or
   5244 /// current line/col.
   5245 /// ":cabove", ":cbelow", ":labove", ":lbelow", ":cafter", ":cbefore",
   5246 /// ":lafter" and ":lbefore" commands
   5247 void ex_cbelow(exarg_T *eap)
   5248 {
   5249  if (eap->addr_count > 0 && eap->line2 <= 0) {
   5250    emsg(_(e_invrange));
   5251    return;
   5252  }
   5253 
   5254  // Check whether the current buffer has any quickfix entries
   5255  int buf_has_flag = (eap->cmdidx == CMD_cabove
   5256                      || eap->cmdidx == CMD_cbelow
   5257                      || eap->cmdidx == CMD_cbefore
   5258                      || eap->cmdidx == CMD_cafter) ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY;
   5259 
   5260  if (!(curbuf->b_has_qf_entry & buf_has_flag)) {
   5261    emsg(_(e_no_errors));
   5262    return;
   5263  }
   5264 
   5265  qf_info_T *qi;
   5266  if ((qi = qf_cmd_get_stack(eap, true)) == NULL) {
   5267    return;
   5268  }
   5269 
   5270  qf_list_T *qfl = qf_get_curlist(qi);
   5271  // check if the list has valid errors
   5272  if (!qf_list_has_valid_entries(qfl)) {
   5273    emsg(_(e_no_errors));
   5274    return;
   5275  }
   5276 
   5277  // Forward motion commands
   5278  int dir = (eap->cmdidx == CMD_cbelow
   5279             || eap->cmdidx == CMD_lbelow
   5280             || eap->cmdidx == CMD_cafter
   5281             || eap->cmdidx == CMD_lafter) ? FORWARD : BACKWARD;
   5282 
   5283  pos_T pos = curwin->w_cursor;
   5284  // A quickfix entry column number is 1 based whereas cursor column
   5285  // number is 0 based. Adjust the column number.
   5286  pos.col++;
   5287  const int errornr = qf_find_nth_adj_entry(qfl,
   5288                                            curbuf->b_fnum,
   5289                                            &pos,
   5290                                            eap->addr_count > 0 ? eap->line2 : 0,
   5291                                            dir,
   5292                                            eap->cmdidx == CMD_cbelow
   5293                                            || eap->cmdidx == CMD_lbelow
   5294                                            || eap->cmdidx == CMD_cabove
   5295                                            || eap->cmdidx == CMD_labove);
   5296 
   5297  if (errornr > 0) {
   5298    qf_jump(qi, 0, errornr, false);
   5299  } else {
   5300    emsg(_(e_no_more_items));
   5301  }
   5302 }
   5303 
   5304 /// Return the autocmd name for the :cfile Ex commands
   5305 static char *cfile_get_auname(cmdidx_T cmdidx)
   5306 {
   5307  switch (cmdidx) {
   5308  case CMD_cfile:
   5309    return "cfile";
   5310  case CMD_cgetfile:
   5311    return "cgetfile";
   5312  case CMD_caddfile:
   5313    return "caddfile";
   5314  case CMD_lfile:
   5315    return "lfile";
   5316  case CMD_lgetfile:
   5317    return "lgetfile";
   5318  case CMD_laddfile:
   5319    return "laddfile";
   5320  default:
   5321    return NULL;
   5322  }
   5323 }
   5324 
   5325 // ":cfile"/":cgetfile"/":caddfile" commands.
   5326 // ":lfile"/":lgetfile"/":laddfile" commands.
   5327 void ex_cfile(exarg_T *eap)
   5328 {
   5329  win_T *wp = NULL;
   5330  qf_info_T *qi = ql_info;
   5331  assert(qi != NULL);
   5332  char *au_name = NULL;
   5333 
   5334  au_name = cfile_get_auname(eap->cmdidx);
   5335  if (au_name != NULL
   5336      && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, NULL, false, curbuf)) {
   5337    if (aborting()) {
   5338      return;
   5339    }
   5340  }
   5341  if (*eap->arg != NUL) {
   5342    set_option_direct(kOptErrorfile, CSTR_AS_OPTVAL(eap->arg), 0, 0);
   5343  }
   5344 
   5345  char *enc = (*curbuf->b_p_menc != NUL) ? curbuf->b_p_menc : p_menc;
   5346 
   5347  if (is_loclist_cmd(eap->cmdidx)) {
   5348    wp = curwin;
   5349  }
   5350 
   5351  incr_quickfix_busy();
   5352 
   5353  // This function is used by the :cfile, :cgetfile and :caddfile
   5354  // commands.
   5355  // :cfile always creates a new quickfix list and may jump to the
   5356  // first error.
   5357  // :cgetfile creates a new quickfix list but doesn't jump to the
   5358  // first error.
   5359  // :caddfile adds to an existing quickfix list. If there is no
   5360  // quickfix list then a new list is created.
   5361  int res = qf_init(wp, p_ef, p_efm, (eap->cmdidx != CMD_caddfile
   5362                                      && eap->cmdidx != CMD_laddfile),
   5363                    qf_cmdtitle(*eap->cmdlinep), enc);
   5364  if (wp != NULL) {
   5365    qi = GET_LOC_LIST(wp);
   5366    if (qi == NULL) {
   5367      decr_quickfix_busy();
   5368      return;
   5369    }
   5370  }
   5371  if (res >= 0) {
   5372    qf_list_changed(qf_get_curlist(qi));
   5373  }
   5374  unsigned save_qfid = qf_get_curlist(qi)->qf_id;
   5375  if (au_name != NULL) {
   5376    apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, NULL, false, curbuf);
   5377  }
   5378  // Jump to the first error for a new list and if autocmds didn't free the
   5379  // list.
   5380  if (res > 0 && (eap->cmdidx == CMD_cfile || eap->cmdidx == CMD_lfile)
   5381      && qflist_valid(wp, save_qfid)) {
   5382    // display the first error
   5383    qf_jump_first(qi, save_qfid, eap->forceit);
   5384  }
   5385 
   5386  decr_quickfix_busy();
   5387 }
   5388 
   5389 /// Return the vimgrep autocmd name.
   5390 static char *vgr_get_auname(cmdidx_T cmdidx)
   5391 {
   5392  switch (cmdidx) {
   5393  case CMD_vimgrep:
   5394    return "vimgrep";
   5395  case CMD_lvimgrep:
   5396    return "lvimgrep";
   5397  case CMD_vimgrepadd:
   5398    return "vimgrepadd";
   5399  case CMD_lvimgrepadd:
   5400    return "lvimgrepadd";
   5401  case CMD_grep:
   5402    return "grep";
   5403  case CMD_lgrep:
   5404    return "lgrep";
   5405  case CMD_grepadd:
   5406    return "grepadd";
   5407  case CMD_lgrepadd:
   5408    return "lgrepadd";
   5409  default:
   5410    return NULL;
   5411  }
   5412 }
   5413 
   5414 /// Initialize the regmatch used by vimgrep for pattern "s".
   5415 static void vgr_init_regmatch(regmmatch_T *regmatch, char *s)
   5416 {
   5417  // Get the search pattern: either white-separated or enclosed in //.
   5418  regmatch->regprog = NULL;
   5419 
   5420  if (s == NULL || *s == NUL) {
   5421    // Pattern is empty, use last search pattern.
   5422    if (last_search_pat() == NULL) {
   5423      emsg(_(e_noprevre));
   5424      return;
   5425    }
   5426    regmatch->regprog = vim_regcomp(last_search_pat(), RE_MAGIC);
   5427  } else {
   5428    regmatch->regprog = vim_regcomp(s, RE_MAGIC);
   5429  }
   5430 
   5431  regmatch->rmm_ic = p_ic;
   5432  regmatch->rmm_maxcol = 0;
   5433 }
   5434 
   5435 /// Display a file name when vimgrep is running.
   5436 static void vgr_display_fname(char *fname)
   5437 {
   5438  msg_start();
   5439  char *p = msg_strtrunc(fname, true);
   5440  if (p == NULL) {
   5441    msg_outtrans(fname, 0, false);
   5442  } else {
   5443    msg_outtrans(p, 0, false);
   5444    xfree(p);
   5445  }
   5446  msg_clr_eos();
   5447  msg_didout = false;  // overwrite this message
   5448  msg_nowait = true;   // don't wait for this message
   5449  msg_col = 0;
   5450  ui_flush();
   5451 }
   5452 
   5453 /// Load a dummy buffer to search for a pattern using vimgrep.
   5454 static buf_T *vgr_load_dummy_buf(char *fname, char *dirname_start, char *dirname_now)
   5455 {
   5456  // Don't do Filetype autocommands to avoid loading syntax and
   5457  // indent scripts, a great speed improvement.
   5458  char *save_ei = au_event_disable(",Filetype");
   5459 
   5460  OptInt save_mls = p_mls;
   5461  p_mls = 0;
   5462 
   5463  // Load file into a buffer, so that 'fileencoding' is detected,
   5464  // autocommands applied, etc.
   5465  buf_T *buf = load_dummy_buffer(fname, dirname_start, dirname_now);
   5466 
   5467  p_mls = save_mls;
   5468  au_event_restore(save_ei);
   5469 
   5470  return buf;
   5471 }
   5472 
   5473 /// Check whether a quickfix/location list is valid. Autocmds may remove or
   5474 /// change a quickfix list when vimgrep is running. If the list is not found,
   5475 /// create a new list.
   5476 static bool vgr_qflist_valid(win_T *wp, qf_info_T *qi, unsigned qfid, char *title)
   5477 {
   5478  // Verify that the quickfix/location list was not freed by an autocmd
   5479  if (!qflist_valid(wp, qfid)) {
   5480    if (wp != NULL) {
   5481      // An autocmd has freed the location list
   5482      emsg(_(e_current_location_list_was_changed));
   5483      return false;
   5484    }
   5485    // Quickfix list is not found, create a new one.
   5486    qf_new_list(qi, title);
   5487    return true;
   5488  }
   5489  if (qf_restore_list(qi, qfid) == FAIL) {
   5490    return false;
   5491  }
   5492 
   5493  return true;
   5494 }
   5495 
   5496 /// Search for a pattern in all the lines in a buffer and add the matching lines
   5497 /// to a quickfix list.
   5498 static bool vgr_match_buflines(qf_list_T *qfl, char *fname, buf_T *buf, char *spat,
   5499                               regmmatch_T *regmatch, int *tomatch, int duplicate_name, int flags)
   5500  FUNC_ATTR_NONNULL_ARG(1, 3, 4, 5, 6)
   5501 {
   5502  bool found_match = false;
   5503  size_t pat_len = strlen(spat);
   5504  pat_len = MIN(pat_len, FUZZY_MATCH_MAX_LEN);
   5505 
   5506  for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count && *tomatch > 0; lnum++) {
   5507    colnr_T col = 0;
   5508    if (!(flags & VGR_FUZZY)) {
   5509      // Regular expression match
   5510      while (vim_regexec_multi(regmatch, curwin, buf, lnum, col, NULL, NULL) > 0) {
   5511        // Pass the buffer number so that it gets used even for a
   5512        // dummy buffer, unless duplicate_name is set, then the
   5513        // buffer will be wiped out below.
   5514        if (qf_add_entry(qfl,
   5515                         NULL,   // dir
   5516                         fname,
   5517                         NULL,
   5518                         duplicate_name ? 0 : buf->b_fnum,
   5519                         ml_get_buf(buf, regmatch->startpos[0].lnum + lnum),
   5520                         regmatch->startpos[0].lnum + lnum,
   5521                         regmatch->endpos[0].lnum + lnum,
   5522                         regmatch->startpos[0].col + 1,
   5523                         regmatch->endpos[0].col + 1,
   5524                         false,  // vis_col
   5525                         NULL,   // search pattern
   5526                         0,      // nr
   5527                         0,      // type
   5528                         NULL,   // user_data
   5529                         true)   // valid
   5530            == QF_FAIL) {
   5531          got_int = true;
   5532          break;
   5533        }
   5534        found_match = true;
   5535        if (--*tomatch == 0) {
   5536          break;
   5537        }
   5538        if ((flags & VGR_GLOBAL) == 0 || regmatch->endpos[0].lnum > 0) {
   5539          break;
   5540        }
   5541        col = regmatch->endpos[0].col + (col == regmatch->endpos[0].col);
   5542        if (col > ml_get_buf_len(buf, lnum)) {
   5543          break;
   5544        }
   5545      }
   5546    } else {
   5547      char *const str = ml_get_buf(buf, lnum);
   5548      const colnr_T linelen = ml_get_buf_len(buf, lnum);
   5549      int score;
   5550      uint32_t matches[FUZZY_MATCH_MAX_LEN];
   5551      const size_t sz = sizeof(matches) / sizeof(matches[0]);
   5552 
   5553      // Fuzzy string match
   5554      CLEAR_FIELD(matches);
   5555      while (fuzzy_match(str + col, spat, false, &score, matches, (int)sz) > 0) {
   5556        // Pass the buffer number so that it gets used even for a
   5557        // dummy buffer, unless duplicate_name is set, then the
   5558        // buffer will be wiped out below.
   5559        if (qf_add_entry(qfl,
   5560                         NULL,   // dir
   5561                         fname,
   5562                         NULL,
   5563                         duplicate_name ? 0 : buf->b_fnum,
   5564                         str,
   5565                         lnum,
   5566                         0,
   5567                         (colnr_T)matches[0] + col + 1,
   5568                         0,
   5569                         false,  // vis_col
   5570                         NULL,   // search pattern
   5571                         0,      // nr
   5572                         0,      // type
   5573                         NULL,   // user_data
   5574                         true)   // valid
   5575            == QF_FAIL) {
   5576          got_int = true;
   5577          break;
   5578        }
   5579        found_match = true;
   5580        if (--*tomatch == 0) {
   5581          break;
   5582        }
   5583        if ((flags & VGR_GLOBAL) == 0) {
   5584          break;
   5585        }
   5586        col = (colnr_T)matches[pat_len - 1] + col + 1;
   5587        if (col > linelen) {
   5588          break;
   5589        }
   5590      }
   5591    }
   5592    line_breakcheck();
   5593    if (got_int) {
   5594      break;
   5595    }
   5596  }
   5597 
   5598  return found_match;
   5599 }
   5600 
   5601 /// Jump to the first match and update the directory.
   5602 static void vgr_jump_to_match(qf_info_T *qi, int forceit, bool *redraw_for_dummy,
   5603                              buf_T *first_match_buf, char *target_dir)  // NOLINT(readability-non-const-parameter)
   5604 {
   5605  buf_T *buf = curbuf;
   5606  qf_jump(qi, 0, 0, forceit);
   5607  if (buf != curbuf) {
   5608    // If we jumped to another buffer redrawing will already be
   5609    // taken care of.
   5610    *redraw_for_dummy = false;
   5611  }
   5612 
   5613  // Jump to the directory used after loading the buffer.
   5614  if (curbuf == first_match_buf && target_dir != NULL) {
   5615    exarg_T ea = {
   5616      .arg = target_dir,
   5617      .cmdidx = CMD_lcd,
   5618    };
   5619    ex_cd(&ea);
   5620  }
   5621 }
   5622 
   5623 // Return true if "buf" had an existing swap file, the current swap file does
   5624 // not end in ".swp".
   5625 static bool existing_swapfile(const buf_T *buf)
   5626  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
   5627 {
   5628  if (buf->b_ml.ml_mfp != NULL && buf->b_ml.ml_mfp->mf_fname != NULL) {
   5629    const char *const fname = buf->b_ml.ml_mfp->mf_fname;
   5630    const size_t len = strlen(fname);
   5631 
   5632    return fname[len - 1] != 'p' || fname[len - 2] != 'w';
   5633  }
   5634  return false;
   5635 }
   5636 
   5637 /// Process :vimgrep command arguments. The command syntax is:
   5638 ///
   5639 /// :{count}vimgrep /{pattern}/[g][j] {file} ...
   5640 static int vgr_process_args(exarg_T *eap, vgr_args_T *args)
   5641 {
   5642  CLEAR_POINTER(args);
   5643 
   5644  args->regmatch.regprog = NULL;
   5645  args->qf_title = xstrdup(qf_cmdtitle(*eap->cmdlinep));
   5646  args->tomatch = eap->addr_count > 0 ? eap->line2 : MAXLNUM;
   5647 
   5648  // Get the search pattern: either white-separated or enclosed in //
   5649  char *p = skip_vimgrep_pat(eap->arg, &args->spat, &args->flags);
   5650  if (p == NULL) {
   5651    emsg(_(e_invalpat));
   5652    return FAIL;
   5653  }
   5654 
   5655  vgr_init_regmatch(&args->regmatch, args->spat);
   5656  if (args->regmatch.regprog == NULL) {
   5657    return FAIL;
   5658  }
   5659 
   5660  p = skipwhite(p);
   5661  if (*p == NUL) {
   5662    emsg(_("E683: File name missing or invalid pattern"));
   5663    return FAIL;
   5664  }
   5665 
   5666  // Parse the list of arguments, wildcards have already been expanded.
   5667  if (get_arglist_exp(p, &args->fcount, &args->fnames, true) == FAIL
   5668      || args->fcount == 0) {
   5669    emsg(_(e_nomatch));
   5670    return FAIL;
   5671  }
   5672 
   5673  return OK;
   5674 }
   5675 
   5676 /// Search for a pattern in a list of files and populate the quickfix list with
   5677 /// the matches.
   5678 static int vgr_process_files(win_T *wp, qf_info_T *qi, vgr_args_T *cmd_args, bool *redraw_for_dummy,
   5679                             buf_T **first_match_buf, char **target_dir)
   5680 {
   5681  int status = FAIL;
   5682  unsigned save_qfid = qf_get_curlist(qi)->qf_id;
   5683  bool duplicate_name = false;
   5684 
   5685  char *dirname_start = xmalloc(MAXPATHL);
   5686  char *dirname_now = xmalloc(MAXPATHL);
   5687 
   5688  // Remember the current directory, because a BufRead autocommand that does
   5689  // ":lcd %:p:h" changes the meaning of short path names.
   5690  os_dirname(dirname_start, MAXPATHL);
   5691 
   5692  time_t seconds = 0;
   5693  for (int fi = 0; fi < cmd_args->fcount && !got_int && cmd_args->tomatch > 0; fi++) {
   5694    char *fname = path_try_shorten_fname(cmd_args->fnames[fi]);
   5695    if (time(NULL) > seconds) {
   5696      // Display the file name every second or so, show the user we are
   5697      // working on it.
   5698      seconds = time(NULL);
   5699      vgr_display_fname(fname);
   5700    }
   5701 
   5702    buf_T *buf = buflist_findname_exp(cmd_args->fnames[fi]);
   5703    bool using_dummy;
   5704    if (buf == NULL || buf->b_ml.ml_mfp == NULL) {
   5705      // Remember that a buffer with this name already exists.
   5706      duplicate_name = (buf != NULL);
   5707      using_dummy = true;
   5708      *redraw_for_dummy = true;
   5709      buf = vgr_load_dummy_buf(fname, dirname_start, dirname_now);
   5710    } else {
   5711      // Use existing, loaded buffer.
   5712      using_dummy = false;
   5713    }
   5714 
   5715    // Check whether the quickfix list is still valid. When loading a
   5716    // buffer above, autocommands might have changed the quickfix list.
   5717    if (!vgr_qflist_valid(wp, qi, save_qfid, cmd_args->qf_title)) {
   5718      goto theend;
   5719    }
   5720 
   5721    save_qfid = qf_get_curlist(qi)->qf_id;
   5722 
   5723    if (buf == NULL) {
   5724      if (!got_int) {
   5725        smsg(0, _("Cannot open file \"%s\""), fname);
   5726      }
   5727    } else {
   5728      // Try for a match in all lines of the buffer.
   5729      // For ":1vimgrep" look for first match only.
   5730      bool found_match = vgr_match_buflines(qf_get_curlist(qi),
   5731                                            fname,
   5732                                            buf,
   5733                                            cmd_args->spat,
   5734                                            &cmd_args->regmatch,
   5735                                            &cmd_args->tomatch,
   5736                                            duplicate_name,
   5737                                            cmd_args->flags);
   5738 
   5739      if (using_dummy) {
   5740        if (found_match && *first_match_buf == NULL) {
   5741          *first_match_buf = buf;
   5742        }
   5743        if (duplicate_name) {
   5744          // Never keep a dummy buffer if there is another buffer
   5745          // with the same name.
   5746          wipe_dummy_buffer(buf, dirname_start);
   5747          buf = NULL;
   5748        } else if ((cmdmod.cmod_flags & CMOD_HIDE) == 0
   5749                   || buf->b_p_bh[0] == 'u'             // "unload"
   5750                   || buf->b_p_bh[0] == 'w'             // "wipe"
   5751                   || buf->b_p_bh[0] == 'd') {          // "delete"
   5752          // When no match was found we don't need to remember the
   5753          // buffer, wipe it out.  If there was a match and it
   5754          // wasn't the first one or we won't jump there: only
   5755          // unload the buffer.
   5756          // Ignore 'hidden' here, because it may lead to having too
   5757          // many swap files.
   5758          if (!found_match) {
   5759            wipe_dummy_buffer(buf, dirname_start);
   5760            buf = NULL;
   5761          } else if (buf != *first_match_buf
   5762                     || (cmd_args->flags & VGR_NOJUMP)
   5763                     || existing_swapfile(buf)) {
   5764            unload_dummy_buffer(buf, dirname_start);
   5765            // Keeping the buffer, remove the dummy flag.
   5766            buf->b_flags &= ~BF_DUMMY;
   5767            buf = NULL;
   5768          }
   5769        }
   5770 
   5771        if (buf != NULL) {
   5772          // Keeping the buffer, remove the dummy flag.
   5773          buf->b_flags &= ~BF_DUMMY;
   5774 
   5775          // If the buffer is still loaded we need to use the
   5776          // directory we jumped to below.
   5777          if (buf == *first_match_buf
   5778              && *target_dir == NULL
   5779              && strcmp(dirname_start, dirname_now) != 0) {
   5780            *target_dir = xstrdup(dirname_now);
   5781          }
   5782 
   5783          // The buffer is still loaded, the Filetype autocommands
   5784          // need to be done now, in that buffer.  And the modelines
   5785          // need to be done (again).  But not the window-local
   5786          // options!
   5787          aco_save_T aco;
   5788          aucmd_prepbuf(&aco, buf);
   5789          apply_autocmds(EVENT_FILETYPE, buf->b_p_ft, buf->b_fname, true, buf);
   5790          do_modelines(OPT_NOWIN);
   5791          aucmd_restbuf(&aco);
   5792        }
   5793      }
   5794    }
   5795  }
   5796 
   5797  status = OK;
   5798 
   5799 theend:
   5800  xfree(dirname_now);
   5801  xfree(dirname_start);
   5802  return status;
   5803 }
   5804 
   5805 /// ":vimgrep {pattern} file(s)"
   5806 /// ":vimgrepadd {pattern} file(s)"
   5807 /// ":lvimgrep {pattern} file(s)"
   5808 /// ":lvimgrepadd {pattern} file(s)"
   5809 void ex_vimgrep(exarg_T *eap)
   5810 {
   5811  if (!check_can_set_curbuf_forceit(eap->forceit)) {
   5812    return;
   5813  }
   5814 
   5815  char *au_name = vgr_get_auname(eap->cmdidx);
   5816  if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
   5817                                        curbuf->b_fname, true, curbuf)) {
   5818    if (aborting()) {
   5819      return;
   5820    }
   5821  }
   5822 
   5823  win_T *wp = NULL;
   5824  qf_info_T *qi = qf_cmd_get_or_alloc_stack(eap, &wp);
   5825  char *target_dir = NULL;
   5826  vgr_args_T args;
   5827  if (vgr_process_args(eap, &args) == FAIL) {
   5828    goto theend;
   5829  }
   5830 
   5831  if ((eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_lgrepadd
   5832       && eap->cmdidx != CMD_vimgrepadd && eap->cmdidx != CMD_lvimgrepadd)
   5833      || qf_stack_empty(qi)) {
   5834    // make place for a new list
   5835    qf_new_list(qi, args.qf_title);
   5836  }
   5837 
   5838  incr_quickfix_busy();
   5839 
   5840  bool redraw_for_dummy = false;
   5841  buf_T *first_match_buf = NULL;
   5842  int status = vgr_process_files(wp, qi, &args, &redraw_for_dummy, &first_match_buf, &target_dir);
   5843 
   5844  if (status != OK) {
   5845    FreeWild(args.fcount, args.fnames);
   5846    decr_quickfix_busy();
   5847    goto theend;
   5848  }
   5849 
   5850  FreeWild(args.fcount, args.fnames);
   5851 
   5852  qf_list_T *qfl = qf_get_curlist(qi);
   5853  qfl->qf_nonevalid = false;
   5854  qfl->qf_ptr = qfl->qf_start;
   5855  qfl->qf_index = 1;
   5856  qf_list_changed(qfl);
   5857 
   5858  qf_update_buffer(qi, NULL);
   5859 
   5860  // Remember the current quickfix list identifier, so that we can check for
   5861  // autocommands changing the current quickfix list.
   5862  unsigned save_qfid = qf_get_curlist(qi)->qf_id;
   5863 
   5864  if (au_name != NULL) {
   5865    apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, curbuf->b_fname, true, curbuf);
   5866  }
   5867 
   5868  // The QuickFixCmdPost autocmd may free the quickfix list. Check the list
   5869  // is still valid.
   5870  if (!qflist_valid(wp, save_qfid) || qf_restore_list(qi, save_qfid) == FAIL) {
   5871    decr_quickfix_busy();
   5872    goto theend;
   5873  }
   5874 
   5875  // Jump to first match.
   5876  if (!qf_list_empty(qf_get_curlist(qi))) {
   5877    if ((args.flags & VGR_NOJUMP) == 0) {
   5878      vgr_jump_to_match(qi, eap->forceit, &redraw_for_dummy, first_match_buf, target_dir);
   5879    }
   5880  } else {
   5881    semsg(_(e_nomatch2), args.spat);
   5882  }
   5883 
   5884  decr_quickfix_busy();
   5885 
   5886  // If we loaded a dummy buffer into the current window, the autocommands
   5887  // may have messed up things, need to redraw and recompute folds.
   5888  if (redraw_for_dummy) {
   5889    foldUpdateAll(curwin);
   5890  }
   5891 
   5892 theend:
   5893  xfree(args.qf_title);
   5894  xfree(target_dir);
   5895  vim_regfree(args.regmatch.regprog);
   5896 }
   5897 
   5898 // Restore current working directory to "dirname_start" if they differ, taking
   5899 // into account whether it is set locally or globally.
   5900 static void restore_start_dir(char *dirname_start)
   5901  FUNC_ATTR_NONNULL_ALL
   5902 {
   5903  char *dirname_now = xmalloc(MAXPATHL);
   5904 
   5905  os_dirname(dirname_now, MAXPATHL);
   5906  if (strcmp(dirname_start, dirname_now) != 0) {
   5907    // If the directory has changed, change it back by building up an
   5908    // appropriate ex command and executing it.
   5909    exarg_T ea = {
   5910      .arg = dirname_start,
   5911      .cmdidx = (curwin->w_localdir == NULL) ? CMD_cd : CMD_lcd,
   5912    };
   5913    ex_cd(&ea);
   5914  }
   5915  xfree(dirname_now);
   5916 }
   5917 
   5918 /// Load file "fname" into a dummy buffer and return the buffer pointer,
   5919 /// placing the directory resulting from the buffer load into the
   5920 /// "resulting_dir" pointer. "resulting_dir" must be allocated by the caller
   5921 /// prior to calling this function. Restores directory to "dirname_start" prior
   5922 /// to returning, if autocmds or the 'autochdir' option have changed it.
   5923 ///
   5924 /// If creating the dummy buffer does not fail, must call unload_dummy_buffer()
   5925 /// or wipe_dummy_buffer() later!
   5926 ///
   5927 /// @param dirname_start  in: old directory
   5928 /// @param resulting_dir  out: new directory
   5929 ///
   5930 /// @return  NULL if it fails.
   5931 static buf_T *load_dummy_buffer(char *fname, char *dirname_start, char *resulting_dir)
   5932 {
   5933  // Allocate a buffer without putting it in the buffer list.
   5934  buf_T *newbuf = buflist_new(NULL, NULL, 1, BLN_DUMMY);
   5935  if (newbuf == NULL) {
   5936    return NULL;
   5937  }
   5938 
   5939  bool failed = true;
   5940  bufref_T newbufref;
   5941  set_bufref(&newbufref, newbuf);
   5942 
   5943  // Init the options.
   5944  buf_copy_options(newbuf, BCO_ENTER | BCO_NOHELP);
   5945 
   5946  // need to open the memfile before putting the buffer in a window
   5947  if (ml_open(newbuf) == OK) {
   5948    // Make sure this buffer isn't wiped out by autocommands.
   5949    newbuf->b_locked++;
   5950    // set curwin/curbuf to buf and save a few things
   5951    aco_save_T aco;
   5952    aucmd_prepbuf(&aco, newbuf);
   5953 
   5954    // Need to set the filename for autocommands.
   5955    setfname(curbuf, fname, NULL, false);
   5956 
   5957    // Create swap file now to avoid the ATTENTION message.
   5958    check_need_swap(true);
   5959 
   5960    // Remove the "dummy" flag, otherwise autocommands may not
   5961    // work.
   5962    curbuf->b_flags &= ~BF_DUMMY;
   5963 
   5964    bufref_T newbuf_to_wipe;
   5965    newbuf_to_wipe.br_buf = NULL;
   5966    int readfile_result = readfile(fname, NULL, 0, 0,
   5967                                   (linenr_T)MAXLNUM, NULL,
   5968                                   READ_NEW | READ_DUMMY, false);
   5969    newbuf->b_locked--;
   5970    if (readfile_result == OK
   5971        && !got_int
   5972        && !(curbuf->b_flags & BF_NEW)) {
   5973      failed = false;
   5974      if (curbuf != newbuf) {
   5975        // Bloody autocommands changed the buffer!  Can happen when
   5976        // using netrw and editing a remote file.  Use the current
   5977        // buffer instead, delete the dummy one after restoring the
   5978        // window stuff.
   5979        set_bufref(&newbuf_to_wipe, newbuf);
   5980        newbuf = curbuf;
   5981      }
   5982    }
   5983 
   5984    // Restore curwin/curbuf and a few other things.
   5985    aucmd_restbuf(&aco);
   5986 
   5987    if (newbuf_to_wipe.br_buf != NULL && bufref_valid(&newbuf_to_wipe)) {
   5988      block_autocmds();
   5989      wipe_dummy_buffer(newbuf_to_wipe.br_buf, NULL);
   5990      unblock_autocmds();
   5991    }
   5992 
   5993    // Add back the "dummy" flag, otherwise buflist_findname_file_id()
   5994    // won't skip it.
   5995    newbuf->b_flags |= BF_DUMMY;
   5996  }
   5997 
   5998  // When autocommands/'autochdir' option changed directory: go back.
   5999  // Let the caller know what the resulting dir was first, in case it is
   6000  // important.
   6001  os_dirname(resulting_dir, MAXPATHL);
   6002  restore_start_dir(dirname_start);
   6003 
   6004  if (!bufref_valid(&newbufref)) {
   6005    return NULL;
   6006  }
   6007  if (failed) {
   6008    wipe_dummy_buffer(newbuf, dirname_start);
   6009    return NULL;
   6010  }
   6011  return newbuf;
   6012 }
   6013 
   6014 /// Wipe out the dummy buffer that load_dummy_buffer() created. Restores
   6015 /// directory to "dirname_start" if not NULL prior to returning, if autocmds or
   6016 /// the 'autochdir' option have changed it.
   6017 static void wipe_dummy_buffer(buf_T *buf, char *dirname_start)
   6018  FUNC_ATTR_NONNULL_ARG(1)
   6019 {
   6020  // If any autocommand opened a window on the dummy buffer, close that
   6021  // window.  If we can't close them all then give up.
   6022  while (buf->b_nwindows > 0) {
   6023    bool did_one = false;
   6024 
   6025    if (firstwin->w_next != NULL) {
   6026      for (win_T *wp = firstwin; wp != NULL; wp = wp->w_next) {
   6027        if (wp->w_buffer == buf) {
   6028          if (win_close(wp, false, false) == OK) {
   6029            did_one = true;
   6030          }
   6031          break;
   6032        }
   6033      }
   6034    }
   6035    if (!did_one) {
   6036      goto fail;
   6037    }
   6038  }
   6039 
   6040  if (curbuf != buf && buf->b_nwindows == 0) {  // safety check
   6041    cleanup_T cs;
   6042 
   6043    // Reset the error/interrupt/exception state here so that aborting()
   6044    // returns false when wiping out the buffer.  Otherwise it doesn't
   6045    // work when got_int is set.
   6046    enter_cleanup(&cs);
   6047 
   6048    wipe_buffer(buf, true);
   6049 
   6050    // Restore the error/interrupt/exception state if not discarded by a
   6051    // new aborting error, interrupt, or uncaught exception.
   6052    leave_cleanup(&cs);
   6053 
   6054    if (dirname_start != NULL) {
   6055      // When autocommands/'autochdir' option changed directory: go back.
   6056      restore_start_dir(dirname_start);
   6057    }
   6058 
   6059    return;
   6060  }
   6061 
   6062 fail:
   6063  // Keeping the buffer, remove the dummy flag.
   6064  buf->b_flags &= ~BF_DUMMY;
   6065 }
   6066 
   6067 /// Unload the dummy buffer that load_dummy_buffer() created. Restores
   6068 /// directory to "dirname_start" prior to returning, if autocmds or the
   6069 /// 'autochdir' option have changed it.
   6070 static void unload_dummy_buffer(buf_T *buf, char *dirname_start)
   6071 {
   6072  if (curbuf == buf) {          // safety check
   6073    return;
   6074  }
   6075 
   6076  close_buffer(NULL, buf, DOBUF_UNLOAD, false, true);
   6077 
   6078  // When autocommands/'autochdir' option changed directory: go back.
   6079  restore_start_dir(dirname_start);
   6080 }
   6081 
   6082 /// Copy the specified quickfix entry items into a new dict and append the dict
   6083 /// to 'list'.  Returns OK on success.
   6084 static int get_qfline_items(qfline_T *qfp, list_T *list)
   6085 {
   6086  // Handle entries with a non-existing buffer number.
   6087  int bufnum = qfp->qf_fnum;
   6088  if (bufnum != 0 && (buflist_findnr(bufnum) == NULL)) {
   6089    bufnum = 0;
   6090  }
   6091 
   6092  dict_T *const dict = tv_dict_alloc();
   6093  tv_list_append_dict(list, dict);
   6094 
   6095  char buf[2];
   6096  buf[0] = qfp->qf_type;
   6097  buf[1] = NUL;
   6098  if (tv_dict_add_nr(dict, S_LEN("bufnr"), (varnumber_T)bufnum) == FAIL
   6099      || (tv_dict_add_nr(dict, S_LEN("lnum"), (varnumber_T)qfp->qf_lnum) == FAIL)
   6100      || (tv_dict_add_nr(dict, S_LEN("end_lnum"), (varnumber_T)qfp->qf_end_lnum) == FAIL)
   6101      || (tv_dict_add_nr(dict, S_LEN("col"), (varnumber_T)qfp->qf_col) == FAIL)
   6102      || (tv_dict_add_nr(dict, S_LEN("end_col"), (varnumber_T)qfp->qf_end_col) == FAIL)
   6103      || (tv_dict_add_nr(dict, S_LEN("vcol"), (varnumber_T)qfp->qf_viscol) == FAIL)
   6104      || (tv_dict_add_nr(dict, S_LEN("nr"), (varnumber_T)qfp->qf_nr) == FAIL)
   6105      || (tv_dict_add_str(dict, S_LEN("module"), (qfp->qf_module == NULL ? "" : qfp->qf_module))
   6106          == FAIL)
   6107      || (tv_dict_add_str(dict, S_LEN("pattern"), (qfp->qf_pattern == NULL ? "" : qfp->qf_pattern))
   6108          == FAIL)
   6109      || (tv_dict_add_str(dict, S_LEN("text"), (qfp->qf_text == NULL ? "" : qfp->qf_text)) == FAIL)
   6110      || (tv_dict_add_str(dict, S_LEN("type"), buf) == FAIL)
   6111      || (qfp->qf_user_data.v_type != VAR_UNKNOWN
   6112          && tv_dict_add_tv(dict, S_LEN("user_data"), &qfp->qf_user_data) == FAIL)
   6113      || (tv_dict_add_nr(dict, S_LEN("valid"), (varnumber_T)qfp->qf_valid) == FAIL)) {
   6114    // tv_dict_add* fail only if key already exist, but this is a newly
   6115    // allocated dictionary which is thus guaranteed to have no existing keys.
   6116    abort();
   6117  }
   6118 
   6119  return OK;
   6120 }
   6121 
   6122 /// Add each quickfix error to list "list" as a dictionary.
   6123 /// If qf_idx is -1, use the current list. Otherwise, use the specified list.
   6124 /// If eidx is not 0, then return only the specified entry. Otherwise return
   6125 /// all the entries.
   6126 static int get_errorlist(qf_info_T *qi_arg, win_T *wp, int qf_idx, int eidx, list_T *list)
   6127 {
   6128  qf_info_T *qi = qi_arg;
   6129 
   6130  if (qi == NULL) {
   6131    qi = ql_info;
   6132    if (wp != NULL) {
   6133      qi = GET_LOC_LIST(wp);
   6134    }
   6135    if (qi == NULL) {
   6136      return FAIL;
   6137    }
   6138  }
   6139 
   6140  if (eidx < 0) {
   6141    return OK;
   6142  }
   6143 
   6144  if (qf_idx == INVALID_QFIDX) {
   6145    qf_idx = qi->qf_curlist;
   6146  }
   6147 
   6148  if (qf_idx >= qi->qf_listcount) {
   6149    return FAIL;
   6150  }
   6151 
   6152  qf_list_T *qfl = qf_get_list(qi, qf_idx);
   6153  if (qf_list_empty(qfl)) {
   6154    return FAIL;
   6155  }
   6156 
   6157  qfline_T *qfp;
   6158  int i;
   6159  FOR_ALL_QFL_ITEMS(qfl, qfp, i) {
   6160    if (eidx > 0) {
   6161      if (eidx == i) {
   6162        return get_qfline_items(qfp, list);
   6163      }
   6164    } else if (get_qfline_items(qfp, list) == FAIL) {
   6165      return FAIL;
   6166    }
   6167  }
   6168 
   6169  return OK;
   6170 }
   6171 
   6172 /// Flags used by getqflist()/getloclist() to determine which fields to return.
   6173 enum {
   6174  QF_GETLIST_NONE = 0x0,
   6175  QF_GETLIST_TITLE = 0x1,
   6176  QF_GETLIST_ITEMS = 0x2,
   6177  QF_GETLIST_NR = 0x4,
   6178  QF_GETLIST_WINID = 0x8,
   6179  QF_GETLIST_CONTEXT = 0x10,
   6180  QF_GETLIST_ID = 0x20,
   6181  QF_GETLIST_IDX = 0x40,
   6182  QF_GETLIST_SIZE = 0x80,
   6183  QF_GETLIST_TICK = 0x100,
   6184  QF_GETLIST_FILEWINID = 0x200,
   6185  QF_GETLIST_QFBUFNR = 0x400,
   6186  QF_GETLIST_QFTF = 0x800,
   6187  QF_GETLIST_ALL = 0xFFF,
   6188 };
   6189 
   6190 /// Parse text from 'di' and return the quickfix list items.
   6191 /// Existing quickfix lists are not modified.
   6192 static int qf_get_list_from_lines(dict_T *what, dictitem_T *di, dict_T *retdict)
   6193 {
   6194  int status = FAIL;
   6195 
   6196  // Only a List value is supported
   6197  if (di->di_tv.v_type != VAR_LIST || di->di_tv.vval.v_list == NULL) {
   6198    return FAIL;
   6199  }
   6200 
   6201  char *errorformat = p_efm;
   6202  dictitem_T *efm_di;
   6203  // If errorformat is supplied then use it, otherwise use the 'efm'
   6204  // option setting
   6205  if ((efm_di = tv_dict_find(what, S_LEN("efm"))) != NULL) {
   6206    if (efm_di->di_tv.v_type != VAR_STRING
   6207        || efm_di->di_tv.vval.v_string == NULL) {
   6208      return FAIL;
   6209    }
   6210    errorformat = efm_di->di_tv.vval.v_string;
   6211  }
   6212 
   6213  list_T *l = tv_list_alloc(kListLenMayKnow);
   6214  qf_info_T *const qi = qf_alloc_stack(QFLT_INTERNAL, 1);
   6215 
   6216  if (qf_init_ext(qi, 0, NULL, NULL, &di->di_tv, errorformat,
   6217                  true, 0, 0, NULL, NULL) > 0) {
   6218    get_errorlist(qi, NULL, 0, 0, l);
   6219    qf_free(&qi->qf_lists[0]);
   6220  }
   6221 
   6222  qf_free_lists(qi);
   6223 
   6224  tv_dict_add_list(retdict, S_LEN("items"), l);
   6225  status = OK;
   6226 
   6227  return status;
   6228 }
   6229 
   6230 /// Return the quickfix/location list window identifier in the current tabpage.
   6231 static int qf_winid(qf_info_T *qi)
   6232 {
   6233  // The quickfix window can be opened even if the quickfix list is not set
   6234  // using ":copen". This is not true for location lists.
   6235  if (qi == NULL) {
   6236    return 0;
   6237  }
   6238  win_T *win = qf_find_win(qi);
   6239  if (win != NULL) {
   6240    return win->handle;
   6241  }
   6242  return 0;
   6243 }
   6244 
   6245 /// Returns the number of the buffer displayed in the quickfix/location list
   6246 /// window. If there is no buffer associated with the list or the buffer is
   6247 /// wiped out, then returns 0.
   6248 static int qf_getprop_qfbufnr(const qf_info_T *qi, dict_T *retdict)
   6249  FUNC_ATTR_NONNULL_ARG(2)
   6250 {
   6251  int bufnum = 0;
   6252 
   6253  if (qi != NULL && buflist_findnr(qi->qf_bufnr) != NULL) {
   6254    bufnum = qi->qf_bufnr;
   6255  }
   6256 
   6257  return tv_dict_add_nr(retdict, S_LEN("qfbufnr"), bufnum);
   6258 }
   6259 
   6260 /// Convert the keys in 'what' to quickfix list property flags.
   6261 static int qf_getprop_keys2flags(const dict_T *what, bool loclist)
   6262  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
   6263 {
   6264  int flags = QF_GETLIST_NONE;
   6265 
   6266  if (tv_dict_find(what, S_LEN("all")) != NULL) {
   6267    flags |= QF_GETLIST_ALL;
   6268    if (!loclist) {
   6269      // File window ID is applicable only to location list windows
   6270      flags &= ~QF_GETLIST_FILEWINID;
   6271    }
   6272  }
   6273  if (tv_dict_find(what, S_LEN("title")) != NULL) {
   6274    flags |= QF_GETLIST_TITLE;
   6275  }
   6276  if (tv_dict_find(what, S_LEN("nr")) != NULL) {
   6277    flags |= QF_GETLIST_NR;
   6278  }
   6279  if (tv_dict_find(what, S_LEN("winid")) != NULL) {
   6280    flags |= QF_GETLIST_WINID;
   6281  }
   6282  if (tv_dict_find(what, S_LEN("context")) != NULL) {
   6283    flags |= QF_GETLIST_CONTEXT;
   6284  }
   6285  if (tv_dict_find(what, S_LEN("id")) != NULL) {
   6286    flags |= QF_GETLIST_ID;
   6287  }
   6288  if (tv_dict_find(what, S_LEN("items")) != NULL) {
   6289    flags |= QF_GETLIST_ITEMS;
   6290  }
   6291  if (tv_dict_find(what, S_LEN("idx")) != NULL) {
   6292    flags |= QF_GETLIST_IDX;
   6293  }
   6294  if (tv_dict_find(what, S_LEN("size")) != NULL) {
   6295    flags |= QF_GETLIST_SIZE;
   6296  }
   6297  if (tv_dict_find(what, S_LEN("changedtick")) != NULL) {
   6298    flags |= QF_GETLIST_TICK;
   6299  }
   6300  if (loclist && tv_dict_find(what, S_LEN("filewinid")) != NULL) {
   6301    flags |= QF_GETLIST_FILEWINID;
   6302  }
   6303  if (tv_dict_find(what, S_LEN("qfbufnr")) != NULL) {
   6304    flags |= QF_GETLIST_QFBUFNR;
   6305  }
   6306  if (tv_dict_find(what, S_LEN("quickfixtextfunc")) != NULL) {
   6307    flags |= QF_GETLIST_QFTF;
   6308  }
   6309 
   6310  return flags;
   6311 }
   6312 
   6313 /// Return the quickfix list index based on 'nr' or 'id' in 'what'.
   6314 ///
   6315 /// If 'nr' and 'id' are not present in 'what' then return the current
   6316 /// quickfix list index.
   6317 /// If 'nr' is zero then return the current quickfix list index.
   6318 /// If 'nr' is '$' then return the last quickfix list index.
   6319 /// If 'id' is present then return the index of the quickfix list with that id.
   6320 /// If 'id' is zero then return the quickfix list index specified by 'nr'.
   6321 /// Return -1, if quickfix list is not present or if the stack is empty.
   6322 static int qf_getprop_qfidx(qf_info_T *qi, dict_T *what)
   6323 {
   6324  dictitem_T *di = NULL;
   6325 
   6326  int qf_idx = qi->qf_curlist;  // default is the current list
   6327  if ((di = tv_dict_find(what, S_LEN("nr"))) != NULL) {
   6328    // Use the specified quickfix/location list
   6329    if (di->di_tv.v_type == VAR_NUMBER) {
   6330      // for zero use the current list
   6331      if (di->di_tv.vval.v_number != 0) {
   6332        qf_idx = (int)di->di_tv.vval.v_number - 1;
   6333        if (qf_idx < 0 || qf_idx >= qi->qf_listcount) {
   6334          qf_idx = INVALID_QFIDX;
   6335        }
   6336      }
   6337    } else if (di->di_tv.v_type == VAR_STRING && strequal(di->di_tv.vval.v_string, "$")) {
   6338      // Get the last quickfix list number
   6339      qf_idx = qi->qf_listcount - 1;
   6340    } else {
   6341      qf_idx = INVALID_QFIDX;
   6342    }
   6343  }
   6344 
   6345  if ((di = tv_dict_find(what, S_LEN("id"))) != NULL) {
   6346    // Look for a list with the specified id
   6347    if (di->di_tv.v_type == VAR_NUMBER) {
   6348      // For zero, use the current list or the list specified by 'nr'
   6349      if (di->di_tv.vval.v_number != 0) {
   6350        qf_idx = qf_id2nr(qi, (unsigned)di->di_tv.vval.v_number);
   6351      }
   6352    } else {
   6353      qf_idx = INVALID_QFIDX;
   6354    }
   6355  }
   6356 
   6357  return qf_idx;
   6358 }
   6359 
   6360 /// Return default values for quickfix list properties in retdict.
   6361 static int qf_getprop_defaults(qf_info_T *qi, int flags, int locstack, dict_T *retdict)
   6362 {
   6363  int status = OK;
   6364 
   6365  if (flags & QF_GETLIST_TITLE) {
   6366    status = tv_dict_add_str(retdict, S_LEN("title"), "");
   6367  }
   6368  if ((status == OK) && (flags & QF_GETLIST_ITEMS)) {
   6369    list_T *l = tv_list_alloc(kListLenMayKnow);
   6370    status = tv_dict_add_list(retdict, S_LEN("items"), l);
   6371  }
   6372  if ((status == OK) && (flags & QF_GETLIST_NR)) {
   6373    status = tv_dict_add_nr(retdict, S_LEN("nr"), 0);
   6374  }
   6375  if ((status == OK) && (flags & QF_GETLIST_WINID)) {
   6376    status = tv_dict_add_nr(retdict, S_LEN("winid"), qf_winid(qi));
   6377  }
   6378  if ((status == OK) && (flags & QF_GETLIST_CONTEXT)) {
   6379    status = tv_dict_add_str(retdict, S_LEN("context"), "");
   6380  }
   6381  if ((status == OK) && (flags & QF_GETLIST_ID)) {
   6382    status = tv_dict_add_nr(retdict, S_LEN("id"), 0);
   6383  }
   6384  if ((status == OK) && (flags & QF_GETLIST_IDX)) {
   6385    status = tv_dict_add_nr(retdict, S_LEN("idx"), 0);
   6386  }
   6387  if ((status == OK) && (flags & QF_GETLIST_SIZE)) {
   6388    status = tv_dict_add_nr(retdict, S_LEN("size"), 0);
   6389  }
   6390  if ((status == OK) && (flags & QF_GETLIST_TICK)) {
   6391    status = tv_dict_add_nr(retdict, S_LEN("changedtick"), 0);
   6392  }
   6393  if ((status == OK) && locstack && (flags & QF_GETLIST_FILEWINID)) {
   6394    status = tv_dict_add_nr(retdict, S_LEN("filewinid"), 0);
   6395  }
   6396  if ((status == OK) && (flags & QF_GETLIST_QFBUFNR)) {
   6397    status = qf_getprop_qfbufnr(qi, retdict);
   6398  }
   6399  if ((status == OK) && (flags & QF_GETLIST_QFTF)) {
   6400    status = tv_dict_add_str(retdict, S_LEN("quickfixtextfunc"), "");
   6401  }
   6402 
   6403  return status;
   6404 }
   6405 
   6406 /// Return the quickfix list title as 'title' in retdict
   6407 static int qf_getprop_title(qf_list_T *qfl, dict_T *retdict)
   6408 {
   6409  return tv_dict_add_str(retdict, S_LEN("title"), qfl->qf_title);
   6410 }
   6411 
   6412 // Returns the identifier of the window used to display files from a location
   6413 // list.  If there is no associated window, then returns 0. Useful only when
   6414 // called from a location list window.
   6415 static int qf_getprop_filewinid(const win_T *wp, const qf_info_T *qi, dict_T *retdict)
   6416  FUNC_ATTR_NONNULL_ARG(3)
   6417 {
   6418  handle_T winid = 0;
   6419 
   6420  if (wp != NULL && IS_LL_WINDOW(wp)) {
   6421    win_T *ll_wp = qf_find_win_with_loclist(qi);
   6422    if (ll_wp != NULL) {
   6423      winid = ll_wp->handle;
   6424    }
   6425  }
   6426 
   6427  return tv_dict_add_nr(retdict, S_LEN("filewinid"), winid);
   6428 }
   6429 
   6430 /// Return the quickfix list items/entries as 'items' in retdict.
   6431 /// If eidx is not 0, then return the item at the specified index.
   6432 static int qf_getprop_items(qf_info_T *qi, int qf_idx, int eidx, dict_T *retdict)
   6433 {
   6434  list_T *l = tv_list_alloc(kListLenMayKnow);
   6435  get_errorlist(qi, NULL, qf_idx, eidx, l);
   6436  tv_dict_add_list(retdict, S_LEN("items"), l);
   6437 
   6438  return OK;
   6439 }
   6440 
   6441 /// Return the quickfix list context (if any) as 'context' in retdict.
   6442 static int qf_getprop_ctx(qf_list_T *qfl, dict_T *retdict)
   6443 {
   6444  int status;
   6445 
   6446  if (qfl->qf_ctx != NULL) {
   6447    dictitem_T *di = tv_dict_item_alloc_len(S_LEN("context"));
   6448    tv_copy(qfl->qf_ctx, &di->di_tv);
   6449    status = tv_dict_add(retdict, di);
   6450    if (status == FAIL) {
   6451      tv_dict_item_free(di);
   6452    }
   6453  } else {
   6454    status = tv_dict_add_str(retdict, S_LEN("context"), "");
   6455  }
   6456 
   6457  return status;
   6458 }
   6459 
   6460 /// Return the current quickfix list index as 'idx' in retdict.
   6461 /// If a specific entry index (eidx) is supplied, then use that.
   6462 static int qf_getprop_idx(qf_list_T *qfl, int eidx, dict_T *retdict)
   6463 {
   6464  if (eidx == 0) {
   6465    eidx = qfl->qf_index;
   6466    if (qf_list_empty(qfl)) {
   6467      // For empty lists, current index is set to 0
   6468      eidx = 0;
   6469    }
   6470  }
   6471  return tv_dict_add_nr(retdict, S_LEN("idx"), eidx);
   6472 }
   6473 
   6474 /// Return the 'quickfixtextfunc' function of a quickfix/location list
   6475 /// @return OK or FAIL
   6476 static int qf_getprop_qftf(qf_list_T *qfl, dict_T *retdict)
   6477  FUNC_ATTR_NONNULL_ALL
   6478 {
   6479  int status;
   6480 
   6481  if (qfl->qf_qftf_cb.type != kCallbackNone) {
   6482    typval_T tv;
   6483 
   6484    callback_put(&qfl->qf_qftf_cb, &tv);
   6485    status = tv_dict_add_tv(retdict, S_LEN("quickfixtextfunc"), &tv);
   6486    tv_clear(&tv);
   6487  } else {
   6488    status = tv_dict_add_str(retdict, S_LEN("quickfixtextfunc"), "");
   6489  }
   6490 
   6491  return status;
   6492 }
   6493 
   6494 /// Return quickfix/location list details (title) as a dictionary.
   6495 /// 'what' contains the details to return. If 'list_idx' is -1,
   6496 /// then current list is used. Otherwise the specified list is used.
   6497 static int qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
   6498 {
   6499  qf_info_T *qi = ql_info;
   6500  assert(qi != NULL);
   6501  dictitem_T *di = NULL;
   6502  int status = OK;
   6503  int qf_idx = INVALID_QFIDX;
   6504 
   6505  if ((di = tv_dict_find(what, S_LEN("lines"))) != NULL) {
   6506    return qf_get_list_from_lines(what, di, retdict);
   6507  }
   6508 
   6509  if (wp != NULL) {
   6510    qi = GET_LOC_LIST(wp);
   6511  }
   6512 
   6513  const int flags = qf_getprop_keys2flags(what, wp != NULL);
   6514 
   6515  if (!qf_stack_empty(qi)) {
   6516    qf_idx = qf_getprop_qfidx(qi, what);
   6517  }
   6518 
   6519  // List is not present or is empty
   6520  if (qf_stack_empty(qi) || qf_idx == INVALID_QFIDX) {
   6521    return qf_getprop_defaults(qi, flags, wp != NULL, retdict);
   6522  }
   6523 
   6524  qf_list_T *qfl = qf_get_list(qi, qf_idx);
   6525  int eidx = 0;
   6526 
   6527  // If an entry index is specified, use that
   6528  if ((di = tv_dict_find(what, S_LEN("idx"))) != NULL) {
   6529    if (di->di_tv.v_type != VAR_NUMBER) {
   6530      return FAIL;
   6531    }
   6532    eidx = (int)di->di_tv.vval.v_number;
   6533  }
   6534 
   6535  if (flags & QF_GETLIST_TITLE) {
   6536    status = qf_getprop_title(qfl, retdict);
   6537  }
   6538  if ((status == OK) && (flags & QF_GETLIST_NR)) {
   6539    status = tv_dict_add_nr(retdict, S_LEN("nr"), qf_idx + 1);
   6540  }
   6541  if ((status == OK) && (flags & QF_GETLIST_WINID)) {
   6542    status = tv_dict_add_nr(retdict, S_LEN("winid"), qf_winid(qi));
   6543  }
   6544  if ((status == OK) && (flags & QF_GETLIST_ITEMS)) {
   6545    status = qf_getprop_items(qi, qf_idx, eidx, retdict);
   6546  }
   6547  if ((status == OK) && (flags & QF_GETLIST_CONTEXT)) {
   6548    status = qf_getprop_ctx(qfl, retdict);
   6549  }
   6550  if ((status == OK) && (flags & QF_GETLIST_ID)) {
   6551    status = tv_dict_add_nr(retdict, S_LEN("id"), qfl->qf_id);
   6552  }
   6553  if ((status == OK) && (flags & QF_GETLIST_IDX)) {
   6554    status = qf_getprop_idx(qfl, eidx, retdict);
   6555  }
   6556  if ((status == OK) && (flags & QF_GETLIST_SIZE)) {
   6557    status = tv_dict_add_nr(retdict, S_LEN("size"),
   6558                            qfl->qf_count);
   6559  }
   6560  if ((status == OK) && (flags & QF_GETLIST_TICK)) {
   6561    status = tv_dict_add_nr(retdict, S_LEN("changedtick"),
   6562                            qfl->qf_changedtick);
   6563  }
   6564  if ((status == OK) && (wp != NULL) && (flags & QF_GETLIST_FILEWINID)) {
   6565    status = qf_getprop_filewinid(wp, qi, retdict);
   6566  }
   6567  if ((status == OK) && (flags & QF_GETLIST_QFBUFNR)) {
   6568    status = qf_getprop_qfbufnr(qi, retdict);
   6569  }
   6570  if ((status == OK) && (flags & QF_GETLIST_QFTF)) {
   6571    status = qf_getprop_qftf(qfl, retdict);
   6572  }
   6573 
   6574  return status;
   6575 }
   6576 
   6577 /// Set the current index in the specified quickfix list
   6578 /// @return OK
   6579 static int qf_setprop_qftf(qf_list_T *qfl, dictitem_T *di)
   6580  FUNC_ATTR_NONNULL_ALL
   6581 {
   6582  Callback cb;
   6583 
   6584  callback_free(&qfl->qf_qftf_cb);
   6585  if (callback_from_typval(&cb, &di->di_tv)) {
   6586    qfl->qf_qftf_cb = cb;
   6587  }
   6588  return OK;
   6589 }
   6590 
   6591 /// Add a new quickfix entry to list at 'qf_idx' in the stack 'qi' from the
   6592 /// items in the dict 'd'. If it is a valid error entry, then set 'valid_entry'
   6593 /// to true.
   6594 static int qf_add_entry_from_dict(qf_list_T *qfl, dict_T *d, bool first_entry, bool *valid_entry)
   6595  FUNC_ATTR_NONNULL_ALL
   6596 {
   6597  static bool did_bufnr_emsg;
   6598 
   6599  if (first_entry) {
   6600    did_bufnr_emsg = false;
   6601  }
   6602 
   6603  char *const filename = tv_dict_get_string(d, "filename", true);
   6604  char *const module = tv_dict_get_string(d, "module", true);
   6605  int bufnum = (int)tv_dict_get_number(d, "bufnr");
   6606  const linenr_T lnum = (linenr_T)tv_dict_get_number(d, "lnum");
   6607  const linenr_T end_lnum = (linenr_T)tv_dict_get_number(d, "end_lnum");
   6608  const int col = (int)tv_dict_get_number(d, "col");
   6609  const int end_col = (int)tv_dict_get_number(d, "end_col");
   6610  const char vcol = (char)tv_dict_get_number(d, "vcol");
   6611  const int nr = (int)tv_dict_get_number(d, "nr");
   6612  const char *const type = tv_dict_get_string(d, "type", false);
   6613  char *const pattern = tv_dict_get_string(d, "pattern", true);
   6614  char *text = tv_dict_get_string(d, "text", true);
   6615  if (text == NULL) {
   6616    text = xcalloc(1, 1);
   6617  }
   6618  typval_T user_data = { .v_type = VAR_UNKNOWN };
   6619  tv_dict_get_tv(d, "user_data", &user_data);
   6620 
   6621  bool valid = true;
   6622  if ((filename == NULL && bufnum == 0)
   6623      || (lnum == 0 && pattern == NULL)) {
   6624    valid = false;
   6625  }
   6626 
   6627  // Mark entries with non-existing buffer number as not valid. Give the
   6628  // error message only once.
   6629  if (bufnum != 0 && (buflist_findnr(bufnum) == NULL)) {
   6630    if (!did_bufnr_emsg) {
   6631      did_bufnr_emsg = true;
   6632      semsg(_("E92: Buffer %d not found"), bufnum);
   6633    }
   6634    valid = false;
   6635    bufnum = 0;
   6636  }
   6637 
   6638  // If the 'valid' field is present it overrules the detected value.
   6639  if (tv_dict_find(d, "valid", -1) != NULL) {
   6640    valid = tv_dict_get_bool(d, "valid", false);
   6641  }
   6642 
   6643  const int status = qf_add_entry(qfl,
   6644                                  NULL,      // dir
   6645                                  filename,
   6646                                  module,
   6647                                  bufnum,
   6648                                  text,
   6649                                  lnum,
   6650                                  end_lnum,
   6651                                  col,
   6652                                  end_col,
   6653                                  vcol,      // vis_col
   6654                                  pattern,   // search pattern
   6655                                  nr,
   6656                                  type == NULL ? NUL : *type,
   6657                                  &user_data,
   6658                                  valid);
   6659 
   6660  xfree(filename);
   6661  xfree(module);
   6662  xfree(pattern);
   6663  xfree(text);
   6664  tv_clear(&user_data);
   6665 
   6666  if (valid) {
   6667    *valid_entry = true;
   6668  }
   6669 
   6670  return status;
   6671 }
   6672 
   6673 /// Check if `entry` is closer to the target than `other_entry`.
   6674 ///
   6675 /// Only returns true if `entry` is definitively closer. If it's further
   6676 /// away, or there's not enough information to tell, return false.
   6677 static bool entry_is_closer_to_target(qfline_T *entry, qfline_T *other_entry, int target_fnum,
   6678                                      int target_lnum, int target_col)
   6679 {
   6680  // First, compare entries to target file.
   6681  if (!target_fnum) {
   6682    // Without a target file, we can't know which is closer.
   6683    return false;
   6684  }
   6685 
   6686  bool is_target_file = entry->qf_fnum && entry->qf_fnum == target_fnum;
   6687  bool other_is_target_file = other_entry->qf_fnum && other_entry->qf_fnum == target_fnum;
   6688  if (!is_target_file && other_is_target_file) {
   6689    return false;
   6690  } else if (is_target_file && !other_is_target_file) {
   6691    return true;
   6692  }
   6693 
   6694  // Both entries are pointing at the exact same file. Now compare line numbers.
   6695  if (!target_lnum) {
   6696    // Without a target line number, we can't know which is closer.
   6697    return false;
   6698  }
   6699 
   6700  int line_distance = entry->qf_lnum
   6701                      ? abs(entry->qf_lnum - target_lnum) : INT_MAX;
   6702  int other_line_distance = other_entry->qf_lnum
   6703                            ? abs(other_entry->qf_lnum - target_lnum) : INT_MAX;
   6704  if (line_distance > other_line_distance) {
   6705    return false;
   6706  } else if (line_distance < other_line_distance) {
   6707    return true;
   6708  }
   6709 
   6710  // Both entries are pointing at the exact same line number (or no line
   6711  // number at all). Now compare columns.
   6712  if (!target_col) {
   6713    // Without a target column, we can't know which is closer.
   6714    return false;
   6715  }
   6716 
   6717  int column_distance = entry->qf_col
   6718                        ? abs(entry->qf_col - target_col) : INT_MAX;
   6719  int other_column_distance = other_entry->qf_col
   6720                              ? abs(other_entry->qf_col - target_col) : INT_MAX;
   6721  if (column_distance > other_column_distance) {
   6722    return false;
   6723  } else if (column_distance < other_column_distance) {
   6724    return true;
   6725  }
   6726 
   6727  // It's a complete tie! The exact same file, line, and column.
   6728  return false;
   6729 }
   6730 
   6731 /// Add list of entries to quickfix/location list. Each list entry is
   6732 /// a dictionary with item information.
   6733 static int qf_add_entries(qf_info_T *qi, int qf_idx, list_T *list, char *title, int action)
   6734 {
   6735  qf_list_T *qfl = qf_get_list(qi, qf_idx);
   6736  qfline_T *old_last = NULL;
   6737  int retval = OK;
   6738  bool valid_entry = false;
   6739 
   6740  // If there's an entry selected in the quickfix list, remember its location
   6741  // (file, line, column), so we can select the nearest entry in the updated
   6742  // quickfix list.
   6743  int prev_fnum = 0;
   6744  int prev_lnum = 0;
   6745  int prev_col = 0;
   6746  if (qfl->qf_ptr) {
   6747    prev_fnum = qfl->qf_ptr->qf_fnum;
   6748    prev_lnum = qfl->qf_ptr->qf_lnum;
   6749    prev_col = qfl->qf_ptr->qf_col;
   6750  }
   6751 
   6752  bool select_first_entry = false;
   6753  bool select_nearest_entry = false;
   6754 
   6755  if (action == ' ' || qf_idx == qi->qf_listcount) {
   6756    select_first_entry = true;
   6757    // make place for a new list
   6758    qf_new_list(qi, title);
   6759    qf_idx = qi->qf_curlist;
   6760    qfl = qf_get_list(qi, qf_idx);
   6761  } else if (action == 'a') {
   6762    if (qf_list_empty(qfl)) {
   6763      // Appending to empty list, select first entry.
   6764      select_first_entry = true;
   6765    } else {
   6766      // Adding to existing list, use last entry.
   6767      old_last = qfl->qf_last;
   6768    }
   6769  } else if (action == 'r') {
   6770    select_first_entry = true;
   6771    qf_free_items(qfl);
   6772    qf_store_title(qfl, title);
   6773  } else if (action == 'u') {
   6774    select_nearest_entry = true;
   6775    qf_free_items(qfl);
   6776    qf_store_title(qfl, title);
   6777  }
   6778 
   6779  qfline_T *entry_to_select = NULL;
   6780  int entry_to_select_index = 0;
   6781 
   6782  TV_LIST_ITER_CONST(list, li, {
   6783    if (TV_LIST_ITEM_TV(li)->v_type != VAR_DICT) {
   6784      continue;  // Skip non-dict items.
   6785    }
   6786 
   6787    dict_T *const d = TV_LIST_ITEM_TV(li)->vval.v_dict;
   6788    if (d == NULL) {
   6789      continue;
   6790    }
   6791 
   6792    retval = qf_add_entry_from_dict(qfl, d, li == tv_list_first(list), &valid_entry);
   6793    if (retval == QF_FAIL) {
   6794      break;
   6795    }
   6796 
   6797    qfline_T *entry = qfl->qf_last;
   6798    if ((select_first_entry && entry_to_select == NULL)
   6799        || (select_nearest_entry
   6800            && (entry_to_select == NULL
   6801                || entry_is_closer_to_target(entry, entry_to_select, prev_fnum,
   6802                                             prev_lnum, prev_col)))) {
   6803      entry_to_select = entry;
   6804      entry_to_select_index = qfl->qf_count;
   6805    }
   6806  });
   6807 
   6808  // Check if any valid error entries are added to the list.
   6809  if (valid_entry) {
   6810    qfl->qf_nonevalid = false;
   6811  } else if (qfl->qf_index == 0) {
   6812    qfl->qf_nonevalid = true;
   6813  }
   6814 
   6815  // Set the current error.
   6816  if (entry_to_select) {
   6817    qfl->qf_ptr = entry_to_select;
   6818    qfl->qf_index = entry_to_select_index;
   6819  }
   6820 
   6821  // Don't update the cursor in quickfix window when appending entries
   6822  qf_update_buffer(qi, old_last);
   6823 
   6824  return retval;
   6825 }
   6826 
   6827 /// Get the quickfix list index from 'nr' or 'id'
   6828 static int qf_setprop_get_qfidx(const qf_info_T *qi, const dict_T *what, int action, bool *newlist)
   6829  FUNC_ATTR_NONNULL_ALL
   6830 {
   6831  dictitem_T *di;
   6832  int qf_idx = qi->qf_curlist;  // default is the current list
   6833 
   6834  if ((di = tv_dict_find(what, S_LEN("nr"))) != NULL) {
   6835    // Use the specified quickfix/location list
   6836    if (di->di_tv.v_type == VAR_NUMBER) {
   6837      // for zero use the current list
   6838      if (di->di_tv.vval.v_number != 0) {
   6839        qf_idx = (int)di->di_tv.vval.v_number - 1;
   6840      }
   6841 
   6842      if ((action == ' ' || action == 'a') && qf_idx == qi->qf_listcount) {
   6843        // When creating a new list, accept qf_idx pointing to the next
   6844        // non-available list and add the new list at the end of the
   6845        // stack.
   6846        *newlist = true;
   6847        qf_idx = qf_stack_empty(qi) ? 0 : qi->qf_listcount - 1;
   6848      } else if (qf_idx < 0 || qf_idx >= qi->qf_listcount) {
   6849        return INVALID_QFIDX;
   6850      } else if (action != ' ') {
   6851        *newlist = false;  // use the specified list
   6852      }
   6853    } else if (di->di_tv.v_type == VAR_STRING && strequal(di->di_tv.vval.v_string, "$")) {
   6854      if (!qf_stack_empty(qi)) {
   6855        qf_idx = qi->qf_listcount - 1;
   6856      } else if (*newlist) {
   6857        qf_idx = 0;
   6858      } else {
   6859        return INVALID_QFIDX;
   6860      }
   6861    } else {
   6862      return INVALID_QFIDX;
   6863    }
   6864  }
   6865 
   6866  if (!*newlist && (di = tv_dict_find(what, S_LEN("id"))) != NULL) {
   6867    // Use the quickfix/location list with the specified id
   6868    if (di->di_tv.v_type != VAR_NUMBER) {
   6869      return INVALID_QFIDX;
   6870    }
   6871    return qf_id2nr(qi, (unsigned)di->di_tv.vval.v_number);
   6872  }
   6873 
   6874  return qf_idx;
   6875 }
   6876 
   6877 // Set the quickfix list title.
   6878 static int qf_setprop_title(qf_info_T *qi, int qf_idx, const dict_T *what, const dictitem_T *di)
   6879  FUNC_ATTR_NONNULL_ALL
   6880 {
   6881  qf_list_T *qfl = qf_get_list(qi, qf_idx);
   6882  if (di->di_tv.v_type != VAR_STRING) {
   6883    return FAIL;
   6884  }
   6885 
   6886  xfree(qfl->qf_title);
   6887  qfl->qf_title = tv_dict_get_string(what, "title", true);
   6888  if (qf_idx == qi->qf_curlist) {
   6889    qf_update_win_titlevar(qi);
   6890  }
   6891 
   6892  return OK;
   6893 }
   6894 
   6895 // Set quickfix list items/entries.
   6896 static int qf_setprop_items(qf_info_T *qi, int qf_idx, dictitem_T *di, int action)
   6897  FUNC_ATTR_NONNULL_ALL
   6898 {
   6899  if (di->di_tv.v_type != VAR_LIST) {
   6900    return FAIL;
   6901  }
   6902 
   6903  char *title_save = xstrdup(qi->qf_lists[qf_idx].qf_title);
   6904  const int retval = qf_add_entries(qi, qf_idx, di->di_tv.vval.v_list, title_save,
   6905                                    action == ' ' ? 'a' : action);
   6906  xfree(title_save);
   6907 
   6908  return retval;
   6909 }
   6910 
   6911 // Set quickfix list items/entries from a list of lines.
   6912 static int qf_setprop_items_from_lines(qf_info_T *qi, int qf_idx, const dict_T *what,
   6913                                       dictitem_T *di, int action)
   6914  FUNC_ATTR_NONNULL_ALL
   6915 {
   6916  char *errorformat = p_efm;
   6917  dictitem_T *efm_di;
   6918  int retval = FAIL;
   6919 
   6920  // Use the user supplied errorformat settings (if present)
   6921  if ((efm_di = tv_dict_find(what, S_LEN("efm"))) != NULL) {
   6922    if (efm_di->di_tv.v_type != VAR_STRING
   6923        || efm_di->di_tv.vval.v_string == NULL) {
   6924      return FAIL;
   6925    }
   6926    errorformat = efm_di->di_tv.vval.v_string;
   6927  }
   6928 
   6929  // Only a List value is supported
   6930  if (di->di_tv.v_type != VAR_LIST || di->di_tv.vval.v_list == NULL) {
   6931    return FAIL;
   6932  }
   6933 
   6934  if (action == 'r' || action == 'u') {
   6935    qf_free_items(&qi->qf_lists[qf_idx]);
   6936  }
   6937  if (qf_init_ext(qi, qf_idx, NULL, NULL, &di->di_tv, errorformat,
   6938                  false, 0, 0, NULL, NULL) >= 0) {
   6939    retval = OK;
   6940  }
   6941 
   6942  return retval;
   6943 }
   6944 
   6945 // Set quickfix list context.
   6946 static int qf_setprop_context(qf_list_T *qfl, dictitem_T *di)
   6947  FUNC_ATTR_NONNULL_ALL
   6948 {
   6949  tv_free(qfl->qf_ctx);
   6950  typval_T *ctx = xcalloc(1, sizeof(typval_T));
   6951  tv_copy(&di->di_tv, ctx);
   6952  qfl->qf_ctx = ctx;
   6953 
   6954  return OK;
   6955 }
   6956 
   6957 // Set the current index in the specified quickfix list
   6958 static int qf_setprop_curidx(qf_info_T *qi, qf_list_T *qfl, const dictitem_T *di)
   6959  FUNC_ATTR_NONNULL_ALL
   6960 {
   6961  int newidx;
   6962 
   6963  // If the specified index is '$', then use the last entry
   6964  if (di->di_tv.v_type == VAR_STRING
   6965      && di->di_tv.vval.v_string != NULL
   6966      && strcmp(di->di_tv.vval.v_string, "$") == 0) {
   6967    newidx = qfl->qf_count;
   6968  } else {
   6969    // Otherwise use the specified index
   6970    bool denote = false;
   6971    newidx = (int)tv_get_number_chk(&di->di_tv, &denote);
   6972    if (denote) {
   6973      return FAIL;
   6974    }
   6975  }
   6976 
   6977  if (newidx < 1) {  // sanity check
   6978    return FAIL;
   6979  }
   6980  newidx = MIN(newidx, qfl->qf_count);
   6981  const int old_qfidx = qfl->qf_index;
   6982  qfline_T *const qf_ptr = get_nth_entry(qfl, newidx, &newidx);
   6983  if (qf_ptr == NULL) {
   6984    return FAIL;
   6985  }
   6986  qfl->qf_ptr = qf_ptr;
   6987  qfl->qf_index = newidx;
   6988 
   6989  // If the current list is modified and it is displayed in the quickfix
   6990  // window, then Update it.
   6991  if (qi->qf_lists[qi->qf_curlist].qf_id == qfl->qf_id) {
   6992    qf_win_pos_update(qi, old_qfidx);
   6993  }
   6994  return OK;
   6995 }
   6996 
   6997 /// Set quickfix/location list properties (title, items, context).
   6998 /// Also used to add items from parsing a list of lines.
   6999 /// Used by the setqflist() and setloclist() Vim script functions.
   7000 static int qf_set_properties(qf_info_T *qi, const dict_T *what, int action, char *title)
   7001  FUNC_ATTR_NONNULL_ALL
   7002 {
   7003  bool newlist = action == ' ' || qf_stack_empty(qi);
   7004  int qf_idx = qf_setprop_get_qfidx(qi, what, action, &newlist);
   7005  if (qf_idx == INVALID_QFIDX) {  // List not found
   7006    return FAIL;
   7007  }
   7008 
   7009  if (newlist) {
   7010    qi->qf_curlist = qf_idx;
   7011    qf_new_list(qi, title);
   7012    qf_idx = qi->qf_curlist;
   7013  }
   7014 
   7015  qf_list_T *qfl = qf_get_list(qi, qf_idx);
   7016  dictitem_T *di;
   7017  int retval = FAIL;
   7018  if ((di = tv_dict_find(what, S_LEN("title"))) != NULL) {
   7019    retval = qf_setprop_title(qi, qf_idx, what, di);
   7020  }
   7021  if ((di = tv_dict_find(what, S_LEN("items"))) != NULL) {
   7022    retval = qf_setprop_items(qi, qf_idx, di, action);
   7023  }
   7024  if ((di = tv_dict_find(what, S_LEN("lines"))) != NULL) {
   7025    retval = qf_setprop_items_from_lines(qi, qf_idx, what, di, action);
   7026  }
   7027  if ((di = tv_dict_find(what, S_LEN("context"))) != NULL) {
   7028    retval = qf_setprop_context(qfl, di);
   7029  }
   7030  if ((di = tv_dict_find(what, S_LEN("idx"))) != NULL) {
   7031    retval = qf_setprop_curidx(qi, qfl, di);
   7032  }
   7033  if ((di = tv_dict_find(what, S_LEN("quickfixtextfunc"))) != NULL) {
   7034    retval = qf_setprop_qftf(qfl, di);
   7035  }
   7036 
   7037  if (newlist || retval == OK) {
   7038    qf_list_changed(qfl);
   7039  }
   7040  if (newlist) {
   7041    qf_update_buffer(qi, NULL);
   7042  }
   7043 
   7044  return retval;
   7045 }
   7046 
   7047 // Free the entire quickfix/location list stack.
   7048 // If the quickfix/location list window is open, then clear it.
   7049 static void qf_free_stack(win_T *wp, qf_info_T *qi)
   7050 {
   7051  win_T *qfwin = qf_find_win(qi);
   7052 
   7053  if (qfwin != NULL) {
   7054    // If the quickfix/location list window is open, then clear it
   7055    if (qi->qf_curlist < qi->qf_listcount) {
   7056      qf_free(qf_get_curlist(qi));
   7057    }
   7058    qf_update_buffer(qi, NULL);
   7059  }
   7060 
   7061  if (wp != NULL && IS_LL_WINDOW(wp)) {
   7062    // If in the location list window, then use the non-location list
   7063    // window with this location list (if present)
   7064    win_T *const llwin = qf_find_win_with_loclist(qi);
   7065    if (llwin != NULL) {
   7066      wp = llwin;
   7067    }
   7068  }
   7069 
   7070  qf_free_all(wp);
   7071  if (wp == NULL) {
   7072    // quickfix list
   7073    qi->qf_curlist = 0;
   7074    qi->qf_listcount = 0;
   7075  } else if (qfwin != NULL) {
   7076    // If the location list window is open, then create a new empty location
   7077    // list
   7078    qf_info_T *new_ll = qf_alloc_stack(QFLT_LOCATION, (int)wp->w_p_lhi);
   7079    new_ll->qf_bufnr = qfwin->w_buffer->b_fnum;
   7080 
   7081    // first free the list reference in the location list window
   7082    ll_free_all(&qfwin->w_llist_ref);
   7083 
   7084    qfwin->w_llist_ref = new_ll;
   7085    if (wp != qfwin) {
   7086      win_set_loclist(wp, new_ll);
   7087    }
   7088  }
   7089 }
   7090 
   7091 /// Populate the quickfix list with the items supplied in the list
   7092 /// of dictionaries. "title" will be copied to w:quickfix_title
   7093 /// "action" is 'a' for add, 'r' for replace, 'u' for update.  Otherwise
   7094 /// create a new list.
   7095 /// When "what" is not NULL then only set some properties.
   7096 int set_errorlist(win_T *wp, list_T *list, int action, char *title, dict_T *what)
   7097 {
   7098  qf_info_T *qi;
   7099  if (wp != NULL) {
   7100    qi = ll_get_or_alloc_list(wp);
   7101  } else {
   7102    qi = ql_info;
   7103  }
   7104  assert(qi != NULL);
   7105 
   7106  if (action == 'f') {
   7107    // Free the entire quickfix or location list stack
   7108    qf_free_stack(wp, qi);
   7109    return OK;
   7110  }
   7111 
   7112  // A dict argument cannot be specified with a non-empty list argument
   7113  if (list != NULL && tv_list_len(list) != 0 && what != NULL) {
   7114    semsg(_(e_invarg2), _("cannot have both a list and a \"what\" argument"));
   7115    return FAIL;
   7116  }
   7117 
   7118  incr_quickfix_busy();
   7119 
   7120  int retval = OK;
   7121  if (what != NULL) {
   7122    retval = qf_set_properties(qi, what, action, title);
   7123  } else {
   7124    retval = qf_add_entries(qi, qi->qf_curlist, list, title, action);
   7125    if (retval == OK) {
   7126      qf_list_changed(qf_get_curlist(qi));
   7127    }
   7128  }
   7129 
   7130  decr_quickfix_busy();
   7131 
   7132  return retval;
   7133 }
   7134 
   7135 static bool mark_quickfix_user_data(qf_info_T *qi, int copyID)
   7136 {
   7137  bool abort = false;
   7138  for (int i = 0; i < qi->qf_maxcount && !abort; i++) {
   7139    qf_list_T *qfl = &qi->qf_lists[i];
   7140    if (!qfl->qf_has_user_data) {
   7141      continue;
   7142    }
   7143    qfline_T *qfp;
   7144    int j;
   7145    FOR_ALL_QFL_ITEMS(qfl, qfp, j) {
   7146      typval_T *user_data = &qfp->qf_user_data;
   7147      if (user_data != NULL && user_data->v_type != VAR_NUMBER
   7148          && user_data->v_type != VAR_STRING && user_data->v_type != VAR_FLOAT) {
   7149        abort = abort || set_ref_in_item(user_data, copyID, NULL, NULL);
   7150      }
   7151    }
   7152  }
   7153  return abort;
   7154 }
   7155 
   7156 /// Mark the quickfix context and callback function as in use for all the lists
   7157 /// in a quickfix stack.
   7158 static bool mark_quickfix_ctx(qf_info_T *qi, int copyID)
   7159 {
   7160  bool abort = false;
   7161 
   7162  for (int i = 0; i < qi->qf_maxcount && !abort; i++) {
   7163    typval_T *ctx = qi->qf_lists[i].qf_ctx;
   7164    if (ctx != NULL && ctx->v_type != VAR_NUMBER
   7165        && ctx->v_type != VAR_STRING && ctx->v_type != VAR_FLOAT) {
   7166      abort = set_ref_in_item(ctx, copyID, NULL, NULL);
   7167    }
   7168 
   7169    Callback *cb = &qi->qf_lists[i].qf_qftf_cb;
   7170    abort = abort || set_ref_in_callback(cb, copyID, NULL, NULL);
   7171  }
   7172 
   7173  return abort;
   7174 }
   7175 
   7176 /// Mark the context of the quickfix list and the location lists (if present) as
   7177 /// "in use". So that garbage collection doesn't free the context.
   7178 bool set_ref_in_quickfix(int copyID)
   7179 {
   7180  assert(ql_info != NULL);
   7181  if (mark_quickfix_ctx(ql_info, copyID)
   7182      || mark_quickfix_user_data(ql_info, copyID)
   7183      || set_ref_in_callback(&qftf_cb, copyID, NULL, NULL)) {
   7184    return true;
   7185  }
   7186 
   7187  FOR_ALL_TAB_WINDOWS(tp, win) {
   7188    if (win->w_llist != NULL) {
   7189      if (mark_quickfix_ctx(win->w_llist, copyID)
   7190          || mark_quickfix_user_data(win->w_llist, copyID)) {
   7191        return true;
   7192      }
   7193    }
   7194 
   7195    if (IS_LL_WINDOW(win) && (win->w_llist_ref->qf_refcount == 1)) {
   7196      // In a location list window and none of the other windows is
   7197      // referring to this location list. Mark the location list
   7198      // context as still in use.
   7199      if (mark_quickfix_ctx(win->w_llist_ref, copyID)
   7200          || mark_quickfix_user_data(win->w_llist_ref, copyID)) {
   7201        return true;
   7202      }
   7203    }
   7204  }
   7205 
   7206  return false;
   7207 }
   7208 
   7209 /// Return the autocmd name for the :cbuffer Ex commands
   7210 static char *cbuffer_get_auname(cmdidx_T cmdidx)
   7211 {
   7212  switch (cmdidx) {
   7213  case CMD_cbuffer:
   7214    return "cbuffer";
   7215  case CMD_cgetbuffer:
   7216    return "cgetbuffer";
   7217  case CMD_caddbuffer:
   7218    return "caddbuffer";
   7219  case CMD_lbuffer:
   7220    return "lbuffer";
   7221  case CMD_lgetbuffer:
   7222    return "lgetbuffer";
   7223  case CMD_laddbuffer:
   7224    return "laddbuffer";
   7225  default:
   7226    return NULL;
   7227  }
   7228 }
   7229 
   7230 /// Process and validate the arguments passed to the :cbuffer, :caddbuffer,
   7231 /// :cgetbuffer, :lbuffer, :laddbuffer, :lgetbuffer Ex commands.
   7232 static int cbuffer_process_args(exarg_T *eap, buf_T **bufp, linenr_T *line1, linenr_T *line2)
   7233 {
   7234  buf_T *buf = NULL;
   7235 
   7236  if (*eap->arg == NUL) {
   7237    buf = curbuf;
   7238  } else if (*skipwhite(skipdigits(eap->arg)) == NUL) {
   7239    buf = buflist_findnr(atoi(eap->arg));
   7240  }
   7241 
   7242  if (buf == NULL) {
   7243    emsg(_(e_invarg));
   7244    return FAIL;
   7245  }
   7246 
   7247  if (buf->b_ml.ml_mfp == NULL) {
   7248    emsg(_(e_buffer_is_not_loaded));
   7249    return FAIL;
   7250  }
   7251 
   7252  if (eap->addr_count == 0) {
   7253    eap->line1 = 1;
   7254    eap->line2 = buf->b_ml.ml_line_count;
   7255  }
   7256 
   7257  if (eap->line1 < 1 || eap->line1 > buf->b_ml.ml_line_count
   7258      || eap->line2 < 1 || eap->line2 > buf->b_ml.ml_line_count) {
   7259    emsg(_(e_invrange));
   7260    return FAIL;
   7261  }
   7262 
   7263  *line1 = eap->line1;
   7264  *line2 = eap->line2;
   7265  *bufp = buf;
   7266 
   7267  return OK;
   7268 }
   7269 
   7270 // ":[range]cbuffer [bufnr]" command.
   7271 // ":[range]caddbuffer [bufnr]" command.
   7272 // ":[range]cgetbuffer [bufnr]" command.
   7273 // ":[range]lbuffer [bufnr]" command.
   7274 // ":[range]laddbuffer [bufnr]" command.
   7275 // ":[range]lgetbuffer [bufnr]" command.
   7276 void ex_cbuffer(exarg_T *eap)
   7277 {
   7278  char *au_name = cbuffer_get_auname(eap->cmdidx);
   7279  if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
   7280                                        curbuf->b_fname, true, curbuf)) {
   7281    if (aborting()) {
   7282      return;
   7283    }
   7284  }
   7285 
   7286  // Must come after autocommands.
   7287  win_T *wp = NULL;
   7288  qf_info_T *qi = qf_cmd_get_or_alloc_stack(eap, &wp);
   7289 
   7290  buf_T *buf = NULL;
   7291  linenr_T line1;
   7292  linenr_T line2;
   7293  if (cbuffer_process_args(eap, &buf, &line1, &line2) == FAIL) {
   7294    return;
   7295  }
   7296 
   7297  char *qf_title = qf_cmdtitle(*eap->cmdlinep);
   7298 
   7299  if (buf->b_sfname) {
   7300    vim_snprintf(IObuff, IOSIZE, "%s (%s)", qf_title, buf->b_sfname);
   7301    qf_title = IObuff;
   7302  }
   7303 
   7304  incr_quickfix_busy();
   7305 
   7306  int res = qf_init_ext(qi, qi->qf_curlist, NULL, buf, NULL, p_efm,
   7307                        (eap->cmdidx != CMD_caddbuffer
   7308                         && eap->cmdidx != CMD_laddbuffer),
   7309                        eap->line1, eap->line2, qf_title, NULL);
   7310  if (qf_stack_empty(qi)) {
   7311    decr_quickfix_busy();
   7312    return;
   7313  }
   7314  if (res >= 0) {
   7315    qf_list_changed(qf_get_curlist(qi));
   7316  }
   7317  // Remember the current quickfix list identifier, so that we can
   7318  // check for autocommands changing the current quickfix list.
   7319  unsigned save_qfid = qf_get_curlist(qi)->qf_id;
   7320  if (au_name != NULL) {
   7321    const buf_T *const curbuf_old = curbuf;
   7322    apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, curbuf->b_fname, true, curbuf);
   7323    if (curbuf != curbuf_old) {
   7324      // Autocommands changed buffer, don't jump now, "qi" may
   7325      // be invalid.
   7326      res = 0;
   7327    }
   7328  }
   7329  // Jump to the first error for new list and if autocmds didn't
   7330  // free the list.
   7331  if (res > 0 && (eap->cmdidx == CMD_cbuffer || eap->cmdidx == CMD_lbuffer)
   7332      && qflist_valid(wp, save_qfid)) {
   7333    // display the first error
   7334    qf_jump_first(qi, save_qfid, eap->forceit);
   7335  }
   7336 
   7337  decr_quickfix_busy();
   7338 }
   7339 
   7340 /// Return the autocmd name for the :cexpr Ex commands.
   7341 static char *cexpr_get_auname(cmdidx_T cmdidx)
   7342 {
   7343  switch (cmdidx) {
   7344  case CMD_cexpr:
   7345    return "cexpr";
   7346  case CMD_cgetexpr:
   7347    return "cgetexpr";
   7348  case CMD_caddexpr:
   7349    return "caddexpr";
   7350  case CMD_lexpr:
   7351    return "lexpr";
   7352  case CMD_lgetexpr:
   7353    return "lgetexpr";
   7354  case CMD_laddexpr:
   7355    return "laddexpr";
   7356  default:
   7357    return NULL;
   7358  }
   7359 }
   7360 
   7361 static int trigger_cexpr_autocmd(int cmdidx)
   7362 {
   7363  char *au_name = cexpr_get_auname(cmdidx);
   7364  if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
   7365                                        curbuf->b_fname, true, curbuf)) {
   7366    if (aborting()) {
   7367      return FAIL;
   7368    }
   7369  }
   7370  return OK;
   7371 }
   7372 
   7373 int cexpr_core(const exarg_T *eap, typval_T *tv)
   7374  FUNC_ATTR_NONNULL_ALL
   7375 {
   7376  win_T *wp = NULL;
   7377  qf_info_T *qi = qf_cmd_get_or_alloc_stack(eap, &wp);
   7378 
   7379  if ((tv->v_type == VAR_STRING && tv->vval.v_string != NULL)
   7380      || tv->v_type == VAR_LIST) {
   7381    char *au_name = cexpr_get_auname(eap->cmdidx);
   7382    incr_quickfix_busy();
   7383    int res = qf_init_ext(qi, qi->qf_curlist, NULL, NULL, tv, p_efm,
   7384                          (eap->cmdidx != CMD_caddexpr
   7385                           && eap->cmdidx != CMD_laddexpr),
   7386                          0, 0,
   7387                          qf_cmdtitle(*eap->cmdlinep), NULL);
   7388    if (qf_stack_empty(qi)) {
   7389      decr_quickfix_busy();
   7390      return FAIL;
   7391    }
   7392    if (res >= 0) {
   7393      qf_list_changed(qf_get_curlist(qi));
   7394    }
   7395    // Remember the current quickfix list identifier, so that we can
   7396    // check for autocommands changing the current quickfix list.
   7397    unsigned save_qfid = qf_get_curlist(qi)->qf_id;
   7398    if (au_name != NULL) {
   7399      apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, curbuf->b_fname, true, curbuf);
   7400    }
   7401    // Jump to the first error for a new list and if autocmds didn't
   7402    // free the list.
   7403    if (res > 0
   7404        && (eap->cmdidx == CMD_cexpr || eap->cmdidx == CMD_lexpr)
   7405        && qflist_valid(wp, save_qfid)) {
   7406      // display the first error
   7407      qf_jump_first(qi, save_qfid, eap->forceit);
   7408    }
   7409    decr_quickfix_busy();
   7410    return OK;
   7411  } else {
   7412    emsg(_("E777: String or List expected"));
   7413  }
   7414  return FAIL;
   7415 }
   7416 
   7417 /// ":cexpr {expr}", ":cgetexpr {expr}", ":caddexpr {expr}" command.
   7418 /// ":lexpr {expr}", ":lgetexpr {expr}", ":laddexpr {expr}" command.
   7419 /// Also: ":caddexpr", ":cgetexpr", "laddexpr" and "laddexpr".
   7420 void ex_cexpr(exarg_T *eap)
   7421 {
   7422  if (trigger_cexpr_autocmd(eap->cmdidx) == FAIL) {
   7423    return;
   7424  }
   7425 
   7426  // Evaluate the expression.  When the result is a string or a list we can
   7427  // use it to fill the errorlist.
   7428  typval_T *tv = eval_expr(eap->arg, eap);
   7429  if (tv == NULL) {
   7430    return;
   7431  }
   7432 
   7433  (void)cexpr_core(eap, tv);
   7434  tv_free(tv);
   7435 }
   7436 
   7437 // Get the location list for ":lhelpgrep"
   7438 static qf_info_T *hgr_get_ll(bool *new_ll)
   7439  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
   7440 {
   7441  // If the current window is a help window, then use it, else find an existing help window
   7442  win_T *wp = bt_help(curwin->w_buffer) ? curwin : qf_find_help_win();
   7443 
   7444  qf_info_T *qi = wp == NULL ? NULL : wp->w_llist;
   7445  if (qi == NULL) {
   7446    // Allocate a new location list for help text matches
   7447    qi = qf_alloc_stack(QFLT_LOCATION, 1);
   7448    *new_ll = true;
   7449  }
   7450 
   7451  return qi;
   7452 }
   7453 
   7454 // Search for a pattern in a help file.
   7455 static void hgr_search_file(qf_list_T *qfl, char *fname, regmatch_T *p_regmatch)
   7456  FUNC_ATTR_NONNULL_ARG(1, 3)
   7457 {
   7458  FILE *const fd = os_fopen(fname, "r");
   7459  if (fd == NULL) {
   7460    return;
   7461  }
   7462 
   7463  linenr_T lnum = 1;
   7464  while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int) {
   7465    char *line = IObuff;
   7466 
   7467    if (vim_regexec(p_regmatch, line, 0)) {
   7468      int l = (int)strlen(line);
   7469 
   7470      // remove trailing CR, LF, spaces, etc.
   7471      while (l > 0 && line[l - 1] <= ' ') {
   7472        line[--l] = NUL;
   7473      }
   7474 
   7475      if (qf_add_entry(qfl,
   7476                       NULL,   // dir
   7477                       fname,
   7478                       NULL,
   7479                       0,
   7480                       line,
   7481                       lnum,
   7482                       0,
   7483                       (int)(p_regmatch->startp[0] - line) + 1,  // col
   7484                       (int)(p_regmatch->endp[0] - line)
   7485                       + 1,    // end_col
   7486                       false,  // vis_col
   7487                       NULL,   // search pattern
   7488                       0,      // nr
   7489                       1,      // type
   7490                       NULL,   // user_data
   7491                       true)   // valid
   7492          == QF_FAIL) {
   7493        got_int = true;
   7494        if (line != IObuff) {
   7495          xfree(line);
   7496        }
   7497        break;
   7498      }
   7499    }
   7500    if (line != IObuff) {
   7501      xfree(line);
   7502    }
   7503    lnum++;
   7504    line_breakcheck();
   7505  }
   7506  fclose(fd);
   7507 }
   7508 
   7509 // Search for a pattern in all the help files in the doc directory under
   7510 // the given directory.
   7511 static void hgr_search_files_in_dir(qf_list_T *qfl, char *dirname, regmatch_T *p_regmatch,
   7512                                    const char *lang)
   7513  FUNC_ATTR_NONNULL_ARG(1, 2, 3)
   7514 {
   7515  int fcount;
   7516  char **fnames;
   7517 
   7518  // Find all "*.txt" and "*.??x" files in the "doc" directory.
   7519  add_pathsep(dirname);
   7520  strcat(dirname, "doc/*.\\(txt\\|??x\\)");  // NOLINT
   7521  if (gen_expand_wildcards(1, &dirname, &fcount, &fnames, EW_FILE|EW_SILENT) == OK
   7522      && fcount > 0) {
   7523    for (int fi = 0; fi < fcount && !got_int; fi++) {
   7524      // Skip files for a different language.
   7525      if (lang != NULL
   7526          && STRNICMP(lang, fnames[fi] + strlen(fnames[fi]) - 3, 2) != 0
   7527          && !(STRNICMP(lang, "en", 2) == 0
   7528               && STRNICMP("txt", fnames[fi] + strlen(fnames[fi]) - 3, 3)
   7529               == 0)) {
   7530        continue;
   7531      }
   7532 
   7533      hgr_search_file(qfl, fnames[fi], p_regmatch);
   7534    }
   7535    FreeWild(fcount, fnames);
   7536  }
   7537 }
   7538 
   7539 // Search for a pattern in all the help files in the 'runtimepath'
   7540 // and add the matches to a quickfix list.
   7541 // 'lang' is the language specifier.  If supplied, then only matches in the
   7542 // specified language are found.
   7543 static void hgr_search_in_rtp(qf_list_T *qfl, regmatch_T *p_regmatch, const char *lang)
   7544  FUNC_ATTR_NONNULL_ARG(1, 2)
   7545 {
   7546  // Go through all directories in 'runtimepath'
   7547  char *p = p_rtp;
   7548  while (*p != NUL && !got_int) {
   7549    copy_option_part(&p, NameBuff, MAXPATHL, ",");
   7550 
   7551    hgr_search_files_in_dir(qfl, NameBuff, p_regmatch, lang);
   7552  }
   7553 }
   7554 
   7555 // ":helpgrep {pattern}"
   7556 void ex_helpgrep(exarg_T *eap)
   7557 {
   7558  qf_info_T *qi = ql_info;
   7559  assert(qi != NULL);
   7560  char *au_name = NULL;
   7561 
   7562  switch (eap->cmdidx) {
   7563  case CMD_helpgrep:
   7564    au_name = "helpgrep"; break;
   7565  case CMD_lhelpgrep:
   7566    au_name = "lhelpgrep"; break;
   7567  default:
   7568    break;
   7569  }
   7570  if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
   7571                                        curbuf->b_fname, true, curbuf)) {
   7572    if (aborting()) {
   7573      return;
   7574    }
   7575  }
   7576 
   7577  bool updated = false;
   7578  // Make 'cpoptions' empty, the 'l' flag should not be used here.
   7579  char *const save_cpo = p_cpo;
   7580  p_cpo = empty_string_option;
   7581 
   7582  bool new_qi = false;
   7583  if (is_loclist_cmd(eap->cmdidx)) {
   7584    qi = hgr_get_ll(&new_qi);
   7585  }
   7586 
   7587  incr_quickfix_busy();
   7588 
   7589  // Check for a specified language
   7590  char *const lang = check_help_lang(eap->arg);
   7591  regmatch_T regmatch = {
   7592    .regprog = vim_regcomp(eap->arg, RE_MAGIC + RE_STRING),
   7593    .rm_ic = false,
   7594  };
   7595  if (regmatch.regprog != NULL) {
   7596    // Create a new quickfix list.
   7597    qf_new_list(qi, qf_cmdtitle(*eap->cmdlinep));
   7598    qf_list_T *const qfl = qf_get_curlist(qi);
   7599 
   7600    hgr_search_in_rtp(qfl, &regmatch, lang);
   7601 
   7602    vim_regfree(regmatch.regprog);
   7603 
   7604    qfl->qf_nonevalid = false;
   7605    qfl->qf_ptr = qfl->qf_start;
   7606    qfl->qf_index = 1;
   7607    qf_list_changed(qfl);
   7608    updated = true;
   7609  }
   7610 
   7611  if (p_cpo == empty_string_option) {
   7612    p_cpo = save_cpo;
   7613  } else {
   7614    // Darn, some plugin changed the value.  If it's still empty it was
   7615    // changed and restored, need to restore in the complicated way.
   7616    if (*p_cpo == NUL) {
   7617      set_option_value_give_err(kOptCpoptions, CSTR_AS_OPTVAL(save_cpo), 0);
   7618    }
   7619    free_string_option(save_cpo);
   7620  }
   7621 
   7622  if (updated) {
   7623    // This may open a window and source scripts, do this after 'cpo' was
   7624    // restored.
   7625    qf_update_buffer(qi, NULL);
   7626  }
   7627 
   7628  if (au_name != NULL) {
   7629    apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, curbuf->b_fname, true, curbuf);
   7630    // When adding a location list to an existing location list stack,
   7631    // if the autocmd made the stack invalid, then just return.
   7632    if (!new_qi && IS_LL_STACK(qi) && qf_find_win_with_loclist(qi) == NULL) {
   7633      decr_quickfix_busy();
   7634      return;
   7635    }
   7636  }
   7637 
   7638  // Jump to first match.
   7639  if (!qf_list_empty(qf_get_curlist(qi))) {
   7640    qf_jump(qi, 0, 0, false);
   7641  } else {
   7642    semsg(_(e_nomatch2), eap->arg);
   7643  }
   7644 
   7645  decr_quickfix_busy();
   7646 
   7647  if (eap->cmdidx == CMD_lhelpgrep) {
   7648    // If the help window is not opened or if it already points to the
   7649    // correct location list, then free the new location list.
   7650    if (!bt_help(curwin->w_buffer) || curwin->w_llist == qi) {
   7651      if (new_qi) {
   7652        ll_free_all(&qi);
   7653      }
   7654    } else if (curwin->w_llist == NULL && new_qi) {
   7655      // current window didn't have a location list associated with it
   7656      // before. Associate the new location list now.
   7657      curwin->w_llist = qi;
   7658    }
   7659  }
   7660 }
   7661 
   7662 #if defined(EXITFREE)
   7663 void free_quickfix(void)
   7664 {
   7665  qf_free_all(NULL);
   7666  // Free all location lists
   7667  FOR_ALL_TAB_WINDOWS(tab, win) {
   7668    qf_free_all(win);
   7669  }
   7670 
   7671  ga_clear(&qfga);
   7672 }
   7673 #endif
   7674 
   7675 static void get_qf_loc_list(bool is_qf, win_T *wp, typval_T *what_arg, typval_T *rettv)
   7676 {
   7677  if (what_arg->v_type == VAR_UNKNOWN) {
   7678    tv_list_alloc_ret(rettv, kListLenMayKnow);
   7679    if (is_qf || wp != NULL) {
   7680      get_errorlist(NULL, wp, -1, 0, rettv->vval.v_list);
   7681    }
   7682  } else {
   7683    tv_dict_alloc_ret(rettv);
   7684    if (is_qf || wp != NULL) {
   7685      if (what_arg->v_type == VAR_DICT) {
   7686        dict_T *d = what_arg->vval.v_dict;
   7687 
   7688        if (d != NULL) {
   7689          qf_get_properties(wp, d, rettv->vval.v_dict);
   7690        }
   7691      } else {
   7692        emsg(_(e_dictreq));
   7693      }
   7694    }
   7695  }
   7696 }
   7697 
   7698 /// "getloclist()" function
   7699 void f_getloclist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
   7700 {
   7701  win_T *wp = find_win_by_nr_or_id(&argvars[0]);
   7702  get_qf_loc_list(false, wp, &argvars[1], rettv);
   7703 }
   7704 
   7705 /// "getqflist()" functions
   7706 void f_getqflist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
   7707 {
   7708  get_qf_loc_list(true, NULL, &argvars[0], rettv);
   7709 }
   7710 
   7711 /// Create quickfix/location list from Vimscript values
   7712 ///
   7713 /// Used by `setqflist()` and `setloclist()` functions. Accepts invalid
   7714 /// args argument in which case errors out, including VAR_UNKNOWN parameters.
   7715 ///
   7716 /// @param[in,out]  wp  Window to create location list for. May be NULL in
   7717 ///                     which case quickfix list will be created.
   7718 /// @param[in]  args  [list, action, what]
   7719 /// @param[in]  args[0]  Quickfix list contents.
   7720 /// @param[in]  args[1]  Optional. Action to perform:
   7721 ///                      append to an existing list, replace its content,
   7722 ///                      or create a new one.
   7723 /// @param[in]  args[2]  Optional. Quickfix list properties or title.
   7724 ///                      Defaults to caller function name.
   7725 /// @param[out]  rettv  Return value: 0 in case of success, -1 otherwise.
   7726 static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv)
   7727  FUNC_ATTR_NONNULL_ARG(2, 3)
   7728 {
   7729  static const char *e_invact = N_("E927: Invalid action: '%s'");
   7730  const char *title = NULL;
   7731  char action = ' ';
   7732  static int recursive = 0;
   7733  rettv->vval.v_number = -1;
   7734  dict_T *what = NULL;
   7735 
   7736  typval_T *list_arg = &args[0];
   7737  if (list_arg->v_type != VAR_LIST) {
   7738    emsg(_(e_listreq));
   7739    return;
   7740  } else if (recursive != 0) {
   7741    emsg(_(e_au_recursive));
   7742    return;
   7743  }
   7744 
   7745  typval_T *action_arg = &args[1];
   7746  if (action_arg->v_type == VAR_UNKNOWN) {
   7747    // Option argument was not given.
   7748    goto skip_args;
   7749  } else if (action_arg->v_type != VAR_STRING) {
   7750    emsg(_(e_string_required));
   7751    return;
   7752  }
   7753  const char *const act = tv_get_string_chk(action_arg);
   7754  if ((*act == 'a' || *act == 'r' || *act == 'u' || *act == ' ' || *act == 'f')
   7755      && act[1] == NUL) {
   7756    action = *act;
   7757  } else {
   7758    semsg(_(e_invact), act);
   7759    return;
   7760  }
   7761 
   7762  typval_T *const what_arg = &args[2];
   7763  if (what_arg->v_type == VAR_UNKNOWN) {
   7764    // Option argument was not given.
   7765    goto skip_args;
   7766  } else if (what_arg->v_type == VAR_STRING) {
   7767    title = tv_get_string_chk(what_arg);
   7768    if (!title) {
   7769      // Type error. Error already printed by tv_get_string_chk().
   7770      return;
   7771    }
   7772  } else if (what_arg->v_type == VAR_DICT && what_arg->vval.v_dict != NULL) {
   7773    what = what_arg->vval.v_dict;
   7774  } else {
   7775    emsg(_(e_dictreq));
   7776    return;
   7777  }
   7778 
   7779 skip_args:
   7780  if (!title) {
   7781    title = (wp ? ":setloclist()" : ":setqflist()");
   7782  }
   7783 
   7784  recursive++;
   7785  list_T *const l = list_arg->vval.v_list;
   7786  if (set_errorlist(wp, l, action, (char *)title, what) == OK) {
   7787    rettv->vval.v_number = 0;
   7788  }
   7789  recursive--;
   7790 }
   7791 
   7792 /// "setloclist()" function
   7793 void f_setloclist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
   7794 {
   7795  rettv->vval.v_number = -1;
   7796 
   7797  win_T *win = find_win_by_nr_or_id(&argvars[0]);
   7798  if (win != NULL) {
   7799    set_qf_ll_list(win, &argvars[1], rettv);
   7800  }
   7801 }
   7802 
   7803 /// "setqflist()" function
   7804 void f_setqflist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
   7805 {
   7806  set_qf_ll_list(NULL, argvars, rettv);
   7807 }