aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2025-02-28 18:40:24 +0800
committerGitHub <noreply@github.com>2025-02-28 18:40:24 +0800
commit77626ed7fd369b797dcb2ad0714a84bfd9afff36 (patch)
treefce024d2f065017d40f1536fa4d948676da54a76 /src
parent9b25c68db21c4a2c1edc0d9eb2cdb80cf249193a (diff)
parentb66f395ff444643852e3539b849267658e885bf4 (diff)
downloadrneovim-77626ed7fd369b797dcb2ad0714a84bfd9afff36.tar.gz
rneovim-77626ed7fd369b797dcb2ad0714a84bfd9afff36.tar.bz2
rneovim-77626ed7fd369b797dcb2ad0714a84bfd9afff36.zip
Merge pull request #28486 from zeertzjq/vim-8.2.4603
vim-patch:8.2.{4594,4603,4607,4647,4974}
Diffstat (limited to 'src')
-rw-r--r--src/nvim/eval.c2
-rw-r--r--src/nvim/ex_cmds.lua2
-rw-r--r--src/nvim/garray.c11
-rw-r--r--src/nvim/lua/executor.c13
-rw-r--r--src/nvim/lua/executor.h1
-rw-r--r--src/nvim/runtime.c356
6 files changed, 206 insertions, 179 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 2b6fefbf82..ee5dd25e93 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -759,7 +759,7 @@ void fill_evalarg_from_eap(evalarg_T *evalarg, exarg_T *eap, bool skip)
return;
}
- if (getline_equal(eap->ea_getline, eap->cookie, getsourceline)) {
+ if (sourcing_a_script(eap)) {
evalarg->eval_getline = eap->ea_getline;
evalarg->eval_cookie = eap->cookie;
}
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
index d118c808d3..d68d5a9afa 100644
--- a/src/nvim/ex_cmds.lua
+++ b/src/nvim/ex_cmds.lua
@@ -2533,7 +2533,7 @@ M.cmds = {
},
{
command = 'source',
- flags = bit.bor(RANGE, DFLALL, WHOLEFOLD, BANG, FILE1, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ flags = bit.bor(RANGE, DFLALL, BANG, FILE1, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
addr_type = 'ADDR_LINES',
func = 'ex_source',
},
diff --git a/src/nvim/garray.c b/src/nvim/garray.c
index a8d15a1fa8..b3dce90b11 100644
--- a/src/nvim/garray.c
+++ b/src/nvim/garray.c
@@ -198,12 +198,13 @@ void ga_concat(garray_T *gap, const char *restrict s)
void ga_concat_len(garray_T *const gap, const char *restrict s, const size_t len)
FUNC_ATTR_NONNULL_ALL
{
- if (len) {
- ga_grow(gap, (int)len);
- char *data = gap->ga_data;
- memcpy(data + gap->ga_len, s, len);
- gap->ga_len += (int)len;
+ if (len == 0) {
+ return;
}
+ ga_grow(gap, (int)len);
+ char *data = gap->ga_data;
+ memcpy(data + gap->ga_len, s, len);
+ gap->ga_len += (int)len;
}
/// Append one byte to a growarray which contains bytes.
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index bd00df395c..b1766db379 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -1461,19 +1461,12 @@ static void nlua_typval_exec(const char *lcmd, size_t lcmd_len, const char *name
}
}
-void nlua_source_str(const char *code, char *name)
+void nlua_exec_ga(garray_T *ga, char *name)
{
- const sctx_T save_current_sctx = current_sctx;
- current_sctx.sc_sid = SID_STR;
- current_sctx.sc_seq = 0;
- current_sctx.sc_lnum = 0;
- estack_push(ETYPE_SCRIPT, name, 0);
-
+ char *code = ga_concat_strings_sep(ga, "\n");
size_t len = strlen(code);
nlua_typval_exec(code, len, name, NULL, 0, false, NULL);
-
- estack_pop();
- current_sctx = save_current_sctx;
+ xfree(code);
}
/// Call a LuaCallable given some typvals
diff --git a/src/nvim/lua/executor.h b/src/nvim/lua/executor.h
index 3a0c03412f..9ff869e221 100644
--- a/src/nvim/lua/executor.h
+++ b/src/nvim/lua/executor.h
@@ -8,6 +8,7 @@
#include "nvim/api/private/helpers.h"
#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
+#include "nvim/garray_defs.h" // IWYU pragma: keep
#include "nvim/macros_defs.h"
#include "nvim/types_defs.h"
#include "nvim/usercmd.h" // IWYU pragma: keep
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
index 861a44cc05..86ca4f08dc 100644
--- a/src/nvim/runtime.c
+++ b/src/nvim/runtime.c
@@ -75,7 +75,10 @@ typedef struct {
FILE *fp; ///< opened file for sourcing
char *nextline; ///< if not NULL: line that was read ahead
linenr_T sourcing_lnum; ///< line number of the source file
- int finished; ///< ":finish" used
+ bool finished; ///< ":finish" used
+ bool source_from_buf_or_str; ///< true if sourcing from a buffer or string
+ int buf_lnum; ///< line number in the buffer or string
+ garray_T buflines; ///< lines in the buffer or string
#ifdef USE_CRNL
int fileformat; ///< EOL_UNKNOWN, EOL_UNIX or EOL_DOS
bool error; ///< true if LF found after CR-LF
@@ -106,6 +109,7 @@ garray_T script_items = { 0, 0, sizeof(scriptitem_T *), 20, NULL };
/// The names of packages that once were loaded are remembered.
static garray_T ga_loaded = { 0, 0, sizeof(char *), 4, NULL };
+/// last used sequence number for sourcing scripts (current_sctx.sc_seq)
static int last_current_SID_seq = 0;
/// Initialize the execution stack.
@@ -1825,8 +1829,20 @@ freeall:
static void cmd_source(char *fname, exarg_T *eap)
{
+ if (*fname != NUL && eap != NULL && eap->addr_count > 0) {
+ // if a filename is specified to :source, then a range is not allowed
+ emsg(_(e_norange));
+ return;
+ }
+
if (eap != NULL && *fname == NUL) {
- cmd_source_buffer(eap, false);
+ if (eap->forceit) {
+ // a file name is needed to source normal mode commands
+ emsg(_(e_argreq));
+ } else {
+ // source ex commands from the current buffer
+ cmd_source_buffer(eap, false);
+ }
} else if (eap != NULL && eap->forceit) {
// ":source!": read Normal mode commands
// Need to execute the commands directly. This is required at least
@@ -1934,42 +1950,6 @@ static bool concat_continued_line(garray_T *const ga, const int init_growsize, c
return true;
}
-typedef struct {
- char *buf;
- size_t offset;
-} GetStrLineCookie;
-
-/// Get one full line from a sourced string (in-memory, no file).
-/// Called by do_cmdline() when it's called from do_source_str().
-///
-/// @return pointer to allocated line, or NULL for end-of-file or
-/// some error.
-static char *get_str_line(int c, void *cookie, int indent, bool do_concat)
-{
- GetStrLineCookie *p = cookie;
- if (strlen(p->buf) <= p->offset) {
- return NULL;
- }
- const char *line = p->buf + p->offset;
- const char *eol = skip_to_newline(line);
- garray_T ga;
- ga_init(&ga, sizeof(char), 400);
- ga_concat_len(&ga, line, (size_t)(eol - line));
- if (do_concat && vim_strchr(p_cpo, CPO_CONCAT) == NULL) {
- while (eol[0] != NUL) {
- line = eol + 1;
- const char *const next_eol = skip_to_newline(line);
- if (!concat_continued_line(&ga, 400, line, (size_t)(next_eol - line))) {
- break;
- }
- eol = next_eol;
- }
- }
- ga_append(&ga, NUL);
- p->offset = (size_t)(eol - p->buf) + 1;
- return ga.ga_data;
-}
-
/// Create a new script item and allocate script-local vars. @see new_script_vars
///
/// @param name File name of the script. NULL for anonymous :source.
@@ -1977,6 +1957,7 @@ static char *get_str_line(int c, void *cookie, int indent, bool do_concat)
///
/// @return pointer to the created script item.
scriptitem_T *new_script_item(char *const name, scid_T *const sid_out)
+ FUNC_ATTR_NONNULL_RET
{
static scid_T last_current_SID = 0;
const scid_T sid = ++last_current_SID;
@@ -1999,99 +1980,97 @@ scriptitem_T *new_script_item(char *const name, scid_T *const sid_out)
return SCRIPT_ITEM(sid);
}
-static int source_using_linegetter(void *cookie, LineGetter fgetline, const char *traceback_name)
+/// Initialization for sourcing lines from the current buffer. Reads all the
+/// lines from the buffer and stores it in the cookie grow array.
+/// Returns a pointer to the name ":source buffer=<n>" on success and NULL on failure.
+static char *do_source_buffer_init(source_cookie_T *sp, const exarg_T *eap, bool ex_lua)
+ FUNC_ATTR_NONNULL_ALL
{
- char *save_sourcing_name = SOURCING_NAME;
- linenr_T save_sourcing_lnum = SOURCING_LNUM;
- char sourcing_name_buf[256];
- char *sname;
- if (save_sourcing_name == NULL) {
- sname = (char *)traceback_name;
+ if (curbuf == NULL) {
+ return NULL;
+ }
+
+ if (ex_lua) {
+ // Use ":{range}lua buffer=<num>" as the script name
+ snprintf(IObuff, IOSIZE, ":{range}lua buffer=%d", curbuf->b_fnum);
} else {
- snprintf(sourcing_name_buf, sizeof(sourcing_name_buf),
- "%s called at %s:%" PRIdLINENR, traceback_name, save_sourcing_name,
- save_sourcing_lnum);
- sname = sourcing_name_buf;
+ // Use ":source buffer=<num>" as the script name
+ snprintf(IObuff, IOSIZE, ":source buffer=%d", curbuf->b_fnum);
}
- estack_push(ETYPE_SCRIPT, sname, 0);
+ char *fname = xstrdup(IObuff);
- const sctx_T save_current_sctx = current_sctx;
- if (!script_is_lua(current_sctx.sc_sid)) {
- current_sctx.sc_sid = SID_STR;
- }
- current_sctx.sc_seq = 0;
- current_sctx.sc_lnum = save_sourcing_lnum;
- funccal_entry_T entry;
- save_funccal(&entry);
- int retval = do_cmdline(NULL, fgetline, cookie,
- DOCMD_VERBOSE | DOCMD_NOWAIT | DOCMD_REPEAT);
- estack_pop();
- current_sctx = save_current_sctx;
- restore_funccal();
- return retval;
+ ga_init(&sp->buflines, sizeof(char *), 100);
+ // Copy the lines from the buffer into a grow array
+ for (linenr_T curr_lnum = eap->line1; curr_lnum <= eap->line2; curr_lnum++) {
+ GA_APPEND(char *, &sp->buflines, xstrdup(ml_get(curr_lnum)));
+ }
+ sp->buf_lnum = 0;
+ sp->source_from_buf_or_str = true;
+ // When sourcing a range of lines from a buffer, use buffer line number.
+ sp->sourcing_lnum = eap->line1 - 1;
+
+ return fname;
}
-void cmd_source_buffer(const exarg_T *const eap, bool ex_lua)
+/// Initialization for sourcing lines from a string. Reads all the
+/// lines from the string and stores it in the cookie grow array.
+static void do_source_str_init(source_cookie_T *sp, const char *str)
FUNC_ATTR_NONNULL_ALL
{
- if (curbuf == NULL) {
- return;
- }
- garray_T ga;
- ga_init(&ga, sizeof(char), 400);
- const linenr_T final_lnum = eap->line2;
- // Copy the contents to be executed.
- for (linenr_T curr_lnum = eap->line1; curr_lnum <= final_lnum; curr_lnum++) {
- // Adjust growsize to current length to speed up concatenating many lines.
- if (ga.ga_len > 400) {
- ga_set_growsize(&ga, MIN(ga.ga_len, 8000));
- }
- ga_concat(&ga, ml_get(curr_lnum));
- ga_append(&ga, NL);
- }
- ((char *)ga.ga_data)[ga.ga_len - 1] = NUL;
- if (ex_lua || strequal(curbuf->b_p_ft, "lua")
- || (curbuf->b_fname && path_with_extension(curbuf->b_fname, "lua"))) {
- char *name = ex_lua ? ":{range}lua" : ":source (no file)";
- nlua_source_str(ga.ga_data, name);
- } else {
- const GetStrLineCookie cookie = {
- .buf = ga.ga_data,
- .offset = 0,
- };
- source_using_linegetter((void *)&cookie, get_str_line, ":source (no file)");
+ ga_init(&sp->buflines, sizeof(char *), 100);
+ // Copy the lines from the string into a grow array
+ while (*str != NUL) {
+ const char *eol = skip_to_newline(str);
+ GA_APPEND(char *, &sp->buflines, xmemdupz(str, (size_t)(eol - str)));
+ str = eol + (*eol != NUL);
}
- ga_clear(&ga);
+ sp->buf_lnum = 0;
+ sp->source_from_buf_or_str = true;
+}
+
+void cmd_source_buffer(const exarg_T *const eap, bool ex_lua)
+ FUNC_ATTR_NONNULL_ALL
+{
+ do_source_ext(NULL, false, DOSO_NONE, NULL, eap, ex_lua, NULL);
}
-/// Executes lines in `src` as Ex commands.
+/// Executes lines in `str` as Ex commands.
///
-/// @see do_source()
-int do_source_str(const char *cmd, const char *traceback_name)
+/// @see do_source_ext()
+int do_source_str(const char *str, char *traceback_name)
+ FUNC_ATTR_NONNULL_ALL
{
- GetStrLineCookie cookie = {
- .buf = (char *)cmd,
- .offset = 0,
- };
- return source_using_linegetter((void *)&cookie, get_str_line, traceback_name);
+ char *const sourcing_name = SOURCING_NAME;
+ const linenr_T sourcing_lnum = SOURCING_LNUM;
+ char sname_buf[256];
+ if (sourcing_name != NULL) {
+ snprintf(sname_buf, sizeof(sname_buf), "%s called at %s:%" PRIdLINENR,
+ traceback_name, sourcing_name, sourcing_lnum);
+ traceback_name = sname_buf;
+ }
+ return do_source_ext(traceback_name, false, DOSO_NONE, NULL, NULL, false, str);
}
-/// When fname is a 'lua' file nlua_exec_file() is invoked to source it.
+/// When fname is a .lua file nlua_exec_file() is invoked to source it.
/// Otherwise reads the file `fname` and executes its lines as Ex commands.
///
/// This function may be called recursively!
///
/// @see do_source_str
///
-/// @param fname
+/// @param fname if NULL, source from the current buffer
/// @param check_other check for .vimrc and _vimrc
/// @param is_vimrc DOSO_ value
/// @param ret_sid if not NULL and we loaded the script before, don't load it again
+/// @param eap used when sourcing lines from a buffer instead of a file
+/// @param str if not NULL, source from the given string
///
/// @return FAIL if file could not be opened, OK otherwise
///
/// If a scriptitem_T was found or created "*ret_sid" is set to the SID.
-int do_source(char *fname, int check_other, int is_vimrc, int *ret_sid)
+static int do_source_ext(char *const fname, const bool check_other, const int is_vimrc,
+ int *const ret_sid, const exarg_T *const eap, const bool ex_lua,
+ const char *const str)
{
source_cookie_T cookie;
uint8_t *firstline = NULL;
@@ -2101,22 +2080,36 @@ int do_source(char *fname, int check_other, int is_vimrc, int *ret_sid)
proftime_T wait_start;
bool trigger_source_post = false;
- char *p = expand_env_save(fname);
- if (p == NULL) {
- return retval;
- }
- char *fname_exp = fix_fname(p);
- xfree(p);
- if (fname_exp == NULL) {
- return retval;
- }
- if (os_isdir(fname_exp)) {
- smsg(0, _("Cannot source a directory: \"%s\""), fname);
- goto theend;
+ CLEAR_FIELD(cookie);
+ char *fname_exp = NULL;
+ if (fname == NULL) {
+ assert(str == NULL);
+ // sourcing lines from a buffer
+ fname_exp = do_source_buffer_init(&cookie, eap, ex_lua);
+ if (fname_exp == NULL) {
+ return FAIL;
+ }
+ } else if (str != NULL) {
+ do_source_str_init(&cookie, str);
+ fname_exp = xstrdup(fname);
+ } else {
+ char *p = expand_env_save(fname);
+ if (p == NULL) {
+ return retval;
+ }
+ fname_exp = fix_fname(p);
+ xfree(p);
+ if (fname_exp == NULL) {
+ return retval;
+ }
+ if (os_isdir(fname_exp)) {
+ smsg(0, _("Cannot source a directory: \"%s\""), fname);
+ goto theend;
+ }
}
// See if we loaded this script before.
- int sid = find_script_by_name(fname_exp);
+ int sid = str != NULL ? SID_STR : find_script_by_name(fname_exp);
if (sid > 0 && ret_sid != NULL) {
// Already loaded and no need to load again, return here.
*ret_sid = sid;
@@ -2124,26 +2117,30 @@ int do_source(char *fname, int check_other, int is_vimrc, int *ret_sid)
goto theend;
}
- // Apply SourceCmd autocommands, they should get the file and source it.
- if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL)
- && apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp,
- false, curbuf)) {
- retval = aborting() ? FAIL : OK;
- if (retval == OK) {
- // Apply SourcePost autocommands.
- apply_autocmds(EVENT_SOURCEPOST, fname_exp, fname_exp, false, curbuf);
+ if (str == NULL) {
+ // Apply SourceCmd autocommands, they should get the file and source it.
+ if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL)
+ && apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp,
+ false, curbuf)) {
+ retval = aborting() ? FAIL : OK;
+ if (retval == OK) {
+ // Apply SourcePost autocommands.
+ apply_autocmds(EVENT_SOURCEPOST, fname_exp, fname_exp, false, curbuf);
+ }
+ goto theend;
}
- goto theend;
- }
- // Apply SourcePre autocommands, they may get the file.
- apply_autocmds(EVENT_SOURCEPRE, fname_exp, fname_exp, false, curbuf);
+ // Apply SourcePre autocommands, they may get the file.
+ apply_autocmds(EVENT_SOURCEPRE, fname_exp, fname_exp, false, curbuf);
+ }
- cookie.fp = fopen_noinh_readbin(fname_exp);
+ if (!cookie.source_from_buf_or_str) {
+ cookie.fp = fopen_noinh_readbin(fname_exp);
+ }
if (cookie.fp == NULL && check_other) {
// Try again, replacing file name ".nvimrc" by "_nvimrc" or vice versa,
// and ".exrc" by "_exrc" or vice versa.
- p = path_tail(fname_exp);
+ char *p = path_tail(fname_exp);
if ((*p == '.' || *p == '_')
&& (STRICMP(p + 1, "nvimrc") == 0 || STRICMP(p + 1, "exrc") == 0)) {
*p = (*p == '_') ? '.' : '_';
@@ -2151,7 +2148,7 @@ int do_source(char *fname, int check_other, int is_vimrc, int *ret_sid)
}
}
- if (cookie.fp == NULL) {
+ if (cookie.fp == NULL && !cookie.source_from_buf_or_str) {
if (p_verbose > 1) {
verbose_enter();
if (SOURCING_NAME == NULL) {
@@ -2188,13 +2185,8 @@ int do_source(char *fname, int check_other, int is_vimrc, int *ret_sid)
} else {
cookie.fileformat = EOL_UNKNOWN;
}
- cookie.error = false;
#endif
- cookie.nextline = NULL;
- cookie.sourcing_lnum = 0;
- cookie.finished = false;
-
// Check if this script has a breakpoint.
cookie.breakpoint = dbg_find_breakpoint(true, fname_exp, 0);
cookie.fname = fname_exp;
@@ -2223,15 +2215,13 @@ int do_source(char *fname, int check_other, int is_vimrc, int *ret_sid)
const sctx_T save_current_sctx = current_sctx;
- current_sctx.sc_lnum = 0;
-
// Always use a new sequence number.
current_sctx.sc_seq = ++last_current_SID_seq;
if (sid > 0) {
// loading the same script again
si = SCRIPT_ITEM(sid);
- } else {
+ } else if (str == NULL) {
// It's new, generate a new SID.
si = new_script_item(fname_exp, &sid);
si->sn_lua = path_with_extension(fname_exp, "lua");
@@ -2240,12 +2230,20 @@ int do_source(char *fname, int check_other, int is_vimrc, int *ret_sid)
*ret_sid = sid;
}
}
- current_sctx.sc_sid = sid;
+ // Sourcing a string doesn't allocate a script item immediately.
+ assert((si != NULL) == (str == NULL));
+
+ // Don't change sc_sid to SID_STR when sourcing a string from a Lua script,
+ // as keeping the current sc_sid allows more useful :verbose messages.
+ if (str == NULL || !script_is_lua(current_sctx.sc_sid)) {
+ current_sctx.sc_sid = sid;
+ current_sctx.sc_lnum = 0;
+ }
// Keep the sourcing name/lnum, for recursive calls.
- estack_push(ETYPE_SCRIPT, si->sn_name, 0);
+ estack_push(ETYPE_SCRIPT, si != NULL ? si->sn_name : fname_exp, 0);
- if (l_do_profiling == PROF_YES) {
+ if (l_do_profiling == PROF_YES && si != NULL) {
bool forceit = false;
// Check if we do profiling for this script.
@@ -2262,7 +2260,12 @@ int do_source(char *fname, int check_other, int is_vimrc, int *ret_sid)
cookie.conv.vc_type = CONV_NONE; // no conversion
- if (si->sn_lua) {
+ if (fname == NULL
+ && (ex_lua || strequal(curbuf->b_p_ft, "lua")
+ || (curbuf->b_fname && path_with_extension(curbuf->b_fname, "lua")))) {
+ // Source lines from the current buffer as lua
+ nlua_exec_ga(&cookie.buflines, fname_exp);
+ } else if (si != NULL && si->sn_lua) {
// Source the file as lua
nlua_exec_file(fname_exp);
} else {
@@ -2272,7 +2275,7 @@ int do_source(char *fname, int check_other, int is_vimrc, int *ret_sid)
&& firstline[1] == 0xbb && firstline[2] == 0xbf) {
// Found BOM; setup conversion, skip over BOM and recode the line.
convert_setup(&cookie.conv, "utf-8", p_enc);
- p = string_convert(&cookie.conv, (char *)firstline + 3, NULL);
+ char *p = string_convert(&cookie.conv, (char *)firstline + 3, NULL);
if (p == NULL) {
p = xstrdup((char *)firstline + 3);
}
@@ -2285,7 +2288,7 @@ int do_source(char *fname, int check_other, int is_vimrc, int *ret_sid)
}
retval = OK;
- if (l_do_profiling == PROF_YES) {
+ if (l_do_profiling == PROF_YES && si != NULL) {
// Get "si" again, "script_items" may have been reallocated.
si = SCRIPT_ITEM(current_sctx.sc_sid);
if (si->sn_prof_on) {
@@ -2332,12 +2335,17 @@ int do_source(char *fname, int check_other, int is_vimrc, int *ret_sid)
if (l_do_profiling == PROF_YES) {
prof_child_exit(&wait_start); // leaving a child now
}
- fclose(cookie.fp);
+ if (cookie.fp != NULL) {
+ fclose(cookie.fp);
+ }
+ if (cookie.source_from_buf_or_str) {
+ ga_clear_strings(&cookie.buflines);
+ }
xfree(cookie.nextline);
xfree(firstline);
convert_setup(&cookie.conv, NULL, NULL);
- if (trigger_source_post) {
+ if (str == NULL && trigger_source_post) {
apply_autocmds(EVENT_SOURCEPOST, fname_exp, fname_exp, false, curbuf);
}
@@ -2346,6 +2354,13 @@ theend:
return retval;
}
+/// @param check_other check for .vimrc and _vimrc
+/// @param is_vimrc DOSO_ value
+int do_source(char *fname, bool check_other, int is_vimrc, int *ret_sid)
+{
+ return do_source_ext(fname, check_other, is_vimrc, ret_sid, NULL, false, NULL);
+}
+
/// Checks if the script with the given script ID is a Lua script.
bool script_is_lua(scid_T sid)
{
@@ -2608,7 +2623,7 @@ char *getsourceline(int c, void *cookie, int indent, bool do_concat)
char *line;
// If breakpoints have been added/deleted need to check for it.
- if (sp->dbg_tick < debug_tick) {
+ if ((sp->dbg_tick < debug_tick) && !sp->source_from_buf_or_str) {
sp->breakpoint = dbg_find_breakpoint(true, sp->fname, SOURCING_LNUM);
sp->dbg_tick = debug_tick;
}
@@ -2619,7 +2634,7 @@ char *getsourceline(int c, void *cookie, int indent, bool do_concat)
SOURCING_LNUM = sp->sourcing_lnum + 1;
// Get current line. If there is a read-ahead line, use it, otherwise get
// one now. "fp" is NULL if actually using a string.
- if (sp->finished || sp->fp == NULL) {
+ if (sp->finished || (!sp->source_from_buf_or_str && sp->fp == NULL)) {
line = NULL;
} else if (sp->nextline == NULL) {
line = get_one_sourceline(sp);
@@ -2672,7 +2687,8 @@ char *getsourceline(int c, void *cookie, int indent, bool do_concat)
}
// Did we encounter a breakpoint?
- if (sp->breakpoint != 0 && sp->breakpoint <= SOURCING_LNUM) {
+ if (!sp->source_from_buf_or_str
+ && sp->breakpoint != 0 && sp->breakpoint <= SOURCING_LNUM) {
dbg_breakpoint(sp->fname, SOURCING_LNUM);
// Find next breakpoint.
sp->breakpoint = dbg_find_breakpoint(true, sp->fname, SOURCING_LNUM);
@@ -2701,19 +2717,28 @@ static char *get_one_sourceline(source_cookie_T *sp)
while (true) {
// make room to read at least 120 (more) characters
ga_grow(&ga, 120);
- buf = ga.ga_data;
-
+ if (sp->source_from_buf_or_str) {
+ if (sp->buf_lnum >= sp->buflines.ga_len) {
+ break; // all the lines are processed
+ }
+ ga_concat(&ga, ((char **)sp->buflines.ga_data)[sp->buf_lnum]);
+ sp->buf_lnum++;
+ ga_grow(&ga, 1);
+ buf = (char *)ga.ga_data;
+ buf[ga.ga_len++] = NUL;
+ len = ga.ga_len;
+ } else {
+ buf = ga.ga_data;
retry:
- errno = 0;
- if (fgets(buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
- sp->fp) == NULL) {
- if (errno == EINTR) {
- goto retry;
+ errno = 0;
+ if (fgets(buf + ga.ga_len, ga.ga_maxlen - ga.ga_len, sp->fp) == NULL) {
+ if (errno == EINTR) {
+ goto retry;
+ }
+ break;
}
-
- break;
+ len = ga.ga_len + (int)strlen(buf + ga.ga_len);
}
- len = ga.ga_len + (int)strlen(buf + ga.ga_len);
#ifdef USE_CRNL
// Ignore a trailing CTRL-Z, when in Dos mode. Only recognize the
// CTRL-Z by its own, or after a NL.
@@ -2784,11 +2809,18 @@ retry:
return NULL;
}
+/// Returns true if sourcing a script either from a file or a buffer or a string.
+/// Otherwise returns false.
+int sourcing_a_script(exarg_T *eap)
+{
+ return getline_equal(eap->ea_getline, eap->cookie, getsourceline);
+}
+
/// ":scriptencoding": Set encoding conversion for a sourced script.
/// Without the multi-byte feature it's simply ignored.
void ex_scriptencoding(exarg_T *eap)
{
- if (!getline_equal(eap->ea_getline, eap->cookie, getsourceline)) {
+ if (!sourcing_a_script(eap)) {
emsg(_("E167: :scriptencoding used outside of a sourced file"));
return;
}
@@ -2807,7 +2839,7 @@ void ex_scriptencoding(exarg_T *eap)
/// ":finish": Mark a sourced file as finished.
void ex_finish(exarg_T *eap)
{
- if (getline_equal(eap->ea_getline, eap->cookie, getsourceline)) {
+ if (sourcing_a_script(eap)) {
do_finish(eap, false);
} else {
emsg(_("E168: :finish used outside of a sourced file"));