From 8728a5d50bc3339db81c7f29d59c55f9f817f06c Mon Sep 17 00:00:00 2001 From: KunMing Xie Date: Wed, 31 Jan 2018 03:29:15 +0800 Subject: vim-patch:8.0.0448: some macros are lower case (#7936) Problem: Some macros are in lower case, which can be confusing. Solution: Make a few lower case macros upper case. https://github.com/vim/vim/commit/b5aedf3e228d35821591da9ae8501b61cf2e264c ref #6297 --- src/nvim/fileio.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'src/nvim/fileio.c') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 1f4cd22754..44d74c92cd 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -5088,14 +5088,12 @@ void buf_reload(buf_T *buf, int orig_mode) flags |= READ_KEEP_UNDO; } - /* - * To behave like when a new file is edited (matters for - * BufReadPost autocommands) we first need to delete the current - * buffer contents. But if reading the file fails we should keep - * the old contents. Can't use memory only, the file might be - * too big. Use a hidden buffer to move the buffer contents to. - */ - if (bufempty() || saved == FAIL) { + // To behave like when a new file is edited (matters for + // BufReadPost autocommands) we first need to delete the current + // buffer contents. But if reading the file fails we should keep + // the old contents. Can't use memory only, the file might be + // too big. Use a hidden buffer to move the buffer contents to. + if (BUFEMPTY() || saved == FAIL) { savebuf = NULL; } else { // Allocate a buffer without putting it in the buffer list. @@ -5128,7 +5126,7 @@ void buf_reload(buf_T *buf, int orig_mode) if (savebuf != NULL && bufref_valid(&bufref) && buf == curbuf) { // Put the text back from the save buffer. First // delete any lines that readfile() added. - while (!bufempty()) { + while (!BUFEMPTY()) { if (ml_delete(buf->b_ml.ml_line_count, false) == FAIL) { break; } -- cgit From fd58863eb62edddf688a71d73448934efa188241 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 2 Feb 2018 02:30:21 +0100 Subject: vim-patch:8.0.0703: illegal memory access with empty :doau command Problem: Illegal memory access with empty :doau command. Solution: Check the event for being out of range. (James McCoy) https://github.com/vim/vim/commit/faf29d7f91477c25c85d9d7165d90e8d8f1c512e --- src/nvim/fileio.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) (limited to 'src/nvim/fileio.c') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 44d74c92cd..54b0032c9c 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -6274,13 +6274,13 @@ do_doautocmd ( fname = skipwhite(fname); - /* - * Loop over the events. - */ - while (*arg && !ascii_iswhite(*arg)) - if (apply_autocmds_group(event_name2nr(arg, &arg), - fname, NULL, TRUE, group, curbuf, NULL)) + // Loop over the events. + while (*arg && !ends_excmd(*arg) && !ascii_iswhite(*arg)) { + if (apply_autocmds_group(event_name2nr(arg, &arg), fname, NULL, TRUE, + group, curbuf, NULL)) { nothing_done = FALSE; + } + } if (nothing_done && do_msg) { MSG(_("No matching autocommands")); @@ -6671,12 +6671,12 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, proftime_T wait_time; bool did_save_redobuff = false; - /* - * Quickly return if there are no autocommands for this event or - * autocommands are blocked. - */ - if (first_autopat[(int)event] == NULL || autocmd_blocked > 0) + // Quickly return if there are no autocommands for this event or + // autocommands are blocked. + if (event == NUM_EVENTS || first_autopat[(int)event] == NULL + || autocmd_blocked > 0) { goto BYPASS_AU; + } /* * When autocommands are busy, new autocommands are only executed when @@ -6742,18 +6742,21 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, * invalid. */ if (fname_io == NULL) { - if (event == EVENT_COLORSCHEME || event == EVENT_OPTIONSET) + if (event == EVENT_COLORSCHEME || event == EVENT_OPTIONSET) { autocmd_fname = NULL; - else if (fname != NULL && *fname != NUL) + } else if (fname != NULL && !ends_excmd(*fname)) { autocmd_fname = fname; - else if (buf != NULL) + } else if (buf != NULL) { autocmd_fname = buf->b_ffname; - else + } else { autocmd_fname = NULL; - } else + } + } else { autocmd_fname = fname_io; - if (autocmd_fname != NULL) + } + if (autocmd_fname != NULL) { autocmd_fname = vim_strsave(autocmd_fname); + } autocmd_fname_full = FALSE; /* call FullName_save() later */ /* -- cgit From f26a4d484b486019c90fc55af5e74e33de374bc4 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 11 Feb 2018 19:02:57 +0100 Subject: lint --- src/nvim/fileio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/fileio.c') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 54b0032c9c..91b0a695f1 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -6276,9 +6276,9 @@ do_doautocmd ( // Loop over the events. while (*arg && !ends_excmd(*arg) && !ascii_iswhite(*arg)) { - if (apply_autocmds_group(event_name2nr(arg, &arg), fname, NULL, TRUE, + if (apply_autocmds_group(event_name2nr(arg, &arg), fname, NULL, true, group, curbuf, NULL)) { - nothing_done = FALSE; + nothing_done = false; } } @@ -6757,7 +6757,7 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, if (autocmd_fname != NULL) { autocmd_fname = vim_strsave(autocmd_fname); } - autocmd_fname_full = FALSE; /* call FullName_save() later */ + autocmd_fname_full = false; // call FullName_save() later /* * Set the buffer number to be used for . -- cgit From 189c5abeba4fb508d879ebbf5fa07965c4092cf2 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 20 Mar 2018 23:57:41 +0100 Subject: provider/RPC: apply_autocmds_group(): fix double-free During provider dispatch, eval_call_provider() saves global state--including pointers, such as `autocmd_fname`--into `provider_caller_scope` which is later restored by f_rpcrequest(). But `autocmd_fname` is special-cased in eval_vars(), for performance (see Vim patch 7.2.021; this is also the singular purpose of the `autocmd_fname_full` global. Yay!) If eval_vars() frees `autocmd_fname` then its provider-RPC-scoped alias becomes a problem. Solution: Don't free autocmd_fname in eval_vars(), just copy into it. closes #5245 closes #5617 Reference ------------------------------------------------------------------------ Vim patch 7.2.021 https://github.com/vim/vim/commit/f6dad43c98f47da1ff9d8c99b320fc3674f83c63 Problem: When executing autocommands getting the full file name may be slow. (David Kotchan) Solution: Postpone calling FullName_save() until autocmd_fname is used. vim_dev discussion (2008): "Problem with CursorMoved AutoCommand when Editing Files on a Remote WIndows Share" https://groups.google.com/d/msg/vim_dev/kj95weZa_eE/GTgj4aq5sIgJ --- src/nvim/fileio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/fileio.c') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 91b0a695f1..4e70daea90 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -6755,7 +6755,8 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, autocmd_fname = fname_io; } if (autocmd_fname != NULL) { - autocmd_fname = vim_strsave(autocmd_fname); + // Allocate MAXPATHL for when eval_vars() resolves the fullpath. + autocmd_fname = vim_strnsave(autocmd_fname, MAXPATHL); } autocmd_fname_full = false; // call FullName_save() later -- cgit From 82cd0be2eaf71c0476e15c66ba3e83c76896d407 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sat, 24 Mar 2018 11:10:01 +0100 Subject: refactor: eliminate `autocmd_fname_full` global It's a micro-optimization; check path_is_absolute_path(autocmd_fname) instead. The main optimization (which is still in place) afforded by Vim 7.2.021 was to avoid resolving when it is not needed. --- src/nvim/fileio.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/nvim/fileio.c') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 4e70daea90..ea214dd38a 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -6655,7 +6655,6 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, char_u *save_sourcing_name; linenr_T save_sourcing_lnum; char_u *save_autocmd_fname; - int save_autocmd_fname_full; int save_autocmd_bufnr; char_u *save_autocmd_match; int save_autocmd_busy; @@ -6728,7 +6727,6 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, * Save the autocmd_* variables and info about the current buffer. */ save_autocmd_fname = autocmd_fname; - save_autocmd_fname_full = autocmd_fname_full; save_autocmd_bufnr = autocmd_bufnr; save_autocmd_match = autocmd_match; save_autocmd_busy = autocmd_busy; @@ -6758,7 +6756,6 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, // Allocate MAXPATHL for when eval_vars() resolves the fullpath. autocmd_fname = vim_strnsave(autocmd_fname, MAXPATHL); } - autocmd_fname_full = false; // call FullName_save() later /* * Set the buffer number to be used for . @@ -6925,7 +6922,6 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, sourcing_lnum = save_sourcing_lnum; xfree(autocmd_fname); autocmd_fname = save_autocmd_fname; - autocmd_fname_full = save_autocmd_fname_full; autocmd_bufnr = save_autocmd_bufnr; autocmd_match = save_autocmd_match; current_SID = save_current_SID; -- cgit From 998a16c926623a667ecb0228f4a6cd8ba1e90201 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sat, 24 Mar 2018 11:21:20 +0100 Subject: refactor/rename: path_is_absolute() --- src/nvim/fileio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/fileio.c') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index ea214dd38a..52686f6651 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -4318,7 +4318,7 @@ void shorten_fnames(int force) && !path_with_url((char *)buf->b_fname) && (force || buf->b_sfname == NULL - || path_is_absolute_path(buf->b_sfname))) { + || path_is_absolute(buf->b_sfname))) { xfree(buf->b_sfname); buf->b_sfname = NULL; p = path_shorten_fname(buf->b_ffname, dirname); -- cgit From e25e552a3d3dda7867b233ffabc5218b331e3a86 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 2 Apr 2018 23:30:30 +0200 Subject: vim-patch:8.0.1284: loading file type detection slows down startup Problem: Loading file type detection slows down startup. Solution: Store the last pattern of an autocommand event to make appending quicker. https://github.com/vim/vim/commit/462455ee8b81cb5709007d91248ac4a88308d6e9 --- src/nvim/fileio.c | 133 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 79 insertions(+), 54 deletions(-) (limited to 'src/nvim/fileio.c') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 52686f6651..02f72dbce3 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -1,9 +1,7 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -/* - * fileio.c: read from and write to a file - */ +// fileio.c: read from and write to a file #include #include @@ -65,57 +63,62 @@ #define BUFSIZE 8192 /* size of normal write buffer */ #define SMBUFSIZE 256 /* size of emergency write buffer */ -/* - * The autocommands are stored in a list for each event. - * Autocommands for the same pattern, that are consecutive, are joined - * together, to avoid having to match the pattern too often. - * The result is an array of Autopat lists, which point to AutoCmd lists: - * - * first_autopat[0] --> Autopat.next --> Autopat.next --> NULL - * Autopat.cmds Autopat.cmds - * | | - * V V - * AutoCmd.next AutoCmd.next - * | | - * V V - * AutoCmd.next NULL - * | - * V - * NULL - * - * first_autopat[1] --> Autopat.next --> NULL - * Autopat.cmds - * | - * V - * AutoCmd.next - * | - * V - * NULL - * etc. - * - * The order of AutoCmds is important, this is the order in which they were - * defined and will have to be executed. - */ +// +// The autocommands are stored in a list for each event. +// Autocommands for the same pattern, that are consecutive, are joined +// together, to avoid having to match the pattern too often. +// The result is an array of Autopat lists, which point to AutoCmd lists: +// +// last_autopat[0] -----------------------------+ +// V +// first_autopat[0] --> Autopat.next --> Autopat.next --> NULL +// Autopat.cmds Autopat.cmds +// | | +// V V +// AutoCmd.next AutoCmd.next +// | | +// V V +// AutoCmd.next NULL +// | +// V +// NULL +// +// last_autopat[1] --------+ +// V +// first_autopat[1] --> Autopat.next --> NULL +// Autopat.cmds +// | +// V +// AutoCmd.next +// | +// V +// NULL +// etc. +// +// The order of AutoCmds is important, this is the order in which they were +// defined and will have to be executed. +// typedef struct AutoCmd { - char_u *cmd; /* The command to be executed (NULL - when command has been removed) */ - char nested; /* If autocommands nest here */ - char last; /* last command in list */ - scid_T scriptID; /* script ID where defined */ - struct AutoCmd *next; /* Next AutoCmd in list */ + char_u *cmd; // The command to be executed (NULL + // when command has been removed) + char nested; // If autocommands nest here + char last; // last command in list + scid_T scriptID; // script ID where defined + struct AutoCmd *next; // Next AutoCmd in list } AutoCmd; typedef struct AutoPat { - char_u *pat; /* pattern as typed (NULL when pattern - has been removed) */ - regprog_T *reg_prog; /* compiled regprog for pattern */ - AutoCmd *cmds; /* list of commands to do */ - struct AutoPat *next; /* next AutoPat in AutoPat list */ - int group; /* group ID */ - int patlen; /* strlen() of pat */ - int buflocal_nr; /* !=0 for buffer-local AutoPat */ - char allow_dirs; /* Pattern may match whole path */ - char last; /* last pattern for apply_autocmds() */ + struct AutoPat *next; // next AutoPat in AutoPat list; MUST + // be the first entry + char_u *pat; // pattern as typed (NULL when pattern + // has been removed) + regprog_T *reg_prog; // compiled regprog for pattern + AutoCmd *cmds; // list of commands to do + int group; // group ID + int patlen; // strlen() of pat + int buflocal_nr; // !=0 for buffer-local AutoPat + char allow_dirs; // Pattern may match whole path + char last; // last pattern for apply_autocmds() } AutoPat; /* @@ -226,6 +229,15 @@ void filemess(buf_T *buf, char_u *name, char_u *s, int attr) msg_scrolled_ign = FALSE; } +static AutoPat *last_autopat[NUM_EVENTS] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + /* * Read lines from file "fname" into the buffer after line "from". * @@ -5528,6 +5540,15 @@ static void au_cleanup(void) /* remove the pattern if it has been marked for deletion */ if (ap->pat == NULL) { + if (ap->next == NULL) { + if (prev_ap == &(first_autopat[(int)event])) { + last_autopat[(int)event] = NULL; + } else { + // this depends on the "next" field being the first in + // the struct + last_autopat[(int)event] = (AutoPat *)prev_ap; + } + } *prev_ap = ap->next; vim_regfree(ap->reg_prog); xfree(ap); @@ -6120,10 +6141,13 @@ static int do_autocmd_event(event_T event, char_u *pat, int nested, char_u *cmd, patlen = (int)STRLEN(buflocal_pat); /* but not endpat */ } - /* - * Find AutoPat entries with this pattern. - */ - prev_ap = &first_autopat[(int)event]; + // Find AutoPat entries with this pattern. When adding a command it + // always goes at or after the last one, so start at the end. + if (!forceit && *cmd != NUL && last_autopat[(int)event] != NULL) { + prev_ap = &last_autopat[(int)event]; + } else { + prev_ap = &first_autopat[(int)event]; + } while ((ap = *prev_ap) != NULL) { if (ap->pat != NULL) { /* Accept a pattern when: @@ -6209,6 +6233,7 @@ static int do_autocmd_event(event_T event, char_u *pat, int nested, char_u *cmd, } ap->cmds = NULL; *prev_ap = ap; + last_autopat[(int)event] = ap; ap->next = NULL; if (group == AUGROUP_ALL) ap->group = current_augroup; -- cgit From 1fd54f29c19e19c9202a108d621b819ac7b5fba2 Mon Sep 17 00:00:00 2001 From: Marco Hinz Date: Wed, 4 Apr 2018 18:53:46 +0200 Subject: Make vim_fgets() return the same values as in Vim The implementation of vim_fgets() differs between Neovim and Vim. Vim says that it only returns `true` for EOF. But it always returns `true` when fgets() returns NULL. This happens for EOF _or_ errors. That probably misguided the author of Neovim's vim_fgets(), which does NOT return `true` for errors. Since all the callers of vim_fgets() probably expect it to work as it does in Vim (and not as it says), it now returns the same values as the Vim implementation. Fixes #8227 --- src/nvim/fileio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/nvim/fileio.c') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 02f72dbce3..25653deb3e 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -4452,7 +4452,7 @@ char *modname(const char *fname, const char *ext, bool prepend_dot) /// @param size size of the buffer /// @param fp file to read from /// -/// @return true for end-of-file. +/// @return true for EOF or error bool vim_fgets(char_u *buf, int size, FILE *fp) FUNC_ATTR_NONNULL_ALL { char *retval; @@ -4463,7 +4463,7 @@ bool vim_fgets(char_u *buf, int size, FILE *fp) FUNC_ATTR_NONNULL_ALL do { errno = 0; retval = fgets((char *)buf, size, fp); - } while (retval == NULL && errno == EINTR); + } while (retval == NULL && errno == EINTR && ferror(fp)); if (buf[size - 2] != NUL && buf[size - 2] != '\n') { char tbuf[200]; @@ -4475,12 +4475,12 @@ bool vim_fgets(char_u *buf, int size, FILE *fp) FUNC_ATTR_NONNULL_ALL tbuf[sizeof(tbuf) - 2] = NUL; errno = 0; retval = fgets((char *)tbuf, sizeof(tbuf), fp); - if (retval == NULL && errno != EINTR) { + if (retval == NULL && (feof(fp) || errno != EINTR)) { break; } } while (tbuf[sizeof(tbuf) - 2] != NUL && tbuf[sizeof(tbuf) - 2] != '\n'); } - return retval ? false : feof(fp); + return retval == NULL; } /// Read 2 bytes from "fd" and turn them into an int, MSB first. -- cgit