# HG changeset patch # User Bram Moolenaar # Date 1609176603 -3600 # Node ID 9a5f12b36273111b7e891c909f15e26101684109 # Parent f67d856ae24e679a02c33f02fa0fc02c1709338c patch 8.2.2238: Vim9: cannot load a Vim9 script without the +eval feature Commit: https://github.com/vim/vim/commit/9b8d62267f583d5dc042920adb1de046959ad11d Author: Bram Moolenaar Date: Mon Dec 28 18:26:00 2020 +0100 patch 8.2.2238: Vim9: cannot load a Vim9 script without the +eval feature Problem: Vim9: cannot load a Vim9 script without the +eval feature. Solution: Support Vim9 script syntax without the +eval feature. diff --git a/src/autocmd.c b/src/autocmd.c --- a/src/autocmd.c +++ b/src/autocmd.c @@ -55,9 +55,7 @@ typedef struct AutoCmd char once; // "One shot": removed after execution char nested; // If autocommands nest here. char last; // last command in list -#ifdef FEAT_EVAL sctx_T script_ctx; // script context where defined -#endif struct AutoCmd *next; // next AutoCmd in list } AutoCmd; @@ -1249,8 +1247,8 @@ do_autocmd_event( if (ac == NULL) return FAIL; ac->cmd = vim_strsave(cmd); + ac->script_ctx = current_sctx; #ifdef FEAT_EVAL - ac->script_ctx = current_sctx; ac->script_ctx.sc_lnum += SOURCING_LNUM; #endif if (ac->cmd == NULL) @@ -1819,8 +1817,8 @@ apply_autocmds_group( static int nesting = 0; AutoPatCmd patcmd; AutoPat *ap; + sctx_T save_current_sctx; #ifdef FEAT_EVAL - sctx_T save_current_sctx; funccal_entry_T funccal_entry; char_u *save_cmdarg; long save_cmdbang; @@ -2029,9 +2027,9 @@ apply_autocmds_group( estack_push(ETYPE_AUCMD, NULL, 0); ESTACK_CHECK_SETUP -#ifdef FEAT_EVAL save_current_sctx = current_sctx; +#ifdef FEAT_EVAL # ifdef FEAT_PROFILE if (do_profiling == PROF_YES) prof_child_enter(&wait_time); // doesn't count for the caller itself @@ -2138,8 +2136,8 @@ apply_autocmds_group( autocmd_fname_full = save_autocmd_fname_full; autocmd_bufnr = save_autocmd_bufnr; autocmd_match = save_autocmd_match; + current_sctx = save_current_sctx; #ifdef FEAT_EVAL - current_sctx = save_current_sctx; restore_funccal(); # ifdef FEAT_PROFILE if (do_profiling == PROF_YES) @@ -2370,9 +2368,7 @@ getnextac( if (ac->once) au_del_cmd(ac); autocmd_nested = ac->nested; -#ifdef FEAT_EVAL current_sctx = ac->script_ctx; -#endif if (ac->last) acp->nextcmd = NULL; else diff --git a/src/buffer.c b/src/buffer.c --- a/src/buffer.c +++ b/src/buffer.c @@ -5371,9 +5371,8 @@ chk_modeline( int vers; int end; int retval = OK; -#ifdef FEAT_EVAL sctx_T save_current_sctx; -#endif + ESTACK_CHECK_DECLARATION prev = -1; @@ -5457,22 +5456,22 @@ chk_modeline( if (*s != NUL) // skip over an empty "::" { int secure_save = secure; + + save_current_sctx = current_sctx; + current_sctx.sc_version = 1; #ifdef FEAT_EVAL - save_current_sctx = current_sctx; current_sctx.sc_sid = SID_MODELINE; current_sctx.sc_seq = 0; current_sctx.sc_lnum = lnum; - current_sctx.sc_version = 1; -#endif +#endif + // Make sure no risky things are executed as a side effect. secure = 1; retval = do_set(s, OPT_MODELINE | OPT_LOCAL | flags); secure = secure_save; -#ifdef FEAT_EVAL current_sctx = save_current_sctx; -#endif if (retval == FAIL) // stop if error found break; } diff --git a/src/errors.h b/src/errors.h --- a/src/errors.h +++ b/src/errors.h @@ -31,8 +31,10 @@ EXTERN char e_assert_fails_second_arg[] INIT(= N_("E856: \"assert_fails()\" second argument must be a string or a list with one or two strings")); EXTERN char e_cannot_index_special_variable[] INIT(= N_("E909: Cannot index a special variable")); -EXTERN char e_missing_var_str[] - INIT(= N_("E1100: Missing :var: %s")); +#endif +EXTERN char e_command_not_supported_in_vim9_script_missing_var_str[] + INIT(= N_("E1100: Command not supported in Vim9 script (missing :var?): %s")); +#ifdef FEAT_EVAL EXTERN char e_variable_not_found_str[] INIT(= N_("E1001: Variable not found: %s")); EXTERN char e_syntax_error_at_str[] @@ -113,8 +115,10 @@ EXTERN char e_vim9script_can_only_be_use INIT(= N_("E1038: \"vim9script\" can only be used in a script")); EXTERN char e_vim9script_must_be_first_command_in_script[] INIT(= N_("E1039: \"vim9script\" must be the first command in a script")); +#endif EXTERN char e_cannot_use_scriptversion_after_vim9script[] INIT(= N_("E1040: Cannot use :scriptversion after :vim9script")); +#ifdef FEAT_EVAL EXTERN char e_redefining_script_item_str[] INIT(= N_("E1041: Redefining script item %s")); EXTERN char e_export_can_only_be_used_in_vim9script[] diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -304,7 +304,6 @@ static void ex_tag_cmd(exarg_T *eap, cha # define ex_try ex_ni # define ex_unlet ex_ni # define ex_unlockvar ex_ni -# define ex_vim9script ex_ni # define ex_while ex_ni # define ex_import ex_ni # define ex_export ex_ni @@ -8011,10 +8010,9 @@ save_current_state(save_state_T *sst) msg_scroll = FALSE; // no msg scrolling in Normal mode restart_edit = 0; // don't go to Insert mode p_im = FALSE; // don't use 'insertmode' -#ifdef FEAT_EVAL + sst->save_script_version = current_sctx.sc_version; current_sctx.sc_version = 1; // not in Vim9 script -#endif /* * Save the current typeahead. This is required to allow using ":normal" @@ -8038,9 +8036,7 @@ restore_current_state(save_state_T *sst) opcount = sst->save_opcount; reg_executing = sst->save_reg_executing; msg_didout |= sst->save_msg_didout; // don't reset msg_didout now -#ifdef FEAT_EVAL current_sctx.sc_version = sst->save_script_version; -#endif // Restore the state (needed when called from a function executed for // 'indentexpr'). Update the mouse and cursor, they may have changed. diff --git a/src/globals.h b/src/globals.h --- a/src/globals.h +++ b/src/globals.h @@ -290,6 +290,14 @@ EXTERN garray_T exestack INIT5(0, 0, siz // line number in the message source or zero #define SOURCING_LNUM (((estack_T *)exestack.ga_data)[exestack.ga_len - 1].es_lnum) +// Script CTX being sourced or was sourced to define the current function. +EXTERN sctx_T current_sctx +#ifdef FEAT_EVAL + INIT4(0, 0, 0, 0); +#else + INIT(= {0}); +#endif + #ifdef FEAT_EVAL // whether inside compile_def_function() EXTERN int estack_compiling INIT(= FALSE); @@ -392,9 +400,6 @@ EXTERN int may_garbage_collect INIT(= FA EXTERN int want_garbage_collect INIT(= FALSE); EXTERN int garbage_collect_at_exit INIT(= FALSE); -// Script CTX being sourced or was sourced to define the current function. -EXTERN sctx_T current_sctx INIT4(0, 0, 0, 0); - // Commonly used types. EXTERN type_T t_unknown INIT6(VAR_UNKNOWN, 0, 0, TTFLAG_STATIC, NULL, NULL); diff --git a/src/main.c b/src/main.c --- a/src/main.c +++ b/src/main.c @@ -3269,9 +3269,8 @@ process_env( int is_viminit) // when TRUE, called for VIMINIT { char_u *initstr; -#ifdef FEAT_EVAL sctx_T save_current_sctx; -#endif + ESTACK_CHECK_DECLARATION if ((initstr = mch_getenv(env)) != NULL && *initstr != NUL) @@ -3280,20 +3279,19 @@ process_env( vimrc_found(NULL, NULL); estack_push(ETYPE_ENV, env, 0); ESTACK_CHECK_SETUP + save_current_sctx = current_sctx; + current_sctx.sc_version = 1; #ifdef FEAT_EVAL - save_current_sctx = current_sctx; current_sctx.sc_sid = SID_ENV; current_sctx.sc_seq = 0; current_sctx.sc_lnum = 0; - current_sctx.sc_version = 1; #endif + do_cmdline_cmd(initstr); ESTACK_CHECK_NOW estack_pop(); -#ifdef FEAT_EVAL current_sctx = save_current_sctx; -#endif return OK; } return FAIL; diff --git a/src/menu.c b/src/menu.c --- a/src/menu.c +++ b/src/menu.c @@ -2310,11 +2310,7 @@ execute_menu(exarg_T *eap, vimmenu_T *me if (idx < 0) { // Use the Insert mode entry when returning to Insert mode. - if (restart_edit -#ifdef FEAT_EVAL - && !current_sctx.sc_sid -#endif - ) + if (restart_edit && !current_sctx.sc_sid) { idx = MENU_INDEX_INSERT; } @@ -2384,11 +2380,7 @@ execute_menu(exarg_T *eap, vimmenu_T *me // When executing a script or function execute the commands right now. // Also for the window toolbar. // Otherwise put them in the typeahead buffer. - if (eap == NULL -#ifdef FEAT_EVAL - || current_sctx.sc_sid != 0 -#endif - ) + if (eap == NULL || current_sctx.sc_sid != 0) { save_state_T save_state; diff --git a/src/proto.h b/src/proto.h --- a/src/proto.h +++ b/src/proto.h @@ -233,10 +233,10 @@ void mbyte_im_set_active(int active_arg) # include "usercmd.pro" # include "userfunc.pro" # include "version.pro" +# include "vim9script.pro" # ifdef FEAT_EVAL # include "vim9compile.pro" # include "vim9execute.pro" -# include "vim9script.pro" # include "vim9type.pro" # endif # include "window.pro" diff --git a/src/scriptfile.c b/src/scriptfile.c --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -1135,8 +1135,8 @@ do_source( char_u *fname_exp; char_u *firstline = NULL; int retval = FAIL; + sctx_T save_current_sctx; #ifdef FEAT_EVAL - sctx_T save_current_sctx; static scid_T last_current_SID = 0; static int last_current_SID_seq = 0; funccal_entry_T funccalp_entry; @@ -1300,6 +1300,9 @@ do_source( time_push(&tv_rel, &tv_start); #endif + save_current_sctx = current_sctx; + current_sctx.sc_version = 1; // default script version + #ifdef FEAT_EVAL # ifdef FEAT_PROFILE if (do_profiling == PROF_YES) @@ -1310,9 +1313,7 @@ do_source( // Also starts profiling timer for nested script. save_funccal(&funccalp_entry); - save_current_sctx = current_sctx; current_sctx.sc_lnum = 0; - current_sctx.sc_version = 1; // default script version // Check if this script was sourced before to finds its SID. // Always use a new sequence number. @@ -1326,7 +1327,6 @@ do_source( // loading the same script again si->sn_state = SN_STATE_RELOAD; - si->sn_version = 1; current_sctx.sc_sid = sid; // Script-local variables remain but "const" can be set again. @@ -1484,13 +1484,14 @@ almosttheend: CLEAR_POINTER(si->sn_save_cpo); } - current_sctx = save_current_sctx; restore_funccal(); # ifdef FEAT_PROFILE if (do_profiling == PROF_YES) prof_child_exit(&wait_start); // leaving a child now # endif #endif + current_sctx = save_current_sctx; + fclose(cookie.fp); vim_free(cookie.nextline); vim_free(firstline); @@ -1903,7 +1904,6 @@ ex_scriptencoding(exarg_T *eap) void ex_scriptversion(exarg_T *eap UNUSED) { -#ifdef FEAT_EVAL int nr; if (!getline_equal(eap->getline, eap->cookie, getsourceline)) @@ -1925,9 +1925,10 @@ ex_scriptversion(exarg_T *eap UNUSED) else { current_sctx.sc_version = nr; +#ifdef FEAT_EVAL SCRIPT_ITEM(current_sctx.sc_sid)->sn_version = nr; +#endif } -#endif } #if defined(FEAT_EVAL) || defined(PROTO) diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -83,9 +83,11 @@ typedef struct VimMenu vimmenu_T; * sc_version is also here, for convenience. */ typedef struct { +#ifdef FEAT_EVAL scid_T sc_sid; // script ID int sc_seq; // sourcing sequence number linenr_T sc_lnum; // line number +#endif int sc_version; // :scriptversion } sctx_T; @@ -1224,8 +1226,8 @@ struct mapblock char m_silent; // used, don't echo commands char m_nowait; // used #ifdef FEAT_EVAL + sctx_T m_script_ctx; // SCTX where map was defined char m_expr; // used, m_str is an expression - sctx_T m_script_ctx; // SCTX where map was defined #endif }; @@ -1567,6 +1569,8 @@ typedef enum { GETLINE_CONCAT_ALL // concatenate continuation and Vim9 # comment lines } getline_opt_T; +typedef struct svar_S svar_T; + #if defined(FEAT_EVAL) || defined(PROTO) typedef struct funccall_S funccall_T; @@ -1766,13 +1770,13 @@ struct sallvar_S { /* * Entry for "sn_var_vals". Used for script-local variables. */ -typedef struct { +struct svar_S { char_u *sv_name; // points into "sn_all_vars" di_key typval_T *sv_tv; // points into "sn_vars" or "sn_all_vars" di_tv type_T *sv_type; int sv_const; int sv_export; // "export let var = val" -} svar_T; +}; typedef struct { char_u *imp_name; // name imported as (allocated) @@ -4164,9 +4168,7 @@ typedef struct { int save_finish_op; int save_opcount; int save_reg_executing; -#ifdef FEAT_EVAL int save_script_version; -#endif tasave_T tabuf; } save_state_T; diff --git a/src/usercmd.c b/src/usercmd.c --- a/src/usercmd.c +++ b/src/usercmd.c @@ -21,8 +21,8 @@ typedef struct ucmd long uc_def; // The default value for a range/count int uc_compl; // completion type cmd_addr_T uc_addr_type; // The command's address type + sctx_T uc_script_ctx; // SCTX where the command was defined # ifdef FEAT_EVAL - sctx_T uc_script_ctx; // SCTX where the command was defined char_u *uc_compl_arg; // completion argument if any # endif } ucmd_T; @@ -954,8 +954,8 @@ uc_add_command( cmd->uc_argt = argt; cmd->uc_def = def; cmd->uc_compl = compl; + cmd->uc_script_ctx = current_sctx; #ifdef FEAT_EVAL - cmd->uc_script_ctx = current_sctx; cmd->uc_script_ctx.sc_lnum += SOURCING_LNUM; cmd->uc_compl_arg = compl_arg; #endif @@ -1573,9 +1573,7 @@ do_ucmd(exarg_T *eap) size_t split_len = 0; char_u *split_buf = NULL; ucmd_T *cmd; -#ifdef FEAT_EVAL sctx_T save_current_sctx = current_sctx; -#endif if (eap->cmdidx == CMD_USER) cmd = USER_CMD(eap->useridx); @@ -1674,15 +1672,13 @@ do_ucmd(exarg_T *eap) } } + current_sctx.sc_version = cmd->uc_script_ctx.sc_version; #ifdef FEAT_EVAL current_sctx.sc_sid = cmd->uc_script_ctx.sc_sid; - current_sctx.sc_version = cmd->uc_script_ctx.sc_version; #endif (void)do_cmdline(buf, eap->getline, eap->cookie, DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED); -#ifdef FEAT_EVAL current_sctx = save_current_sctx; -#endif vim_free(buf); vim_free(split_buf); } diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2238, +/**/ 2237, /**/ 2236, diff --git a/src/vim9script.c b/src/vim9script.c --- a/src/vim9script.c +++ b/src/vim9script.c @@ -13,9 +13,9 @@ #include "vim.h" -#if defined(FEAT_EVAL) || defined(PROTO) - -#include "vim9.h" +#if defined(FEAT_EVAL) +# include "vim9.h" +#endif int in_vim9script(void) @@ -30,8 +30,9 @@ in_vim9script(void) * ":vim9script". */ void -ex_vim9script(exarg_T *eap) +ex_vim9script(exarg_T *eap UNUSED) { +#ifdef FEAT_EVAL int sid = current_sctx.sc_sid; scriptitem_T *si; @@ -75,6 +76,10 @@ ex_vim9script(exarg_T *eap) si->sn_save_cpo = vim_strsave(p_cpo); set_option_value((char_u *)"cpo", 0L, (char_u *)CPO_VIM, 0); } +#else + // No check for this being the first command, it doesn't matter. + current_sctx.sc_version = SCRIPT_VERSION_VIM9; +#endif } /* @@ -91,13 +96,15 @@ not_in_vim9(exarg_T *eap) case CMD_insert: case CMD_t: case CMD_xit: - semsg(_(e_missing_var_str), eap->cmd); + semsg(_(e_command_not_supported_in_vim9_script_missing_var_str), eap->cmd); return FAIL; default: break; } return OK; } +#if defined(FEAT_EVAL) || defined(PROTO) + /* * ":export let Name: type" * ":export const Name: type"