diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/eval.c | 2 | ||||
-rw-r--r-- | src/nvim/ex_cmds.lua | 2 | ||||
-rw-r--r-- | src/nvim/garray.c | 11 | ||||
-rw-r--r-- | src/nvim/lua/executor.c | 13 | ||||
-rw-r--r-- | src/nvim/lua/executor.h | 1 | ||||
-rw-r--r-- | src/nvim/runtime.c | 356 |
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")); |