aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile9
-rw-r--r--cmake/RunTests.cmake2
-rw-r--r--runtime/autoload/health/nvim.vim8
-rw-r--r--runtime/doc/eval.txt50
-rw-r--r--runtime/doc/options.txt75
-rw-r--r--src/nvim/eval.c317
-rw-r--r--src/nvim/eval.lua1
-rw-r--r--src/nvim/ex_cmds.lua6
-rw-r--r--src/nvim/generators/gen_options.lua1
-rw-r--r--src/nvim/getchar.c12
-rw-r--r--src/nvim/option.c6
-rw-r--r--src/nvim/option_defs.h1
-rw-r--r--src/nvim/options.lua21
-rw-r--r--src/nvim/os/dl.c1
-rw-r--r--src/nvim/testdir/shared.vim14
-rw-r--r--src/nvim/testdir/test49.vim3
-rw-r--r--src/nvim/testdir/test_bufline.vim67
-rw-r--r--src/nvim/testdir/test_const.vim237
-rw-r--r--src/nvim/testdir/test_functions.vim48
-rw-r--r--src/nvim/testdir/test_modeline.vim95
-rw-r--r--src/nvim/testdir/test_source.vim10
-rw-r--r--src/nvim/testdir/test_vimscript.vim1
-rw-r--r--src/nvim/testdir/test_writefile.vim2
-rw-r--r--third-party/CMakeLists.txt6
-rw-r--r--third-party/cmake/BuildLuajit.cmake2
-rw-r--r--third-party/cmake/BuildLuarocks.cmake18
26 files changed, 866 insertions, 147 deletions
diff --git a/Makefile b/Makefile
index 79dbc27504..1025f08b61 100644
--- a/Makefile
+++ b/Makefile
@@ -88,15 +88,18 @@ ifeq ($(call filter-true,$(USE_BUNDLED)),)
+$(BUILD_CMD) -C $(DEPS_BUILD_DIR)
endif
-build/.ran-third-party-cmake:
+build/.ran-third-party-cmake::
+ mkdir -p build
+ touch $@
+
ifeq ($(call filter-true,$(USE_BUNDLED)),)
+build/.ran-third-party-cmake:: $(DEPS_BUILD_DIR)
+$(DEPS_BUILD_DIR):
mkdir -p $(DEPS_BUILD_DIR)
cd $(DEPS_BUILD_DIR) && \
$(CMAKE_PRG) -G '$(BUILD_TYPE)' $(BUNDLED_CMAKE_FLAG) $(BUNDLED_LUA_CMAKE_FLAG) \
$(DEPS_CMAKE_FLAGS) $(THIS_DIR)/third-party
endif
- mkdir -p build
- touch $@
# TODO: cmake 3.2+ add_custom_target() has a USES_TERMINAL flag.
oldtest: | nvim helptags
diff --git a/cmake/RunTests.cmake b/cmake/RunTests.cmake
index 0282d1c738..db67b14917 100644
--- a/cmake/RunTests.cmake
+++ b/cmake/RunTests.cmake
@@ -44,7 +44,7 @@ execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory $ENV{TMPDIR})
set(ENV{SYSTEM_NAME} ${SYSTEM_NAME})
execute_process(
COMMAND ${BUSTED_PRG} -v -o ${BUSTED_OUTPUT_TYPE}
- --lua=${LUA_PRG} --lazy --helper=${TEST_DIR}/${TEST_TYPE}/preload.lua
+ --lazy --helper=${TEST_DIR}/${TEST_TYPE}/preload.lua
--lpath=${BUILD_DIR}/?.lua
--lpath=${WORKING_DIR}/runtime/lua/?.lua
--lpath=?.lua
diff --git a/runtime/autoload/health/nvim.vim b/runtime/autoload/health/nvim.vim
index 8fcea2e941..a2227e3b29 100644
--- a/runtime/autoload/health/nvim.vim
+++ b/runtime/autoload/health/nvim.vim
@@ -8,7 +8,7 @@ function! s:check_config() abort
if !filereadable(vimrc)
let ok = v:false
let has_vim = filereadable(expand('~/.vimrc'))
- call health#report_warn('Missing user config file: '.vimrc,
+ call health#report_warn((-1 == getfsize(vimrc) ? 'Missing' : 'Unreadable').' user config file: '.vimrc,
\[ has_vim ? ':help nvim-from-vim' : ':help init.vim' ])
endif
@@ -41,6 +41,12 @@ function! s:check_config() abort
\ 'Check `:verbose set paste?` to see if a plugin or script set the option.', ])
endif
+ let shadafile = (empty(&shadafile) || &shadafile ==# 'NONE') ? stdpath('data').'/shada/main.shada' : &shadafile
+ if !empty(shadafile) && (!filereadable(shadafile) || !filewritable(shadafile))
+ let ok = v:false
+ call health#report_error('shada file is not '.(filereadable(shadafile) ? 'writeable' : 'readable').":\n".shadafile)
+ endif
+
if ok
call health#report_ok('no issues found')
endif
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 4eaa72ee68..afbe4f2661 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2286,6 +2286,9 @@ searchpos({pattern} [, {flags} [, {stopline} [, {timeout}]]])
server2client({clientid}, {string})
Number send reply string
serverlist() String get a list of available servers
+setbufline( {expr}, {lnum}, {line})
+ Number set line {lnum} to {line} in buffer
+ {expr}
setbufvar({expr}, {varname}, {val}) set {varname} in buffer {expr} to {val}
setcharsearch({dict}) Dict set character search from {dict}
setcmdpos({pos}) Number set cursor position in command-line
@@ -6997,6 +7000,19 @@ serverstop({address}) *serverstop()*
If |v:servername| is stopped it is set to the next available
address returned by |serverlist()|.
+setbufline({expr}, {lnum}, {text}) *setbufline()*
+ Set line {lnum} to {text} in buffer {expr}. To insert
+ lines use |append()|.
+
+ For the use of {expr}, see |bufname()| above.
+
+ {lnum} is used like with |setline()|.
+ This works like |setline()| for the specified buffer.
+ On success 0 is returned, on failure 1 is returned.
+
+ If {expr} is not a valid buffer or {lnum} is not valid, an
+ error message is given.
+
setbufvar({expr}, {varname}, {val}) *setbufvar()*
Set option or local variable {varname} in buffer {expr} to
{val}.
@@ -7064,13 +7080,19 @@ setfperm({fname}, {mode}) *setfperm()* *chmod*
setline({lnum}, {text}) *setline()*
Set line {lnum} of the current buffer to {text}. To insert
- lines use |append()|.
+ lines use |append()|. To set lines in another buffer use
+ |setbufline()|.
+
{lnum} is used like with |getline()|.
When {lnum} is just below the last line the {text} will be
added as a new line.
+
If this succeeds, 0 is returned. If this fails (most likely
- because {lnum} is invalid) 1 is returned. Example: >
+ because {lnum} is invalid) 1 is returned.
+
+ Example: >
:call setline(5, strftime("%c"))
+
< When {text} is a |List| then line {lnum} and following lines
will be set to the items in the list. Example: >
:call setline(5, ['aaa', 'bbb', 'ccc'])
@@ -9629,7 +9651,29 @@ This does NOT work: >
No error message is given for a non-existing
variable, also without !.
If the system does not support deleting an environment
- variable, it is made emtpy.
+ variable, it is made empty.
+
+ *:cons* *:const*
+:cons[t] {var-name} = {expr1}
+:cons[t] [{name1}, {name2}, ...] = {expr1}
+:cons[t] [{name}, ..., ; {lastname}] = {expr1}
+ Similar to |:let|, but additionally lock the variable
+ after setting the value. This is the same as locking
+ the variable with |:lockvar| just after |:let|, thus: >
+ :const x = 1
+< is equivalent to: >
+ :let x = 1
+ :lockvar 1 x
+< This is useful if you want to make sure the variable
+ is not modified.
+ *E995*
+ |:const| does not allow to for changing a variable. >
+ :let x = 1
+ :const x = 2 " Error!
+< *E996*
+ Note that environment variables, option values and
+ register values cannot be used here, since they cannot
+ be locked.
:lockv[ar][!] [depth] {name} ... *:lockvar* *:lockv*
Lock the internal variable {name}. Locking means that
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index b2efd9287d..212e686f96 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -478,14 +478,17 @@ backslash in front of the ':' will be removed. Example:
/* vi:set dir=c\:\tmp: */ ~
This sets the 'dir' option to "c:\tmp". Only a single backslash before the
':' is removed. Thus to include "\:" you have to specify "\\:".
-
+ *E992*
No other commands than "set" are supported, for security reasons (somebody
might create a Trojan horse text file with modelines). And not all options
-can be set. For some options a flag is set, so that when it's used the
-|sandbox| is effective. Still, there is always a small risk that a modeline
-causes trouble. E.g., when some joker sets 'textwidth' to 5 all your lines
-are wrapped unexpectedly. So disable modelines before editing untrusted text.
-The mail ftplugin does this, for example.
+can be set. For some options a flag is set, so that when the value is used
+the |sandbox| is effective. Some options can only be set from the modeline
+when 'modelineexpr' is set (the default is off).
+
+Still, there is always a small risk that a modeline causes trouble. E.g.,
+when some joker sets 'textwidth' to 5 all your lines are wrapped unexpectedly.
+So disable modelines before editing untrusted text. The mail ftplugin does
+this, for example.
Hint: If you would like to do something else than setting an option, you could
define an autocommand that checks the file for a specific string. For
@@ -2427,7 +2430,7 @@ A jump table for the options with a short description can be found at |Q_op|.
The expression will be evaluated in the |sandbox| if set from a
modeline, see |sandbox-option|.
This option can't be set from a |modeline| when the 'diff' option is
- on.
+ on or the 'modelineexpr' option is off.
It is not allowed to change text or jump to another window while
evaluating 'foldexpr' |textlock|.
@@ -2542,6 +2545,7 @@ A jump table for the options with a short description can be found at |Q_op|.
The expression will be evaluated in the |sandbox| if set from a
modeline, see |sandbox-option|.
+ This option cannot be set in a modeline when 'modelineexpr' is off.
It is not allowed to change text or jump to another window while
evaluating 'foldtext' |textlock|.
@@ -2577,16 +2581,8 @@ A jump table for the options with a short description can be found at |Q_op|.
The expression will be evaluated in the |sandbox| when set from a
modeline, see |sandbox-option|. That stops the option from working,
since changing the buffer text is not allowed.
-
- *'formatoptions'* *'fo'*
-'formatoptions' 'fo' string (default: "tcqj", Vi default: "vt")
- local to buffer
- This is a sequence of letters which describes how automatic
- formatting is to be done. See |fo-table|. When the 'paste' option is
- on, no formatting is done (like 'formatoptions' is empty). Commas can
- be inserted for readability.
- To avoid problems with flags that are added in the future, use the
- "+=" and "-=" feature of ":set" |add-option-flags|.
+ This option cannot be set in a modeline when 'modelineexpr' is off.
+ NOTE: This option is set to "" when 'compatible' is set.
*'formatlistpat'* *'flp'*
'formatlistpat' 'flp' string (default: "^\s*\d\+[\]:.)}\t ]\s*")
@@ -2601,6 +2597,16 @@ A jump table for the options with a short description can be found at |Q_op|.
The default recognizes a number, followed by an optional punctuation
character and white space.
+ *'formatoptions'* *'fo'*
+'formatoptions' 'fo' string (default: "tcqj", Vi default: "vt")
+ local to buffer
+ This is a sequence of letters which describes how automatic
+ formatting is to be done. See |fo-table|. When the 'paste' option is
+ on, no formatting is done (like 'formatoptions' is empty). Commas can
+ be inserted for readability.
+ To avoid problems with flags that are added in the future, use the
+ "+=" and "-=" feature of ":set" |add-option-flags|.
+
*'formatprg'* *'fp'*
'formatprg' 'fp' string (default "")
global or local to buffer |global-local|
@@ -2631,6 +2637,9 @@ A jump table for the options with a short description can be found at |Q_op|.
- system signals low battery life
- Nvim exits abnormally
+ This option cannot be set from a |modeline| or in the |sandbox|, for
+ security reasons.
+
*'gdefault'* *'gd'* *'nogdefault'* *'nogd'*
'gdefault' 'gd' boolean (default off)
global
@@ -2972,6 +2981,7 @@ A jump table for the options with a short description can be found at |Q_op|.
'guitabtooltip' is used for the tooltip, see below.
The expression will be evaluated in the |sandbox| when set from a
modeline, see |sandbox-option|.
+ This option cannot be set in a modeline when 'modelineexpr' is off.
Only used when the GUI tab pages line is displayed. 'e' must be
present in 'guioptions'. For the non-GUI tab pages line 'tabline' is
@@ -3100,6 +3110,7 @@ A jump table for the options with a short description can be found at |Q_op|.
When this option contains printf-style '%' items, they will be
expanded according to the rules used for 'statusline'. See
'titlestring' for example settings.
+ This option cannot be set in a modeline when 'modelineexpr' is off.
*'ignorecase'* *'ic'* *'noignorecase'* *'noic'*
'ignorecase' 'ic' boolean (default off)
@@ -3203,6 +3214,7 @@ A jump table for the options with a short description can be found at |Q_op|.
The expression will be evaluated in the |sandbox| when set from a
modeline, see |sandbox-option|.
+ This option cannot be set in a modeline when 'modelineexpr' is off.
It is not allowed to change text or jump to another window while
evaluating 'includeexpr' |textlock|.
@@ -3271,6 +3283,7 @@ A jump table for the options with a short description can be found at |Q_op|.
The expression will be evaluated in the |sandbox| when set from a
modeline, see |sandbox-option|.
+ This option cannot be set in a modeline when 'modelineexpr' is off.
It is not allowed to change text or jump to another window while
evaluating 'indentexpr' |textlock|.
@@ -3888,10 +3901,23 @@ A jump table for the options with a short description can be found at |Q_op|.
< If you have less than 512 Mbyte |:mkspell| may fail for some
languages, no matter what you set 'mkspellmem' to.
+ This option cannot be set from a |modeline| or in the |sandbox|.
+
*'modeline'* *'ml'* *'nomodeline'* *'noml'*
'modeline' 'ml' boolean (Vim default: on (off for root),
Vi default: off)
local to buffer
+ If 'modeline' is on 'modelines' gives the number of lines that is
+ checked for set commands. If 'modeline' is off or 'modelines' is zero
+ no lines are checked. See |modeline|.
+
+ *'modelineexpr'* *'mle'* *'nomodelineexpr'* *'nomle'*
+'modelineexpr' 'mle' boolean (default: off)
+ global
+ When on allow some options that are an expression to be set in the
+ modeline. Check the option for whether it is affected by
+ 'modelineexpr'. Also see |modeline|.
+
*'modelines'* *'mls'*
'modelines' 'mls' number (default 5)
global
@@ -4668,6 +4694,8 @@ A jump table for the options with a short description can be found at |Q_op|.
When this option is not empty, it determines the content of the ruler
string, as displayed for the 'ruler' option.
The format of this option is like that of 'statusline'.
+ This option cannot be set in a modeline when 'modelineexpr' is off.
+
The default ruler width is 17 characters. To make the ruler 15
characters wide, put "%15(" at the start and "%)" at the end.
Example: >
@@ -5065,6 +5093,8 @@ A jump table for the options with a short description can be found at |Q_op|.
When equal to "NONE" no shada file will be read or written.
This option can be set with the |-i| command line flag. The |--clean|
command line flag sets it to "NONE".
+ This option cannot be set from a |modeline| or in the |sandbox|, for
+ security reasons.
*'shell'* *'sh'* *E91*
'shell' 'sh' string (default $SHELL or "sh",
@@ -5304,7 +5334,8 @@ A jump table for the options with a short description can be found at |Q_op|.
"Pattern not found", "Back at original", etc.
q use "recording" instead of "recording @a"
F don't give the file info when editing a file, like `:silent`
- was used for the command
+ was used for the command; note that this also affects messages
+ from autocommands
S do not show search count message when searching, e.g.
"[1/5]"
@@ -5831,6 +5862,7 @@ A jump table for the options with a short description can be found at |Q_op|.
The 'statusline' option will be evaluated in the |sandbox| if set from
a modeline, see |sandbox-option|.
+ This option cannot be set in a modeline when 'modelineexpr' is off.
It is not allowed to change text or jump to another window while
evaluating 'statusline' |textlock|.
@@ -5985,6 +6017,8 @@ A jump table for the options with a short description can be found at |Q_op|.
the text to be displayed. Use "%1T" for the first label, "%2T" for
the second one, etc. Use "%X" items for closing labels.
+ This option cannot be set in a modeline when 'modelineexpr' is off.
+
Keep in mind that only one of the tab pages is the current one, others
are invisible and you can't jump to their windows.
@@ -6264,8 +6298,11 @@ A jump table for the options with a short description can be found at |Q_op|.
global
When this option is not empty, it will be used for the title of the
window. This happens only when the 'title' option is on.
+
When this option contains printf-style '%' items, they will be
expanded according to the rules used for 'statusline'.
+ This option cannot be set in a modeline when 'modelineexpr' is off.
+
Example: >
:auto BufEnter * let &titlestring = hostname() . "/" . expand("%:p")
:set title titlestring=%<%F%=%l/%L-%P titlelen=70
@@ -6299,6 +6336,8 @@ A jump table for the options with a short description can be found at |Q_op|.
undo file that exists is used. When it cannot be read an error is
given, no further entry is used.
See |undo-persistence|.
+ This option cannot be set from a |modeline| or in the |sandbox|, for
+ security reasons.
*'undofile'* *'noundofile'* *'udf'* *'noudf'*
'undofile' 'udf' boolean (default off)
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index f19fbe112f..cd2888883b 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -176,6 +176,7 @@ static char *e_funcref = N_("E718: Funcref required");
static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary");
static char *e_nofunc = N_("E130: Unknown function: %s");
static char *e_illvar = N_("E461: Illegal variable name: %s");
+static char *e_cannot_mod = N_("E995: Cannot modify existing variable");
static const char *e_readonlyvar = N_(
"E46: Cannot change read-only variable \"%.*s\"");
@@ -776,10 +777,11 @@ var_redir_start(
did_emsg = FALSE;
tv.v_type = VAR_STRING;
tv.vval.v_string = (char_u *)"";
- if (append)
- set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)".");
- else
- set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)"=");
+ if (append) {
+ set_var_lval(redir_lval, redir_endp, &tv, true, false, (char_u *)".");
+ } else {
+ set_var_lval(redir_lval, redir_endp, &tv, true, false, (char_u *)"=");
+ }
clear_lval(redir_lval);
err = did_emsg;
did_emsg |= save_emsg;
@@ -837,7 +839,7 @@ void var_redir_stop(void)
redir_endp = (char_u *)get_lval(redir_varname, NULL, redir_lval,
false, false, 0, FNE_CHECK_START);
if (redir_endp != NULL && redir_lval->ll_name != NULL) {
- set_var_lval(redir_lval, redir_endp, &tv, false, (char_u *)".");
+ set_var_lval(redir_lval, redir_endp, &tv, false, false, (char_u *)".");
}
clear_lval(redir_lval);
}
@@ -1518,21 +1520,33 @@ int eval_foldexpr(char_u *arg, int *cp)
return (int)retval;
}
-/*
- * ":let" list all variable values
- * ":let var1 var2" list variable values
- * ":let var = expr" assignment command.
- * ":let var += expr" assignment command.
- * ":let var -= expr" assignment command.
- * ":let var *= expr" assignment command.
- * ":let var /= expr" assignment command.
- * ":let var %= expr" assignment command.
- * ":let var .= expr" assignment command.
- * ":let var ..= expr" assignment command.
- * ":let [var1, var2] = expr" unpack list.
- */
+// ":cons[t] var = expr1" define constant
+// ":cons[t] [name1, name2, ...] = expr1" define constants unpacking list
+// ":cons[t] [name, ..., ; lastname] = expr" define constants unpacking list
+void ex_const(exarg_T *eap)
+{
+ ex_let_const(eap, true);
+}
+
+// ":let" list all variable values
+// ":let var1 var2" list variable values
+// ":let var = expr" assignment command.
+// ":let var += expr" assignment command.
+// ":let var -= expr" assignment command.
+// ":let var *= expr" assignment command.
+// ":let var /= expr" assignment command.
+// ":let var %= expr" assignment command.
+// ":let var .= expr" assignment command.
+// ":let var ..= expr" assignment command.
+// ":let [var1, var2] = expr" unpack list.
+// ":let [name, ..., ; lastname] = expr" unpack list.
void ex_let(exarg_T *eap)
{
+ ex_let_const(eap, false);
+}
+
+static void ex_let_const(exarg_T *eap, const bool is_const)
+{
char_u *arg = eap->arg;
char_u *expr = NULL;
typval_T rettv;
@@ -1594,7 +1608,8 @@ void ex_let(exarg_T *eap)
}
emsg_skip--;
} else if (i != FAIL) {
- (void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, op);
+ (void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count,
+ is_const, op);
tv_clear(&rettv);
}
}
@@ -1612,9 +1627,10 @@ static int
ex_let_vars(
char_u *arg_start,
typval_T *tv,
- int copy, /* copy values from "tv", don't move */
- int semicolon, /* from skip_var_list() */
- int var_count, /* from skip_var_list() */
+ int copy, // copy values from "tv", don't move
+ int semicolon, // from skip_var_list()
+ int var_count, // from skip_var_list()
+ int is_const, // lock variables for :const
char_u *nextchars
)
{
@@ -1625,8 +1641,9 @@ ex_let_vars(
/*
* ":let var = expr" or ":for var in list"
*/
- if (ex_let_one(arg, tv, copy, nextchars, nextchars) == NULL)
+ if (ex_let_one(arg, tv, copy, is_const, nextchars, nextchars) == NULL) {
return FAIL;
+ }
return OK;
}
@@ -1654,8 +1671,8 @@ ex_let_vars(
size_t rest_len = tv_list_len(l);
while (*arg != ']') {
arg = skipwhite(arg + 1);
- arg = ex_let_one(arg, TV_LIST_ITEM_TV(item), true, (const char_u *)",;]",
- nextchars);
+ arg = ex_let_one(arg, TV_LIST_ITEM_TV(item), true, is_const,
+ (const char_u *)",;]", nextchars);
if (arg == NULL) {
return FAIL;
}
@@ -1677,7 +1694,7 @@ ex_let_vars(
ltv.vval.v_list = rest_list;
tv_list_ref(rest_list);
- arg = ex_let_one(skipwhite(arg + 1), &ltv, false,
+ arg = ex_let_one(skipwhite(arg + 1), &ltv, false, is_const,
(char_u *)"]", nextchars);
tv_clear(&ltv);
if (arg == NULL) {
@@ -1933,8 +1950,8 @@ static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first)
/// @return a pointer to the char just after the var name or NULL in case of
/// error.
static char_u *ex_let_one(char_u *arg, typval_T *const tv,
- const bool copy, const char_u *const endchars,
- const char_u *const op)
+ const bool copy, const bool is_const,
+ const char_u *const endchars, const char_u *const op)
FUNC_ATTR_NONNULL_ARG(1, 2) FUNC_ATTR_WARN_UNUSED_RESULT
{
char_u *arg_end = NULL;
@@ -1946,6 +1963,10 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv,
* ":let $VAR = expr": Set environment variable.
*/
if (*arg == '$') {
+ if (is_const) {
+ EMSG(_("E996: Cannot lock an environment variable"));
+ return NULL;
+ }
// Find the end of the name.
arg++;
char *name = (char *)arg;
@@ -1991,6 +2012,10 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv,
// ":let &l:option = expr": Set local option value.
// ":let &g:option = expr": Set global option value.
} else if (*arg == '&') {
+ if (is_const) {
+ EMSG(_("E996: Cannot lock an option"));
+ return NULL;
+ }
// Find the end of the name.
char *const p = (char *)find_option_end((const char **)&arg, &opt_flags);
if (p == NULL
@@ -2041,6 +2066,10 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv,
}
// ":let @r = expr": Set register contents.
} else if (*arg == '@') {
+ if (is_const) {
+ EMSG(_("E996: Cannot lock a register"));
+ return NULL;
+ }
arg++;
if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL) {
emsgf(_(e_letwrong), op);
@@ -2080,7 +2109,7 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv,
if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL) {
EMSG(_(e_letunexp));
} else {
- set_var_lval(&lv, p, tv, copy, op);
+ set_var_lval(&lv, p, tv, copy, is_const, op);
arg_end = p;
}
}
@@ -2445,7 +2474,7 @@ static void clear_lval(lval_T *lp)
* "%" for "%=", "." for ".=" or "=" for "=".
*/
static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv,
- int copy, const char_u *op)
+ int copy, const bool is_const, const char_u *op)
{
int cc;
listitem_T *ri;
@@ -2457,6 +2486,12 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv,
if (op != NULL && *op != '=') {
typval_T tv;
+ if (is_const) {
+ EMSG(_(e_cannot_mod));
+ *endp = cc;
+ return;
+ }
+
// handle +=, -=, *=, /=, %= and .=
di = NULL;
if (get_var_tv((const char *)lp->ll_name, (int)STRLEN(lp->ll_name),
@@ -2472,7 +2507,7 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv,
tv_clear(&tv);
}
} else {
- set_var(lp->ll_name, lp->ll_name_len, rettv, copy);
+ set_var_const(lp->ll_name, lp->ll_name_len, rettv, copy, is_const);
}
*endp = cc;
} else if (tv_check_lock(lp->ll_newkey == NULL
@@ -2483,6 +2518,11 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv,
listitem_T *ll_li = lp->ll_li;
int ll_n1 = lp->ll_n1;
+ if (is_const) {
+ EMSG(_("E996: Cannot lock a range"));
+ return;
+ }
+
// Check whether any of the list items is locked
for (ri = tv_list_first(rettv->vval.v_list);
ri != NULL && ll_li != NULL; ) {
@@ -2538,6 +2578,11 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv,
dict_T *dict = lp->ll_dict;
bool watched = tv_dict_is_watched(dict);
+ if (is_const) {
+ EMSG(_("E996: Cannot lock a list or dict"));
+ return;
+ }
+
// Assign to a List or Dictionary item.
if (lp->ll_newkey != NULL) {
if (op != NULL && *op != '=') {
@@ -2661,7 +2706,7 @@ bool next_for_item(void *fi_void, char_u *arg)
} else {
fi->fi_lw.lw_item = TV_LIST_ITEM_NEXT(fi->fi_list, item);
return (ex_let_vars(arg, TV_LIST_ITEM_TV(item), true,
- fi->fi_semicolon, fi->fi_varcount, NULL) == OK);
+ fi->fi_semicolon, fi->fi_varcount, false, NULL) == OK);
}
}
@@ -14912,6 +14957,123 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
+/// Set line or list of lines in buffer "buf".
+static void set_buffer_lines(buf_T *buf, linenr_T lnum, typval_T *lines,
+ typval_T *rettv)
+{
+ list_T *l = NULL;
+ listitem_T *li = NULL;
+ long added = 0;
+ linenr_T lcount;
+ buf_T *curbuf_save = NULL;
+ win_T *curwin_save = NULL;
+ int is_curbuf = buf == curbuf;
+
+ // When using the current buffer ml_mfp will be set if needed. Useful when
+ // setline() is used on startup. For other buffers the buffer must be
+ // loaded.
+ if (buf == NULL || (!is_curbuf && buf->b_ml.ml_mfp == NULL) || lnum < 1) {
+ rettv->vval.v_number = 1; // FAIL
+ return;
+ }
+
+ if (!is_curbuf) {
+ wininfo_T *wip;
+
+ curbuf_save = curbuf;
+ curwin_save = curwin;
+ curbuf = buf;
+ for (wip = buf->b_wininfo; wip != NULL; wip = wip->wi_next) {
+ if (wip->wi_win != NULL) {
+ curwin = wip->wi_win;
+ break;
+ }
+ }
+ }
+
+ lcount = curbuf->b_ml.ml_line_count;
+
+ const char *line = NULL;
+
+ if (lines->v_type == VAR_LIST) {
+ l = lines->vval.v_list;
+ li = tv_list_first(l);
+ } else {
+ line = tv_get_string_chk(lines);
+ }
+
+ // Default result is zero == OK.
+ for (;; ) {
+ if (lines->v_type == VAR_LIST) {
+ // List argument, get next string.
+ if (li == NULL) {
+ break;
+ }
+ line = tv_get_string_chk(TV_LIST_ITEM_TV(li));
+ li = TV_LIST_ITEM_NEXT(l, li);
+ }
+
+ rettv->vval.v_number = 1; // FAIL
+ if (line == NULL || lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1) {
+ break;
+ }
+
+ /* When coming here from Insert mode, sync undo, so that this can be
+ * undone separately from what was previously inserted. */
+ if (u_sync_once == 2) {
+ u_sync_once = 1; /* notify that u_sync() was called */
+ u_sync(TRUE);
+ }
+
+ if (lnum <= curbuf->b_ml.ml_line_count) {
+ // Existing line, replace it.
+ if (u_savesub(lnum) == OK
+ && ml_replace(lnum, (char_u *)line, true) == OK) {
+ changed_bytes(lnum, 0);
+ if (is_curbuf && lnum == curwin->w_cursor.lnum) {
+ check_cursor_col();
+ }
+ rettv->vval.v_number = 0; // OK
+ }
+ } else if (added > 0 || u_save(lnum - 1, lnum) == OK) {
+ // lnum is one past the last line, append the line.
+ added++;
+ if (ml_append(lnum - 1, (char_u *)line, 0, false) == OK) {
+ rettv->vval.v_number = 0; // OK
+ }
+ }
+
+ if (l == NULL) /* only one string argument */
+ break;
+ ++lnum;
+ }
+
+ if (added > 0) {
+ appended_lines_mark(lcount, added);
+ }
+
+ if (!is_curbuf) {
+ curbuf = curbuf_save;
+ curwin = curwin_save;
+ }
+}
+
+/// "setbufline()" function
+static void f_setbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ linenr_T lnum;
+ buf_T *buf;
+
+ buf = tv_get_buf(&argvars[0], false);
+ if (buf == NULL) {
+ rettv->vval.v_number = 1; // FAIL
+ } else {
+ lnum = tv_get_lnum_buf(&argvars[1], buf);
+
+ set_buffer_lines(buf, lnum, &argvars[2], rettv);
+ }
+}
+
/*
* "setbufvar()" function
*/
@@ -15044,67 +15206,8 @@ static void f_setfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_setline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- list_T *l = NULL;
- listitem_T *li = NULL;
- long added = 0;
- linenr_T lcount = curbuf->b_ml.ml_line_count;
-
linenr_T lnum = tv_get_lnum(&argvars[0]);
- const char *line = NULL;
- if (argvars[1].v_type == VAR_LIST) {
- l = argvars[1].vval.v_list;
- li = tv_list_first(l);
- } else {
- line = tv_get_string_chk(&argvars[1]);
- }
-
- // Default result is zero == OK.
- for (;; ) {
- if (argvars[1].v_type == VAR_LIST) {
- // List argument, get next string.
- if (li == NULL) {
- break;
- }
- line = tv_get_string_chk(TV_LIST_ITEM_TV(li));
- li = TV_LIST_ITEM_NEXT(l, li);
- }
-
- rettv->vval.v_number = 1; // FAIL
- if (line == NULL || lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1) {
- break;
- }
-
- /* When coming here from Insert mode, sync undo, so that this can be
- * undone separately from what was previously inserted. */
- if (u_sync_once == 2) {
- u_sync_once = 1; /* notify that u_sync() was called */
- u_sync(TRUE);
- }
-
- if (lnum <= curbuf->b_ml.ml_line_count) {
- // Existing line, replace it.
- if (u_savesub(lnum) == OK
- && ml_replace(lnum, (char_u *)line, true) == OK) {
- changed_bytes(lnum, 0);
- if (lnum == curwin->w_cursor.lnum)
- check_cursor_col();
- rettv->vval.v_number = 0; /* OK */
- }
- } else if (added > 0 || u_save(lnum - 1, lnum) == OK) {
- // lnum is one past the last line, append the line.
- added++;
- if (ml_append(lnum - 1, (char_u *)line, 0, false) == OK) {
- rettv->vval.v_number = 0; // OK
- }
- }
-
- if (l == NULL) /* only one string argument */
- break;
- ++lnum;
- }
-
- if (added > 0)
- appended_lines_mark(lcount, added);
+ set_buffer_lines(curbuf, lnum, &argvars[1], rettv);
}
/// Create quickfix/location list from VimL values
@@ -20112,6 +20215,24 @@ static void set_var(const char *name, const size_t name_len, typval_T *const tv,
const bool copy)
FUNC_ATTR_NONNULL_ALL
{
+ set_var_const(name, name_len, tv, copy, false);
+}
+
+/// Set variable to the given value
+///
+/// If the variable already exists, the value is updated. Otherwise the variable
+/// is created.
+///
+/// @param[in] name Variable name to set.
+/// @param[in] name_len Length of the variable name.
+/// @param tv Variable value.
+/// @param[in] copy True if value in tv is to be copied.
+/// @param[in] is_const True if value in tv is to be locked.
+static void set_var_const(const char *name, const size_t name_len,
+ typval_T *const tv, const bool copy,
+ const bool is_const)
+ FUNC_ATTR_NONNULL_ALL
+{
dictitem_T *v;
hashtab_T *ht;
dict_T *dict;
@@ -20137,6 +20258,11 @@ static void set_var(const char *name, const size_t name_len, typval_T *const tv,
typval_T oldtv = TV_INITIAL_VALUE;
if (v != NULL) {
+ if (is_const) {
+ EMSG(_(e_cannot_mod));
+ return;
+ }
+
// existing variable, need to clear the value
if (var_check_ro(v->di_flags, name, name_len)
|| tv_check_lock(v->di_tv.v_lock, name, name_len)) {
@@ -20203,6 +20329,9 @@ static void set_var(const char *name, const size_t name_len, typval_T *const tv,
return;
}
v->di_flags = DI_FLAGS_ALLOC;
+ if (is_const) {
+ v->di_flags |= DI_FLAGS_LOCK;
+ }
}
if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT) {
@@ -20221,6 +20350,10 @@ static void set_var(const char *name, const size_t name_len, typval_T *const tv,
tv_clear(&oldtv);
}
}
+
+ if (is_const) {
+ v->di_tv.v_lock |= VAR_LOCKED;
+ }
}
/// Check whether variable is read-only (DI_FLAGS_RO, DI_FLAGS_RO_SBX)
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index 6159103767..9deee69f32 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -263,6 +263,7 @@ return {
serverlist={},
serverstart={args={0, 1}},
serverstop={args=1},
+ setbufline={args=3},
setbufvar={args=3},
setcharsearch={args=1},
setcmdpos={args=1},
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
index 0f69d476f9..58dc62e953 100644
--- a/src/nvim/ex_cmds.lua
+++ b/src/nvim/ex_cmds.lua
@@ -601,6 +601,12 @@ return {
func='ex_wrongmodifier',
},
{
+ command='const',
+ flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, CMDWIN),
+ addr_type=ADDR_LINES,
+ func='ex_const',
+ },
+ {
command='copen',
flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
addr_type=ADDR_LINES,
diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua
index fdc00d5dc0..d9c65e17c5 100644
--- a/src/nvim/generators/gen_options.lua
+++ b/src/nvim/generators/gen_options.lua
@@ -79,6 +79,7 @@ local get_flags = function(o)
{'pri_mkrc'},
{'deny_in_modelines', 'P_NO_ML'},
{'deny_duplicates', 'P_NODUP'},
+ {'modelineexpr', 'P_MLE'},
}) do
local key_name = flag_desc[1]
local def_name = flag_desc[2] or ('P_' .. key_name:upper())
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 27ad6bb86c..7efae1e637 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -1253,9 +1253,17 @@ openscript (
EMSG(_(e_nesting));
return;
}
- if (ignore_script)
- /* Not reading from script, also don't open one. Warning message? */
+
+ // Disallow sourcing a file in the sandbox, the commands would be executed
+ // later, possibly outside of the sandbox.
+ if (check_secure()) {
return;
+ }
+
+ if (ignore_script) {
+ // Not reading from script, also don't open one. Warning message?
+ return;
+ }
if (scriptin[curscript] != NULL) /* already reading script */
++curscript;
diff --git a/src/nvim/option.c b/src/nvim/option.c
index a39be0fe96..8dadf926b9 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -253,6 +253,7 @@ typedef struct vimoption {
#define P_RWINONLY 0x10000000U ///< only redraw current window
#define P_NDNAME 0x20000000U ///< only normal dir name chars allowed
#define P_UI_OPTION 0x40000000U ///< send option to remote ui
+#define P_MLE 0x80000000U ///< under control of 'modelineexpr'
#define HIGHLIGHT_INIT \
"8:SpecialKey,~:EndOfBuffer,z:TermCursor,Z:TermCursorNC,@:NonText," \
@@ -1327,6 +1328,11 @@ int do_set(
errmsg = (char_u *)_("E520: Not allowed in a modeline");
goto skip;
}
+ if ((flags & P_MLE) && !p_mle) {
+ errmsg = (char_u *)_(
+ "E992: Not allowed in a modeline when 'modelineexpr' is off");
+ goto skip;
+ }
// In diff mode some options are overruled. This avoids that
// 'foldmethod' becomes "marker" instead of "diff" and that
// "wrap" gets set.
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index f9f2a7d5dc..8df5039037 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -496,6 +496,7 @@ EXTERN long p_mmd; // 'maxmapdepth'
EXTERN long p_mmp; // 'maxmempattern'
EXTERN long p_mis; // 'menuitems'
EXTERN char_u *p_msm; // 'mkspellmem'
+EXTERN long p_mle; // 'modelineexpr'
EXTERN long p_mls; // 'modelines'
EXTERN char_u *p_mouse; // 'mouse'
EXTERN char_u *p_mousem; // 'mousemodel'
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 96e098778c..e892e59ba6 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -8,6 +8,7 @@
-- defaults={condition=nil, if_true={vi=224, vim=0}, if_false=nil},
-- secure=nil, gettext=nil, noglob=nil, normal_fname_chars=nil,
-- pri_mkrc=nil, deny_in_modelines=nil, normal_dname_chars=nil,
+-- modelineexpr=nil,
-- expand=nil, nodefault=nil, no_mkrc=nil, vi_def=true, vim=true,
-- alloced=nil,
-- save_pv_indir=nil,
@@ -283,6 +284,7 @@ return {
deny_duplicates=true,
vi_def=true,
expand=true,
+ secure=true,
varname='p_cdpath',
defaults={if_true={vi=",,"}}
},
@@ -847,6 +849,7 @@ return {
type='string', scope={'window'},
vi_def=true,
vim=true,
+ modelineexpr=true,
alloced=true,
redraw={'current_window'},
defaults={if_true={vi="0"}}
@@ -922,6 +925,7 @@ return {
type='string', scope={'window'},
vi_def=true,
vim=true,
+ modelineexpr=true,
alloced=true,
redraw={'current_window'},
defaults={if_true={vi="foldtext()"}}
@@ -931,6 +935,7 @@ return {
type='string', scope={'buffer'},
vi_def=true,
vim=true,
+ modelineexpr=true,
alloced=true,
varname='p_fex',
defaults={if_true={vi=""}}
@@ -1045,6 +1050,7 @@ return {
full_name='guitablabel', abbreviation='gtl',
type='string', scope={'global'},
vi_def=true,
+ modelineexpr=true,
redraw={'current_window'},
enable_if=false,
},
@@ -1136,6 +1142,7 @@ return {
full_name='iconstring',
type='string', scope={'global'},
vi_def=true,
+ modelineexpr=true,
varname='p_iconstring',
defaults={if_true={vi=""}}
},
@@ -1198,6 +1205,7 @@ return {
full_name='includeexpr', abbreviation='inex',
type='string', scope={'buffer'},
vi_def=true,
+ modelineexpr=true,
alloced=true,
varname='p_inex',
defaults={if_true={vi=""}}
@@ -1214,6 +1222,7 @@ return {
type='string', scope={'buffer'},
vi_def=true,
vim=true,
+ modelineexpr=true,
alloced=true,
varname='p_inde',
defaults={if_true={vi=""}}
@@ -1528,6 +1537,14 @@ return {
defaults={if_true={vi=false, vim=true}}
},
{
+ full_name='modelineexpr', abbreviation='mle',
+ type='bool', scope={'global'},
+ vi_def=true,
+ secure=true,
+ varname='p_mle',
+ defaults={if_true={vi=false}}
+ },
+ {
full_name='modelines', abbreviation='mls',
type='number', scope={'global'},
vi_def=true,
@@ -1903,6 +1920,7 @@ return {
type='string', scope={'global'},
vi_def=true,
alloced=true,
+ modelineexpr=true,
redraw={'statuslines'},
varname='p_ruf',
defaults={if_true={vi=""}}
@@ -2310,6 +2328,7 @@ return {
type='string', scope={'global', 'window'},
vi_def=true,
alloced=true,
+ modelineexpr=true,
redraw={'statuslines'},
varname='p_stl',
defaults={if_true={vi=""}}
@@ -2369,6 +2388,7 @@ return {
full_name='tabline', abbreviation='tal',
type='string', scope={'global'},
vi_def=true,
+ modelineexpr=true,
redraw={'all_windows'},
varname='p_tal',
defaults={if_true={vi=""}}
@@ -2528,6 +2548,7 @@ return {
full_name='titlestring',
type='string', scope={'global'},
vi_def=true,
+ modelineexpr=true,
varname='p_titlestring',
defaults={if_true={vi=""}}
},
diff --git a/src/nvim/os/dl.c b/src/nvim/os/dl.c
index bbd0424a82..f0fadb16f2 100644
--- a/src/nvim/os/dl.c
+++ b/src/nvim/os/dl.c
@@ -54,6 +54,7 @@ bool os_libcall(const char *libname,
// open the dynamic loadable library
if (uv_dlopen(libname, &lib)) {
EMSG2(_("dlerror = \"%s\""), uv_dlerror(&lib));
+ uv_dlclose(&lib);
return false;
}
diff --git a/src/nvim/testdir/shared.vim b/src/nvim/testdir/shared.vim
index ac34dec569..a5cf4def4f 100644
--- a/src/nvim/testdir/shared.vim
+++ b/src/nvim/testdir/shared.vim
@@ -190,12 +190,18 @@ func s:feedkeys(timer)
endfunc
" Get the command to run Vim, with -u NONE and --headless arguments.
+" If there is an argument use it instead of "NONE".
" Returns an empty string on error.
-func GetVimCommand()
+func GetVimCommand(...)
+ if a:0 == 0
+ let name = 'NONE'
+ else
+ let name = a:1
+ endif
let cmd = v:progpath
- let cmd = substitute(cmd, '-u \f\+', '-u NONE', '')
- if cmd !~ '-u NONE'
- let cmd = cmd . ' -u NONE'
+ let cmd = substitute(cmd, '-u \f\+', '-u ' . name, '')
+ if cmd !~ '-u '. name
+ let cmd = cmd . ' -u ' . name
endif
let cmd .= ' --headless -i NONE'
let cmd = substitute(cmd, 'VIMRUNTIME=.*VIMRUNTIME;', '', '')
diff --git a/src/nvim/testdir/test49.vim b/src/nvim/testdir/test49.vim
index 467abcd9b9..837e55ebca 100644
--- a/src/nvim/testdir/test49.vim
+++ b/src/nvim/testdir/test49.vim
@@ -1,6 +1,6 @@
" Vim script language tests
" Author: Servatius Brandt <Servatius.Brandt@fujitsu-siemens.com>
-" Last Change: 2016 Feb 07
+" Last Change: 2019 May 24
"-------------------------------------------------------------------------------
" Test environment {{{1
@@ -9005,5 +9005,4 @@ Xcheck 50443995
"-------------------------------------------------------------------------------
" Modelines {{{1
" vim: ts=8 sw=4 tw=80 fdm=marker
-" vim: fdt=substitute(substitute(foldtext(),\ '\\%(^+--\\)\\@<=\\(\\s*\\)\\(.\\{-}\\)\:\ \\%(\"\ \\)\\=\\(Test\ \\d*\\)\:\\s*',\ '\\3\ (\\2)\:\ \\1',\ \"\"),\ '\\(Test\\s*\\)\\(\\d\\)\\D\\@=',\ '\\1\ \\2',\ "")
"-------------------------------------------------------------------------------
diff --git a/src/nvim/testdir/test_bufline.vim b/src/nvim/testdir/test_bufline.vim
new file mode 100644
index 0000000000..b886e99506
--- /dev/null
+++ b/src/nvim/testdir/test_bufline.vim
@@ -0,0 +1,67 @@
+" Tests for setbufline() and getbufline()
+
+source shared.vim
+
+func Test_setbufline_getbufline()
+ new
+ let b = bufnr('%')
+ hide
+ call assert_equal(0, setbufline(b, 1, ['foo', 'bar']))
+ call assert_equal(['foo'], getbufline(b, 1))
+ call assert_equal(['bar'], getbufline(b, 2))
+ call assert_equal(['foo', 'bar'], getbufline(b, 1, 2))
+ exe "bd!" b
+ call assert_equal([], getbufline(b, 1, 2))
+
+ split Xtest
+ call setline(1, ['a', 'b', 'c'])
+ let b = bufnr('%')
+ wincmd w
+ call assert_equal(1, setbufline(b, 5, ['x']))
+ call assert_equal(1, setbufline(1234, 1, ['x']))
+ call assert_equal(0, setbufline(b, 4, ['d', 'e']))
+ call assert_equal(['c'], getbufline(b, 3))
+ call assert_equal(['d'], getbufline(b, 4))
+ call assert_equal(['e'], getbufline(b, 5))
+ call assert_equal([], getbufline(b, 6))
+ exe "bwipe! " . b
+endfunc
+
+func Test_setbufline_getbufline_fold()
+ split Xtest
+ setlocal foldmethod=expr foldexpr=0
+ let b = bufnr('%')
+ new
+ call assert_equal(0, setbufline(b, 1, ['foo', 'bar']))
+ call assert_equal(['foo'], getbufline(b, 1))
+ call assert_equal(['bar'], getbufline(b, 2))
+ call assert_equal(['foo', 'bar'], getbufline(b, 1, 2))
+ exe "bwipe!" b
+ bwipe!
+endfunc
+
+func Test_setbufline_getbufline_fold_tab()
+ split Xtest
+ setlocal foldmethod=expr foldexpr=0
+ let b = bufnr('%')
+ tab new
+ call assert_equal(0, setbufline(b, 1, ['foo', 'bar']))
+ call assert_equal(['foo'], getbufline(b, 1))
+ call assert_equal(['bar'], getbufline(b, 2))
+ call assert_equal(['foo', 'bar'], getbufline(b, 1, 2))
+ exe "bwipe!" b
+ bwipe!
+endfunc
+
+func Test_setline_startup()
+ let cmd = GetVimCommand('Xscript')
+ if cmd == ''
+ return
+ endif
+ call writefile(['call setline(1, "Hello")', 'silent w Xtest', 'q!'], 'Xscript')
+ call system(cmd)
+ call assert_equal(['Hello'], readfile('Xtest'))
+
+ call delete('Xscript')
+ call delete('Xtest')
+endfunc
diff --git a/src/nvim/testdir/test_const.vim b/src/nvim/testdir/test_const.vim
new file mode 100644
index 0000000000..06062c5e58
--- /dev/null
+++ b/src/nvim/testdir/test_const.vim
@@ -0,0 +1,237 @@
+
+" Test for :const
+
+func s:noop()
+endfunc
+
+func Test_define_var_with_lock()
+ const i = 1
+ const f = 1.1
+ const s = 'vim'
+ const F = funcref('s:noop')
+ const l = [1, 2, 3]
+ const d = {'foo': 10}
+ if has('channel')
+ const j = test_null_job()
+ const c = test_null_channel()
+ endif
+ const b = v:true
+ const n = v:null
+
+ call assert_true(exists('i'))
+ call assert_true(exists('f'))
+ call assert_true(exists('s'))
+ call assert_true(exists('F'))
+ call assert_true(exists('l'))
+ call assert_true(exists('d'))
+ if has('channel')
+ call assert_true(exists('j'))
+ call assert_true(exists('c'))
+ endif
+ call assert_true(exists('b'))
+ call assert_true(exists('n'))
+
+ call assert_fails('let i = 1', 'E741:')
+ call assert_fails('let f = 1.1', 'E741:')
+ call assert_fails('let s = "vim"', 'E741:')
+ call assert_fails('let F = funcref("s:noop")', 'E741:')
+ call assert_fails('let l = [1, 2, 3]', 'E741:')
+ call assert_fails('let d = {"foo": 10}', 'E741:')
+ if has('channel')
+ call assert_fails('let j = test_null_job()', 'E741:')
+ call assert_fails('let c = test_null_channel()', 'E741:')
+ endif
+ call assert_fails('let b = v:true', 'E741:')
+ call assert_fails('let n = v:null', 'E741:')
+
+ " Unlet
+ unlet i
+ unlet f
+ unlet s
+ unlet F
+ unlet l
+ unlet d
+ if has('channel')
+ unlet j
+ unlet c
+ endif
+ unlet b
+ unlet n
+endfunc
+
+func Test_define_l_var_with_lock()
+ " With l: prefix
+ const l:i = 1
+ const l:f = 1.1
+ const l:s = 'vim'
+ const l:F = funcref('s:noop')
+ const l:l = [1, 2, 3]
+ const l:d = {'foo': 10}
+ if has('channel')
+ const l:j = test_null_job()
+ const l:c = test_null_channel()
+ endif
+ const l:b = v:true
+ const l:n = v:null
+
+ call assert_fails('let l:i = 1', 'E741:')
+ call assert_fails('let l:f = 1.1', 'E741:')
+ call assert_fails('let l:s = "vim"', 'E741:')
+ call assert_fails('let l:F = funcref("s:noop")', 'E741:')
+ call assert_fails('let l:l = [1, 2, 3]', 'E741:')
+ call assert_fails('let l:d = {"foo": 10}', 'E741:')
+ if has('channel')
+ call assert_fails('let l:j = test_null_job()', 'E741:')
+ call assert_fails('let l:c = test_null_channel()', 'E741:')
+ endif
+ call assert_fails('let l:b = v:true', 'E741:')
+ call assert_fails('let l:n = v:null', 'E741:')
+
+ " Unlet
+ unlet l:i
+ unlet l:f
+ unlet l:s
+ unlet l:F
+ unlet l:l
+ unlet l:d
+ if has('channel')
+ unlet l:j
+ unlet l:c
+ endif
+ unlet l:b
+ unlet l:n
+endfunc
+
+func Test_define_script_var_with_lock()
+ const s:x = 0
+ call assert_fails('let s:x = 1', 'E741:')
+ unlet s:x
+endfunc
+
+func Test_descructuring_with_lock()
+ const [a, b, c] = [1, 1.1, 'vim']
+
+ call assert_fails('let a = 1', 'E741:')
+ call assert_fails('let b = 1.1', 'E741:')
+ call assert_fails('let c = "vim"', 'E741:')
+
+ const [d; e] = [1, 1.1, 'vim']
+ call assert_fails('let d = 1', 'E741:')
+ call assert_fails('let e = [2.2, "a"]', 'E741:')
+endfunc
+
+func Test_cannot_modify_existing_variable()
+ let i = 1
+ let f = 1.1
+ let s = 'vim'
+ let F = funcref('s:noop')
+ let l = [1, 2, 3]
+ let d = {'foo': 10}
+ if has('channel')
+ let j = test_null_job()
+ let c = test_null_channel()
+ endif
+ let b = v:true
+ let n = v:null
+
+ call assert_fails('const i = 1', 'E995:')
+ call assert_fails('const f = 1.1', 'E995:')
+ call assert_fails('const s = "vim"', 'E995:')
+ call assert_fails('const F = funcref("s:noop")', 'E995:')
+ call assert_fails('const l = [1, 2, 3]', 'E995:')
+ call assert_fails('const d = {"foo": 10}', 'E995:')
+ if has('channel')
+ call assert_fails('const j = test_null_job()', 'E995:')
+ call assert_fails('const c = test_null_channel()', 'E995:')
+ endif
+ call assert_fails('const b = v:true', 'E995:')
+ call assert_fails('const n = v:null', 'E995:')
+ call assert_fails('const [i, f, s] = [1, 1.1, "vim"]', 'E995:')
+
+ const i2 = 1
+ const f2 = 1.1
+ const s2 = 'vim'
+ const F2 = funcref('s:noop')
+ const l2 = [1, 2, 3]
+ const d2 = {'foo': 10}
+ if has('channel')
+ const j2 = test_null_job()
+ const c2 = test_null_channel()
+ endif
+ const b2 = v:true
+ const n2 = v:null
+
+ call assert_fails('const i2 = 1', 'E995:')
+ call assert_fails('const f2 = 1.1', 'E995:')
+ call assert_fails('const s2 = "vim"', 'E995:')
+ call assert_fails('const F2 = funcref("s:noop")', 'E995:')
+ call assert_fails('const l2 = [1, 2, 3]', 'E995:')
+ call assert_fails('const d2 = {"foo": 10}', 'E995:')
+ if has('channel')
+ call assert_fails('const j2 = test_null_job()', 'E995:')
+ call assert_fails('const c2 = test_null_channel()', 'E995:')
+ endif
+ call assert_fails('const b2 = v:true', 'E995:')
+ call assert_fails('const n2 = v:null', 'E995:')
+ call assert_fails('const [i2, f2, s2] = [1, 1.1, "vim"]', 'E995:')
+endfunc
+
+func Test_const_with_index_access()
+ let l = [1, 2, 3]
+ call assert_fails('const l[0] = 4', 'E996:')
+ call assert_fails('const l[0:1] = [1, 2]', 'E996:')
+
+ let d = {'aaa': 0}
+ call assert_fails("const d['aaa'] = 4", 'E996:')
+ call assert_fails("const d.aaa = 4", 'E996:')
+endfunc
+
+func Test_const_with_compound_assign()
+ let i = 0
+ call assert_fails('const i += 4', 'E995:')
+ call assert_fails('const i -= 4', 'E995:')
+ call assert_fails('const i *= 4', 'E995:')
+ call assert_fails('const i /= 4', 'E995:')
+ call assert_fails('const i %= 4', 'E995:')
+
+ let s = 'a'
+ call assert_fails('const s .= "b"', 'E995:')
+
+ let [a, b, c] = [1, 2, 3]
+ call assert_fails('const [a, b, c] += [4, 5, 6]', 'E995:')
+
+ let [d; e] = [1, 2, 3]
+ call assert_fails('const [d; e] += [4, 5, 6]', 'E995:')
+endfunc
+
+func Test_const_with_special_variables()
+ call assert_fails('const $FOO = "hello"', 'E996:')
+ call assert_fails('const @a = "hello"', 'E996:')
+ call assert_fails('const &filetype = "vim"', 'E996:')
+ call assert_fails('const &l:filetype = "vim"', 'E996:')
+ call assert_fails('const &g:encoding = "utf-8"', 'E996:')
+endfunc
+
+func Test_const_with_eval_name()
+ let s = 'foo'
+
+ " eval name with :const should work
+ const abc_{s} = 1
+ const {s}{s} = 1
+
+ let s2 = 'abc_foo'
+ call assert_fails('const {s2} = "bar"', 'E995:')
+endfunc
+
+func Test_lock_depth_is_1()
+ const l = [1, 2, 3]
+ const d = {'foo': 10}
+
+ " Modify list
+ call add(l, 4)
+ let l[0] = 42
+
+ " Modify dict
+ let d['bar'] = 'hello'
+ let d.foo = 44
+endfunc
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index ed9c70403e..0c3c356622 100644
--- a/src/nvim/testdir/test_functions.vim
+++ b/src/nvim/testdir/test_functions.vim
@@ -1,4 +1,5 @@
" Tests for various functions.
+source shared.vim
" Must be done first, since the alternate buffer must be unset.
func Test_00_bufexists()
@@ -1140,3 +1141,50 @@ func Test_reg_executing_and_recording()
delfunc s:save_reg_stat
unlet s:reg_stat
endfunc
+
+func Test_libcall_libcallnr()
+ if !has('libcall')
+ return
+ endif
+
+ if has('win32')
+ let libc = 'msvcrt.dll'
+ elseif has('mac')
+ let libc = 'libSystem.B.dylib'
+ elseif system('uname -s') =~ 'SunOS'
+ " Set the path to libc.so according to the architecture.
+ let test_bits = system('file ' . GetVimProg())
+ let test_arch = system('uname -p')
+ if test_bits =~ '64-bit' && test_arch =~ 'sparc'
+ let libc = '/usr/lib/sparcv9/libc.so'
+ elseif test_bits =~ '64-bit' && test_arch =~ 'i386'
+ let libc = '/usr/lib/amd64/libc.so'
+ else
+ let libc = '/usr/lib/libc.so'
+ endif
+ else
+ " On Unix, libc.so can be in various places.
+ " Interestingly, using an empty string for the 1st argument of libcall
+ " allows to call functions from libc which is not documented.
+ let libc = ''
+ endif
+
+ if has('win32')
+ call assert_equal($USERPROFILE, libcall(libc, 'getenv', 'USERPROFILE'))
+ else
+ call assert_equal($HOME, libcall(libc, 'getenv', 'HOME'))
+ endif
+
+ " If function returns NULL, libcall() should return an empty string.
+ call assert_equal('', libcall(libc, 'getenv', 'X_ENV_DOES_NOT_EXIT'))
+
+ " Test libcallnr() with string and integer argument.
+ call assert_equal(4, libcallnr(libc, 'strlen', 'abcd'))
+ call assert_equal(char2nr('A'), libcallnr(libc, 'toupper', char2nr('a')))
+
+ call assert_fails("call libcall(libc, 'Xdoesnotexist_', '')", 'E364:')
+ call assert_fails("call libcallnr(libc, 'Xdoesnotexist_', '')", 'E364:')
+
+ call assert_fails("call libcall('Xdoesnotexist_', 'getenv', 'HOME')", 'E364:')
+ call assert_fails("call libcallnr('Xdoesnotexist_', 'strlen', 'abcd')", 'E364:')
+endfunc
diff --git a/src/nvim/testdir/test_modeline.vim b/src/nvim/testdir/test_modeline.vim
index 091a833774..1e196e07f0 100644
--- a/src/nvim/testdir/test_modeline.vim
+++ b/src/nvim/testdir/test_modeline.vim
@@ -60,14 +60,17 @@ func Test_modeline_keymap()
set keymap= iminsert=0 imsearch=-1
endfunc
-func s:modeline_fails(what, text)
+func s:modeline_fails(what, text, error)
+ if !exists('+' . a:what)
+ return
+ endif
let fname = "Xmodeline_fails_" . a:what
call writefile(['vim: set ' . a:text . ' :', 'nothing'], fname)
let modeline = &modeline
set modeline
filetype plugin on
syntax enable
- call assert_fails('split ' . fname, 'E474:')
+ call assert_fails('split ' . fname, a:error)
call assert_equal("", &filetype)
call assert_equal("", &syntax)
@@ -79,16 +82,92 @@ func s:modeline_fails(what, text)
endfunc
func Test_modeline_filetype_fails()
- call s:modeline_fails('filetype', 'ft=evil$CMD')
+ call s:modeline_fails('filetype', 'ft=evil$CMD', 'E474:')
endfunc
func Test_modeline_syntax_fails()
- call s:modeline_fails('syntax', 'syn=evil$CMD')
+ call s:modeline_fails('syntax', 'syn=evil$CMD', 'E474:')
endfunc
func Test_modeline_keymap_fails()
- if !has('keymap')
- return
- endif
- call s:modeline_fails('keymap', 'keymap=evil$CMD')
+ call s:modeline_fails('keymap', 'keymap=evil$CMD', 'E474:')
+endfunc
+
+func Test_modeline_fails_always()
+ call s:modeline_fails('backupdir', 'backupdir=Something()', 'E520:')
+ call s:modeline_fails('cdpath', 'cdpath=Something()', 'E520:')
+ call s:modeline_fails('charconvert', 'charconvert=Something()', 'E520:')
+ call s:modeline_fails('completefunc', 'completefunc=Something()', 'E520:')
+ call s:modeline_fails('cscopeprg', 'cscopeprg=Something()', 'E520:')
+ call s:modeline_fails('diffexpr', 'diffexpr=Something()', 'E520:')
+ call s:modeline_fails('directory', 'directory=Something()', 'E520:')
+ call s:modeline_fails('equalprg', 'equalprg=Something()', 'E520:')
+ call s:modeline_fails('errorfile', 'errorfile=Something()', 'E520:')
+ call s:modeline_fails('exrc', 'exrc=Something()', 'E520:')
+ call s:modeline_fails('formatprg', 'formatprg=Something()', 'E520:')
+ call s:modeline_fails('fsync', 'fsync=Something()', 'E520:')
+ call s:modeline_fails('grepprg', 'grepprg=Something()', 'E520:')
+ call s:modeline_fails('helpfile', 'helpfile=Something()', 'E520:')
+ call s:modeline_fails('imactivatefunc', 'imactivatefunc=Something()', 'E520:')
+ call s:modeline_fails('imstatusfunc', 'imstatusfunc=Something()', 'E520:')
+ call s:modeline_fails('imstyle', 'imstyle=Something()', 'E520:')
+ call s:modeline_fails('keywordprg', 'keywordprg=Something()', 'E520:')
+ call s:modeline_fails('langmap', 'langmap=Something()', 'E520:')
+ call s:modeline_fails('luadll', 'luadll=Something()', 'E520:')
+ call s:modeline_fails('makeef', 'makeef=Something()', 'E520:')
+ call s:modeline_fails('makeprg', 'makeprg=Something()', 'E520:')
+ call s:modeline_fails('mkspellmem', 'mkspellmem=Something()', 'E520:')
+ call s:modeline_fails('mzschemedll', 'mzschemedll=Something()', 'E520:')
+ call s:modeline_fails('mzschemegcdll', 'mzschemegcdll=Something()', 'E520:')
+ call s:modeline_fails('modelineexpr', 'modelineexpr=Something()', 'E520:')
+ call s:modeline_fails('omnifunc', 'omnifunc=Something()', 'E520:')
+ call s:modeline_fails('operatorfunc', 'operatorfunc=Something()', 'E520:')
+ call s:modeline_fails('perldll', 'perldll=Something()', 'E520:')
+ call s:modeline_fails('printdevice', 'printdevice=Something()', 'E520:')
+ call s:modeline_fails('patchexpr', 'patchexpr=Something()', 'E520:')
+ call s:modeline_fails('printexpr', 'printexpr=Something()', 'E520:')
+ call s:modeline_fails('pythondll', 'pythondll=Something()', 'E520:')
+ call s:modeline_fails('pythonhome', 'pythonhome=Something()', 'E520:')
+ call s:modeline_fails('pythonthreedll', 'pythonthreedll=Something()', 'E520:')
+ call s:modeline_fails('pythonthreehome', 'pythonthreehome=Something()', 'E520:')
+ call s:modeline_fails('pyxversion', 'pyxversion=Something()', 'E520:')
+ call s:modeline_fails('rubydll', 'rubydll=Something()', 'E520:')
+ call s:modeline_fails('runtimepath', 'runtimepath=Something()', 'E520:')
+ call s:modeline_fails('secure', 'secure=Something()', 'E520:')
+ call s:modeline_fails('shell', 'shell=Something()', 'E520:')
+ call s:modeline_fails('shellcmdflag', 'shellcmdflag=Something()', 'E520:')
+ call s:modeline_fails('shellpipe', 'shellpipe=Something()', 'E520:')
+ call s:modeline_fails('shellquote', 'shellquote=Something()', 'E520:')
+ call s:modeline_fails('shellredir', 'shellredir=Something()', 'E520:')
+ call s:modeline_fails('shellxquote', 'shellxquote=Something()', 'E520:')
+ call s:modeline_fails('spellfile', 'spellfile=Something()', 'E520:')
+ call s:modeline_fails('spellsuggest', 'spellsuggest=Something()', 'E520:')
+ call s:modeline_fails('tcldll', 'tcldll=Something()', 'E520:')
+ call s:modeline_fails('titleold', 'titleold=Something()', 'E520:')
+ call s:modeline_fails('viewdir', 'viewdir=Something()', 'E520:')
+ call s:modeline_fails('viminfo', 'viminfo=Something()', 'E520:')
+ call s:modeline_fails('viminfofile', 'viminfofile=Something()', 'E520:')
+ call s:modeline_fails('winptydll', 'winptydll=Something()', 'E520:')
+ call s:modeline_fails('undodir', 'undodir=Something()', 'E520:')
+ " only check a few terminal options
+ " Skip these since nvim doesn't support termcodes as options
+ "call s:modeline_fails('t_AB', 't_AB=Something()', 'E520:')
+ "call s:modeline_fails('t_ce', 't_ce=Something()', 'E520:')
+ "call s:modeline_fails('t_sr', 't_sr=Something()', 'E520:')
+ "call s:modeline_fails('t_8b', 't_8b=Something()', 'E520:')
+endfunc
+
+func Test_modeline_fails_modelineexpr()
+ call s:modeline_fails('balloonexpr', 'balloonexpr=Something()', 'E992:')
+ call s:modeline_fails('foldexpr', 'foldexpr=Something()', 'E992:')
+ call s:modeline_fails('foldtext', 'foldtext=Something()', 'E992:')
+ call s:modeline_fails('formatexpr', 'formatexpr=Something()', 'E992:')
+ call s:modeline_fails('guitablabel', 'guitablabel=Something()', 'E992:')
+ call s:modeline_fails('iconstring', 'iconstring=Something()', 'E992:')
+ call s:modeline_fails('includeexpr', 'includeexpr=Something()', 'E992:')
+ call s:modeline_fails('indentexpr', 'indentexpr=Something()', 'E992:')
+ call s:modeline_fails('rulerformat', 'rulerformat=Something()', 'E992:')
+ call s:modeline_fails('statusline', 'statusline=Something()', 'E992:')
+ call s:modeline_fails('tabline', 'tabline=Something()', 'E992:')
+ call s:modeline_fails('titlestring', 'titlestring=Something()', 'E992:')
endfunc
diff --git a/src/nvim/testdir/test_source.vim b/src/nvim/testdir/test_source.vim
new file mode 100644
index 0000000000..42ac0c4d0f
--- /dev/null
+++ b/src/nvim/testdir/test_source.vim
@@ -0,0 +1,10 @@
+" Tests for the :source command.
+
+func Test_source_sandbox()
+ new
+ call writefile(["Ohello\<Esc>"], 'Xsourcehello')
+ source! Xsourcehello | echo
+ call assert_equal('hello', getline(1))
+ call assert_fails('sandbox source! Xsourcehello', 'E48:')
+ bwipe!
+endfunc
diff --git a/src/nvim/testdir/test_vimscript.vim b/src/nvim/testdir/test_vimscript.vim
index d0ecbef7e1..f3e40e1210 100644
--- a/src/nvim/testdir/test_vimscript.vim
+++ b/src/nvim/testdir/test_vimscript.vim
@@ -1375,5 +1375,4 @@ endfunc
"-------------------------------------------------------------------------------
" Modelines {{{1
" vim: ts=8 sw=4 tw=80 fdm=marker
-" vim: fdt=substitute(substitute(foldtext(),\ '\\%(^+--\\)\\@<=\\(\\s*\\)\\(.\\{-}\\)\:\ \\%(\"\ \\)\\=\\(Test\ \\d*\\)\:\\s*',\ '\\3\ (\\2)\:\ \\1',\ \"\"),\ '\\(Test\\s*\\)\\(\\d\\)\\D\\@=',\ '\\1\ \\2',\ "")
"-------------------------------------------------------------------------------
diff --git a/src/nvim/testdir/test_writefile.vim b/src/nvim/testdir/test_writefile.vim
index 9da9df2150..6d88c0d8cd 100644
--- a/src/nvim/testdir/test_writefile.vim
+++ b/src/nvim/testdir/test_writefile.vim
@@ -33,7 +33,7 @@ func Test_writefile_fails_gently()
endfunc
func Test_writefile_fails_conversion()
- if !has('multi_byte') || !has('iconv')
+ if !has('multi_byte') || !has('iconv') || system('uname -s') =~ 'SunOS'
return
endif
" Without a backup file the write won't happen if there is a conversion
diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt
index c9e8537272..90581462d7 100644
--- a/third-party/CMakeLists.txt
+++ b/third-party/CMakeLists.txt
@@ -135,13 +135,13 @@ endif()
set(MSGPACK_URL https://github.com/msgpack/msgpack-c/releases/download/cpp-3.0.0/msgpack-3.0.0.tar.gz)
set(MSGPACK_SHA256 bfbb71b7c02f806393bc3cbc491b40523b89e64f83860c58e3e54af47de176e4)
-set(LUAJIT_URL https://github.com/LuaJIT/LuaJIT/archive/7dbf0b05f1228c1c719866db5e5f3d58f87f74c8.tar.gz)
-set(LUAJIT_SHA256 cbae019b5e396164eb5f0d07777b55cc03931bb944f83c61a010c053c9f5fd5b)
+# https://github.com/LuaJIT/LuaJIT/tree/v2.0
+set(LUAJIT_URL https://github.com/LuaJIT/LuaJIT/archive/61464b0a5b685489bee7b6680c0e9663f2143a84.tar.gz)
+set(LUAJIT_SHA256 033fa4ef19f559ef18a9b9fb017d0cb8be58befe05ab604e92814234910f1c68)
set(LUA_URL https://www.lua.org/ftp/lua-5.1.5.tar.gz)
set(LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333)
-# NOTE: Version must match LUAROCKS_VERSION in third-party/cmake/BuildLuarocks.cmake
set(LUAROCKS_URL https://github.com/luarocks/luarocks/archive/v2.4.4.tar.gz)
set(LUAROCKS_SHA256 9eb3d0738fd02ad8bf39bcedccac4e83e9b5fff2bcca247c3584b925b2075d9c)
diff --git a/third-party/cmake/BuildLuajit.cmake b/third-party/cmake/BuildLuajit.cmake
index e965927f4e..791da4b7df 100644
--- a/third-party/cmake/BuildLuajit.cmake
+++ b/third-party/cmake/BuildLuajit.cmake
@@ -41,7 +41,6 @@ else()
set(AMD64_ABI "")
endif()
set(INSTALLCMD_UNIX ${MAKE_PRG} CFLAGS=-fPIC
- CFLAGS+=-DLUAJIT_DISABLE_JIT
CFLAGS+=-DLUA_USE_APICHECK
CFLAGS+=-DLUA_USE_ASSERT
${AMD64_ABI}
@@ -94,7 +93,6 @@ elseif(MINGW)
endif()
BuildLuaJit(BUILD_COMMAND ${LUAJIT_MAKE_PRG} CC=${DEPS_C_COMPILER}
PREFIX=${DEPS_INSTALL_DIR}
- CFLAGS+=-DLUAJIT_DISABLE_JIT
CFLAGS+=-DLUA_USE_APICHECK
CFLAGS+=-DLUA_USE_ASSERT
CCDEBUG+=-g
diff --git a/third-party/cmake/BuildLuarocks.cmake b/third-party/cmake/BuildLuarocks.cmake
index 140c50ba0d..1f707ddd8a 100644
--- a/third-party/cmake/BuildLuarocks.cmake
+++ b/third-party/cmake/BuildLuarocks.cmake
@@ -41,9 +41,6 @@ endfunction()
# The luarocks binary location
set(LUAROCKS_BINARY ${HOSTDEPS_BIN_DIR}/luarocks)
-# NOTE: Version must match version of LuaRocks in third-party/CMakeLists.txt
-set(LUAROCKS_VERSION 2.4)
-
# Arguments for calls to 'luarocks build'
if(NOT MSVC)
# In MSVC don't pass the compiler/linker to luarocks, the bundled
@@ -61,6 +58,15 @@ if(UNIX OR (MINGW AND CMAKE_CROSSCOMPILING))
elseif(USE_BUNDLED_LUA)
list(APPEND LUAROCKS_OPTS
--with-lua=${HOSTDEPS_INSTALL_DIR})
+ else()
+ list(APPEND CMAKE_MODULE_PATH "../cmake")
+ find_package(LuaJit)
+ if(LUAJIT_FOUND)
+ list(APPEND LUAROCKS_OPTS
+ --lua-version=5.1
+ --with-lua-include=${LUAJIT_INCLUDE_DIRS}
+ --lua-suffix=jit)
+ endif()
endif()
BuildLuarocks(
@@ -80,14 +86,14 @@ elseif(MSVC OR MINGW)
/LUA ${DEPS_INSTALL_DIR}
/LIB ${DEPS_LIB_DIR}
/BIN ${DEPS_BIN_DIR}
- /INC ${DEPS_INSTALL_DIR}/include/luajit-2.0/
- /P ${DEPS_INSTALL_DIR}/${LUAROCKS_VERSION} /TREE ${DEPS_INSTALL_DIR}
+ /INC ${DEPS_INSTALL_DIR}/include/luajit-2.0
+ /P ${DEPS_INSTALL_DIR}/luarocks /TREE ${DEPS_INSTALL_DIR}
/SCRIPTS ${DEPS_BIN_DIR}
/CMOD ${DEPS_BIN_DIR}
${COMPILER_FLAG}
/LUAMOD ${DEPS_BIN_DIR}/lua)
- set(LUAROCKS_BINARY ${DEPS_INSTALL_DIR}/${LUAROCKS_VERSION}/luarocks.bat)
+ set(LUAROCKS_BINARY ${DEPS_INSTALL_DIR}/luarocks/luarocks.bat)
else()
message(FATAL_ERROR "Trying to build luarocks in an unsupported system ${CMAKE_SYSTEM_NAME}/${CMAKE_C_COMPILER_ID}")
endif()