Merge #5119 from ZyX-I/split-eval

This commit is contained in:
Justin M. Keyes 2017-03-29 23:15:07 +02:00 committed by GitHub
commit c60e409471
113 changed files with 13200 additions and 7975 deletions

View File

@ -181,11 +181,6 @@ vim.eval(str) *python-eval*
# string.atoi() to convert to
# a number.
:py tagList = vim.eval('taglist("eval_expr")')
< The latter will return a python list of python dicts, for instance:
[{'cmd': '/^eval_expr(arg, nextcmd)$/', 'static': 0, 'name':
'eval_expr', 'kind': 'f', 'filename': './src/eval.c'}]
vim.bindeval(str) *python-bindeval*
Like |python-eval|, but returns special objects described in
|python-bindeval-objects|. These python objects let you modify (|List|

66
scripts/check-includes.py Executable file
View File

@ -0,0 +1,66 @@
#!/usr/bin/env python
import sys
import re
import os
from subprocess import Popen, PIPE
from argparse import ArgumentParser
GENERATED_INCLUDE_RE = re.compile(
r'^\s*#\s*include\s*"([/a-z_0-9.]+\.generated\.h)"(\s+//.*)?$')
def main(argv):
argparser = ArgumentParser()
argparser.add_argument('--generated-includes-dir', action='append',
help='Directory where generated includes are located.')
argparser.add_argument('--file', type=open, help='File to check.')
argparser.add_argument('iwyu_args', nargs='*',
help='IWYU arguments, must go after --.')
args = argparser.parse_args(argv)
with args.file:
include_dirs = []
iwyu = Popen(['include-what-you-use', '-xc'] + args.iwyu_args + ['/dev/stdin'],
stdin=PIPE, stdout=PIPE, stderr=PIPE)
for line in args.file:
match = GENERATED_INCLUDE_RE.match(line)
if match:
for d in args.generated_includes_dir:
try:
f = open(os.path.join(d, match.group(1)))
except IOError:
continue
else:
with f:
for generated_line in f:
iwyu.stdin.write(generated_line)
break
else:
raise IOError('Failed to find {0}'.format(match.group(1)))
else:
iwyu.stdin.write(line)
iwyu.stdin.close()
out = iwyu.stdout.read()
err = iwyu.stderr.read()
ret = iwyu.wait()
if ret != 2:
print('IWYU failed with exit code {0}:'.format(ret))
print('{0} stdout {0}'.format('=' * ((80 - len(' stdout ')) // 2)))
print(out)
print('{0} stderr {0}'.format('=' * ((80 - len(' stderr ')) // 2)))
print(err)
return 1
return 0
if __name__ == '__main__':
raise SystemExit(main(sys.argv[1:]))

View File

@ -1,3 +1,3 @@
# multiqueue.h pointer arithmetic is not accepted by asan
fun:multiqueue_node_data
fun:dictwatcher_node_data
fun:tv_dict_watcher_node_data

View File

@ -2268,11 +2268,14 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
# //!< Header comment
# or they begin with multiple slashes followed by a space:
# //////// Header comment
# or they are Vim {{{ fold markers
match = (Search(r'[=/-]{4,}\s*$', line[commentend:]) or
Search(r'^/$', line[commentend:]) or
Search(r'^!< ', line[commentend:]) or
Search(r'^/< ', line[commentend:]) or
Search(r'^/+ ', line[commentend:]))
Search(r'^/+ ', line[commentend:]) or
Search(r'^(?:\{{3}|\}{3})\d*(?: |$)',
line[commentend:]))
if not match:
error(filename, linenum, 'whitespace/comments', 4,
'Should have a space between // and comment')
@ -3575,7 +3578,7 @@ def main():
if __name__ == '__main__':
main()
# vim: ts=4 sts=4 sw=4
# vim: ts=4 sts=4 sw=4 foldmarker=▶,▲
# Ignore "too complex" warnings when using pymode.
# pylama:ignore=C901

View File

@ -22,7 +22,6 @@ set(GENERATED_API_DISPATCH ${GENERATED_DIR}/api/private/dispatch_wrappers.genera
set(GENERATED_FUNCS_METADATA ${GENERATED_DIR}/api/private/funcs_metadata.generated.h)
set(GENERATED_EX_CMDS_ENUM ${GENERATED_INCLUDES_DIR}/ex_cmds_enum.generated.h)
set(GENERATED_EX_CMDS_DEFS ${GENERATED_DIR}/ex_cmds_defs.generated.h)
set(GENERATED_FUNCS_HASH_INPUT ${GENERATED_DIR}/funcs.generated.h.gperf)
set(GENERATED_FUNCS ${GENERATED_DIR}/funcs.generated.h)
set(GENERATED_EVENTS_ENUM ${GENERATED_INCLUDES_DIR}/auevents_enum.generated.h)
set(GENERATED_EVENTS_NAMES_MAP ${GENERATED_DIR}/auevents_name_map.generated.h)
@ -31,10 +30,6 @@ set(EX_CMDS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genex_cmds.lua)
set(FUNCS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/geneval.lua)
set(EVENTS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gen_events.lua)
set(OPTIONS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genoptions.lua)
set(EVENTS_LIST_FILE ${PROJECT_SOURCE_DIR}/src/nvim/auevents.lua)
set(EX_CMDS_DEFS_FILE ${PROJECT_SOURCE_DIR}/src/nvim/ex_cmds.lua)
set(EVAL_DEFS_FILE ${PROJECT_SOURCE_DIR}/src/nvim/eval.lua)
set(OPTIONS_LIST_FILE ${PROJECT_SOURCE_DIR}/src/nvim/options.lua)
set(UNICODE_TABLES_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genunicodetables.lua)
set(UNICODE_DIR ${PROJECT_SOURCE_DIR}/unicode)
file(GLOB UNICODE_FILES ${UNICODE_DIR}/*.txt)
@ -112,7 +107,7 @@ set(CONV_SOURCES
window.c)
foreach(sfile ${CONV_SOURCES})
if(NOT EXISTS "${PROJECT_SOURCE_DIR}/src/nvim/${sfile}")
if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/${sfile}")
message(FATAL_ERROR "${sfile} doesn't exist (it was added to CONV_SOURCES)")
endif()
endforeach()
@ -167,11 +162,11 @@ endfunction()
# NVIM_GENERATED_SOURCES: generated source files
# These lists must be mutually exclusive.
foreach(sfile ${NVIM_SOURCES}
"${PROJECT_SOURCE_DIR}/src/nvim/regexp_nfa.c"
"${CMAKE_CURRENT_LIST_DIR}/regexp_nfa.c"
${GENERATED_API_DISPATCH})
get_filename_component(full_d ${sfile} PATH)
file(RELATIVE_PATH d "${PROJECT_SOURCE_DIR}/src/nvim" "${full_d}")
if(${d} MATCHES "^([.][.]|auto/)")
file(RELATIVE_PATH d "${CMAKE_CURRENT_LIST_DIR}" "${full_d}")
if(${d} MATCHES "^[.][.]|auto/")
file(RELATIVE_PATH d "${GENERATED_DIR}" "${full_d}")
endif()
get_filename_component(f ${sfile} NAME)
@ -239,8 +234,8 @@ list(APPEND NVIM_GENERATED_SOURCES
add_custom_command(OUTPUT ${GENERATED_EX_CMDS_ENUM} ${GENERATED_EX_CMDS_DEFS}
COMMAND ${LUA_PRG} ${EX_CMDS_GENERATOR}
${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_INCLUDES_DIR} ${GENERATED_DIR}
DEPENDS ${EX_CMDS_GENERATOR} ${EX_CMDS_DEFS_FILE}
${CMAKE_CURRENT_LIST_DIR} ${GENERATED_INCLUDES_DIR} ${GENERATED_DIR}
DEPENDS ${EX_CMDS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/ex_cmds.lua
)
if(NOT GPERF_PRG)
@ -248,24 +243,24 @@ if(NOT GPERF_PRG)
endif()
add_custom_command(OUTPUT ${GENERATED_FUNCS} ${FUNCS_DATA}
COMMAND ${LUA_PRG} ${FUNCS_GENERATOR}
${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_DIR} ${API_METADATA} ${FUNCS_DATA}
${CMAKE_CURRENT_LIST_DIR} ${GENERATED_DIR} ${API_METADATA} ${FUNCS_DATA}
COMMAND ${GPERF_PRG}
${GENERATED_FUNCS_HASH_INPUT} --output-file=${GENERATED_FUNCS}
DEPENDS ${FUNCS_GENERATOR} ${EVAL_DEFS_FILE} ${API_METADATA}
${GENERATED_DIR}/funcs.generated.h.gperf --output-file=${GENERATED_FUNCS}
DEPENDS ${FUNCS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/eval.lua ${API_METADATA}
)
list(APPEND NVIM_GENERATED_FOR_SOURCES
"${GENERATED_FUNCS}")
add_custom_command(OUTPUT ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP}
COMMAND ${LUA_PRG} ${EVENTS_GENERATOR}
${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP}
DEPENDS ${EVENTS_GENERATOR} ${EVENTS_LIST_FILE}
${CMAKE_CURRENT_LIST_DIR} ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP}
DEPENDS ${EVENTS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/auevents.lua
)
add_custom_command(OUTPUT ${GENERATED_OPTIONS}
COMMAND ${LUA_PRG} ${OPTIONS_GENERATOR}
${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_OPTIONS}
DEPENDS ${OPTIONS_GENERATOR} ${OPTIONS_LIST_FILE}
${CMAKE_CURRENT_LIST_DIR} ${GENERATED_OPTIONS}
DEPENDS ${OPTIONS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/options.lua
)
# NVIM_GENERATED_FOR_SOURCES and NVIM_GENERATED_FOR_HEADERS must be mutually exclusive.

View File

@ -296,7 +296,7 @@ void nvim_buf_set_lines(uint64_t channel_id,
tabpage_T *save_curtab = NULL;
size_t new_len = replacement.size;
size_t old_len = (size_t)(end - start);
ssize_t extra = 0; // lines added to text, can be negative
ptrdiff_t extra = 0; // lines added to text, can be negative
char **lines = (new_len != 0) ? xcalloc(new_len, sizeof(char *)) : NULL;
for (size_t i = 0; i < new_len; i++) {
@ -342,8 +342,8 @@ void nvim_buf_set_lines(uint64_t channel_id,
}
}
if ((ssize_t)to_delete > 0) {
extra -= (ssize_t)to_delete;
if (to_delete > 0) {
extra -= (ptrdiff_t)to_delete;
}
// For as long as possible, replace the existing old_len with the
@ -395,10 +395,10 @@ void nvim_buf_set_lines(uint64_t channel_id,
mark_adjust((linenr_T)start, (linenr_T)(end - 1), MAXLNUM, extra);
}
changed_lines((linenr_T)start, 0, (linenr_T)end, extra);
changed_lines((linenr_T)start, 0, (linenr_T)end, (long)extra);
if (save_curbuf.br_buf == NULL) {
fix_cursor((linenr_T)start, (linenr_T)end, extra);
fix_cursor((linenr_T)start, (linenr_T)end, (linenr_T)extra);
}
end:

View File

@ -14,6 +14,7 @@
#include "nvim/window.h"
#include "nvim/memory.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
#include "nvim/map_defs.h"
#include "nvim/map.h"
#include "nvim/option.h"
@ -87,14 +88,13 @@ bool try_end(Error *err)
/// @param[out] err Details of an error that may have occurred
Object dict_get_value(dict_T *dict, String key, Error *err)
{
hashitem_T *hi = hash_find(&dict->dv_hashtab, (uint8_t *) key.data);
dictitem_T *const di = tv_dict_find(dict, key.data, (ptrdiff_t)key.size);
if (HASHITEM_EMPTY(hi)) {
if (di == NULL) {
api_set_error(err, Validation, _("Key not found"));
return (Object) OBJECT_INIT;
}
dictitem_T *di = dict_lookup(hi);
return vim_to_object(&di->di_tv);
}
@ -129,7 +129,7 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del,
return rv;
}
dictitem_T *di = dict_find(dict, (char_u *)key.data, (int)key.size);
dictitem_T *di = tv_dict_find(dict, key.data, (ptrdiff_t)key.size);
if (di != NULL) {
if (di->di_flags & DI_FLAGS_RO) {
@ -155,9 +155,7 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del,
rv = vim_to_object(&di->di_tv);
}
// Delete the entry
hashitem_T *hi = hash_find(&dict->dv_hashtab, di->di_key);
hash_remove(&dict->dv_hashtab, hi);
dictitem_free(di);
tv_dict_item_remove(dict, di);
}
} else {
// Update the key
@ -170,20 +168,20 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del,
if (di == NULL) {
// Need to create an entry
di = dictitem_alloc((uint8_t *) key.data);
dict_add(dict, di);
di = tv_dict_item_alloc_len(key.data, key.size);
tv_dict_add(dict, di);
} else {
// Return the old value
if (retval) {
rv = vim_to_object(&di->di_tv);
}
clear_tv(&di->di_tv);
tv_clear(&di->di_tv);
}
// Update the value
copy_tv(&tv, &di->di_tv);
tv_copy(&tv, &di->di_tv);
// Clear the temporary variable
clear_tv(&tv);
tv_clear(&tv);
}
return rv;
@ -682,20 +680,20 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
break;
case kObjectTypeArray: {
list_T *list = list_alloc();
list_T *const list = tv_list_alloc();
for (uint32_t i = 0; i < obj.data.array.size; i++) {
Object item = obj.data.array.items[i];
listitem_T *li = listitem_alloc();
listitem_T *li = tv_list_item_alloc();
if (!object_to_vim(item, &li->li_tv, err)) {
// cleanup
listitem_free(li);
list_free(list);
tv_list_item_free(li);
tv_list_free(list);
return false;
}
list_append(list, li);
tv_list_append(list, li);
}
list->lv_refcount++;
@ -705,7 +703,7 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
}
case kObjectTypeDictionary: {
dict_T *dict = dict_alloc();
dict_T *const dict = tv_dict_alloc();
for (uint32_t i = 0; i < obj.data.dictionary.size; i++) {
KeyValuePair item = obj.data.dictionary.items[i];
@ -715,20 +713,20 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
api_set_error(err, Validation,
_("Empty dictionary keys aren't allowed"));
// cleanup
dict_free(dict);
tv_dict_free(dict);
return false;
}
dictitem_T *di = dictitem_alloc((uint8_t *)key.data);
dictitem_T *const di = tv_dict_item_alloc(key.data);
if (!object_to_vim(item.value, &di->di_tv, err)) {
// cleanup
dictitem_free(di);
dict_free(dict);
tv_dict_item_free(di);
tv_dict_free(dict);
return false;
}
dict_add(dict, di);
tv_dict_add(dict, di);
}
dict->dv_refcount++;
@ -959,11 +957,7 @@ static void set_option_value_err(char *key,
{
char *errmsg;
if ((errmsg = (char *)set_option_value((uint8_t *)key,
numval,
(uint8_t *)stringval,
opt_flags)))
{
if ((errmsg = set_option_value(key, numval, stringval, opt_flags))) {
if (try_end(err)) {
return;
}

View File

@ -22,6 +22,7 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
#include "nvim/option.h"
#include "nvim/syntax.h"
#include "nvim/getchar.h"
@ -181,19 +182,20 @@ Object nvim_eval(String expr, Error *err)
Object rv = OBJECT_INIT;
// Evaluate the expression
try_start();
typval_T *expr_result = eval_expr((char_u *)expr.data, NULL);
if (!expr_result) {
api_set_error(err, Exception, _("Failed to evaluate expression"));
typval_T rettv;
if (eval0((char_u *)expr.data, &rettv, NULL, true) == FAIL) {
api_set_error(err, Exception, "Failed to evaluate expression");
}
if (!try_end(err)) {
// No errors, convert the result
rv = vim_to_object(expr_result);
rv = vim_to_object(&rettv);
}
// Free the vim object
free_tv(expr_result);
// Free the Vim object
tv_clear(&rettv);
return rv;
}
@ -237,11 +239,11 @@ Object nvim_call_function(String fname, Array args, Error *err)
if (!try_end(err)) {
rv = vim_to_object(&rettv);
}
clear_tv(&rettv);
tv_clear(&rettv);
free_vim_args:
while (i > 0) {
clear_tv(&vim_args[--i]);
tv_clear(&vim_args[--i]);
}
return rv;

View File

@ -8,9 +8,11 @@
// Definitions of various common control characters.
#define CharOrd(x) ((x) < 'a' ? (x) - 'A' : (x) - 'a')
#define CharOrdLow(x) ((x) - 'a')
#define CharOrdUp(x) ((x) - 'A')
#define CharOrd(x) ((uint8_t)(x) < 'a' \
? (uint8_t)(x) - 'A'\
: (uint8_t)(x) - 'a')
#define CharOrdLow(x) ((uint8_t)(x) - 'a')
#define CharOrdUp(x) ((uint8_t)(x) - 'A')
#define ROT13(c, a) (((((c) - (a)) + 13) % 26) + (a))
#define NUL '\000'
@ -18,15 +20,14 @@
#define BS '\010'
#define TAB '\011'
#define NL '\012'
#define NL_STR (char_u *)"\012"
#define NL_STR "\012"
#define FF '\014'
#define CAR '\015' /* CR is used by Mac OS X */
#define ESC '\033'
#define ESC_STR (char_u *)"\033"
#define ESC_STR_nc "\033"
#define ESC_STR "\033"
#define DEL 0x7f
#define DEL_STR (char_u *)"\177"
#define CSI 0x9b /* Control Sequence Introducer */
#define DEL_STR "\177"
#define CSI 0x9b // Control Sequence Introducer
#define CSI_STR "\233"
#define DCS 0x90 /* Device Control String */
#define STERM 0x9c /* String Terminator */

View File

@ -661,7 +661,7 @@ static void free_buffer(buf_T *buf)
free_buffer_stuff(buf, true);
unref_var_dict(buf->b_vars);
aubuflocal_remove(buf);
dict_unref(buf->additional_data);
tv_dict_unref(buf->additional_data);
clear_fmark(&buf->b_last_cursor);
clear_fmark(&buf->b_last_insert);
clear_fmark(&buf->b_last_change);
@ -1472,7 +1472,7 @@ static inline void buf_init_changedtick(buf_T *const buf)
{
STATIC_ASSERT(sizeof("changedtick") <= sizeof(buf->changedtick_di.di_key),
"buf->changedtick_di cannot hold large enough keys");
buf->changedtick_di = (dictitem16_T) {
buf->changedtick_di = (ChangedtickDictItem) {
.di_flags = DI_FLAGS_RO|DI_FLAGS_FIX, // Must not include DI_FLAGS_ALLOC.
.di_tv = (typval_T) {
.v_type = VAR_NUMBER,
@ -1481,7 +1481,7 @@ static inline void buf_init_changedtick(buf_T *const buf)
},
.di_key = "changedtick",
};
dict_add(buf->b_vars, (dictitem_T *)&buf->changedtick_di);
tv_dict_add(buf->b_vars, (dictitem_T *)&buf->changedtick_di);
}
/// Add a file name to the buffer list.
@ -1573,7 +1573,7 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags)
if (buf != curbuf || curbuf == NULL) {
buf = xcalloc(1, sizeof(buf_T));
// init b: variables
buf->b_vars = dict_alloc();
buf->b_vars = tv_dict_alloc();
init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE);
buf_init_changedtick(buf);
}
@ -3504,7 +3504,7 @@ int build_stl_str_hl(
curbuf = o_curbuf;
// Remove the variable we just stored
do_unlet((char_u *)"g:actual_curbuf", true);
do_unlet(S_LEN("g:actual_curbuf"), true);
// }
@ -4207,11 +4207,11 @@ void fname_expand(buf_T *buf, char_u **ffname, char_u **sfname)
#ifdef WIN32
if (!buf->b_p_bin) {
// If the file name is a shortcut file, use the file it links to.
char_u *rfname = (char_u *)os_resolve_shortcut(*ffname);
char *rfname = os_resolve_shortcut((const char *)(*ffname));
if (rfname != NULL) {
xfree(*ffname);
*ffname = rfname;
*sfname = rfname;
*ffname = (char_u *)rfname;
*sfname = (char_u *)rfname;
}
}
#endif
@ -5443,8 +5443,8 @@ void buf_open_scratch(handle_T bufnr, char *bufname)
{
(void)do_ecmd((int)bufnr, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, NULL);
(void)setfname(curbuf, (char_u *)bufname, NULL, true);
set_option_value((char_u *)"bh", 0L, (char_u *)"hide", OPT_LOCAL);
set_option_value((char_u *)"bt", 0L, (char_u *)"nofile", OPT_LOCAL);
set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL);
set_option_value("bh", 0L, "hide", OPT_LOCAL);
set_option_value("bt", 0L, "nofile", OPT_LOCAL);
set_option_value("swf", 0L, NULL, OPT_LOCAL);
RESET_BINDING(curwin);
}

View File

@ -7,6 +7,7 @@
#include "nvim/screen.h" // for StlClickRecord
#include "nvim/func_attr.h"
#include "nvim/eval.h"
#include "nvim/macros.h"
// Values for buflist_getfile()
enum getf_values {
@ -91,8 +92,8 @@ static inline void buf_set_changedtick(buf_T *const buf, const int changedtick)
static inline void buf_set_changedtick(buf_T *const buf, const int changedtick)
{
#ifndef NDEBUG
dictitem_T *const changedtick_di = dict_find(
buf->b_vars, (char_u *)"changedtick", sizeof("changedtick") - 1);
dictitem_T *const changedtick_di = tv_dict_find(
buf->b_vars, S_LEN("changedtick"));
assert(changedtick_di != NULL);
assert(changedtick_di->di_tv.v_type == VAR_NUMBER);
assert(changedtick_di->di_tv.v_lock == VAR_FIXED);

View File

@ -21,8 +21,6 @@ typedef struct {
#include "nvim/pos.h"
// for the number window-local and buffer-local options
#include "nvim/option_defs.h"
// for optional iconv support
#include "nvim/iconv.h"
// for jump list and tag stack sizes in a buffer and mark types
#include "nvim/mark_defs.h"
// for u_header_T; needs buf_T.
@ -30,7 +28,9 @@ typedef struct {
// for hashtab_T
#include "nvim/hashtab.h"
// for dict_T
#include "nvim/eval_defs.h"
#include "nvim/eval/typval.h"
// for proftime_T
#include "nvim/profile.h"
// for String
#include "nvim/api/private/defs.h"
// for Map(K, V)
@ -318,25 +318,6 @@ typedef struct {
String save_inputbuf;
} tasave_T;
/*
* Used for conversion of terminal I/O and script files.
*/
typedef struct {
int vc_type; /* zero or one of the CONV_ values */
int vc_factor; /* max. expansion factor */
# ifdef USE_ICONV
iconv_t vc_fd; /* for CONV_ICONV */
# endif
bool vc_fail; /* fail for invalid char, don't use '?' */
} vimconv_T;
#define CONV_NONE 0
#define CONV_TO_UTF8 1
#define CONV_9_TO_UTF8 2
#define CONV_TO_LATIN1 3
#define CONV_TO_LATIN9 4
#define CONV_ICONV 5
/*
* Structure used for mappings and abbreviations.
*/
@ -447,6 +428,10 @@ typedef struct {
char_u *b_syn_isk; // iskeyword option
} synblock_T;
/// Type used for changedtick_di member in buf_T
///
/// Primary exists so that literals of relevant type can be made.
typedef TV_DICTITEM_STRUCT(sizeof("changedtick")) ChangedtickDictItem;
#define BUF_HAS_QF_ENTRY 1
#define BUF_HAS_LL_ENTRY 2
@ -491,7 +476,7 @@ struct file_buffer {
// file has been changed and not written out.
/// Change identifier incremented for each change, including undo
#define b_changedtick changedtick_di.di_tv.vval.v_number
dictitem16_T changedtick_di; // b:changedtick dictionary item.
ChangedtickDictItem changedtick_di; // b:changedtick dictionary item.
bool b_saving; /* Set to true if we are in the middle of
saving the buffer. */
@ -735,8 +720,8 @@ struct file_buffer {
int b_bad_char; /* "++bad=" argument when edit started or 0 */
int b_start_bomb; /* 'bomb' when it was read */
dictitem_T b_bufvar; /* variable for "b:" Dictionary */
dict_T *b_vars; /* internal variables, local to buffer */
ScopeDictDictItem b_bufvar; ///< Variable for "b:" Dictionary.
dict_T *b_vars; ///< b: scope dictionary.
/* When a buffer is created, it starts without a swap file. b_may_swap is
* then set to indicate that a swap file may be opened later. It is reset
@ -824,9 +809,9 @@ struct tabpage_S {
buf_T *(tp_diffbuf[DB_COUNT]);
int tp_diff_invalid; ///< list of diffs is outdated
frame_T *(tp_snapshot[SNAP_COUNT]); ///< window layout snapshots
dictitem_T tp_winvar; ///< variable for "t:" Dictionary
dict_T *tp_vars; ///< internal variables, local to tab page
char_u *tp_localdir; ///< Absolute path of local CWD or NULL
ScopeDictDictItem tp_winvar; ///< Variable for "t:" Dictionary.
dict_T *tp_vars; ///< Internal variables, local to tab page.
char_u *tp_localdir; ///< Absolute path of local cwd or NULL.
};
/*
@ -1118,8 +1103,8 @@ struct window_S {
long w_scbind_pos;
dictitem_T w_winvar; /* variable for "w:" Dictionary */
dict_T *w_vars; /* internal variables, local to window */
ScopeDictDictItem w_winvar; ///< Variable for "w:" dictionary.
dict_T *w_vars; ///< Dictionary with w: variables.
int w_farsi; /* for the window dependent Farsi functions */

View File

@ -41,8 +41,10 @@ static bool chartab_initialized = false;
(buf)->b_chartab[(unsigned)(c) >> 6] |= (1ull << ((c) & 0x3f))
#define RESET_CHARTAB(buf, c) \
(buf)->b_chartab[(unsigned)(c) >> 6] &= ~(1ull << ((c) & 0x3f))
#define GET_CHARTAB_TAB(chartab, c) \
((chartab)[(unsigned)(c) >> 6] & (1ull << ((c) & 0x3f)))
#define GET_CHARTAB(buf, c) \
((buf)->b_chartab[(unsigned)(c) >> 6] & (1ull << ((c) & 0x3f)))
GET_CHARTAB_TAB((buf)->b_chartab, c)
// Table used below, see init_chartab() for an explanation
static char_u g_chartab[256];
@ -88,7 +90,6 @@ int buf_init_chartab(buf_T *buf, int global)
{
int c;
int c2;
char_u *p;
int i;
bool tilde;
bool do_isalpha;
@ -142,7 +143,8 @@ int buf_init_chartab(buf_T *buf, int global)
// Walk through the 'isident', 'iskeyword', 'isfname' and 'isprint'
// options Each option is a list of characters, character numbers or
// ranges, separated by commas, e.g.: "200-210,x,#-178,-"
for (i = global ? 0 : 3; i <= 3; ++i) {
for (i = global ? 0 : 3; i <= 3; i++) {
const char_u *p;
if (i == 0) {
// first round: 'isident'
p = p_isi;
@ -167,7 +169,7 @@ int buf_init_chartab(buf_T *buf, int global)
}
if (ascii_isdigit(*p)) {
c = getdigits_int(&p);
c = getdigits_int((char_u **)&p);
} else {
c = mb_ptr2char_adv(&p);
}
@ -177,7 +179,7 @@ int buf_init_chartab(buf_T *buf, int global)
++p;
if (ascii_isdigit(*p)) {
c2 = getdigits_int(&p);
c2 = getdigits_int((char_u **)&p);
} else {
c2 = mb_ptr2char_adv(&p);
}
@ -634,7 +636,7 @@ int char2cells(int c)
/// @param p
///
/// @return number of display cells.
int ptr2cells(char_u *p)
int ptr2cells(const char_u *p)
{
// For UTF-8 we need to look at more bytes if the first byte is >= 0x80.
if (*p >= 0x80) {
@ -776,6 +778,20 @@ bool vim_iswordc(int c)
return vim_iswordc_buf(c, curbuf);
}
/// Check that "c" is a keyword character
/// Letters and characters from 'iskeyword' option for given buffer.
/// For multi-byte characters mb_get_class() is used (builtin rules).
///
/// @param[in] c Character to check.
/// @param[in] chartab Buffer chartab.
bool vim_iswordc_tab(const int c, const uint64_t *const chartab)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
return (c >= 0x100
? (utf_class(c) >= 2)
: (c > 0 && GET_CHARTAB_TAB(chartab, c) != 0));
}
/// Check that "c" is a keyword character:
/// Letters and characters from 'iskeyword' option for given buffer.
/// For multi-byte characters mb_get_class() is used (builtin rules).
@ -785,10 +801,7 @@ bool vim_iswordc(int c)
bool vim_iswordc_buf(int c, buf_T *buf)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(2)
{
if (c >= 0x100) {
return utf_class(c) >= 2;
}
return c > 0 && c < 0x100 && GET_CHARTAB(buf, c) != 0;
return vim_iswordc_tab(c, buf->b_chartab);
}
/// Just like vim_iswordc() but uses a pointer to the (multi-byte) character.
@ -1384,7 +1397,8 @@ void getvcols(win_T *wp, pos_T *pos1, pos_T *pos2, colnr_T *left,
///
/// @return Pointer to character after the skipped whitespace.
char_u *skipwhite(const char_u *q)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
FUNC_ATTR_NONNULL_RET
{
const char_u *p = q;
while (ascii_iswhite(*p)) {
@ -1393,19 +1407,21 @@ char_u *skipwhite(const char_u *q)
return (char_u *)p;
}
/// skip over digits
/// Skip over digits
///
/// @param q
/// @param[in] q String to skip digits in.
///
/// @return Pointer to the character after the skipped digits.
char_u* skipdigits(char_u *q)
char_u *skipdigits(const char_u *q)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
FUNC_ATTR_NONNULL_RET
{
char_u *p = q;
const char_u *p = q;
while (ascii_isdigit(*p)) {
// skip to next non-digit
p++;
}
return p;
return (char_u *)p;
}
/// skip over binary digits
@ -1551,17 +1567,17 @@ int vim_tolower(int c)
return TOLOWER_LOC(c);
}
/// skiptowhite: skip over text until ' ' or '\t' or NUL.
/// Skip over text until ' ' or '\t' or NUL
///
/// @param p
/// @param[in] p Text to skip over.
///
/// @return Pointer to the next whitespace or NUL character.
char_u* skiptowhite(char_u *p)
char_u *skiptowhite(const char_u *p)
{
while (*p != ' ' && *p != '\t' && *p != NUL) {
p++;
}
return p;
return (char_u *)p;
}
/// skiptowhite_esc: Like skiptowhite(), but also skip escaped chars

View File

@ -5,6 +5,16 @@
#include "nvim/pos.h"
#include "nvim/buffer_defs.h"
/// Return the folded-case equivalent of the given character
///
/// @param[in] c Character to transform.
///
/// @return Folded variant.
#define CH_FOLD(c) \
utf_fold((sizeof(c) == sizeof(char)) \
?((int)(uint8_t)(c)) \
:((int)(c)))
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "charset.h.generated.h"
#endif

View File

@ -12,6 +12,7 @@
#include "nvim/state.h"
#include "nvim/vim.h"
#include "nvim/ascii.h"
#include "nvim/mark.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "cursor.c.generated.h"
@ -227,9 +228,10 @@ static int coladvance2(
}
}
/* prevent from moving onto a trail byte */
if (has_mbyte)
mb_adjustpos(curbuf, pos);
// Prevent from moving onto a trail byte.
if (has_mbyte) {
mark_mb_adjustpos(curbuf, pos);
}
if (col < wcol)
return FAIL;
@ -361,9 +363,10 @@ void check_cursor_col_win(win_T *win)
win->w_cursor.col = len;
} else {
win->w_cursor.col = len - 1;
/* Move the cursor to the head byte. */
if (has_mbyte)
mb_adjustpos(win->w_buffer, &win->w_cursor);
// Move the cursor to the head byte.
if (has_mbyte) {
mark_mb_adjustpos(win->w_buffer, &win->w_cursor);
}
}
} else if (win->w_cursor.col < 0) {
win->w_cursor.col = 0;

View File

@ -1586,7 +1586,7 @@ static int diff_cmp(char_u *s1, char_u *s2)
}
if ((diff_flags & DIFF_ICASE) && !(diff_flags & DIFF_IWHITE)) {
return mb_stricmp(s1, s2);
return mb_stricmp((const char *)s1, (const char *)s2);
}
// Ignore white space changes and possibly ignore case.

View File

@ -15,6 +15,7 @@
#include "nvim/cursor.h"
#include "nvim/digraph.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
#include "nvim/farsi.h"
@ -1422,7 +1423,7 @@ static void ins_ctrl_v(void)
edit_putchar('^', TRUE);
did_putchar = TRUE;
}
AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */
AppendToRedobuff(CTRL_V_STR);
add_to_showcmd_c(Ctrl_V);
@ -1976,7 +1977,6 @@ static bool ins_compl_accept_char(int c)
*/
int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int dir, int flags)
{
char_u *p;
int i, c;
int actual_len; /* Take multi-byte characters */
int actual_compl_length; /* into account. */
@ -1986,11 +1986,11 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int
int was_letter = FALSE;
if (p_ic && curbuf->b_p_inf && len > 0) {
/* Infer case of completed part. */
// Infer case of completed part.
/* Find actual length of completion. */
// Find actual length of completion.
if (has_mbyte) {
p = str;
const char_u *p = str;
actual_len = 0;
while (*p != NUL) {
mb_ptr_adv(p);
@ -2001,7 +2001,7 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int
/* Find actual length of original text. */
if (has_mbyte) {
p = compl_orig_text;
const char_u *p = compl_orig_text;
actual_compl_length = 0;
while (*p != NUL) {
mb_ptr_adv(p);
@ -2017,114 +2017,148 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int
/* Allocate wide character array for the completion and fill it. */
wca = xmalloc(actual_len * sizeof(*wca));
p = str;
for (i = 0; i < actual_len; ++i)
if (has_mbyte)
{
const char_u *p = str;
for (i = 0; i < actual_len; i++) {
if (has_mbyte) {
wca[i] = mb_ptr2char_adv(&p);
else
} else {
wca[i] = *(p++);
}
}
}
/* Rule 1: Were any chars converted to lower? */
p = compl_orig_text;
for (i = 0; i < min_len; ++i) {
if (has_mbyte)
// Rule 1: Were any chars converted to lower?
{
const char_u *p = compl_orig_text;
for (i = 0; i < min_len; i++) {
if (has_mbyte) {
c = mb_ptr2char_adv(&p);
else
} else {
c = *(p++);
}
if (vim_islower(c)) {
has_lower = TRUE;
has_lower = true;
if (vim_isupper(wca[i])) {
/* Rule 1 is satisfied. */
for (i = actual_compl_length; i < actual_len; ++i)
// Rule 1 is satisfied.
for (i = actual_compl_length; i < actual_len; i++) {
wca[i] = vim_tolower(wca[i]);
}
break;
}
}
}
}
/*
* Rule 2: No lower case, 2nd consecutive letter converted to
* upper case.
*/
if (!has_lower) {
p = compl_orig_text;
for (i = 0; i < min_len; ++i) {
if (has_mbyte)
const char_u *p = compl_orig_text;
for (i = 0; i < min_len; i++) {
if (has_mbyte) {
c = mb_ptr2char_adv(&p);
else
} else {
c = *(p++);
}
if (was_letter && vim_isupper(c) && vim_islower(wca[i])) {
/* Rule 2 is satisfied. */
for (i = actual_compl_length; i < actual_len; ++i)
// Rule 2 is satisfied.
for (i = actual_compl_length; i < actual_len; i++) {
wca[i] = vim_toupper(wca[i]);
}
break;
}
was_letter = vim_islower(c) || vim_isupper(c);
}
}
/* Copy the original case of the part we typed. */
p = compl_orig_text;
for (i = 0; i < min_len; ++i) {
if (has_mbyte)
// Copy the original case of the part we typed.
{
const char_u *p = compl_orig_text;
for (i = 0; i < min_len; i++) {
if (has_mbyte) {
c = mb_ptr2char_adv(&p);
else
} else {
c = *(p++);
if (vim_islower(c))
}
if (vim_islower(c)) {
wca[i] = vim_tolower(wca[i]);
else if (vim_isupper(c))
} else if (vim_isupper(c)) {
wca[i] = vim_toupper(wca[i]);
}
}
}
/*
* Generate encoding specific output from wide character array.
* Multi-byte characters can occupy up to five bytes more than
* ASCII characters, and we also need one byte for NUL, so stay
* six bytes away from the edge of IObuff.
*/
p = IObuff;
// Generate encoding specific output from wide character array.
// Multi-byte characters can occupy up to five bytes more than
// ASCII characters, and we also need one byte for NUL, so stay
// six bytes away from the edge of IObuff.
{
char_u *p = IObuff;
i = 0;
while (i < actual_len && (p - IObuff + 6) < IOSIZE)
if (has_mbyte)
while (i < actual_len && (p - IObuff + 6) < IOSIZE) {
if (has_mbyte) {
p += (*mb_char2bytes)(wca[i++], p);
else
} else {
*(p++) = wca[i++];
}
}
*p = NUL;
}
xfree(wca);
return ins_compl_add(IObuff, len, icase, fname, NULL, dir,
flags, FALSE);
return ins_compl_add(IObuff, len, icase, fname, NULL, true, dir, flags,
false);
}
return ins_compl_add(str, len, icase, fname, NULL, dir, flags, FALSE);
return ins_compl_add(str, len, icase, fname, NULL, false, dir, flags, false);
}
/*
* Add a match to the list of matches.
* If the given string is already in the list of completions, then return
* NOTDONE, otherwise add it to the list and return OK. If there is an error
* then FAIL is returned.
*/
static int
ins_compl_add (
char_u *str,
int len,
int icase,
char_u *fname,
char_u **cptext, /* extra text for popup menu or NULL */
int cdir,
int flags,
int adup /* accept duplicate match */
)
/// Add a match to the list of matches
///
/// @param[in] str Match to add.
/// @param[in] len Match length, -1 to use #STRLEN.
/// @param[in] icase Whether case is to be ignored.
/// @param[in] fname File name match comes from. May be NULL.
/// @param[in] cptext Extra text for popup menu. May be NULL. If not NULL,
/// must have exactly #CPT_COUNT items.
/// @param[in] cptext_allocated If true, will not copy cptext strings.
///
/// @note Will free strings in case of error.
/// cptext itself will not be freed.
/// @param[in] cdir Completion direction.
/// @param[in] adup True if duplicate matches are to be accepted.
///
/// @return NOTDONE if the given string is already in the list of completions,
/// otherwise it is added to the list and OK is returned. FAIL will be
/// returned in case of error.
static int ins_compl_add(char_u *const str, int len,
const bool icase, char_u *const fname,
char_u *const *const cptext,
const bool cptext_allocated,
const Direction cdir, int flags, const bool adup)
FUNC_ATTR_NONNULL_ARG(1)
{
compl_T *match;
int dir = (cdir == 0 ? compl_direction : cdir);
int dir = (cdir == kDirectionNotSet ? compl_direction : cdir);
os_breakcheck();
if (got_int)
#define FREE_CPTEXT(cptext, cptext_allocated) \
do { \
if (cptext_allocated) { \
for (size_t i = 0; i < CPT_COUNT; i++) { \
xfree(cptext[i]); \
} \
} \
} while (0)
if (got_int) {
FREE_CPTEXT(cptext, cptext_allocated);
return FAIL;
if (len < 0)
}
if (len < 0) {
len = (int)STRLEN(str);
}
/*
* If the same match is already present, don't add it.
@ -2134,8 +2168,10 @@ ins_compl_add (
do {
if (!(match->cp_flags & ORIGINAL_TEXT)
&& STRNCMP(match->cp_str, str, len) == 0
&& match->cp_str[len] == NUL)
&& match->cp_str[len] == NUL) {
FREE_CPTEXT(cptext, cptext_allocated);
return NOTDONE;
}
match = match->cp_next;
} while (match != NULL && match != compl_first_match);
}
@ -2166,16 +2202,26 @@ ins_compl_add (
else if (fname != NULL) {
match->cp_fname = vim_strsave(fname);
flags |= FREE_FNAME;
} else
} else {
match->cp_fname = NULL;
}
match->cp_flags = flags;
if (cptext != NULL) {
int i;
for (i = 0; i < CPT_COUNT; ++i)
if (cptext[i] != NULL && *cptext[i] != NUL)
match->cp_text[i] = vim_strsave(cptext[i]);
for (i = 0; i < CPT_COUNT; i++) {
if (cptext[i] == NULL) {
continue;
}
if (*cptext[i] != NUL) {
match->cp_text[i] = (cptext_allocated
? cptext[i]
: (char_u *)xstrdup((char *)cptext[i]));
} else if (cptext_allocated) {
xfree(cptext[i]);
}
}
}
/*
@ -2298,9 +2344,10 @@ static void ins_compl_add_matches(int num_matches, char_u **matches, int icase)
for (i = 0; i < num_matches && add_r != FAIL; i++)
if ((add_r = ins_compl_add(matches[i], -1, icase,
NULL, NULL, dir, 0, FALSE)) == OK)
/* if dir was BACKWARD then honor it just once */
NULL, NULL, false, dir, 0, false)) == OK) {
// If dir was BACKWARD then honor it just once.
dir = FORWARD;
}
FreeWild(num_matches, matches);
}
@ -2364,8 +2411,8 @@ void set_completion(colnr_T startcol, list_T *list)
/* compl_pattern doesn't need to be set */
compl_orig_text = vim_strnsave(get_cursor_line_ptr() + compl_col,
compl_length);
if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, 0,
ORIGINAL_TEXT, FALSE) != OK) {
if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, false, 0,
ORIGINAL_TEXT, false) != OK) {
return;
}
@ -2887,7 +2934,7 @@ static void ins_compl_clear(void)
compl_orig_text = NULL;
compl_enter_selects = FALSE;
// clear v:completed_item
set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc());
set_vim_var_dict(VV_COMPLETED_ITEM, tv_dict_alloc());
}
/// Check that Insert completion is active.
@ -3432,7 +3479,6 @@ expand_by_function (
{
list_T *matchlist = NULL;
dict_T *matchdict = NULL;
char_u *args[2];
char_u *funcname;
pos_T pos;
win_T *curwin_save;
@ -3443,9 +3489,8 @@ expand_by_function (
if (*funcname == NUL)
return;
/* Call 'completefunc' to obtain the list of matches. */
args[0] = (char_u *)"0";
args[1] = base;
// Call 'completefunc' to obtain the list of matches.
const char_u *const args[2] = { (char_u *)"0", base };
pos = curwin->w_cursor;
curwin_save = curwin;
@ -3461,8 +3506,8 @@ expand_by_function (
matchdict = rettv.vval.v_dict;
break;
default:
/* TODO: Give error message? */
clear_tv(&rettv);
// TODO(brammool): Give error message?
tv_clear(&rettv);
break;
}
}
@ -3484,10 +3529,12 @@ expand_by_function (
ins_compl_add_dict(matchdict);
theend:
if (matchdict != NULL)
dict_unref(matchdict);
if (matchlist != NULL)
list_unref(matchlist);
if (matchdict != NULL) {
tv_dict_unref(matchdict);
}
if (matchlist != NULL) {
tv_list_unref(matchlist);
}
}
/*
@ -3516,53 +3563,60 @@ static void ins_compl_add_dict(dict_T *dict)
dictitem_T *di_refresh;
dictitem_T *di_words;
/* Check for optional "refresh" item. */
compl_opt_refresh_always = FALSE;
di_refresh = dict_find(dict, (char_u *)"refresh", 7);
// Check for optional "refresh" item.
compl_opt_refresh_always = false;
di_refresh = tv_dict_find(dict, S_LEN("refresh"));
if (di_refresh != NULL && di_refresh->di_tv.v_type == VAR_STRING) {
char_u *v = di_refresh->di_tv.vval.v_string;
const char *v = (const char *)di_refresh->di_tv.vval.v_string;
if (v != NULL && STRCMP(v, (char_u *)"always") == 0)
compl_opt_refresh_always = TRUE;
if (v != NULL && strcmp(v, "always") == 0) {
compl_opt_refresh_always = true;
}
}
/* Add completions from a "words" list. */
di_words = dict_find(dict, (char_u *)"words", 5);
if (di_words != NULL && di_words->di_tv.v_type == VAR_LIST)
// Add completions from a "words" list.
di_words = tv_dict_find(dict, S_LEN("words"));
if (di_words != NULL && di_words->di_tv.v_type == VAR_LIST) {
ins_compl_add_list(di_words->di_tv.vval.v_list);
}
}
/*
* Add a match to the list of matches from a typeval_T.
* If the given string is already in the list of completions, then return
* NOTDONE, otherwise add it to the list and return OK. If there is an error
* then FAIL is returned.
*/
int ins_compl_add_tv(typval_T *tv, int dir)
/// Add a match to the list of matches from VimL object
///
/// @param[in] tv Object to get matches from.
/// @param[in] dir Completion direction.
///
/// @return NOTDONE if the given string is already in the list of completions,
/// otherwise it is added to the list and OK is returned. FAIL will be
/// returned in case of error.
int ins_compl_add_tv(typval_T *const tv, const Direction dir)
FUNC_ATTR_NONNULL_ALL
{
char_u *word;
int icase = FALSE;
int adup = FALSE;
int aempty = FALSE;
char_u *(cptext[CPT_COUNT]);
const char *word;
bool icase = false;
bool adup = false;
bool aempty = false;
char *(cptext[CPT_COUNT]);
if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL) {
word = get_dict_string(tv->vval.v_dict, "word", false);
cptext[CPT_ABBR] = get_dict_string(tv->vval.v_dict, "abbr", false);
cptext[CPT_MENU] = get_dict_string(tv->vval.v_dict, "menu", false);
cptext[CPT_KIND] = get_dict_string(tv->vval.v_dict, "kind", false);
cptext[CPT_INFO] = get_dict_string(tv->vval.v_dict, "info", false);
word = tv_dict_get_string(tv->vval.v_dict, "word", false);
cptext[CPT_ABBR] = tv_dict_get_string(tv->vval.v_dict, "abbr", true);
cptext[CPT_MENU] = tv_dict_get_string(tv->vval.v_dict, "menu", true);
cptext[CPT_KIND] = tv_dict_get_string(tv->vval.v_dict, "kind", true);
cptext[CPT_INFO] = tv_dict_get_string(tv->vval.v_dict, "info", true);
icase = get_dict_number(tv->vval.v_dict, "icase");
adup = get_dict_number(tv->vval.v_dict, "dup");
aempty = get_dict_number(tv->vval.v_dict, "empty");
icase = (bool)tv_dict_get_number(tv->vval.v_dict, "icase");
adup = (bool)tv_dict_get_number(tv->vval.v_dict, "dup");
aempty = (bool)tv_dict_get_number(tv->vval.v_dict, "empty");
} else {
word = get_tv_string_chk(tv);
word = (const char *)tv_get_string_chk(tv);
memset(cptext, 0, sizeof(cptext));
}
if (word == NULL || (!aempty && *word == NUL))
if (word == NULL || (!aempty && *word == NUL)) {
return FAIL;
return ins_compl_add(word, -1, icase, NULL, cptext, dir, 0, adup);
}
return ins_compl_add((char_u *)word, -1, icase, NULL,
(char_u **)cptext, true, dir, 0, adup);
}
/*
@ -3977,7 +4031,7 @@ static void ins_compl_delete(void)
// causes flicker, thus we can't do that.
changed_cline_bef_curs();
// clear v:completed_item
set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc());
set_vim_var_dict(VV_COMPLETED_ITEM, tv_dict_alloc());
}
// Insert the new text being completed.
@ -3992,17 +4046,21 @@ static void ins_compl_insert(int in_compl_func)
// Set completed item.
// { word, abbr, menu, kind, info }
dict_T *dict = dict_alloc();
dict_add_nr_str(dict, "word", 0L,
EMPTY_IF_NULL(compl_shown_match->cp_str));
dict_add_nr_str(dict, "abbr", 0L,
EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_ABBR]));
dict_add_nr_str(dict, "menu", 0L,
EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_MENU]));
dict_add_nr_str(dict, "kind", 0L,
EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_KIND]));
dict_add_nr_str(dict, "info", 0L,
EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_INFO]));
dict_T *dict = tv_dict_alloc();
tv_dict_add_str(dict, S_LEN("word"),
(const char *)EMPTY_IF_NULL(compl_shown_match->cp_str));
tv_dict_add_str(
dict, S_LEN("abbr"),
(const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_ABBR]));
tv_dict_add_str(
dict, S_LEN("menu"),
(const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_MENU]));
tv_dict_add_str(
dict, S_LEN("kind"),
(const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_KIND]));
tv_dict_add_str(
dict, S_LEN("info"),
(const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_INFO]));
set_vim_var_dict(VV_COMPLETED_ITEM, dict);
if (!in_compl_func) {
compl_curr_match = compl_shown_match;
@ -4544,7 +4602,6 @@ static int ins_complete(int c, bool enable_pum)
* Call user defined function 'completefunc' with "a:findstart"
* set to 1 to obtain the length of text to use for completion.
*/
char_u *args[2];
int col;
char_u *funcname;
pos_T pos;
@ -4563,8 +4620,7 @@ static int ins_complete(int c, bool enable_pum)
return FAIL;
}
args[0] = (char_u *)"1";
args[1] = NULL;
const char_u *const args[2] = { (char_u *)"1", NULL };
pos = curwin->w_cursor;
curwin_save = curwin;
curbuf_save = curbuf;
@ -4664,8 +4720,8 @@ static int ins_complete(int c, bool enable_pum)
/* Always add completion for the original text. */
xfree(compl_orig_text);
compl_orig_text = vim_strnsave(line + compl_col, compl_length);
if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, 0,
ORIGINAL_TEXT, FALSE) != OK) {
if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, false, 0,
ORIGINAL_TEXT, false) != OK) {
xfree(compl_pattern);
compl_pattern = NULL;
xfree(compl_orig_text);
@ -5744,16 +5800,17 @@ comp_textwidth (
*/
static void redo_literal(int c)
{
char_u buf[10];
char buf[10];
/* Only digits need special treatment. Translate them into a string of
* three digits. */
// Only digits need special treatment. Translate them into a string of
// three digits.
if (ascii_isdigit(c)) {
vim_snprintf((char *)buf, sizeof(buf), "%03d", c);
vim_snprintf(buf, sizeof(buf), "%03d", c);
AppendToRedobuff(buf);
} else
} else {
AppendCharToRedobuff(c);
}
}
// start_arrow() is called when an arrow key is used in insert mode.
// For undo/redo it resembles hitting the <ESC> key.
@ -5781,8 +5838,8 @@ static void start_arrow_common(pos_T *end_insert_pos, bool end_change)
{
if (!arrow_used && end_change) { // something has been inserted
AppendToRedobuff(ESC_STR);
stop_insert(end_insert_pos, FALSE, FALSE);
arrow_used = TRUE; /* this means we stopped the current insert */
stop_insert(end_insert_pos, false, false);
arrow_used = true; // This means we stopped the current insert.
}
check_spell_redraw();
}
@ -5839,7 +5896,7 @@ int stop_arrow(void)
vr_lines_changed = 1;
}
ResetRedobuff();
AppendToRedobuff((char_u *)"1i"); /* pretend we start an insertion */
AppendToRedobuff("1i"); // Pretend we start an insertion.
new_insert_skip = 2;
} else if (ins_need_undo) {
if (u_save_cursor() == OK)
@ -6304,12 +6361,13 @@ stuff_inserted (
}
do {
stuffReadbuff(ptr);
/* a trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^" */
if (last)
stuffReadbuff((char_u *)(last == '0'
stuffReadbuff((const char *)ptr);
// A trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^".
if (last) {
stuffReadbuff((last == '0'
? "\026\060\064\070"
: "\026^"));
}
} while (--count > 0);
if (last)
@ -7066,8 +7124,8 @@ static void ins_ctrl_g(void)
*/
static void ins_ctrl_hat(void)
{
if (map_to_exists_mode((char_u *)"", LANGMAP, FALSE)) {
/* ":lmap" mappings exists, Toggle use of ":lmap" mappings. */
if (map_to_exists_mode("", LANGMAP, false)) {
// ":lmap" mappings exists, Toggle use of ":lmap" mappings.
if (State & LANGMAP) {
curbuf->b_p_iminsert = B_IMODE_NONE;
State &= ~LANGMAP;
@ -7102,13 +7160,12 @@ static bool ins_esc(long *count, int cmdchar, bool nomove)
disabled_redraw = false;
}
if (!arrow_used) {
/*
* Don't append the ESC for "r<CR>" and "grx".
* When 'insertmode' is set only CTRL-L stops Insert mode. Needed for
* when "count" is non-zero.
*/
if (cmdchar != 'r' && cmdchar != 'v')
AppendToRedobuff(p_im ? (char_u *)"\014" : ESC_STR);
// Don't append the ESC for "r<CR>" and "grx".
// When 'insertmode' is set only CTRL-L stops Insert mode. Needed for
// when "count" is non-zero.
if (cmdchar != 'r' && cmdchar != 'v') {
AppendToRedobuff(p_im ? "\014" : ESC_STR);
}
/*
* Repeating insert may take a long time. Check for
@ -7262,7 +7319,8 @@ static bool ins_start_select(int c)
// Execute the key in (insert) Select mode.
stuffcharReadbuff(Ctrl_O);
if (mod_mask) {
char_u buf[4] = { K_SPECIAL, KS_MODIFIER, mod_mask, NUL };
const char buf[] = { (char)K_SPECIAL, (char)KS_MODIFIER,
(char)(uint8_t)mod_mask, NUL };
stuffReadbuff(buf);
}
stuffcharReadbuff(c);
@ -8070,11 +8128,11 @@ static bool ins_tab(void)
return true;
}
did_ai = FALSE;
did_si = FALSE;
can_si = FALSE;
can_si_back = FALSE;
AppendToRedobuff((char_u *)"\t");
did_ai = false;
did_si = false;
can_si = false;
can_si_back = false;
AppendToRedobuff("\t");
if (p_sta && ind) { // insert tab in indent, use "shiftwidth"
temp = get_sw_value(curbuf);
@ -8339,8 +8397,8 @@ static int ins_digraph(void)
edit_unputchar();
}
if (cc != ESC) {
AppendToRedobuff((char_u *)CTRL_V_STR);
c = getdigraph(c, cc, TRUE);
AppendToRedobuff(CTRL_V_STR);
c = getdigraph(c, cc, true);
clear_showcmd();
return c;
}
@ -8402,12 +8460,13 @@ static int ins_ctrl_ey(int tc)
if (c != NUL) {
long tw_save;
/* The character must be taken literally, insert like it
* was typed after a CTRL-V, and pretend 'textwidth'
* wasn't set. Digits, 'o' and 'x' are special after a
* CTRL-V, don't use it for these. */
if (c < 256 && !isalnum(c))
AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */
// The character must be taken literally, insert like it
// was typed after a CTRL-V, and pretend 'textwidth'
// wasn't set. Digits, 'o' and 'x' are special after a
// CTRL-V, don't use it for these.
if (c < 256 && !isalnum(c)) {
AppendToRedobuff(CTRL_V_STR);
}
tw_save = curbuf->b_p_tw;
curbuf->b_p_tw = -1;
insert_special(c, TRUE, FALSE);

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,23 @@
#ifndef NVIM_EVAL_H
#define NVIM_EVAL_H
#include "nvim/profile.h"
#include "nvim/hashtab.h" // For hashtab_T
#include "nvim/garray.h" // For garray_T
#include "nvim/buffer_defs.h" // For scid_T
#include "nvim/buffer_defs.h"
#include "nvim/ex_cmds_defs.h" // For exarg_T
#include "nvim/eval/typval.h"
#include "nvim/profile.h"
#include "nvim/garray.h"
#define COPYID_INC 2
#define COPYID_MASK (~0x1)
// All user-defined functions are found in this hashtable.
extern hashtab_T func_hashtab;
// From user function to hashitem and back.
EXTERN ufunc_T dumuf;
#define UF2HIKEY(fp) ((fp)->uf_name)
#define HIKEY2UF(p) ((ufunc_T *)(p - (dumuf.uf_name - (char_u *)&dumuf)))
#define HIKEY2UF(p) ((ufunc_T *)(p - offsetof(ufunc_T, uf_name)))
#define HI2UF(hi) HIKEY2UF((hi)->hi_key)
/// Defines for Vim variables

View File

@ -2,10 +2,11 @@
#include <msgpack.h>
#include "nvim/eval_defs.h"
#include "nvim/eval/typval.h"
#include "nvim/eval.h"
#include "nvim/eval/encode.h"
#include "nvim/ascii.h"
#include "nvim/macros.h"
#include "nvim/message.h"
#include "nvim/charset.h" // vim_str2nr
#include "nvim/lib/kvec.h"
@ -51,16 +52,16 @@ static inline void create_special_dict(typval_T *const rettv,
typval_T val)
FUNC_ATTR_NONNULL_ALL
{
dict_T *const dict = dict_alloc();
dictitem_T *const type_di = dictitem_alloc((char_u *) "_TYPE");
dict_T *const dict = tv_dict_alloc();
dictitem_T *const type_di = tv_dict_item_alloc_len(S_LEN("_TYPE"));
type_di->di_tv.v_type = VAR_LIST;
type_di->di_tv.v_lock = VAR_UNLOCKED;
type_di->di_tv.vval.v_list = (list_T *) eval_msgpack_type_lists[type];
type_di->di_tv.vval.v_list->lv_refcount++;
dict_add(dict, type_di);
dictitem_T *const val_di = dictitem_alloc((char_u *) "_VAL");
tv_dict_add(dict, type_di);
dictitem_T *const val_di = tv_dict_item_alloc_len(S_LEN("_VAL"));
val_di->di_tv = val;
dict_add(dict, val_di);
tv_dict_add(dict, val_di);
dict->dv_refcount++;
*rettv = (typval_T) {
.v_type = VAR_DICT,
@ -118,18 +119,18 @@ static inline int json_decoder_pop(ValuesStackItem obj,
if (last_container.container.vval.v_list->lv_len != 0
&& !obj.didcomma) {
EMSG2(_("E474: Expected comma before list item: %s"), val_location);
clear_tv(&obj.val);
tv_clear(&obj.val);
return FAIL;
}
assert(last_container.special_val == NULL);
listitem_T *obj_li = listitem_alloc();
listitem_T *obj_li = tv_list_item_alloc();
obj_li->li_tv = obj.val;
list_append(last_container.container.vval.v_list, obj_li);
tv_list_append(last_container.container.vval.v_list, obj_li);
} else if (last_container.stack_index == kv_size(*stack) - 2) {
if (!obj.didcolon) {
EMSG2(_("E474: Expected colon before dictionary value: %s"),
val_location);
clear_tv(&obj.val);
tv_clear(&obj.val);
return FAIL;
}
ValuesStackItem key = kv_pop(*stack);
@ -138,34 +139,35 @@ static inline int json_decoder_pop(ValuesStackItem obj,
assert(!(key.is_special_string
|| key.val.vval.v_string == NULL
|| *key.val.vval.v_string == NUL));
dictitem_T *obj_di = dictitem_alloc(key.val.vval.v_string);
clear_tv(&key.val);
if (dict_add(last_container.container.vval.v_dict, obj_di)
dictitem_T *const obj_di = tv_dict_item_alloc(
(const char *)key.val.vval.v_string);
tv_clear(&key.val);
if (tv_dict_add(last_container.container.vval.v_dict, obj_di)
== FAIL) {
assert(false);
}
obj_di->di_tv = obj.val;
} else {
list_T *const kv_pair = list_alloc();
list_append_list(last_container.special_val, kv_pair);
listitem_T *const key_li = listitem_alloc();
list_T *const kv_pair = tv_list_alloc();
tv_list_append_list(last_container.special_val, kv_pair);
listitem_T *const key_li = tv_list_item_alloc();
key_li->li_tv = key.val;
list_append(kv_pair, key_li);
listitem_T *const val_li = listitem_alloc();
tv_list_append(kv_pair, key_li);
listitem_T *const val_li = tv_list_item_alloc();
val_li->li_tv = obj.val;
list_append(kv_pair, val_li);
tv_list_append(kv_pair, val_li);
}
} else {
// Object with key only
if (!obj.is_special_string && obj.val.v_type != VAR_STRING) {
EMSG2(_("E474: Expected string key: %s"), *pp);
clear_tv(&obj.val);
tv_clear(&obj.val);
return FAIL;
} else if (!obj.didcomma
&& (last_container.special_val == NULL
&& (DICT_LEN(last_container.container.vval.v_dict) != 0))) {
EMSG2(_("E474: Expected comma before dictionary key: %s"), val_location);
clear_tv(&obj.val);
tv_clear(&obj.val);
return FAIL;
}
// Handle empty key and key represented as special dictionary
@ -173,16 +175,16 @@ static inline int json_decoder_pop(ValuesStackItem obj,
&& (obj.is_special_string
|| obj.val.vval.v_string == NULL
|| *obj.val.vval.v_string == NUL
|| dict_find(last_container.container.vval.v_dict,
obj.val.vval.v_string, -1))) {
clear_tv(&obj.val);
|| tv_dict_find(last_container.container.vval.v_dict,
(const char *)obj.val.vval.v_string, -1))) {
tv_clear(&obj.val);
// Restart
(void) kv_pop(*container_stack);
ValuesStackItem last_container_val =
kv_A(*stack, last_container.stack_index);
while (kv_size(*stack) > last_container.stack_index) {
clear_tv(&(kv_pop(*stack).val));
tv_clear(&(kv_pop(*stack).val));
}
*pp = last_container.s;
*didcomma = last_container_val.didcomma;
@ -430,7 +432,7 @@ static inline int parse_json_string(vimconv_T *const conv,
}
if (hasnul) {
typval_T obj;
list_T *const list = list_alloc();
list_T *const list = tv_list_alloc();
list->lv_refcount++;
create_special_dict(&obj, kMPString, ((typval_T) {
.v_type = VAR_LIST,
@ -439,7 +441,7 @@ static inline int parse_json_string(vimconv_T *const conv,
}));
if (encode_list_write((void *) list, str, (size_t) (str_end - str))
== -1) {
clear_tv(&obj);
tv_clear(&obj);
goto parse_json_string_fail;
}
xfree(str);
@ -806,7 +808,7 @@ json_decode_string_cycle_start:
break;
}
case '[': {
list_T *list = list_alloc();
list_T *list = tv_list_alloc();
list->lv_refcount++;
typval_T tv = {
.v_type = VAR_LIST,
@ -827,7 +829,7 @@ json_decode_string_cycle_start:
list_T *val_list = NULL;
if (next_map_special) {
next_map_special = false;
val_list = list_alloc();
val_list = tv_list_alloc();
val_list->lv_refcount++;
create_special_dict(&tv, kMPMap, ((typval_T) {
.v_type = VAR_LIST,
@ -835,7 +837,7 @@ json_decode_string_cycle_start:
.vval = { .v_list = val_list },
}));
} else {
dict_T *dict = dict_alloc();
dict_T *dict = tv_dict_alloc();
dict->dv_refcount++;
tv = (typval_T) {
.v_type = VAR_DICT,
@ -887,7 +889,7 @@ json_decode_string_after_cycle:
json_decode_string_fail:
ret = FAIL;
while (kv_size(stack)) {
clear_tv(&(kv_pop(stack).val));
tv_clear(&(kv_pop(stack).val));
}
json_decode_string_ret:
kv_destroy(stack);
@ -933,7 +935,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
.vval = { .v_number = (varnumber_T) mobj.via.u64 },
};
} else {
list_T *const list = list_alloc();
list_T *const list = tv_list_alloc();
list->lv_refcount++;
create_special_dict(rettv, kMPInteger, ((typval_T) {
.v_type = VAR_LIST,
@ -941,10 +943,10 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
.vval = { .v_list = list },
}));
uint64_t n = mobj.via.u64;
list_append_number(list, 1);
list_append_number(list, (varnumber_T) ((n >> 62) & 0x3));
list_append_number(list, (varnumber_T) ((n >> 31) & 0x7FFFFFFF));
list_append_number(list, (varnumber_T) (n & 0x7FFFFFFF));
tv_list_append_number(list, 1);
tv_list_append_number(list, (varnumber_T)((n >> 62) & 0x3));
tv_list_append_number(list, (varnumber_T)((n >> 31) & 0x7FFFFFFF));
tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF));
}
break;
}
@ -956,7 +958,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
.vval = { .v_number = (varnumber_T) mobj.via.i64 },
};
} else {
list_T *const list = list_alloc();
list_T *const list = tv_list_alloc();
list->lv_refcount++;
create_special_dict(rettv, kMPInteger, ((typval_T) {
.v_type = VAR_LIST,
@ -964,10 +966,10 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
.vval = { .v_list = list },
}));
uint64_t n = -((uint64_t)mobj.via.i64);
list_append_number(list, -1);
list_append_number(list, (varnumber_T) ((n >> 62) & 0x3));
list_append_number(list, (varnumber_T) ((n >> 31) & 0x7FFFFFFF));
list_append_number(list, (varnumber_T) (n & 0x7FFFFFFF));
tv_list_append_number(list, -1);
tv_list_append_number(list, (varnumber_T)((n >> 62) & 0x3));
tv_list_append_number(list, (varnumber_T)((n >> 31) & 0x7FFFFFFF));
tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF));
}
break;
}
@ -980,7 +982,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
break;
}
case MSGPACK_OBJECT_STR: {
list_T *const list = list_alloc();
list_T *const list = tv_list_alloc();
list->lv_refcount++;
create_special_dict(rettv, kMPString, ((typval_T) {
.v_type = VAR_LIST,
@ -1002,7 +1004,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
};
break;
}
list_T *const list = list_alloc();
list_T *const list = tv_list_alloc();
list->lv_refcount++;
create_special_dict(rettv, kMPBinary, ((typval_T) {
.v_type = VAR_LIST,
@ -1016,7 +1018,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
break;
}
case MSGPACK_OBJECT_ARRAY: {
list_T *const list = list_alloc();
list_T *const list = tv_list_alloc();
list->lv_refcount++;
*rettv = (typval_T) {
.v_type = VAR_LIST,
@ -1024,9 +1026,9 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
.vval = { .v_list = list },
};
for (size_t i = 0; i < mobj.via.array.size; i++) {
listitem_T *const li = listitem_alloc();
listitem_T *const li = tv_list_item_alloc();
li->li_tv.v_type = VAR_UNKNOWN;
list_append(list, li);
tv_list_append(list, li);
if (msgpack_to_vim(mobj.via.array.ptr[i], &li->li_tv) == FAIL) {
return FAIL;
}
@ -1042,7 +1044,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
goto msgpack_to_vim_generic_map;
}
}
dict_T *const dict = dict_alloc();
dict_T *const dict = tv_dict_alloc();
dict->dv_refcount++;
*rettv = (typval_T) {
.v_type = VAR_DICT,
@ -1055,9 +1057,9 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
memcpy(&di->di_key[0], mobj.via.map.ptr[i].key.via.str.ptr,
mobj.via.map.ptr[i].key.via.str.size);
di->di_tv.v_type = VAR_UNKNOWN;
if (dict_add(dict, di) == FAIL) {
if (tv_dict_add(dict, di) == FAIL) {
// Duplicate key: fallback to generic map
clear_tv(rettv);
tv_clear(rettv);
xfree(di);
goto msgpack_to_vim_generic_map;
}
@ -1067,7 +1069,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
}
break;
msgpack_to_vim_generic_map: {}
list_T *const list = list_alloc();
list_T *const list = tv_list_alloc();
list->lv_refcount++;
create_special_dict(rettv, kMPMap, ((typval_T) {
.v_type = VAR_LIST,
@ -1075,14 +1077,14 @@ msgpack_to_vim_generic_map: {}
.vval = { .v_list = list },
}));
for (size_t i = 0; i < mobj.via.map.size; i++) {
list_T *const kv_pair = list_alloc();
list_append_list(list, kv_pair);
listitem_T *const key_li = listitem_alloc();
list_T *const kv_pair = tv_list_alloc();
tv_list_append_list(list, kv_pair);
listitem_T *const key_li = tv_list_item_alloc();
key_li->li_tv.v_type = VAR_UNKNOWN;
list_append(kv_pair, key_li);
listitem_T *const val_li = listitem_alloc();
tv_list_append(kv_pair, key_li);
listitem_T *const val_li = tv_list_item_alloc();
val_li->li_tv.v_type = VAR_UNKNOWN;
list_append(kv_pair, val_li);
tv_list_append(kv_pair, val_li);
if (msgpack_to_vim(mobj.via.map.ptr[i].key, &key_li->li_tv) == FAIL) {
return FAIL;
}
@ -1093,11 +1095,11 @@ msgpack_to_vim_generic_map: {}
break;
}
case MSGPACK_OBJECT_EXT: {
list_T *const list = list_alloc();
list_T *const list = tv_list_alloc();
list->lv_refcount++;
list_append_number(list, mobj.via.ext.type);
list_T *const ext_val_list = list_alloc();
list_append_list(list, ext_val_list);
tv_list_append_number(list, mobj.via.ext.type);
list_T *const ext_val_list = tv_list_alloc();
tv_list_append_list(list, ext_val_list);
create_special_dict(rettv, kMPExt, ((typval_T) {
.v_type = VAR_LIST,
.v_lock = VAR_UNLOCKED,

View File

@ -5,7 +5,7 @@
#include <msgpack.h>
#include "nvim/eval_defs.h"
#include "nvim/eval/typval.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval/decode.h.generated.h"

View File

@ -13,7 +13,7 @@
#include "nvim/eval/encode.h"
#include "nvim/buffer_defs.h" // vimconv_T
#include "nvim/eval.h"
#include "nvim/eval_defs.h"
#include "nvim/eval/typval.h"
#include "nvim/garray.h"
#include "nvim/mbyte.h"
#include "nvim/message.h"
@ -45,7 +45,8 @@ const char *const encode_special_var_names[] = {
#endif
/// Msgpack callback for writing to readfile()-style list
int encode_list_write(void *data, const char *buf, size_t len)
int encode_list_write(void *const data, const char *const buf, const size_t len)
FUNC_ATTR_NONNULL_ARG(1)
{
if (len == 0) {
return 0;
@ -80,11 +81,11 @@ int encode_list_write(void *data, const char *buf, size_t len)
str = xmemdupz(line_start, line_length);
memchrsub(str, NUL, NL, line_length);
}
list_append_allocated_string(list, str);
tv_list_append_allocated_string(list, str);
line_end++;
}
if (line_end == end) {
list_append_allocated_string(list, NULL);
tv_list_append_allocated_string(list, NULL);
}
return 0;
}
@ -743,11 +744,11 @@ bool encode_check_json_key(const typval_T *const tv)
}
const dictitem_T *type_di;
const dictitem_T *val_di;
if ((type_di = dict_find((dict_T *) spdict, (char_u *) "_TYPE", -1)) == NULL
if ((type_di = tv_dict_find(spdict, S_LEN("_TYPE"))) == NULL
|| type_di->di_tv.v_type != VAR_LIST
|| (type_di->di_tv.vval.v_list != eval_msgpack_type_lists[kMPString]
&& type_di->di_tv.vval.v_list != eval_msgpack_type_lists[kMPBinary])
|| (val_di = dict_find((dict_T *) spdict, (char_u *) "_VAL", -1)) == NULL
|| (val_di = tv_dict_find(spdict, S_LEN("_VAL"))) == NULL
|| val_di->di_tv.v_type != VAR_LIST) {
return false;
}

115
src/nvim/eval/executor.c Normal file
View File

@ -0,0 +1,115 @@
#include "nvim/eval/typval.h"
#include "nvim/eval/executor.h"
#include "nvim/eval.h"
#include "nvim/message.h"
#include "nvim/vim.h"
#include "nvim/globals.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval/executor.c.generated.h"
#endif
static char *e_letwrong = N_("E734: Wrong variable type for %s=");
char *e_listidx = N_("E684: list index out of range: %" PRId64);
/// Hanle tv1 += tv2, -=, .=
///
/// @param[in,out] tv1 First operand, modified typval.
/// @param[in] tv2 Second operand.
/// @param[in] op Used operator.
///
/// @return OK or FAIL.
int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2,
const char *const op)
FUNC_ATTR_NONNULL_ALL
{
// Can't do anything with a Funcref, a Dict or special value on the right.
if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT) {
switch (tv1->v_type) {
case VAR_DICT:
case VAR_FUNC:
case VAR_PARTIAL:
case VAR_SPECIAL: {
break;
}
case VAR_LIST: {
if (*op != '+' || tv2->v_type != VAR_LIST) {
break;
}
// List += List
if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL) {
tv_list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL);
}
return OK;
}
case VAR_NUMBER:
case VAR_STRING: {
if (tv2->v_type == VAR_LIST) {
break;
}
if (*op == '+' || *op == '-') {
// nr += nr or nr -= nr
varnumber_T n = tv_get_number(tv1);
if (tv2->v_type == VAR_FLOAT) {
float_T f = n;
if (*op == '+') {
f += tv2->vval.v_float;
} else {
f -= tv2->vval.v_float;
}
tv_clear(tv1);
tv1->v_type = VAR_FLOAT;
tv1->vval.v_float = f;
} else {
if (*op == '+') {
n += tv_get_number(tv2);
} else {
n -= tv_get_number(tv2);
}
tv_clear(tv1);
tv1->v_type = VAR_NUMBER;
tv1->vval.v_number = n;
}
} else {
// str .= str
if (tv2->v_type == VAR_FLOAT) {
break;
}
const char *tvs = tv_get_string(tv1);
char numbuf[NUMBUFLEN];
char *const s = (char *)concat_str(
(const char_u *)tvs, (const char_u *)tv_get_string_buf(tv2,
numbuf));
tv_clear(tv1);
tv1->v_type = VAR_STRING;
tv1->vval.v_string = (char_u *)s;
}
return OK;
}
case VAR_FLOAT: {
if (*op == '.' || (tv2->v_type != VAR_FLOAT
&& tv2->v_type != VAR_NUMBER
&& tv2->v_type != VAR_STRING)) {
break;
}
const float_T f = (tv2->v_type == VAR_FLOAT
? tv2->vval.v_float
: tv_get_number(tv2));
if (*op == '+') {
tv1->vval.v_float += f;
} else {
tv1->vval.v_float -= f;
}
return OK;
}
case VAR_UNKNOWN: {
assert(false);
}
}
}
EMSG2(_(e_letwrong), op);
return FAIL;
}

11
src/nvim/eval/executor.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef NVIM_EVAL_EXECUTOR_H
#define NVIM_EVAL_EXECUTOR_H
#include "nvim/eval/typval.h"
extern char *e_listidx;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval/executor.h.generated.h"
#endif
#endif // NVIM_EVAL_EXECUTOR_H

11
src/nvim/eval/gc.c Normal file
View File

@ -0,0 +1,11 @@
#include "nvim/eval/typval.h"
#include "nvim/eval/gc.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval/gc.c.generated.h"
#endif
/// Head of list of all dictionaries
dict_T *gc_first_dict = NULL;
/// Head of list of all lists
list_T *gc_first_list = NULL;

12
src/nvim/eval/gc.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef NVIM_EVAL_GC_H
#define NVIM_EVAL_GC_H
#include "nvim/eval/typval.h"
extern dict_T *gc_first_dict;
extern list_T *gc_first_list;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval/gc.h.generated.h"
#endif
#endif // NVIM_EVAL_GC_H

2556
src/nvim/eval/typval.c Normal file

File diff suppressed because it is too large Load Diff

429
src/nvim/eval/typval.h Normal file
View File

@ -0,0 +1,429 @@
#ifndef NVIM_EVAL_TYPVAL_H
#define NVIM_EVAL_TYPVAL_H
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include "nvim/types.h"
#include "nvim/hashtab.h"
#include "nvim/garray.h"
#include "nvim/mbyte.h"
#include "nvim/func_attr.h"
#include "nvim/lib/queue.h"
#include "nvim/profile.h" // for proftime_T
#include "nvim/pos.h" // for linenr_T
#include "nvim/gettext.h"
#include "nvim/message.h"
/// Type used for VimL VAR_NUMBER values
typedef int varnumber_T;
/// Type used for VimL VAR_FLOAT values
typedef double float_T;
/// Maximal possible value of varnumber_T variable
#define VARNUMBER_MAX INT_MAX
/// Mimimal possible value of varnumber_T variable
#define VARNUMBER_MIN INT_MIN
#define PRIdVARNUMBER "d"
/// %d printf format specifier for varnumber_T
#define PRIdVARNUMBER "d"
typedef struct listvar_S list_T;
typedef struct dictvar_S dict_T;
typedef struct partial_S partial_T;
typedef struct ufunc ufunc_T;
typedef enum {
kCallbackNone,
kCallbackFuncref,
kCallbackPartial,
} CallbackType;
typedef struct {
union {
char_u *funcref;
partial_T *partial;
} data;
CallbackType type;
} Callback;
#define CALLBACK_NONE ((Callback){ .type = kCallbackNone })
/// Structure holding dictionary watcher
typedef struct dict_watcher {
Callback callback;
char *key_pattern;
size_t key_pattern_len;
QUEUE node;
bool busy; // prevent recursion if the dict is changed in the callback
} DictWatcher;
/// Special variable values
typedef enum {
kSpecialVarFalse, ///< v:false
kSpecialVarTrue, ///< v:true
kSpecialVarNull, ///< v:null
} SpecialVarValue;
/// Variable lock status for typval_T.v_lock
typedef enum {
VAR_UNLOCKED = 0, ///< Not locked.
VAR_LOCKED = 1, ///< User lock, can be unlocked.
VAR_FIXED = 2, ///< Locked forever.
} VarLockStatus;
/// VimL variable types, for use in typval_T.v_type
typedef enum {
VAR_UNKNOWN = 0, ///< Unknown (unspecified) value.
VAR_NUMBER, ///< Number, .v_number is used.
VAR_STRING, ///< String, .v_string is used.
VAR_FUNC, ///< Function reference, .v_string is used as function name.
VAR_LIST, ///< List, .v_list is used.
VAR_DICT, ///< Dictionary, .v_dict is used.
VAR_FLOAT, ///< Floating-point value, .v_float is used.
VAR_SPECIAL, ///< Special value (true, false, null), .v_special
///< is used.
VAR_PARTIAL, ///< Partial, .v_partial is used.
} VarType;
/// Structure that holds an internal variable value
typedef struct {
VarType v_type; ///< Variable type.
VarLockStatus v_lock; ///< Variable lock status.
union typval_vval_union {
varnumber_T v_number; ///< Number, for VAR_NUMBER.
SpecialVarValue v_special; ///< Special value, for VAR_SPECIAL.
float_T v_float; ///< Floating-point number, for VAR_FLOAT.
char_u *v_string; ///< String, for VAR_STRING and VAR_FUNC, can be NULL.
list_T *v_list; ///< List for VAR_LIST, can be NULL.
dict_T *v_dict; ///< Dictionary for VAR_DICT, can be NULL.
partial_T *v_partial; ///< Closure: function with args.
} vval; ///< Actual value.
} typval_T;
/// Values for (struct dictvar_S).dv_scope
typedef enum {
VAR_NO_SCOPE = 0, ///< Not a scope dictionary.
VAR_SCOPE = 1, ///< Scope dictionary which requires prefix (a:, v:, …).
VAR_DEF_SCOPE = 2, ///< Scope dictionary which may be accessed without prefix
///< (l:, g:).
} ScopeType;
/// Structure to hold an item of a list
typedef struct listitem_S listitem_T;
struct listitem_S {
listitem_T *li_next; ///< Next item in list.
listitem_T *li_prev; ///< Previous item in list.
typval_T li_tv; ///< Item value.
};
/// Structure used by those that are using an item in a list
typedef struct listwatch_S listwatch_T;
struct listwatch_S {
listitem_T *lw_item; ///< Item being watched.
listwatch_T *lw_next; ///< Next watcher.
};
/// Structure to hold info about a list
struct listvar_S {
listitem_T *lv_first; ///< First item, NULL if none.
listitem_T *lv_last; ///< Last item, NULL if none.
int lv_refcount; ///< Reference count.
int lv_len; ///< Number of items.
listwatch_T *lv_watch; ///< First watcher, NULL if none.
int lv_idx; ///< Index of a cached item, used for optimising repeated l[idx].
listitem_T *lv_idx_item; ///< When not NULL item at index "lv_idx".
int lv_copyID; ///< ID used by deepcopy().
list_T *lv_copylist; ///< Copied list used by deepcopy().
VarLockStatus lv_lock; ///< Zero, VAR_LOCKED, VAR_FIXED.
list_T *lv_used_next; ///< next list in used lists list.
list_T *lv_used_prev; ///< Previous list in used lists list.
};
// Static list with 10 items. Use init_static_list() to initialize.
typedef struct {
list_T sl_list; // must be first
listitem_T sl_items[10];
} staticList10_T;
// Structure to hold an item of a Dictionary.
// Also used for a variable.
// The key is copied into "di_key" to avoid an extra alloc/free for it.
struct dictitem_S {
typval_T di_tv; ///< type and value of the variable
char_u di_flags; ///< flags (only used for variable)
char_u di_key[1]; ///< key (actually longer!)
};
#define TV_DICTITEM_STRUCT(KEY_LEN) \
struct { \
typval_T di_tv; /* Structure that holds scope dictionary itself. */ \
uint8_t di_flags; /* Flags. */ \
char_u di_key[KEY_LEN]; /* Key value. */ \
}
/// Structure to hold a scope dictionary
///
/// @warning Must be compatible with dictitem_T.
///
/// For use in find_var_in_ht to pretend that it found dictionary item when it
/// finds scope dictionary.
typedef TV_DICTITEM_STRUCT(1) ScopeDictDictItem;
/// Structure to hold an item of a Dictionary
///
/// @warning Must be compatible with ScopeDictDictItem.
///
/// Also used for a variable.
typedef TV_DICTITEM_STRUCT() dictitem_T;
/// Flags for dictitem_T.di_flags
typedef enum {
DI_FLAGS_RO = 1, ///< Read-only value
DI_FLAGS_RO_SBX = 2, ///< Value, read-only in the sandbox
DI_FLAGS_FIX = 4, ///< Fixed value: cannot be :unlet or remove()d.
DI_FLAGS_LOCK = 8, ///< Locked value.
DI_FLAGS_ALLOC = 16, ///< Separately allocated.
} DictItemFlags;
/// Structure representing a Dictionary
struct dictvar_S {
VarLockStatus dv_lock; ///< Whole dictionary lock status.
ScopeType dv_scope; ///< Non-zero (#VAR_SCOPE, #VAR_DEF_SCOPE) if
///< dictionary represents a scope (i.e. g:, l: …).
int dv_refcount; ///< Reference count.
int dv_copyID; ///< ID used when recursivery traversing a value.
hashtab_T dv_hashtab; ///< Hashtab containing all items.
dict_T *dv_copydict; ///< Copied dict used by deepcopy().
dict_T *dv_used_next; ///< Next dictionary in used dictionaries list.
dict_T *dv_used_prev; ///< Previous dictionary in used dictionaries list.
QUEUE watchers; ///< Dictionary key watchers set by user code.
};
/// Type used for script ID
typedef int scid_T;
/// Format argument for scid_T
#define PRIdSCID "d"
// Structure to hold info for a function that is currently being executed.
typedef struct funccall_S funccall_T;
/// Structure to hold info for a user function.
struct ufunc {
int uf_varargs; ///< variable nr of arguments
int uf_flags;
int uf_calls; ///< nr of active calls
bool uf_cleared; ///< func_clear() was already called
garray_T uf_args; ///< arguments
garray_T uf_lines; ///< function lines
int uf_profiling; ///< true when func is being profiled
// Profiling the function as a whole.
int uf_tm_count; ///< nr of calls
proftime_T uf_tm_total; ///< time spent in function + children
proftime_T uf_tm_self; ///< time spent in function itself
proftime_T uf_tm_children; ///< time spent in children this call
// Profiling the function per line.
int *uf_tml_count; ///< nr of times line was executed
proftime_T *uf_tml_total; ///< time spent in a line + children
proftime_T *uf_tml_self; ///< time spent in a line itself
proftime_T uf_tml_start; ///< start time for current line
proftime_T uf_tml_children; ///< time spent in children for this line
proftime_T uf_tml_wait; ///< start wait time for current line
int uf_tml_idx; ///< index of line being timed; -1 if none
int uf_tml_execed; ///< line being timed was executed
scid_T uf_script_ID; ///< ID of script where function was defined,
///< used for s: variables
int uf_refcount; ///< reference count, see func_name_refcount()
funccall_T *uf_scoped; ///< l: local variables for closure
char_u uf_name[1]; ///< name of function (actually longer); can
///< start with <SNR>123_ (<SNR> is K_SPECIAL
///< KS_EXTRA KE_SNR)
};
/// Maximum number of function arguments
#define MAX_FUNC_ARGS 20
struct partial_S {
int pt_refcount; ///< Reference count.
char_u *pt_name; ///< Function name; when NULL use pt_func->name.
ufunc_T *pt_func; ///< Function pointer; when NULL lookup function with
///< pt_name.
bool pt_auto; ///< When true the partial was created by using dict.member
///< in handle_subscript().
int pt_argc; ///< Number of arguments.
typval_T *pt_argv; ///< Arguments in allocated array.
dict_T *pt_dict; ///< Dict for "self".
};
/// Structure used for explicit stack while garbage collecting hash tables
typedef struct ht_stack_S {
hashtab_T *ht;
struct ht_stack_S *prev;
} ht_stack_T;
/// Structure used for explicit stack while garbage collecting lists
typedef struct list_stack_S {
list_T *list;
struct list_stack_S *prev;
} list_stack_T;
// In a hashtab item "hi_key" points to "di_key" in a dictitem.
// This avoids adding a pointer to the hashtab item.
/// Convert a hashitem pointer to a dictitem pointer
#define TV_DICT_HI2DI(hi) \
((dictitem_T *)((hi)->hi_key - offsetof(dictitem_T, di_key)))
static inline long tv_list_len(const list_T *const l)
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
/// Get the number of items in a list
///
/// @param[in] l List to check.
static inline long tv_list_len(const list_T *const l)
{
if (l == NULL) {
return 0;
}
return l->lv_len;
}
static inline long tv_dict_len(const dict_T *const d)
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
/// Get the number of items in a Dictionary
///
/// @param[in] d Dictionary to check.
static inline long tv_dict_len(const dict_T *const d)
{
if (d == NULL) {
return 0L;
}
return (long)d->dv_hashtab.ht_used;
}
static inline bool tv_dict_is_watched(const dict_T *const d)
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
/// Check if dictionary is watched
///
/// @param[in] d Dictionary to check.
///
/// @return true if there is at least one watcher.
static inline bool tv_dict_is_watched(const dict_T *const d)
{
return d && !QUEUE_EMPTY(&d->watchers);
}
/// Initialize VimL object
///
/// Initializes to unlocked VAR_UNKNOWN object.
///
/// @param[out] tv Object to initialize.
static inline void tv_init(typval_T *const tv)
{
if (tv != NULL) {
memset(tv, 0, sizeof(*tv));
}
}
#define TV_INITIAL_VALUE \
((typval_T) { \
.v_type = VAR_UNKNOWN, \
.v_lock = VAR_UNLOCKED, \
})
/// Empty string
///
/// Needed for hack which allows not allocating empty string and still not
/// crashing when freeing it.
extern const char *const tv_empty_string;
/// Specifies that free_unref_items() function has (not) been entered
extern bool tv_in_free_unref_items;
/// Iterate over a dictionary
///
/// @param[in] d Dictionary to iterate over.
/// @param di Name of the variable with current dictitem_T entry.
/// @param code Cycle body.
#define TV_DICT_ITER(d, di, code) \
HASHTAB_ITER(&(d)->dv_hashtab, di##hi_, { \
{ \
dictitem_T *const di = TV_DICT_HI2DI(di##hi_); \
{ \
code \
} \
} \
})
static inline bool tv_get_float_chk(const typval_T *const tv,
float_T *const ret_f)
REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT;
// FIXME circular dependency, cannot import message.h.
bool emsgf(const char *const fmt, ...);
/// Get the float value
///
/// Raises an error if object is not number or floating-point.
///
/// @param[in] tv VimL object to get value from.
/// @param[out] ret_f Location where resulting float is stored.
///
/// @return true in case of success, false if tv is not a number or float.
static inline bool tv_get_float_chk(const typval_T *const tv,
float_T *const ret_f)
{
if (tv->v_type == VAR_FLOAT) {
*ret_f = tv->vval.v_float;
return true;
}
if (tv->v_type == VAR_NUMBER) {
*ret_f = (float_T)tv->vval.v_number;
return true;
}
emsgf(_("E808: Number or Float required"));
return false;
}
static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q)
REAL_FATTR_NONNULL_ALL REAL_FATTR_NONNULL_RET REAL_FATTR_PURE
REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE;
/// Compute the `DictWatcher` address from a QUEUE node.
///
/// This only exists for .asan-blacklist (ASAN doesn't handle QUEUE_DATA pointer
/// arithmetic).
static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q)
{
return QUEUE_DATA(q, DictWatcher, node);
}
static inline bool tv_is_func(const typval_T tv)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_CONST;
/// Check whether given typval_T contains a function
///
/// That is, whether it contains VAR_FUNC or VAR_PARTIAL.
///
/// @param[in] tv Typval to check.
///
/// @return True if it is a function or a partial, false otherwise.
static inline bool tv_is_func(const typval_T tv)
{
return tv.v_type == VAR_FUNC || tv.v_type == VAR_PARTIAL;
}
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval/typval.h.generated.h"
#endif
#endif // NVIM_EVAL_TYPVAL_H

View File

@ -242,7 +242,7 @@
#include <assert.h>
#include "nvim/lib/kvec.h"
#include "nvim/eval_defs.h"
#include "nvim/eval/typval.h"
#include "nvim/eval/encode.h"
#include "nvim/func_attr.h"
#include "nvim/eval/typval_encode.h"
@ -406,11 +406,11 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
const dictitem_T *val_di;
if (TYPVAL_ENCODE_ALLOW_SPECIALS
&& tv->vval.v_dict->dv_hashtab.ht_used == 2
&& (type_di = dict_find((dict_T *)tv->vval.v_dict,
(char_u *)"_TYPE", -1)) != NULL
&& (type_di = tv_dict_find((dict_T *)tv->vval.v_dict,
S_LEN("_TYPE"))) != NULL
&& type_di->di_tv.v_type == VAR_LIST
&& (val_di = dict_find((dict_T *)tv->vval.v_dict,
(char_u *)"_VAL", -1)) != NULL) {
&& (val_di = tv_dict_find((dict_T *)tv->vval.v_dict,
S_LEN("_VAL"))) != NULL) {
size_t i;
for (i = 0; i < ARRAY_SIZE(eval_msgpack_type_lists); i++) {
if (type_di->di_tv.vval.v_list == eval_msgpack_type_lists[i]) {
@ -662,7 +662,7 @@ typval_encode_stop_converting_one_item:
while (HASHITEM_EMPTY(cur_mpsv->data.d.hi)) {
cur_mpsv->data.d.hi++;
}
dictitem_T *const di = HI2DI(cur_mpsv->data.d.hi);
dictitem_T *const di = TV_DICT_HI2DI(cur_mpsv->data.d.hi);
cur_mpsv->data.d.todo--;
cur_mpsv->data.d.hi++;
TYPVAL_ENCODE_CONV_STR_STRING(NULL, &di->di_key[0],

View File

@ -11,7 +11,7 @@
#include <assert.h>
#include "nvim/lib/kvec.h"
#include "nvim/eval_defs.h"
#include "nvim/eval/typval.h"
#include "nvim/func_attr.h"
/// Type of the stack entry

View File

@ -1,286 +0,0 @@
#ifndef NVIM_EVAL_DEFS_H
#define NVIM_EVAL_DEFS_H
#include <limits.h>
#include <stddef.h>
#include <stdbool.h>
#include "nvim/hashtab.h"
#include "nvim/lib/queue.h"
#include "nvim/garray.h" // for garray_T
#include "nvim/profile.h" // for proftime_T
#include "nvim/pos.h" // for linenr_T
typedef int varnumber_T;
typedef double float_T;
#define VARNUMBER_MAX INT_MAX
#define VARNUMBER_MIN INT_MIN
typedef struct listvar_S list_T;
typedef struct dictvar_S dict_T;
typedef struct partial_S partial_T;
/// Special variable values
typedef enum {
kSpecialVarFalse, ///< v:false
kSpecialVarTrue, ///< v:true
kSpecialVarNull, ///< v:null
} SpecialVarValue;
/// Variable lock status for typval_T.v_lock
typedef enum {
VAR_UNLOCKED = 0, ///< Not locked.
VAR_LOCKED = 1, ///< User lock, can be unlocked.
VAR_FIXED = 2, ///< Locked forever.
} VarLockStatus;
/// VimL variable types, for use in typval_T.v_type
typedef enum {
VAR_UNKNOWN = 0, ///< Unknown (unspecified) value.
VAR_NUMBER, ///< Number, .v_number is used.
VAR_STRING, ///< String, .v_string is used.
VAR_FUNC, ///< Function reference, .v_string is used as function name.
VAR_LIST, ///< List, .v_list is used.
VAR_DICT, ///< Dictionary, .v_dict is used.
VAR_FLOAT, ///< Floating-point value, .v_float is used.
VAR_SPECIAL, ///< Special value (true, false, null), .v_special
///< is used.
VAR_PARTIAL, ///< Partial, .v_partial is used.
} VarType;
/// Structure that holds an internal variable value
typedef struct {
VarType v_type; ///< Variable type.
VarLockStatus v_lock; ///< Variable lock status.
union typval_vval_union {
varnumber_T v_number; ///< Number, for VAR_NUMBER.
SpecialVarValue v_special; ///< Special value, for VAR_SPECIAL.
float_T v_float; ///< Floating-point number, for VAR_FLOAT.
char_u *v_string; ///< String, for VAR_STRING and VAR_FUNC, can be NULL.
list_T *v_list; ///< List for VAR_LIST, can be NULL.
dict_T *v_dict; ///< Dictionary for VAR_DICT, can be NULL.
partial_T *v_partial; ///< Closure: function with args.
} vval; ///< Actual value.
} typval_T;
/* Values for "dv_scope". */
#define VAR_SCOPE 1 /* a:, v:, s:, etc. scope dictionaries */
#define VAR_DEF_SCOPE 2 /* l:, g: scope dictionaries: here funcrefs are not
allowed to mask existing functions */
/*
* Structure to hold an item of a list: an internal variable without a name.
*/
typedef struct listitem_S listitem_T;
struct listitem_S {
listitem_T *li_next; /* next item in list */
listitem_T *li_prev; /* previous item in list */
typval_T li_tv; /* type and value of the variable */
};
/*
* Struct used by those that are using an item in a list.
*/
typedef struct listwatch_S listwatch_T;
struct listwatch_S {
listitem_T *lw_item; /* item being watched */
listwatch_T *lw_next; /* next watcher */
};
/*
* Structure to hold info about a list.
*/
struct listvar_S {
listitem_T *lv_first; ///< First item, NULL if none.
listitem_T *lv_last; ///< Last item, NULL if none.
int lv_refcount; ///< Reference count.
int lv_len; ///< Number of items.
listwatch_T *lv_watch; ///< First watcher, NULL if none.
int lv_idx; ///< Index of a cached item, used for optimising repeated l[idx].
listitem_T *lv_idx_item; ///< When not NULL item at index "lv_idx".
int lv_copyID; ///< ID used by deepcopy().
list_T *lv_copylist; ///< Copied list used by deepcopy().
VarLockStatus lv_lock; ///< Zero, VAR_LOCKED, VAR_FIXED.
list_T *lv_used_next; ///< next list in used lists list.
list_T *lv_used_prev; ///< Previous list in used lists list.
};
// Static list with 10 items. Use init_static_list() to initialize.
typedef struct {
list_T sl_list; // must be first
listitem_T sl_items[10];
} staticList10_T;
// Structure to hold an item of a Dictionary.
// Also used for a variable.
// The key is copied into "di_key" to avoid an extra alloc/free for it.
struct dictitem_S {
typval_T di_tv; ///< type and value of the variable
char_u di_flags; ///< flags (only used for variable)
char_u di_key[1]; ///< key (actually longer!)
};
typedef struct dictitem_S dictitem_T;
/// A dictitem with a 16 character key (plus NUL)
struct dictitem16_S {
typval_T di_tv; ///< type and value of the variable
char_u di_flags; ///< flags (only used for variable)
char_u di_key[17]; ///< key
};
typedef struct dictitem16_S dictitem16_T;
#define DI_FLAGS_RO 1 // "di_flags" value: read-only variable
#define DI_FLAGS_RO_SBX 2 // "di_flags" value: read-only in the sandbox
#define DI_FLAGS_FIX 4 // "di_flags" value: fixed: no :unlet or remove()
#define DI_FLAGS_LOCK 8 // "di_flags" value: locked variable
#define DI_FLAGS_ALLOC 16 // "di_flags" value: separately allocated
/// Structure representing a Dictionary
struct dictvar_S {
VarLockStatus dv_lock; ///< Whole dictionary lock status.
char dv_scope; ///< Non-zero (#VAR_SCOPE, #VAR_DEF_SCOPE) if
///< dictionary represents a scope (i.e. g:, l: …).
int dv_refcount; ///< Reference count.
int dv_copyID; ///< ID used when recursivery traversing a value.
hashtab_T dv_hashtab; ///< Hashtab containing all items.
dict_T *dv_copydict; ///< Copied dict used by deepcopy().
dict_T *dv_used_next; ///< Next dictionary in used dictionaries list.
dict_T *dv_used_prev; ///< Previous dictionary in used dictionaries list.
QUEUE watchers; ///< Dictionary key watchers set by user code.
};
typedef int scid_T; // script ID
typedef struct funccall_S funccall_T;
// Structure to hold info for a user function.
typedef struct ufunc ufunc_T;
struct ufunc {
int uf_varargs; ///< variable nr of arguments
int uf_flags;
int uf_calls; ///< nr of active calls
bool uf_cleared; ///< func_clear() was already called
garray_T uf_args; ///< arguments
garray_T uf_lines; ///< function lines
int uf_profiling; ///< true when func is being profiled
// Profiling the function as a whole.
int uf_tm_count; ///< nr of calls
proftime_T uf_tm_total; ///< time spent in function + children
proftime_T uf_tm_self; ///< time spent in function itself
proftime_T uf_tm_children; ///< time spent in children this call
// Profiling the function per line.
int *uf_tml_count; ///< nr of times line was executed
proftime_T *uf_tml_total; ///< time spent in a line + children
proftime_T *uf_tml_self; ///< time spent in a line itself
proftime_T uf_tml_start; ///< start time for current line
proftime_T uf_tml_children; ///< time spent in children for this line
proftime_T uf_tml_wait; ///< start wait time for current line
int uf_tml_idx; ///< index of line being timed; -1 if none
int uf_tml_execed; ///< line being timed was executed
scid_T uf_script_ID; ///< ID of script where function was defined,
// used for s: variables
int uf_refcount; ///< reference count, see func_name_refcount()
funccall_T *uf_scoped; ///< l: local variables for closure
char_u uf_name[1]; ///< name of function (actually longer); can
// start with <SNR>123_ (<SNR> is K_SPECIAL
// KS_EXTRA KE_SNR)
};
/// Maximum number of function arguments
#define MAX_FUNC_ARGS 20
#define VAR_SHORT_LEN 20 // short variable name length
#define FIXVAR_CNT 12 // number of fixed variables
// structure to hold info for a function that is currently being executed.
struct funccall_S {
ufunc_T *func; ///< function being called
int linenr; ///< next line to be executed
int returned; ///< ":return" used
struct { ///< fixed variables for arguments
dictitem_T var; ///< variable (without room for name)
char_u room[VAR_SHORT_LEN]; ///< room for the name
} fixvar[FIXVAR_CNT];
dict_T l_vars; ///< l: local function variables
dictitem_T l_vars_var; ///< variable for l: scope
dict_T l_avars; ///< a: argument variables
dictitem_T l_avars_var; ///< variable for a: scope
list_T l_varlist; ///< list for a:000
listitem_T l_listitems[MAX_FUNC_ARGS]; ///< listitems for a:000
typval_T *rettv; ///< return value
linenr_T breakpoint; ///< next line with breakpoint or zero
int dbg_tick; ///< debug_tick when breakpoint was set
int level; ///< top nesting level of executed function
proftime_T prof_child; ///< time spent in a child
funccall_T *caller; ///< calling function or NULL
int fc_refcount; ///< number of user functions that reference
// this funccal
int fc_copyID; ///< for garbage collection
garray_T fc_funcs; ///< list of ufunc_T* which keep a reference
// to "func"
};
// structure used by trans_function_name()
typedef struct {
dict_T *fd_dict; ///< Dictionary used.
char_u *fd_newkey; ///< New key in "dict" in allocated memory.
dictitem_T *fd_di; ///< Dictionary item used.
} funcdict_T;
struct partial_S {
int pt_refcount; ///< Reference count.
char_u *pt_name; ///< Function name; when NULL use pt_func->name.
ufunc_T *pt_func; ///< Function pointer; when NULL lookup function
///< with pt_name.
bool pt_auto; ///< when true the partial was created for using
///< dict.member in handle_subscript().
int pt_argc; ///< Number of arguments.
typval_T *pt_argv; ///< Arguments in allocated array.
dict_T *pt_dict; ///< Dict for "self".
};
// structure used for explicit stack while garbage collecting hash tables
typedef struct ht_stack_S {
hashtab_T *ht;
struct ht_stack_S *prev;
} ht_stack_T;
// structure used for explicit stack while garbage collecting lists
typedef struct list_stack_S {
list_T *list;
struct list_stack_S *prev;
} list_stack_T;
// In a hashtab item "hi_key" points to "di_key" in a dictitem.
// This avoids adding a pointer to the hashtab item.
/// Convert a dictitem pointer to a hashitem key pointer
#define DI2HIKEY(di) ((di)->di_key)
/// Convert a hashitem key pointer to a dictitem pointer
#define HIKEY2DI(p) ((dictitem_T *)(p - offsetof(dictitem_T, di_key)))
/// Convert a hashitem value pointer to a dictitem pointer
#define HIVAL2DI(p) \
((dictitem_T *)(((char *)p) - offsetof(dictitem_T, di_tv)))
/// Convert a hashitem pointer to a dictitem pointer
#define HI2DI(hi) HIKEY2DI((hi)->hi_key)
/// Type of assert_* check being performed
typedef enum
{
ASSERT_EQUAL,
ASSERT_NOTEQUAL,
ASSERT_MATCH,
ASSERT_NOTMATCH,
ASSERT_INRANGE,
ASSERT_OTHER,
} assert_type_T;
#endif // NVIM_EVAL_DEFS_H

View File

@ -21,7 +21,7 @@ struct process {
int pid, status, refcount;
// set to the hrtime of when process_stop was called for the process.
uint64_t stopped_time;
char *cwd;
const char *cwd;
char **argv;
Stream *in, *out, *err;
process_exit_cb cb;

View File

@ -89,7 +89,10 @@ static void on_rbuffer_nonfull(RBuffer *buf, void *data)
static void alloc_cb(uv_handle_t *handle, size_t suggested, uv_buf_t *buf)
{
Stream *stream = handle->data;
buf->base = rbuffer_write_ptr(stream->buffer, &buf->len);
// `uv_buf_t.len` happens to have different size on Windows.
size_t write_count;
buf->base = rbuffer_write_ptr(stream->buffer, &write_count);
buf->len = write_count;
}
// Callback invoked by libuv after it copies the data into the buffer provided
@ -136,7 +139,10 @@ static void fread_idle_cb(uv_idle_t *handle)
uv_fs_t req;
Stream *stream = handle->data;
stream->uvbuf.base = rbuffer_write_ptr(stream->buffer, &stream->uvbuf.len);
// `uv_buf_t.len` happens to have different size on Windows.
size_t write_count;
stream->uvbuf.base = rbuffer_write_ptr(stream->buffer, &write_count);
stream->uvbuf.len = write_count;
// the offset argument to uv_fs_read is int64_t, could someone really try
// to read more than 9 quintillion (9e18) bytes?

View File

@ -1008,8 +1008,8 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out)
AppendToRedobuffLit(cmd, -1);
xfree(cmd);
AppendToRedobuff((char_u *)"\n");
bangredo = FALSE;
AppendToRedobuff("\n");
bangredo = false;
}
/*
* Add quotes around the command, for shells that need them.
@ -2958,7 +2958,7 @@ void sub_set_replacement(SubReplacementString sub)
{
xfree(old_sub.sub);
if (sub.additional_elements != old_sub.additional_elements) {
list_unref(old_sub.additional_elements);
tv_list_unref(old_sub.additional_elements);
}
old_sub = sub;
}
@ -4764,8 +4764,8 @@ void fix_help_buffer(void)
char_u *p;
char_u *rt;
/* set filetype to "help". */
set_option_value((char_u *)"ft", 0L, (char_u *)"help", OPT_LOCAL);
// Set filetype to "help".
set_option_value("ft", 0L, "help", OPT_LOCAL);
if (!syntax_present(curwin)) {
for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum) {

View File

@ -4,8 +4,8 @@
#include <stdbool.h>
#include "nvim/os/time.h"
#include "nvim/eval_defs.h"
#include "nvim/pos.h"
#include "nvim/eval/typval.h"
// flags for do_ecmd()
#define ECMD_HIDE 0x01 // don't free the current buffer

View File

@ -957,23 +957,21 @@ char_u *get_profile_name(expand_T *xp, int idx)
}
/// Handle command line completion for :profile command.
void set_context_in_profile_cmd(expand_T *xp, char_u *arg)
void set_context_in_profile_cmd(expand_T *xp, const char *arg)
{
char_u *end_subcmd;
// Default: expand subcommands.
xp->xp_context = EXPAND_PROFILE;
pexpand_what = PEXP_SUBCMD;
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
end_subcmd = skiptowhite(arg);
char_u *const end_subcmd = skiptowhite((const char_u *)arg);
if (*end_subcmd == NUL) {
return;
}
if (end_subcmd - arg == 5 && STRNCMP(arg, "start", 5) == 0) {
if ((const char *)end_subcmd - arg == 5 && strncmp(arg, "start", 5) == 0) {
xp->xp_context = EXPAND_FILES;
xp->xp_pattern = skipwhite(end_subcmd);
xp->xp_pattern = skipwhite((const char_u *)end_subcmd);
return;
}
@ -2073,9 +2071,9 @@ void ex_listdo(exarg_T *eap)
// Clear 'shm' to avoid that the file message overwrites
// any output from the command.
p_shm_save = vim_strsave(p_shm);
set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
set_option_value("shm", 0L, "", 0);
do_argfile(eap, i);
set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
set_option_value("shm", 0L, (char *)p_shm_save, 0);
xfree(p_shm_save);
}
if (curwin->w_arg_idx != i) {
@ -2138,9 +2136,9 @@ void ex_listdo(exarg_T *eap)
// Go to the next buffer. Clear 'shm' to avoid that the file
// message overwrites any output from the command.
p_shm_save = vim_strsave(p_shm);
set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
set_option_value("shm", 0L, "", 0);
goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum);
set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
set_option_value("shm", 0L, (char *)p_shm_save, 0);
xfree(p_shm_save);
// If autocommands took us elsewhere, quit here.
@ -2256,8 +2254,8 @@ void ex_compiler(exarg_T *eap)
}
do_cmdline_cmd("command -nargs=* CompilerSet setlocal <args>");
}
do_unlet((char_u *)"g:current_compiler", true);
do_unlet((char_u *)"b:current_compiler", true);
do_unlet(S_LEN("g:current_compiler"), true);
do_unlet(S_LEN("b:current_compiler"), true);
snprintf((char *)buf, bufsize, "compiler/%s.vim", eap->arg);
if (source_runtime(buf, DIP_ALL) == FAIL) {
@ -2280,7 +2278,7 @@ void ex_compiler(exarg_T *eap)
old_cur_comp);
xfree(old_cur_comp);
} else {
do_unlet((char_u *)"g:current_compiler", true);
do_unlet(S_LEN("g:current_compiler"), true);
}
}
}
@ -2496,16 +2494,16 @@ static int APP_BOTH;
static void add_pack_plugin(char_u *fname, void *cookie)
{
char_u *p4, *p3, *p2, *p1, *p;
char_u *new_rtp;
char_u *ffname = (char_u *)fix_fname((char *)fname);
char *const ffname = fix_fname((char *)fname);
if (ffname == NULL) {
return;
}
if (cookie != &APP_LOAD && strstr((char *)p_rtp, (char *)ffname) == NULL) {
if (cookie != &APP_LOAD && strstr((char *)p_rtp, ffname) == NULL) {
// directory is not yet in 'runtimepath', add it
p4 = p3 = p2 = p1 = get_past_head(ffname);
p4 = p3 = p2 = p1 = get_past_head((char_u *)ffname);
for (p = p1; *p; mb_ptr_adv(p)) {
if (vim_ispathsep_nocolon(*p)) {
p4 = p3; p3 = p2; p2 = p1; p1 = p;
@ -2521,13 +2519,13 @@ static void add_pack_plugin(char_u *fname, void *cookie)
*p4 = NUL;
// Find "ffname" in "p_rtp", ignoring '/' vs '\' differences
size_t fname_len = STRLEN(ffname);
char_u *insp = p_rtp;
size_t fname_len = strlen(ffname);
const char *insp = (const char *)p_rtp;
for (;;) {
if (vim_fnamencmp(insp, ffname, fname_len) == 0) {
if (path_fnamencmp(insp, ffname, fname_len) == 0) {
break;
}
insp = vim_strchr(insp, ',');
insp = strchr(insp, ',');
if (insp == NULL) {
break;
}
@ -2536,10 +2534,10 @@ static void add_pack_plugin(char_u *fname, void *cookie)
if (insp == NULL) {
// not found, append at the end
insp = p_rtp + STRLEN(p_rtp);
insp = (const char *)p_rtp + STRLEN(p_rtp);
} else {
// append after the matching directory.
insp += STRLEN(ffname);
insp += strlen(ffname);
while (*insp != NUL && *insp != ',') {
insp++;
}
@ -2547,31 +2545,40 @@ static void add_pack_plugin(char_u *fname, void *cookie)
*p4 = c;
// check if rtp/pack/name/start/name/after exists
char *afterdir = concat_fnames((char *)ffname, "after", true);
char *afterdir = concat_fnames(ffname, "after", true);
size_t afterlen = 0;
if (os_isdir((char_u *)afterdir)) {
afterlen = STRLEN(afterdir) + 1; // add one for comma
afterlen = strlen(afterdir) + 1; // add one for comma
}
size_t oldlen = STRLEN(p_rtp);
size_t addlen = STRLEN(ffname) + 1; // add one for comma
new_rtp = try_malloc(oldlen + addlen + afterlen + 1); // add one for NUL
const size_t oldlen = STRLEN(p_rtp);
const size_t addlen = strlen(ffname) + 1; // add one for comma
const size_t new_rtp_len = oldlen + addlen + afterlen + 1;
// add one for NUL -------------------------------------^
char *const new_rtp = try_malloc(new_rtp_len);
if (new_rtp == NULL) {
goto theend;
}
uintptr_t keep = (uintptr_t)(insp - p_rtp);
const size_t keep = (size_t)(insp - (const char *)p_rtp);
size_t new_rtp_fill = 0;
memmove(new_rtp, p_rtp, keep);
new_rtp[keep] = ',';
memmove(new_rtp + keep + 1, ffname, addlen);
new_rtp_fill += keep;
new_rtp[new_rtp_fill++] = ',';
memmove(new_rtp + new_rtp_fill, ffname, addlen);
new_rtp_fill += addlen - 1;
assert(new_rtp[new_rtp_fill] == NUL || new_rtp[new_rtp_fill] == ',');
if (p_rtp[keep] != NUL) {
memmove(new_rtp + keep + addlen, p_rtp + keep,
oldlen - keep + 1);
memmove(new_rtp + new_rtp_fill, p_rtp + keep, oldlen - keep + 1);
new_rtp_fill += oldlen - keep;
}
if (afterlen > 0) {
STRCAT(new_rtp, ",");
STRCAT(new_rtp, afterdir);
assert(new_rtp[new_rtp_fill] == NUL);
new_rtp[new_rtp_fill++] = ',';
memmove(new_rtp + new_rtp_fill, afterdir, afterlen - 1);
new_rtp_fill += afterlen - 1;
}
set_option_value((char_u *)"rtp", 0L, new_rtp, 0);
new_rtp[new_rtp_fill] = NUL;
set_option_value("rtp", 0L, new_rtp, 0);
xfree(new_rtp);
xfree(afterdir);
}
@ -2580,7 +2587,7 @@ static void add_pack_plugin(char_u *fname, void *cookie)
static const char *plugpat = "%s/plugin/**/*.vim"; // NOLINT
static const char *ftpat = "%s/ftdetect/*.vim"; // NOLINT
size_t len = STRLEN(ffname) + STRLEN(ftpat);
size_t len = strlen(ffname) + STRLEN(ftpat);
char_u *pat = try_malloc(len + 1);
if (pat == NULL) {
goto theend;
@ -3698,12 +3705,12 @@ static void script_host_execute(char *name, exarg_T *eap)
uint8_t *script = script_get(eap, eap->arg);
if (!eap->skip) {
list_T *args = list_alloc();
list_T *args = tv_list_alloc();
// script
list_append_string(args, script ? script : eap->arg, -1);
tv_list_append_string(args, (const char *)(script ? script : eap->arg), -1);
// current range
list_append_number(args, (int)eap->line1);
list_append_number(args, (int)eap->line2);
tv_list_append_number(args, (int)eap->line1);
tv_list_append_number(args, (int)eap->line2);
(void)eval_call_provider(name, "execute", args);
}
@ -3715,21 +3722,21 @@ static void script_host_execute_file(char *name, exarg_T *eap)
uint8_t buffer[MAXPATHL];
vim_FullName((char *)eap->arg, (char *)buffer, sizeof(buffer), false);
list_T *args = list_alloc();
list_T *args = tv_list_alloc();
// filename
list_append_string(args, buffer, -1);
tv_list_append_string(args, (const char *)buffer, -1);
// current range
list_append_number(args, (int)eap->line1);
list_append_number(args, (int)eap->line2);
tv_list_append_number(args, (int)eap->line1);
tv_list_append_number(args, (int)eap->line2);
(void)eval_call_provider(name, "execute_file", args);
}
static void script_host_do_range(char *name, exarg_T *eap)
{
list_T *args = list_alloc();
list_append_number(args, (int)eap->line1);
list_append_number(args, (int)eap->line2);
list_append_string(args, eap->arg, -1);
list_T *args = tv_list_alloc();
tv_list_append_number(args, (int)eap->line1);
tv_list_append_number(args, (int)eap->line2);
tv_list_append_string(args, (const char *)eap->arg, -1);
(void)eval_call_provider(name, "do_range", args);
}

View File

@ -270,7 +270,7 @@ do_exmode (
/*
* Execute a simple command line. Used for translated commands like "*".
*/
int do_cmdline_cmd(char *cmd)
int do_cmdline_cmd(const char *cmd)
{
return do_cmdline((char_u *)cmd, NULL, NULL,
DOCMD_NOWAIT|DOCMD_KEYTYPED);
@ -2633,32 +2633,27 @@ int cmd_exists(const char *const name)
* perfectly compatible with each other, but then the command line syntax
* probably won't change that much -- webb.
*/
char_u *
set_one_cmd_context (
const char * set_one_cmd_context(
expand_T *xp,
char_u *buff /* buffer for command string */
const char *buff // buffer for command string
)
{
char_u *p;
char_u *cmd, *arg;
int len = 0;
size_t len = 0;
exarg_T ea;
int compl = EXPAND_NOTHING;
int delim;
int forceit = FALSE;
int usefilter = FALSE; /* filter instead of file name */
int context = EXPAND_NOTHING;
int forceit = false;
int usefilter = false; // Filter instead of file name.
ExpandInit(xp);
xp->xp_pattern = buff;
xp->xp_context = EXPAND_COMMANDS; /* Default until we get past command */
xp->xp_pattern = (char_u *)buff;
xp->xp_context = EXPAND_COMMANDS; // Default until we get past command
ea.argt = 0;
/*
* 2. skip comment lines and leading space, colons or bars
*/
for (cmd = buff; vim_strchr((char_u *)" \t:|", *cmd) != NULL; cmd++)
;
xp->xp_pattern = cmd;
// 2. skip comment lines and leading space, colons or bars
const char *cmd;
for (cmd = buff; strchr(" \t:|", *cmd) != NULL; cmd++) {
}
xp->xp_pattern = (char_u *)cmd;
if (*cmd == NUL)
return NULL;
@ -2670,14 +2665,15 @@ set_one_cmd_context (
/*
* 3. parse a range specifier of the form: addr [,addr] [;addr] ..
*/
cmd = skip_range(cmd, &xp->xp_context);
cmd = (const char *)skip_range((const char_u *)cmd, &xp->xp_context);
/*
* 4. parse command
*/
xp->xp_pattern = cmd;
if (*cmd == NUL)
xp->xp_pattern = (char_u *)cmd;
if (*cmd == NUL) {
return NULL;
}
if (*cmd == '"') {
xp->xp_context = EXPAND_NOTHING;
return NULL;
@ -2693,6 +2689,7 @@ set_one_cmd_context (
* do accept "keepmarks", "keepalt" and "keepjumps".
* - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
*/
const char *p;
if (*cmd == 'k' && cmd[1] != 'e') {
ea.cmdidx = CMD_k;
p = cmd + 1;
@ -2715,20 +2712,21 @@ set_one_cmd_context (
}
}
// check for non-alpha command
if (p == cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL) {
if (p == cmd && strchr("@*!=><&~#", *p) != NULL) {
p++;
}
len = (int)(p - cmd);
len = (size_t)(p - cmd);
if (len == 0) {
xp->xp_context = EXPAND_UNSUCCESSFUL;
return NULL;
}
for (ea.cmdidx = (cmdidx_T)0; (int)ea.cmdidx < (int)CMD_SIZE;
ea.cmdidx = (cmdidx_T)((int)ea.cmdidx + 1))
if (STRNCMP(cmdnames[(int)ea.cmdidx].cmd_name, cmd,
(size_t)len) == 0)
ea.cmdidx = (cmdidx_T)((int)ea.cmdidx + 1)) {
if (STRNCMP(cmdnames[(int)ea.cmdidx].cmd_name, cmd, len) == 0) {
break;
}
}
if (cmd[0] >= 'A' && cmd[0] <= 'Z') {
while (ASCII_ISALNUM(*p) || *p == '*') { // Allow * wild card
@ -2745,16 +2743,15 @@ set_one_cmd_context (
return NULL;
if (ea.cmdidx == CMD_SIZE) {
if (*cmd == 's' && vim_strchr((char_u *)"cgriI", cmd[1]) != NULL) {
if (*cmd == 's' && strchr("cgriI", cmd[1]) != NULL) {
ea.cmdidx = CMD_substitute;
p = cmd + 1;
} else if (cmd[0] >= 'A' && cmd[0] <= 'Z') {
ea.cmd = cmd;
p = find_ucmd(&ea, p, NULL, xp,
&compl
);
if (p == NULL)
ea.cmdidx = CMD_SIZE; /* ambiguous user command */
ea.cmd = (char_u *)cmd;
p = (const char *)find_ucmd(&ea, (char_u *)p, NULL, xp, &context);
if (p == NULL) {
ea.cmdidx = CMD_SIZE; // Ambiguous user command.
}
}
}
if (ea.cmdidx == CMD_SIZE) {
@ -2777,16 +2774,17 @@ set_one_cmd_context (
ea.argt = cmdnames[(int)ea.cmdidx].cmd_argt;
}
arg = skipwhite(p);
const char *arg = (const char *)skipwhite((const char_u *)p);
if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update) {
if (*arg == '>') { /* append */
if (*++arg == '>')
++arg;
arg = skipwhite(arg);
} else if (*arg == '!' && ea.cmdidx == CMD_write) { /* :w !filter */
++arg;
usefilter = TRUE;
if (*arg == '>') { // Append.
if (*++arg == '>') {
arg++;
}
arg = (const char *)skipwhite((const char_u *)arg);
} else if (*arg == '!' && ea.cmdidx == CMD_write) { // :w !filter
arg++;
usefilter = true;
}
}
@ -2799,23 +2797,24 @@ set_one_cmd_context (
}
if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift) {
while (*arg == *cmd) /* allow any number of '>' or '<' */
++arg;
arg = skipwhite(arg);
while (*arg == *cmd) { // allow any number of '>' or '<'
arg++;
}
arg = (const char *)skipwhite((const char_u *)arg);
}
/* Does command allow "+command"? */
if ((ea.argt & EDITCMD) && !usefilter && *arg == '+') {
/* Check if we're in the +command */
p = arg + 1;
arg = skip_cmd_arg(arg, FALSE);
arg = (const char *)skip_cmd_arg((char_u *)arg, false);
/* Still touching the command after '+'? */
if (*arg == NUL)
return p;
/* Skip space(s) after +command to get to the real argument */
arg = skipwhite(arg);
// Skip space(s) after +command to get to the real argument.
arg = (const char *)skipwhite((const char_u *)arg);
}
/*
@ -2844,19 +2843,18 @@ set_one_cmd_context (
}
// no arguments allowed
if (!(ea.argt & EXTRA) && *arg != NUL
&& vim_strchr((char_u *)"|\"", *arg) == NULL) {
if (!(ea.argt & EXTRA) && *arg != NUL && strchr("|\"", *arg) == NULL) {
return NULL;
}
/* Find start of last argument (argument just before cursor): */
p = buff;
xp->xp_pattern = p;
len = (int)STRLEN(buff);
xp->xp_pattern = (char_u *)p;
len = strlen(buff);
while (*p && p < buff + len) {
if (*p == ' ' || *p == TAB) {
/* argument starts after a space */
xp->xp_pattern = ++p;
// Argument starts after a space.
xp->xp_pattern = (char_u *)++p;
} else {
if (*p == '\\' && *(p + 1) != NUL)
++p; /* skip over escaped character */
@ -2866,25 +2864,26 @@ set_one_cmd_context (
if (ea.argt & XFILE) {
int c;
int in_quote = FALSE;
char_u *bow = NULL; /* Beginning of word */
int in_quote = false;
const char *bow = NULL; // Beginning of word.
/*
* Allow spaces within back-quotes to count as part of the argument
* being expanded.
*/
xp->xp_pattern = skipwhite(arg);
p = xp->xp_pattern;
xp->xp_pattern = skipwhite((const char_u *)arg);
p = (const char *)xp->xp_pattern;
while (*p != NUL) {
if (has_mbyte)
c = mb_ptr2char(p);
else
c = *p;
if (c == '\\' && p[1] != NUL)
++p;
else if (c == '`') {
if (has_mbyte) {
c = mb_ptr2char((const char_u *)p);
} else {
c = (uint8_t)(*p);
}
if (c == '\\' && p[1] != NUL) {
p++;
} else if (c == '`') {
if (!in_quote) {
xp->xp_pattern = p;
xp->xp_pattern = (char_u *)p;
bow = p + 1;
}
in_quote = !in_quote;
@ -2897,22 +2896,26 @@ set_one_cmd_context (
|| ascii_iswhite(c)) {
len = 0; /* avoid getting stuck when space is in 'isfname' */
while (*p != NUL) {
if (has_mbyte)
c = mb_ptr2char(p);
else
if (has_mbyte) {
c = mb_ptr2char((const char_u *)p);
} else {
c = *p;
if (c == '`' || vim_isfilec_or_wc(c))
}
if (c == '`' || vim_isfilec_or_wc(c)) {
break;
if (has_mbyte)
len = (*mb_ptr2len)(p);
else
}
if (has_mbyte) {
len = (size_t)(*mb_ptr2len)((const char_u *)p);
} else {
len = 1;
}
mb_ptr_adv(p);
}
if (in_quote)
if (in_quote) {
bow = p;
else
xp->xp_pattern = p;
} else {
xp->xp_pattern = (char_u *)p;
}
p -= len;
}
mb_ptr_adv(p);
@ -2922,8 +2925,9 @@ set_one_cmd_context (
* If we are still inside the quotes, and we passed a space, just
* expand from there.
*/
if (bow != NULL && in_quote)
xp->xp_pattern = bow;
if (bow != NULL && in_quote) {
xp->xp_pattern = (char_u *)bow;
}
xp->xp_context = EXPAND_FILES;
/* For a shell command more chars need to be escaped. */
@ -2931,33 +2935,36 @@ set_one_cmd_context (
#ifndef BACKSLASH_IN_FILENAME
xp->xp_shell = TRUE;
#endif
/* When still after the command name expand executables. */
if (xp->xp_pattern == skipwhite(arg))
// When still after the command name expand executables.
if (xp->xp_pattern == skipwhite((const char_u *)arg)) {
xp->xp_context = EXPAND_SHELLCMD;
}
}
/* Check for environment variable */
if (*xp->xp_pattern == '$'
) {
for (p = xp->xp_pattern + 1; *p != NUL; ++p)
if (!vim_isIDc(*p))
// Check for environment variable.
if (*xp->xp_pattern == '$') {
for (p = (const char *)xp->xp_pattern + 1; *p != NUL; p++) {
if (!vim_isIDc((uint8_t)(*p))) {
break;
}
}
if (*p == NUL) {
xp->xp_context = EXPAND_ENV_VARS;
++xp->xp_pattern;
/* Avoid that the assignment uses EXPAND_FILES again. */
if (compl != EXPAND_USER_DEFINED && compl != EXPAND_USER_LIST)
compl = EXPAND_ENV_VARS;
xp->xp_pattern++;
// Avoid that the assignment uses EXPAND_FILES again.
if (context != EXPAND_USER_DEFINED && context != EXPAND_USER_LIST) {
context = EXPAND_ENV_VARS;
}
}
}
/* Check for user names */
if (*xp->xp_pattern == '~') {
for (p = xp->xp_pattern + 1; *p != NUL && *p != '/'; ++p)
;
/* Complete ~user only if it partially matches a user name.
* A full match ~user<Tab> will be replaced by user's home
* directory i.e. something like ~user<Tab> -> /home/user/ */
if (*p == NUL && p > xp->xp_pattern + 1
for (p = (const char *)xp->xp_pattern + 1; *p != NUL && *p != '/'; p++) {
}
// Complete ~user only if it partially matches a user name.
// A full match ~user<Tab> will be replaced by user's home
// directory i.e. something like ~user<Tab> -> /home/user/
if (*p == NUL && p > (const char *)xp->xp_pattern + 1
&& match_user(xp->xp_pattern + 1) == 1) {
xp->xp_context = EXPAND_USER;
++xp->xp_pattern;
@ -2987,7 +2994,7 @@ set_one_cmd_context (
break;
case CMD_help:
xp->xp_context = EXPAND_HELP;
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
break;
/* Command modifiers: return the argument.
@ -3030,13 +3037,14 @@ set_one_cmd_context (
if (*arg == NUL || !ends_excmd(*arg)) {
/* also complete "None" */
set_context_in_echohl_cmd(xp, arg);
arg = skipwhite(skiptowhite(arg));
arg = (const char *)skipwhite(skiptowhite((const char_u *)arg));
if (*arg != NUL) {
xp->xp_context = EXPAND_NOTHING;
arg = skip_regexp(arg + 1, *arg, p_magic, NULL);
arg = (const char *)skip_regexp((char_u *)arg + 1, (uint8_t)(*arg),
p_magic, NULL);
}
}
return find_nextcmd(arg);
return (const char *)find_nextcmd((char_u *)arg);
/*
* All completion for the +cmdline_compl feature goes here.
@ -3045,15 +3053,15 @@ set_one_cmd_context (
case CMD_command:
/* Check for attributes */
while (*arg == '-') {
arg++; /* Skip "-" */
p = skiptowhite(arg);
arg++; // Skip "-".
p = (const char *)skiptowhite((const char_u *)arg);
if (*p == NUL) {
/* Cursor is still in the attribute */
p = vim_strchr(arg, '=');
// Cursor is still in the attribute.
p = strchr(arg, '=');
if (p == NULL) {
/* No "=", so complete attribute names */
// No "=", so complete attribute names.
xp->xp_context = EXPAND_USER_CMD_FLAGS;
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
return NULL;
}
@ -3061,73 +3069,81 @@ set_one_cmd_context (
// their arguments as well.
if (STRNICMP(arg, "complete", p - arg) == 0) {
xp->xp_context = EXPAND_USER_COMPLETE;
xp->xp_pattern = p + 1;
xp->xp_pattern = (char_u *)p + 1;
return NULL;
} else if (STRNICMP(arg, "nargs", p - arg) == 0) {
xp->xp_context = EXPAND_USER_NARGS;
xp->xp_pattern = p + 1;
xp->xp_pattern = (char_u *)p + 1;
return NULL;
} else if (STRNICMP(arg, "addr", p - arg) == 0) {
xp->xp_context = EXPAND_USER_ADDR_TYPE;
xp->xp_pattern = p + 1;
xp->xp_pattern = (char_u *)p + 1;
return NULL;
}
return NULL;
}
arg = skipwhite(p);
arg = (const char *)skipwhite((char_u *)p);
}
/* After the attributes comes the new command name */
p = skiptowhite(arg);
// After the attributes comes the new command name.
p = (const char *)skiptowhite((const char_u *)arg);
if (*p == NUL) {
xp->xp_context = EXPAND_USER_COMMANDS;
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
break;
}
/* And finally comes a normal command */
return skipwhite(p);
// And finally comes a normal command.
return (const char *)skipwhite((const char_u *)p);
case CMD_delcommand:
xp->xp_context = EXPAND_USER_COMMANDS;
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
break;
case CMD_global:
case CMD_vglobal:
delim = *arg; /* get the delimiter */
if (delim)
++arg; /* skip delimiter if there is one */
case CMD_vglobal: {
const int delim = (uint8_t)(*arg); // Get the delimiter.
if (delim) {
arg++; // Skip delimiter if there is one.
}
while (arg[0] != NUL && arg[0] != delim) {
if (arg[0] == '\\' && arg[1] != NUL)
++arg;
++arg;
while (arg[0] != NUL && (uint8_t)arg[0] != delim) {
if (arg[0] == '\\' && arg[1] != NUL) {
arg++;
}
arg++;
}
if (arg[0] != NUL)
return arg + 1;
break;
}
case CMD_and:
case CMD_substitute:
delim = *arg;
case CMD_substitute: {
const int delim = (uint8_t)(*arg);
if (delim) {
/* skip "from" part */
++arg;
arg = skip_regexp(arg, delim, p_magic, NULL);
// Skip "from" part.
arg++;
arg = (const char *)skip_regexp((char_u *)arg, delim, p_magic, NULL);
}
/* skip "to" part */
while (arg[0] != NUL && arg[0] != delim) {
if (arg[0] == '\\' && arg[1] != NUL)
++arg;
++arg;
// Skip "to" part.
while (arg[0] != NUL && (uint8_t)arg[0] != delim) {
if (arg[0] == '\\' && arg[1] != NUL) {
arg++;
}
if (arg[0] != NUL) /* skip delimiter */
++arg;
while (arg[0] && vim_strchr((char_u *)"|\"#", arg[0]) == NULL)
++arg;
if (arg[0] != NUL)
arg++;
}
if (arg[0] != NUL) { // Skip delimiter.
arg++;
}
while (arg[0] && strchr("|\"#", arg[0]) == NULL) {
arg++;
}
if (arg[0] != NUL) {
return arg;
}
break;
}
case CMD_isearch:
case CMD_dsearch:
case CMD_ilist:
@ -3137,36 +3153,40 @@ set_one_cmd_context (
case CMD_djump:
case CMD_isplit:
case CMD_dsplit:
arg = skipwhite(skipdigits(arg)); /* skip count */
if (*arg == '/') { /* Match regexp, not just whole words */
for (++arg; *arg && *arg != '/'; arg++)
if (*arg == '\\' && arg[1] != NUL)
// Skip count.
arg = (const char *)skipwhite(skipdigits((const char_u *)arg));
if (*arg == '/') { // Match regexp, not just whole words.
for (++arg; *arg && *arg != '/'; arg++) {
if (*arg == '\\' && arg[1] != NUL) {
arg++;
}
}
if (*arg) {
arg = skipwhite(arg + 1);
arg = (const char *)skipwhite((const char_u *)arg + 1);
/* Check for trailing illegal characters */
if (*arg && vim_strchr((char_u *)"|\"\n", *arg) == NULL)
// Check for trailing illegal characters.
if (*arg && strchr("|\"\n", *arg) == NULL) {
xp->xp_context = EXPAND_NOTHING;
else
} else {
return arg;
}
}
}
break;
case CMD_autocmd:
return set_context_in_autocmd(xp, arg, FALSE);
return (const char *)set_context_in_autocmd(xp, (char_u *)arg, false);
case CMD_doautocmd:
case CMD_doautoall:
return set_context_in_autocmd(xp, arg, TRUE);
return (const char *)set_context_in_autocmd(xp, (char_u *)arg, true);
case CMD_set:
set_context_in_set_cmd(xp, arg, 0);
set_context_in_set_cmd(xp, (char_u *)arg, 0);
break;
case CMD_setglobal:
set_context_in_set_cmd(xp, arg, OPT_GLOBAL);
set_context_in_set_cmd(xp, (char_u *)arg, OPT_GLOBAL);
break;
case CMD_setlocal:
set_context_in_set_cmd(xp, arg, OPT_LOCAL);
set_context_in_set_cmd(xp, (char_u *)arg, OPT_LOCAL);
break;
case CMD_tag:
case CMD_stag:
@ -3178,15 +3198,16 @@ set_one_cmd_context (
case CMD_tjump:
case CMD_stjump:
case CMD_ptjump:
if (*p_wop != NUL)
if (*p_wop != NUL) {
xp->xp_context = EXPAND_TAGS_LISTFILES;
else
} else {
xp->xp_context = EXPAND_TAGS;
xp->xp_pattern = arg;
}
xp->xp_pattern = (char_u *)arg;
break;
case CMD_augroup:
xp->xp_context = EXPAND_AUGROUP;
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
break;
case CMD_syntax:
set_context_in_syntax_cmd(xp, arg);
@ -3203,20 +3224,21 @@ set_one_cmd_context (
case CMD_echoerr:
case CMD_call:
case CMD_return:
set_context_for_expression(xp, arg, ea.cmdidx);
set_context_for_expression(xp, (char_u *)arg, ea.cmdidx);
break;
case CMD_unlet:
while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL)
arg = xp->xp_pattern + 1;
while ((xp->xp_pattern = (char_u *)strchr(arg, ' ')) != NULL) {
arg = (const char *)xp->xp_pattern + 1;
}
xp->xp_context = EXPAND_USER_VARS;
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
break;
case CMD_function:
case CMD_delfunction:
xp->xp_context = EXPAND_USER_FUNC;
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
break;
case CMD_echohl:
@ -3231,33 +3253,37 @@ set_one_cmd_context (
set_context_in_cscope_cmd(xp, arg, ea.cmdidx);
break;
case CMD_sign:
set_context_in_sign_cmd(xp, arg);
set_context_in_sign_cmd(xp, (char_u *)arg);
break;
case CMD_bdelete:
case CMD_bwipeout:
case CMD_bunload:
while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL)
arg = xp->xp_pattern + 1;
/*FALLTHROUGH*/
while ((xp->xp_pattern = (char_u *)strchr(arg, ' ')) != NULL) {
arg = (const char *)xp->xp_pattern + 1;
}
// FALLTHROUGH
case CMD_buffer:
case CMD_sbuffer:
case CMD_checktime:
xp->xp_context = EXPAND_BUFFERS;
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
break;
case CMD_USER:
case CMD_USER_BUF:
if (compl != EXPAND_NOTHING) {
/* XFILE: file names are handled above */
if (context != EXPAND_NOTHING) {
// XFILE: file names are handled above.
if (!(ea.argt & XFILE)) {
if (compl == EXPAND_MENUS)
return set_context_in_menu_cmd(xp, cmd, arg, forceit);
if (compl == EXPAND_COMMANDS)
if (context == EXPAND_MENUS) {
return (const char *)set_context_in_menu_cmd(xp, (char_u *)cmd,
(char_u *)arg, forceit);
} else if (context == EXPAND_COMMANDS) {
return arg;
if (compl == EXPAND_MAPPINGS)
return set_context_in_map_cmd(xp, (char_u *)"map",
arg, forceit, FALSE, FALSE, CMD_map);
/* Find start of last argument. */
} else if (context == EXPAND_MAPPINGS) {
return (const char *)set_context_in_map_cmd(
xp, (char_u *)"map", (char_u *)arg, forceit, false, false,
CMD_map);
}
// Find start of last argument.
p = arg;
while (*p) {
if (*p == ' ')
@ -3267,9 +3293,9 @@ set_one_cmd_context (
++p; /* skip over escaped character */
mb_ptr_adv(p);
}
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
}
xp->xp_context = compl;
xp->xp_context = context;
}
break;
case CMD_map: case CMD_noremap:
@ -3281,8 +3307,8 @@ set_one_cmd_context (
case CMD_lmap: case CMD_lnoremap:
case CMD_smap: case CMD_snoremap:
case CMD_xmap: case CMD_xnoremap:
return set_context_in_map_cmd(xp, cmd, arg, forceit,
FALSE, FALSE, ea.cmdidx);
return (const char *)set_context_in_map_cmd(
xp, (char_u *)cmd, (char_u *)arg, forceit, false, false, ea.cmdidx);
case CMD_unmap:
case CMD_nunmap:
case CMD_vunmap:
@ -3292,18 +3318,18 @@ set_one_cmd_context (
case CMD_lunmap:
case CMD_sunmap:
case CMD_xunmap:
return set_context_in_map_cmd(xp, cmd, arg, forceit,
FALSE, TRUE, ea.cmdidx);
return (const char *)set_context_in_map_cmd(
xp, (char_u *)cmd, (char_u *)arg, forceit, false, true, ea.cmdidx);
case CMD_abbreviate: case CMD_noreabbrev:
case CMD_cabbrev: case CMD_cnoreabbrev:
case CMD_iabbrev: case CMD_inoreabbrev:
return set_context_in_map_cmd(xp, cmd, arg, forceit,
TRUE, FALSE, ea.cmdidx);
return (const char *)set_context_in_map_cmd(
xp, (char_u *)cmd, (char_u *)arg, forceit, true, false, ea.cmdidx);
case CMD_unabbreviate:
case CMD_cunabbrev:
case CMD_iunabbrev:
return set_context_in_map_cmd(xp, cmd, arg, forceit,
TRUE, TRUE, ea.cmdidx);
return (const char *)set_context_in_map_cmd(
xp, (char_u *)cmd, (char_u *)arg, forceit, true, true, ea.cmdidx);
case CMD_menu: case CMD_noremenu: case CMD_unmenu:
case CMD_amenu: case CMD_anoremenu: case CMD_aunmenu:
case CMD_nmenu: case CMD_nnoremenu: case CMD_nunmenu:
@ -3313,48 +3339,50 @@ set_one_cmd_context (
case CMD_cmenu: case CMD_cnoremenu: case CMD_cunmenu:
case CMD_tmenu: case CMD_tunmenu:
case CMD_popup: case CMD_emenu:
return set_context_in_menu_cmd(xp, cmd, arg, forceit);
return (const char *)set_context_in_menu_cmd(
xp, (char_u *)cmd, (char_u *)arg, forceit);
case CMD_colorscheme:
xp->xp_context = EXPAND_COLORS;
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
break;
case CMD_compiler:
xp->xp_context = EXPAND_COMPILER;
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
break;
case CMD_ownsyntax:
xp->xp_context = EXPAND_OWNSYNTAX;
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
break;
case CMD_setfiletype:
xp->xp_context = EXPAND_FILETYPE;
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
break;
case CMD_packadd:
xp->xp_context = EXPAND_PACKADD;
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
break;
#ifdef HAVE_WORKING_LIBINTL
case CMD_language:
p = skiptowhite(arg);
p = (const char *)skiptowhite((const char_u *)arg);
if (*p == NUL) {
xp->xp_context = EXPAND_LANGUAGE;
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
} else {
if ( STRNCMP(arg, "messages", p - arg) == 0
|| STRNCMP(arg, "ctype", p - arg) == 0
|| STRNCMP(arg, "time", p - arg) == 0) {
if (strncmp(arg, "messages", p - arg) == 0
|| strncmp(arg, "ctype", p - arg) == 0
|| strncmp(arg, "time", p - arg) == 0) {
xp->xp_context = EXPAND_LOCALES;
xp->xp_pattern = skipwhite(p);
} else
xp->xp_pattern = skipwhite((const char_u *)p);
} else {
xp->xp_context = EXPAND_NOTHING;
}
}
break;
#endif
case CMD_profile:
@ -3362,16 +3390,16 @@ set_one_cmd_context (
break;
case CMD_behave:
xp->xp_context = EXPAND_BEHAVE;
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
break;
case CMD_history:
xp->xp_context = EXPAND_HISTORY;
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
break;
case CMD_syntime:
xp->xp_context = EXPAND_SYNTIME;
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
break;
@ -3390,10 +3418,9 @@ set_one_cmd_context (
* Also skip white space and ":" characters.
* Returns the "cmd" pointer advanced to beyond the range.
*/
char_u *
skip_range (
char_u *cmd,
int *ctx /* pointer to xp_context or NULL */
char_u *skip_range(
const char_u *cmd,
int *ctx // pointer to xp_context or NULL
)
{
unsigned delim;
@ -3418,7 +3445,7 @@ skip_range (
while (*cmd == ':')
cmd = skipwhite(cmd + 1);
return cmd;
return (char_u *)cmd;
}
/*
@ -4585,14 +4612,15 @@ int ends_excmd(int c) FUNC_ATTR_CONST
* Return the next command, after the first '|' or '\n'.
* Return NULL if not found.
*/
char_u *find_nextcmd(char_u *p)
char_u *find_nextcmd(const char_u *p)
{
while (*p != '|' && *p != '\n') {
if (*p == NUL)
if (*p == NUL) {
return NULL;
++p;
}
return p + 1;
p++;
}
return (char_u *)p + 1;
}
/*
@ -6794,7 +6822,7 @@ do_exedit (
int ms = msg_scroll;
if (eap->nextcmd != NULL) {
stuffReadbuff(eap->nextcmd);
stuffReadbuff((const char *)eap->nextcmd);
eap->nextcmd = NULL;
}
@ -7724,7 +7752,7 @@ static void ex_mkrc(exarg_T *eap)
/* When using 'viewdir' may have to create the directory. */
if (using_vdir && !os_isdir(p_vdir)) {
vim_mkdir_emsg(p_vdir, 0755);
vim_mkdir_emsg((const char *)p_vdir, 0755);
}
fd = open_exfile((char_u *) fname, eap->forceit, WRITEBIN);
@ -7836,10 +7864,17 @@ static void ex_mkrc(exarg_T *eap)
xfree(viewFile);
}
int vim_mkdir_emsg(char_u *name, int prot)
/// Try creating a directory, give error message on failure
///
/// @param[in] name Directory to create.
/// @param[in] prot Directory permissions.
///
/// @return OK in case of success, FAIL otherwise.
int vim_mkdir_emsg(const char *const name, const int prot)
FUNC_ATTR_NONNULL_ALL
{
int ret;
if ((ret = os_mkdir((char *)name, prot)) != 0) {
if ((ret = os_mkdir(name, prot)) != 0) {
EMSG3(_(e_mkdir), name, os_strerror(ret));
return FAIL;
}
@ -8416,8 +8451,8 @@ eval_vars (
*usedlen = 1;
return NULL;
}
result = list_find_str(get_vim_var_list(VV_OLDFILES),
(long)i);
result = (char_u *)tv_list_find_str(get_vim_var_list(VV_OLDFILES),
i - 1);
if (result == NULL) {
*errormsg = (char_u *)"";
return NULL;
@ -9347,8 +9382,8 @@ static int ses_put_fname(FILE *fd, char_u *name, unsigned *flagp)
*p = '/';
}
/* escape special characters */
p = vim_strsave_fnameescape(sname, FALSE);
// Escape special characters.
p = (char_u *)vim_strsave_fnameescape((const char *)sname, false);
xfree(sname);
/* write the result */
@ -9483,19 +9518,19 @@ void dialog_msg(char_u *buff, char *format, char_u *fname)
static void ex_behave(exarg_T *eap)
{
if (STRCMP(eap->arg, "mswin") == 0) {
set_option_value((char_u *)"selection", 0L, (char_u *)"exclusive", 0);
set_option_value((char_u *)"selectmode", 0L, (char_u *)"mouse,key", 0);
set_option_value((char_u *)"mousemodel", 0L, (char_u *)"popup", 0);
set_option_value((char_u *)"keymodel", 0L,
(char_u *)"startsel,stopsel", 0);
set_option_value("selection", 0L, "exclusive", 0);
set_option_value("selectmode", 0L, "mouse,key", 0);
set_option_value("mousemodel", 0L, "popup", 0);
set_option_value("keymodel", 0L, "startsel,stopsel", 0);
} else if (STRCMP(eap->arg, "xterm") == 0) {
set_option_value((char_u *)"selection", 0L, (char_u *)"inclusive", 0);
set_option_value((char_u *)"selectmode", 0L, (char_u *)"", 0);
set_option_value((char_u *)"mousemodel", 0L, (char_u *)"extend", 0);
set_option_value((char_u *)"keymodel", 0L, (char_u *)"", 0);
} else
set_option_value("selection", 0L, "inclusive", 0);
set_option_value("selectmode", 0L, "", 0);
set_option_value("mousemodel", 0L, "extend", 0);
set_option_value("keymodel", 0L, "", 0);
} else {
EMSG2(_(e_invarg2), eap->arg);
}
}
/*
* Function given to ExpandGeneric() to obtain the possible arguments of the
@ -9608,8 +9643,9 @@ void filetype_maybe_enable(void)
*/
static void ex_setfiletype(exarg_T *eap)
{
if (!did_filetype)
set_option_value((char_u *)"filetype", 0L, eap->arg, OPT_LOCAL);
if (!did_filetype) {
set_option_value("filetype", 0L, (char *)eap->arg, OPT_LOCAL);
}
}
static void ex_digraphs(exarg_T *eap)
@ -9695,7 +9731,8 @@ static void ex_match(exarg_T *eap)
c = *end;
*end = NUL;
match_add(curwin, g, p + 1, 10, id, NULL, NULL);
match_add(curwin, (const char *)g, (const char *)p + 1, 10, id,
NULL, NULL);
xfree(g);
*end = c;
}

View File

@ -1,6 +1,8 @@
/*
* ex_eval.c: functions for Ex command line for the +eval feature.
*/
// TODO(ZyX-I): move to eval/executor
/// @file ex_eval.c
///
/// Functions for Ex command line for the +eval feature.
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
@ -12,6 +14,7 @@
#include "nvim/ex_eval.h"
#include "nvim/charset.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
#include "nvim/ex_cmds2.h"
#include "nvim/ex_docmd.h"
#include "nvim/message.h"
@ -19,8 +22,6 @@
#include "nvim/regexp.h"
#include "nvim/strings.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ex_eval.c.generated.h"
#endif
@ -57,12 +58,14 @@
* is an error exception.) - The macros can be defined as expressions checking
* for a variable that is allowed to be changed during execution of a script.
*/
/* Values used for the Vim release. */
# define THROW_ON_ERROR TRUE
// Values used for the Vim release.
#define THROW_ON_ERROR true
#define THROW_ON_ERROR_TRUE
# define THROW_ON_INTERRUPT TRUE
#define THROW_ON_INTERRUPT true
#define THROW_ON_INTERRUPT_TRUE
#define discard_pending_return(p) tv_free((typval_T *)(p))
/*
* When several errors appear in a row, setting "force_abort" is delayed until
@ -779,7 +782,6 @@ void report_discard_pending(int pending, void *value)
*/
void ex_if(exarg_T *eap)
{
int error;
int skip;
int result;
struct condstack *cstack = eap->cstack;
@ -800,6 +802,7 @@ void ex_if(exarg_T *eap)
1] &
CSF_ACTIVE));
bool error;
result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip);
if (!skip && !error) {
@ -844,7 +847,6 @@ void ex_endif(exarg_T *eap)
*/
void ex_else(exarg_T *eap)
{
int error;
int skip;
int result;
struct condstack *cstack = eap->cstack;
@ -901,6 +903,7 @@ void ex_else(exarg_T *eap)
}
if (eap->cmdidx == CMD_elseif) {
bool error;
result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip);
/* When throwing error exceptions, we want to throw always the first
* of several errors in a row. This is what actually happens when
@ -925,7 +928,7 @@ void ex_else(exarg_T *eap)
*/
void ex_while(exarg_T *eap)
{
int error;
bool error;
int skip;
int result;
struct condstack *cstack = eap->cstack;
@ -1147,25 +1150,27 @@ void ex_endwhile(exarg_T *eap)
*/
void ex_throw(exarg_T *eap)
{
char_u *arg = eap->arg;
char_u *value;
const char *arg = (const char *)eap->arg;
char *value;
if (*arg != NUL && *arg != '|' && *arg != '\n')
value = eval_to_string_skip(arg, &eap->nextcmd, eap->skip);
else {
if (*arg != NUL && *arg != '|' && *arg != '\n') {
value = eval_to_string_skip(arg, (const char **)&eap->nextcmd,
(bool)eap->skip);
} else {
EMSG(_(e_argreq));
value = NULL;
}
/* On error or when an exception is thrown during argument evaluation, do
* not throw. */
// On error or when an exception is thrown during argument evaluation, do
// not throw.
if (!eap->skip && value != NULL) {
if (throw_exception(value, ET_USER, NULL) == FAIL)
if (throw_exception((char_u *)value, ET_USER, NULL) == FAIL) {
xfree(value);
else
} else {
do_throw(eap->cstack);
}
}
}
/*
* Throw the current exception through the specified cstack. Common routine

View File

@ -8,6 +8,7 @@
#include <stdlib.h>
#include <inttypes.h>
#include "nvim/assert.h"
#include "nvim/vim.h"
#include "nvim/ascii.h"
#include "nvim/arabic.h"
@ -578,7 +579,7 @@ static int command_line_execute(VimState *state, int key)
}
if (vim_ispathsep(ccline.cmdbuff[s->j])
#ifdef BACKSLASH_IN_FILENAME
&& vim_strchr(" *?[{`$%#", ccline.cmdbuff[s->j + 1])
&& strchr(" *?[{`$%#", ccline.cmdbuff[s->j + 1])
== NULL
#endif
) {
@ -960,7 +961,7 @@ static int command_line_handle_key(CommandLineState *s)
return command_line_not_changed(s);
case Ctrl_HAT:
if (map_to_exists_mode((char_u *)"", LANGMAP, false)) {
if (map_to_exists_mode("", LANGMAP, false)) {
// ":lmap" mappings exists, toggle use of mappings.
State ^= LANGMAP;
if (s->b_im_ptr != NULL) {
@ -2553,19 +2554,22 @@ void cmdline_paste_str(char_u *s, int literally)
else
while (*s != NUL) {
cv = *s;
if (cv == Ctrl_V && s[1])
++s;
if (has_mbyte)
c = mb_cptr2char_adv(&s);
else
if (cv == Ctrl_V && s[1]) {
s++;
}
if (has_mbyte) {
c = mb_cptr2char_adv((const char_u **)&s);
} else {
c = *s++;
}
if (cv == Ctrl_V || c == ESC || c == Ctrl_C
|| c == CAR || c == NL || c == Ctrl_L
#ifdef UNIX
|| c == intr_char
#endif
|| (c == Ctrl_BSL && *s == Ctrl_N))
|| (c == Ctrl_BSL && *s == Ctrl_N)) {
stuffcharReadbuff(Ctrl_V);
}
stuffcharReadbuff(c);
}
}
@ -3120,9 +3124,10 @@ void ExpandEscape(expand_T *xp, char_u *str, int numfiles, char_u **files, int o
#endif
}
#ifdef BACKSLASH_IN_FILENAME
p = vim_strsave_fnameescape(files[i], FALSE);
p = (char_u *)vim_strsave_fnameescape((const char *)files[i], false);
#else
p = vim_strsave_fnameescape(files[i], xp->xp_shell);
p = (char_u *)vim_strsave_fnameescape((const char *)files[i],
xp->xp_shell);
#endif
xfree(files[i]);
files[i] = p;
@ -3152,42 +3157,49 @@ void ExpandEscape(expand_T *xp, char_u *str, int numfiles, char_u **files, int o
}
}
/*
* Escape special characters in "fname" for when used as a file name argument
* after a Vim command, or, when "shell" is non-zero, a shell command.
* Returns the result in allocated memory.
*/
char_u *vim_strsave_fnameescape(char_u *fname, int shell) FUNC_ATTR_NONNULL_RET
/// Escape special characters in a file name for use as a command argument
///
/// @param[in] fname File name to escape.
/// @param[in] shell What to escape for: if false, escapes for VimL command,
/// if true then it escapes for a shell command.
///
/// @return [allocated] escaped file name.
char *vim_strsave_fnameescape(const char *const fname, const bool shell)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
{
char_u *p;
#ifdef BACKSLASH_IN_FILENAME
#define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`%#'\"|!<")
char_u buf[20];
#define PATH_ESC_CHARS " \t\n*?[{`%#'\"|!<"
char_u buf[sizeof(PATH_ESC_CHARS)];
int j = 0;
/* Don't escape '[', '{' and '!' if they are in 'isfname'. */
for (p = PATH_ESC_CHARS; *p != NUL; ++p)
if ((*p != '[' && *p != '{' && *p != '!') || !vim_isfilec(*p))
buf[j++] = *p;
// Don't escape '[', '{' and '!' if they are in 'isfname'.
for (const char *s = PATH_ESC_CHARS; *s != NUL; s++) {
if ((*s != '[' && *s != '{' && *s != '!') || !vim_isfilec(*s)) {
buf[j++] = *s;
}
}
buf[j] = NUL;
p = vim_strsave_escaped(fname, buf);
char *p = (char *)vim_strsave_escaped((const char_u *)fname,
(const char_u *)buf);
#else
#define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<")
#define SHELL_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<>();&")
p = vim_strsave_escaped(fname, shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS);
char *p = (char *)vim_strsave_escaped(
(const char_u *)fname, (shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS));
if (shell && csh_like_shell()) {
/* For csh and similar shells need to put two backslashes before '!'.
* One is taken by Vim, one by the shell. */
char_u *s = vim_strsave_escaped(p, (char_u *)"!");
// For csh and similar shells need to put two backslashes before '!'.
// One is taken by Vim, one by the shell.
char *s = (char *)vim_strsave_escaped((const char_u *)p,
(const char_u *)"!");
xfree(p);
p = s;
}
#endif
/* '>' and '+' are special at the start of some commands, e.g. ":edit" and
* ":write". "cd -" has a special meaning. */
// '>' and '+' are special at the start of some commands, e.g. ":edit" and
// ":write". "cd -" has a special meaning.
if (*p == '>' || *p == '+' || (*p == '-' && p[1] == NUL)) {
escape_fname(&p);
escape_fname((char_u **)&p);
}
return p;
@ -3624,7 +3636,6 @@ set_cmd_context (
)
{
int old_char = NUL;
char_u *nextcomm;
/*
* Avoid a UMR warning from Purify, only save the character if it has been
@ -3633,7 +3644,7 @@ set_cmd_context (
if (col < len)
old_char = str[col];
str[col] = NUL;
nextcomm = str;
const char *nextcomm = (const char *)str;
if (use_ccline && ccline.cmdfirstc == '=') {
// pass CMD_SIZE because there is no real command
@ -3642,9 +3653,11 @@ set_cmd_context (
xp->xp_context = ccline.xp_context;
xp->xp_pattern = ccline.cmdbuff;
xp->xp_arg = ccline.xp_arg;
} else
while (nextcomm != NULL)
} else {
while (nextcomm != NULL) {
nextcomm = set_one_cmd_context(xp, nextcomm);
}
}
/* Store the string here so that call_user_expand_func() can get to them
* easily. */
@ -4197,9 +4210,11 @@ static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, int *num_file,
char_u keep;
garray_T ga;
retstr = call_user_expand_func(call_func_retstr, xp, num_file, file);
if (retstr == NULL)
retstr = call_user_expand_func((user_expand_func_T)call_func_retstr, xp,
num_file, file);
if (retstr == NULL) {
return FAIL;
}
ga_init(&ga, (int)sizeof(char *), 3);
for (s = retstr; *s != NUL; s = e) {
@ -4237,9 +4252,11 @@ static int ExpandUserList(expand_T *xp, int *num_file, char_u ***file)
listitem_T *li;
garray_T ga;
retlist = call_user_expand_func(call_func_retlist, xp, num_file, file);
if (retlist == NULL)
retlist = call_user_expand_func((user_expand_func_T)call_func_retlist, xp,
num_file, file);
if (retlist == NULL) {
return FAIL;
}
ga_init(&ga, (int)sizeof(char *), 3);
/* Loop over the items in the list. */
@ -4249,7 +4266,7 @@ static int ExpandUserList(expand_T *xp, int *num_file, char_u ***file)
GA_APPEND(char_u *, &ga, vim_strsave(li->li_tv.vval.v_string));
}
list_unref(retlist);
tv_list_unref(retlist);
*file = ga.ga_data;
*num_file = ga.ga_len;
@ -4545,7 +4562,7 @@ static inline void hist_free_entry(histentry_T *hisptr)
FUNC_ATTR_NONNULL_ALL
{
xfree(hisptr->hisstr);
list_unref(hisptr->additional_elements);
tv_list_unref(hisptr->additional_elements);
clear_hist_entry(hisptr);
}
@ -4601,7 +4618,7 @@ in_history (
history[type][last_i] = history[type][i];
last_i = i;
}
list_unref(list);
tv_list_unref(list);
history[type][i].hisnum = ++hisnum[type];
history[type][i].hisstr = str;
history[type][i].timestamp = os_time();
@ -4623,7 +4640,7 @@ in_history (
///
/// @return Any value from HistoryType enum, including HIST_INVALID. May not
/// return HIST_DEFAULT unless return_default is true.
HistoryType get_histtype(const char_u *const name, const size_t len,
HistoryType get_histtype(const char *const name, const size_t len,
const bool return_default)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
@ -5016,7 +5033,7 @@ void ex_history(exarg_T *eap)
while (ASCII_ISALPHA(*end)
|| vim_strchr((char_u *)":=@>/?", *end) != NULL)
end++;
histype1 = get_histtype(arg, end - arg, false);
histype1 = get_histtype((const char *)arg, end - arg, false);
if (histype1 == HIST_INVALID) {
if (STRNICMP(arg, "all", end - arg) == 0) {
histype1 = 0;
@ -5173,7 +5190,7 @@ static int ex_window(void)
// Create empty command-line buffer.
buf_open_scratch(0, "[Command Line]");
// Command-line buffer has bufhidden=wipe, unlike a true "scratch" buffer.
set_option_value((char_u *)"bh", 0L, (char_u *)"wipe", OPT_LOCAL);
set_option_value("bh", 0L, "wipe", OPT_LOCAL);
curwin->w_p_rl = cmdmsg_rl;
cmdmsg_rl = false;
curbuf->b_p_ma = true;
@ -5191,7 +5208,7 @@ static int ex_window(void)
add_map((char_u *)"<buffer> <Tab> <C-X><C-V>", INSERT);
add_map((char_u *)"<buffer> <Tab> a<C-X><C-V>", NORMAL);
}
set_option_value((char_u *)"ft", 0L, (char_u *)"vim", OPT_LOCAL);
set_option_value("ft", 0L, "vim", OPT_LOCAL);
}
/* Reset 'textwidth' after setting 'filetype' (the Vim filetype plugin
@ -5275,18 +5292,18 @@ static int ex_window(void)
cmdwin_result = Ctrl_C;
/* Set the new command line from the cmdline buffer. */
xfree(ccline.cmdbuff);
if (cmdwin_result == K_XF1 || cmdwin_result == K_XF2) { /* :qa[!] typed */
char *p = (cmdwin_result == K_XF2) ? "qa" : "qa!";
if (cmdwin_result == K_XF1 || cmdwin_result == K_XF2) { // :qa[!] typed
const char *p = (cmdwin_result == K_XF2) ? "qa" : "qa!";
if (histtype == HIST_CMD) {
/* Execute the command directly. */
ccline.cmdbuff = vim_strsave((char_u *)p);
// Execute the command directly.
ccline.cmdbuff = (char_u *)xstrdup(p);
cmdwin_result = CAR;
} else {
/* First need to cancel what we were doing. */
// First need to cancel what we were doing.
ccline.cmdbuff = NULL;
stuffcharReadbuff(':');
stuffReadbuff((char_u *)p);
stuffReadbuff(p);
stuffcharReadbuff(CAR);
}
} else if (cmdwin_result == K_XF2) { /* :qa typed */

View File

@ -1,7 +1,7 @@
#ifndef NVIM_EX_GETLN_H
#define NVIM_EX_GETLN_H
#include "nvim/eval_defs.h"
#include "nvim/eval/typval.h"
#include "nvim/ex_cmds.h"
/* Values for nextwild() and ExpandOne(). See ExpandOne() for meaning. */

View File

@ -322,8 +322,11 @@ vim_findfile_init (
drive[0] = path[0];
drive[1] = ':';
drive[2] = NUL;
if (vim_FullName(drive, ff_expand_buffer, MAXPATHL, TRUE) == FAIL)
if (vim_FullName((const char *)drive, (char *)ff_expand_buffer, MAXPATHL,
true)
== FAIL) {
goto error_return;
}
path += 2;
} else
#endif
@ -1549,14 +1552,14 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope)
assert(false);
}
dict_add_nr_str(dict, "scope", 0L, (char_u *)buf);
dict_add_nr_str(dict, "cwd", 0L, (char_u *)new_dir);
dict_set_keys_readonly(dict);
tv_dict_add_str(dict, S_LEN("scope"), buf);
tv_dict_add_str(dict, S_LEN("cwd"), new_dir);
tv_dict_set_keys_readonly(dict);
apply_autocmds(EVENT_DIRCHANGED, (char_u *)buf, (char_u *)new_dir, false,
NULL);
dict_clear(dict);
tv_dict_clear(dict);
recursive = false;
}

View File

@ -428,7 +428,7 @@ readfile (
}
if (!read_buffer && !read_stdin) {
perm = os_getperm(fname);
perm = os_getperm((const char *)fname);
#ifdef UNIX
// On Unix it is possible to read a directory, so we have to
// check for it before os_open().
@ -614,10 +614,12 @@ readfile (
return FAIL;
}
#ifdef UNIX
/* Set swap file protection bits after creating it. */
// Set swap file protection bits after creating it.
if (swap_mode > 0 && curbuf->b_ml.ml_mfp != NULL
&& curbuf->b_ml.ml_mfp->mf_fname != NULL)
(void)os_setperm(curbuf->b_ml.ml_mfp->mf_fname, (long)swap_mode);
&& curbuf->b_ml.ml_mfp->mf_fname != NULL) {
(void)os_setperm((const char *)curbuf->b_ml.ml_mfp->mf_fname,
(long)swap_mode);
}
#endif
}
@ -2606,10 +2608,10 @@ buf_write (
newfile = TRUE;
perm = -1;
} else {
perm = os_getperm(fname);
if (perm < 0)
newfile = TRUE;
else if (os_isdir(fname)) {
perm = os_getperm((const char *)fname);
if (perm < 0) {
newfile = true;
} else if (os_isdir(fname)) {
errnum = (char_u *)"E502: ";
errmsg = (char_u *)_("is a directory");
goto fail;
@ -2870,9 +2872,9 @@ buf_write (
xfree(backup);
backup = NULL;
} else {
/* set file protection same as original file, but
* strip s-bit */
(void)os_setperm(backup, perm & 0777);
// set file protection same as original file, but
// strip s-bit.
(void)os_setperm((const char *)backup, perm & 0777);
#ifdef UNIX
/*
@ -2883,7 +2885,8 @@ buf_write (
*/
if (file_info_new.stat.st_gid != file_info_old.stat.st_gid
&& os_fchown(bfd, -1, file_info_old.stat.st_gid) != 0) {
os_setperm(backup, (perm & 0707) | ((perm & 07) << 3));
os_setperm((const char *)backup,
(perm & 0707) | ((perm & 07) << 3));
}
# ifdef HAVE_SELINUX
mch_copy_sec(fname, backup);
@ -3037,8 +3040,8 @@ nobackup:
&& file_info_old.stat.st_uid == getuid()
&& vim_strchr(p_cpo, CPO_FWRITE) == NULL) {
perm |= 0200;
(void)os_setperm(fname, perm);
made_writable = TRUE;
(void)os_setperm((const char *)fname, perm);
made_writable = true;
}
#endif
@ -3402,8 +3405,9 @@ restore_backup:
|| file_info.stat.st_uid != file_info_old.stat.st_uid
|| file_info.stat.st_gid != file_info_old.stat.st_gid) {
os_fchown(fd, file_info_old.stat.st_uid, file_info_old.stat.st_gid);
if (perm >= 0) /* set permission again, may have changed */
(void)os_setperm(wfname, perm);
if (perm >= 0) { // Set permission again, may have changed.
(void)os_setperm((const char *)wfname, perm);
}
}
buf_set_file_id(buf);
} else if (!buf->file_id_valid) {
@ -3421,8 +3425,9 @@ restore_backup:
if (made_writable)
perm &= ~0200; /* reset 'w' bit for security reasons */
#endif
if (perm >= 0) /* set perm. of new file same as old file */
(void)os_setperm(wfname, perm);
if (perm >= 0) { // Set perm. of new file same as old file.
(void)os_setperm((const char *)wfname, perm);
}
#ifdef HAVE_ACL
/* Probably need to set the ACL before changing the user (can't set the
* ACL on a file the user doesn't own). */
@ -3628,7 +3633,7 @@ restore_backup:
close(empty_fd);
}
if (org != NULL) {
os_setperm((char_u *)org, os_getperm(fname) & 0777);
os_setperm(org, os_getperm((const char *)fname) & 0777);
xfree(org);
}
}
@ -4548,9 +4553,9 @@ int put_time(FILE *fd, time_t time_)
/// os_rename() only works if both files are on the same file system, this
/// function will (attempts to?) copy the file across if rename fails -- webb
//
///
/// @return -1 for failure, 0 for success
int vim_rename(char_u *from, char_u *to)
int vim_rename(const char_u *from, const char_u *to)
{
int fd_in;
int fd_out;
@ -4569,11 +4574,13 @@ int vim_rename(char_u *from, char_u *to)
* the file name differs we need to go through a temp file.
*/
if (fnamecmp(from, to) == 0) {
if (p_fic && STRCMP(path_tail(from), path_tail(to)) != 0)
if (p_fic && (STRCMP(path_tail((char_u *)from), path_tail((char_u *)to))
!= 0)) {
use_tmp_file = true;
else
} else {
return 0;
}
}
// Fail if the "from" file doesn't exist. Avoids that "to" is deleted.
FileInfo from_info;
@ -4638,9 +4645,9 @@ int vim_rename(char_u *from, char_u *to)
/*
* Rename() failed, try copying the file.
*/
perm = os_getperm(from);
perm = os_getperm((const char *)from);
#ifdef HAVE_ACL
/* For systems that support ACL: get the ACL from the original file. */
// For systems that support ACL: get the ACL from the original file.
acl = mch_get_acl(from);
#endif
fd_in = os_open((char *)from, O_RDONLY, 0);
@ -4688,8 +4695,8 @@ int vim_rename(char_u *from, char_u *to)
errmsg = _("E210: Error reading \"%s\"");
to = from;
}
#ifndef UNIX /* for Unix os_open() already set the permission */
os_setperm(to, perm);
#ifndef UNIX // For Unix os_open() already set the permission.
os_setperm((const char *)to, perm);
#endif
#ifdef HAVE_ACL
mch_set_acl(to, acl);
@ -5200,7 +5207,7 @@ void forward_slash(char_u *fname)
{
char_u *p;
if (path_with_url(fname)) {
if (path_with_url((const char *)fname)) {
return;
}
for (p = fname; *p != NUL; p++) {
@ -5261,7 +5268,7 @@ static void vim_maketempdir(void)
/// Delete "name" and everything in it, recursively.
/// @param name The path which should be deleted.
/// @return 0 for success, -1 if some file was not deleted.
int delete_recursive(char_u *name)
int delete_recursive(const char *name)
{
int result = 0;
@ -5275,7 +5282,7 @@ int delete_recursive(char_u *name)
EW_DIR | EW_FILE | EW_SILENT | EW_ALLLINKS
| EW_DODOT | EW_EMPTYOK) == OK) {
for (int i = 0; i < file_count; i++) {
if (delete_recursive(files[i]) != 0) {
if (delete_recursive((const char *)files[i]) != 0) {
result = -1;
}
}
@ -5285,9 +5292,9 @@ int delete_recursive(char_u *name)
}
xfree(exp);
os_rmdir((char *)name);
os_rmdir(name);
} else {
result = os_remove((char *)name) == 0 ? 0 : -1;
result = os_remove(name) == 0 ? 0 : -1;
}
return result;
@ -5299,7 +5306,7 @@ void vim_deltempdir(void)
if (vim_tempdir != NULL) {
// remove the trailing path separator
path_tail(vim_tempdir)[-1] = NUL;
delete_recursive(vim_tempdir);
delete_recursive((const char *)vim_tempdir);
xfree(vim_tempdir);
vim_tempdir = NULL;
}

View File

@ -235,19 +235,18 @@ char_u *get_inserted(void)
return get_buffcont(&redobuff, FALSE);
}
/*
* Add string "s" after the current block of buffer "buf".
* K_SPECIAL and CSI should have been escaped already.
*/
static void
add_buff (
buffheader_T *buf,
char_u *s,
ssize_t slen // length of "s" or -1
)
/// Add string after the current block of the given buffer
///
/// K_SPECIAL and CSI should have been escaped already.
///
/// @param[out] buf Buffer to add to.
/// @param[in] s String to add.
/// @param[in] slen String length or -1 for NUL-terminated string.
static void add_buff(buffheader_T *const buf, const char *const s,
ptrdiff_t slen)
{
if (slen < 0) {
slen = (ssize_t)STRLEN(s);
slen = (ptrdiff_t)strlen(s);
}
if (slen == 0) { // don't add empty strings
return;
@ -292,9 +291,8 @@ add_buff (
*/
static void add_num_buff(buffheader_T *buf, long n)
{
char_u number[32];
sprintf((char *)number, "%" PRId64, (int64_t)n);
char number[32];
snprintf(number, sizeof(number), "%ld", n);
add_buff(buf, number, -1L);
}
@ -304,27 +302,29 @@ static void add_num_buff(buffheader_T *buf, long n)
*/
static void add_char_buff(buffheader_T *buf, int c)
{
char_u bytes[MB_MAXBYTES + 1];
char bytes[MB_MAXBYTES + 1];
int len;
int i;
char_u temp[4];
if (IS_SPECIAL(c))
if (IS_SPECIAL(c)) {
len = 1;
else
len = (*mb_char2bytes)(c, bytes);
for (i = 0; i < len; ++i) {
if (!IS_SPECIAL(c))
c = bytes[i];
} else {
len = (*mb_char2bytes)(c, (char_u *)bytes);
}
for (int i = 0; i < len; i++) {
if (!IS_SPECIAL(c)) {
c = bytes[i];
}
char temp[4];
if (IS_SPECIAL(c) || c == K_SPECIAL || c == NUL) {
/* translate special key code into three byte sequence */
temp[0] = K_SPECIAL;
temp[1] = (char_u)K_SECOND(c);
temp[2] = (char_u)K_THIRD(c);
// Translate special key code into three byte sequence.
temp[0] = (char)K_SPECIAL;
temp[1] = (char)K_SECOND(c);
temp[2] = (char)K_THIRD(c);
temp[3] = NUL;
} else {
temp[0] = (char_u)c;
temp[0] = (char)c;
temp[1] = NUL;
}
add_buff(buf, temp, -1L);
@ -479,16 +479,14 @@ static int save_level = 0;
void saveRedobuff(void)
{
char_u *s;
if (save_level++ == 0) {
save_redobuff = redobuff;
redobuff.bh_first.b_next = NULL;
save_old_redobuff = old_redobuff;
old_redobuff.bh_first.b_next = NULL;
/* Make a copy, so that ":normal ." in a function works. */
s = get_buffcont(&save_redobuff, FALSE);
// Make a copy, so that ":normal ." in a function works.
char *const s = (char *)get_buffcont(&save_redobuff, false);
if (s != NULL) {
add_buff(&redobuff, s, -1L);
xfree(s);
@ -514,10 +512,11 @@ void restoreRedobuff(void)
* Append "s" to the redo buffer.
* K_SPECIAL and CSI should already have been escaped.
*/
void AppendToRedobuff(char_u *s)
void AppendToRedobuff(const char *s)
{
if (!block_redo)
add_buff(&redobuff, s, -1L);
if (!block_redo) {
add_buff(&redobuff, (const char *)s, -1L);
}
}
/*
@ -530,46 +529,49 @@ AppendToRedobuffLit (
int len /* length of "str" or -1 for up to the NUL */
)
{
char_u *s = str;
int c;
char_u *start;
if (block_redo)
if (block_redo) {
return;
}
while (len < 0 ? *s != NUL : s - str < len) {
/* Put a string of normal characters in the redo buffer (that's
* faster). */
start = s;
while (*s >= ' ' && *s < DEL && (len < 0 || s - str < len))
++s;
const char *s = (const char *)str;
while (len < 0 ? *s != NUL : s - (const char *)str < len) {
// Put a string of normal characters in the redo buffer (that's
// faster).
const char *start = s;
while (*s >= ' ' && *s < DEL && (len < 0 || s - (const char *)str < len)) {
s++;
}
/* Don't put '0' or '^' as last character, just in case a CTRL-D is
* typed next. */
if (*s == NUL && (s[-1] == '0' || s[-1] == '^'))
--s;
if (s > start)
// Don't put '0' or '^' as last character, just in case a CTRL-D is
// typed next.
if (*s == NUL && (s[-1] == '0' || s[-1] == '^')) {
s--;
}
if (s > start) {
add_buff(&redobuff, start, (long)(s - start));
}
if (*s == NUL || (len >= 0 && s - str >= len))
if (*s == NUL || (len >= 0 && s - (const char *)str >= len)) {
break;
}
/* Handle a special or multibyte character. */
if (has_mbyte)
/* Handle composing chars separately. */
c = mb_cptr2char_adv(&s);
else
c = *s++;
if (c < ' ' || c == DEL || (*s == NUL && (c == '0' || c == '^')))
// Handle a special or multibyte character.
// Composing chars separately are handled separately.
const int c = (has_mbyte
? mb_cptr2char_adv((const char_u **)&s)
: (uint8_t)(*s++));
if (c < ' ' || c == DEL || (*s == NUL && (c == '0' || c == '^'))) {
add_char_buff(&redobuff, Ctrl_V);
}
/* CTRL-V '0' must be inserted as CTRL-V 048 */
if (*s == NUL && c == '0')
add_buff(&redobuff, (char_u *)"048", 3L);
else
// CTRL-V '0' must be inserted as CTRL-V 048.
if (*s == NUL && c == '0') {
add_buff(&redobuff, "048", 3L);
} else {
add_char_buff(&redobuff, c);
}
}
}
/*
* Append a character to the redo buffer.
@ -594,19 +596,19 @@ void AppendNumberToRedobuff(long n)
* Append string "s" to the stuff buffer.
* CSI and K_SPECIAL must already have been escaped.
*/
void stuffReadbuff(char_u *s)
void stuffReadbuff(const char *s)
{
add_buff(&readbuf1, s, -1L);
}
/// Append string "s" to the redo stuff buffer.
/// @remark CSI and K_SPECIAL must already have been escaped.
void stuffRedoReadbuff(char_u *s)
void stuffRedoReadbuff(const char *s)
{
add_buff(&readbuf2, s, -1L);
}
void stuffReadbuffLen(char_u *s, long len)
void stuffReadbuffLen(const char *s, long len)
{
add_buff(&readbuf1, s, len);
}
@ -616,19 +618,18 @@ void stuffReadbuffLen(char_u *s, long len)
* escaping other K_SPECIAL and CSI bytes.
* Change CR, LF and ESC into a space.
*/
void stuffReadbuffSpec(char_u *s)
void stuffReadbuffSpec(const char *s)
{
int c;
while (*s != NUL) {
if (*s == K_SPECIAL && s[1] != NUL && s[2] != NUL) {
/* Insert special key literally. */
stuffReadbuffLen(s, 3L);
if ((uint8_t)(*s) == K_SPECIAL && s[1] != NUL && s[2] != NUL) {
// Insert special key literally.
stuffReadbuffLen(s, 3);
s += 3;
} else {
c = mb_ptr2char_adv(&s);
if (c == CAR || c == NL || c == ESC)
int c = mb_ptr2char_adv((const char_u **)&s);
if (c == CAR || c == NL || c == ESC) {
c = ' ';
}
stuffcharReadbuff(c);
}
}
@ -747,8 +748,8 @@ int start_redo(long count, int old_redo)
/* copy the buffer name, if present */
if (c == '"') {
add_buff(&readbuf2, (char_u *)"\"", 1L);
c = read_redo(FALSE, old_redo);
add_buff(&readbuf2, "\"", 1L);
c = read_redo(false, old_redo);
/* if a numbered buffer is used, increment the number */
if (c >= '1' && c < '9')
@ -1091,21 +1092,19 @@ static void gotchars(char_u *chars, size_t len)
{
char_u *s = chars;
int c;
char_u buf[2];
// remember how many chars were last recorded
if (Recording) {
last_recorded_len += len;
}
buf[1] = NUL;
while (len--) {
// Handle one byte at a time; no translation to be done.
c = *s++;
updatescript(c);
if (Recording) {
buf[0] = (char_u)c;
char buf[2] = { (char)c, NUL };
add_buff(&recordbuff, buf, 1L);
}
}
@ -1881,9 +1880,8 @@ static int vgetorpeek(int advance)
(size_t)(mlen - typebuf.tb_maplen));
}
del_typebuf(mlen, 0); /* remove the chars */
set_option_value((char_u *)"paste",
(long)!p_paste, NULL, 0);
del_typebuf(mlen, 0); // Remove the chars.
set_option_value("paste", !p_paste, NULL, 0);
if (!(State & INSERT)) {
msg_col = 0;
msg_row = (int)Rows - 1;
@ -3219,82 +3217,99 @@ showmap (
ui_flush(); /* show one line at a time */
}
/*
* Return TRUE if a map exists that has "str" in the rhs for mode "modechars".
* Recognize termcap codes in "str".
* Also checks mappings local to the current buffer.
*/
int map_to_exists(char_u *str, char_u *modechars, int abbr)
/// Check if a map exists that has given string in the rhs
///
/// Also checks mappings local to the current buffer.
///
/// @param[in] str String which mapping must have in the rhs. Termcap codes
/// are recognized in this argument.
/// @param[in] modechars Mode(s) in which mappings are checked.
/// @param[in] abbr true if checking abbreviations in place of mappings.
///
/// @return true if there is at least one mapping with given parameters.
bool map_to_exists(const char *const str, const char *const modechars,
const bool abbr)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
{
int mode = 0;
char_u *rhs;
char_u *buf;
int retval;
rhs = replace_termcodes(str, STRLEN(str), &buf, false, true, false,
char_u *buf;
char_u *const rhs = replace_termcodes((const char_u *)str, strlen(str), &buf,
false, true, false,
CPO_TO_CPO_FLAGS);
if (vim_strchr(modechars, 'n') != NULL)
mode |= NORMAL;
if (vim_strchr(modechars, 'v') != NULL)
mode |= VISUAL + SELECTMODE;
if (vim_strchr(modechars, 'x') != NULL)
mode |= VISUAL;
if (vim_strchr(modechars, 's') != NULL)
mode |= SELECTMODE;
if (vim_strchr(modechars, 'o') != NULL)
mode |= OP_PENDING;
if (vim_strchr(modechars, 'i') != NULL)
mode |= INSERT;
if (vim_strchr(modechars, 'l') != NULL)
mode |= LANGMAP;
if (vim_strchr(modechars, 'c') != NULL)
mode |= CMDLINE;
#define MAPMODE(mode, modechars, chr, modeflags) \
do { \
if (strchr(modechars, chr) != NULL) { \
mode |= modeflags; \
} \
} while (0)
MAPMODE(mode, modechars, 'n', NORMAL);
MAPMODE(mode, modechars, 'v', VISUAL|SELECTMODE);
MAPMODE(mode, modechars, 'x', VISUAL);
MAPMODE(mode, modechars, 's', SELECTMODE);
MAPMODE(mode, modechars, 'o', OP_PENDING);
MAPMODE(mode, modechars, 'i', INSERT);
MAPMODE(mode, modechars, 'l', LANGMAP);
MAPMODE(mode, modechars, 'c', CMDLINE);
#undef MAPMODE
retval = map_to_exists_mode(rhs, mode, abbr);
retval = map_to_exists_mode((const char *)rhs, mode, abbr);
xfree(buf);
return retval;
}
/*
* Return TRUE if a map exists that has "str" in the rhs for mode "mode".
* Also checks mappings local to the current buffer.
*/
int map_to_exists_mode(char_u *rhs, int mode, int abbr)
/// Check if a map exists that has given string in the rhs
///
/// Also checks mappings local to the current buffer.
///
/// @param[in] rhs String which mapping must have in the rhs. Termcap codes
/// are recognized in this argument.
/// @param[in] mode Mode(s) in which mappings are checked.
/// @param[in] abbr true if checking abbreviations in place of mappings.
///
/// @return true if there is at least one mapping with given parameters.
int map_to_exists_mode(const char *const rhs, const int mode, const bool abbr)
{
mapblock_T *mp;
int hash;
int expand_buffer = FALSE;
bool expand_buffer = false;
validate_maphash();
/* Do it twice: once for global maps and once for local maps. */
// Do it twice: once for global maps and once for local maps.
for (;;) {
for (hash = 0; hash < 256; ++hash) {
for (hash = 0; hash < 256; hash++) {
if (abbr) {
if (hash > 0) /* there is only one abbr list */
if (hash > 0) { // There is only one abbr list.
break;
if (expand_buffer)
}
if (expand_buffer) {
mp = curbuf->b_first_abbr;
else
} else {
mp = first_abbr;
} else if (expand_buffer)
}
} else if (expand_buffer) {
mp = curbuf->b_maphash[hash];
else
} else {
mp = maphash[hash];
}
for (; mp; mp = mp->m_next) {
if ((mp->m_mode & mode)
&& strstr((char *)mp->m_str, (char *)rhs) != NULL)
return TRUE;
&& strstr((char *)mp->m_str, rhs) != NULL) {
return true;
}
}
if (expand_buffer)
}
if (expand_buffer) {
break;
expand_buffer = TRUE;
}
expand_buffer = true;
}
return FALSE;
return false;
}
/*

21
src/nvim/gettext.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef NVIM_GETTEXT_H
#define NVIM_GETTEXT_H
#ifdef HAVE_WORKING_LIBINTL
# include <libintl.h>
# define _(x) gettext((char *)(x))
// XXX do we actually need this?
# ifdef gettext_noop
# define N_(x) gettext_noop(x)
# else
# define N_(x) x
# endif
#else
# define _(x) ((char *)(x))
# define N_(x) x
# define bindtextdomain(x, y) // empty
# define bind_textdomain_codeset(x, y) // empty
# define textdomain(x) // empty
#endif
#endif // NVIM_GETTEXT_H

View File

@ -12,6 +12,7 @@
#include "nvim/syntax_defs.h"
#include "nvim/types.h"
#include "nvim/event/loop.h"
#include "nvim/os/os_defs.h"
#define IOSIZE (1024+1) // file I/O and sprintf buffer size
@ -21,16 +22,6 @@
# define MSG_BUF_CLEN (MSG_BUF_LEN / 6) // cell length (worst case: utf-8
// takes 6 bytes for one cell)
// Maximum length of a file path. Make it a bit long, to stay
// on the safe side. But not too long to put on the stack.
#ifndef MAXPATHL
# ifdef MAXPATHLEN
# define MAXPATHL MAXPATHLEN
# else
# define MAXPATHL 256
# endif
#endif
#ifdef WIN32
# define _PATHSEPSTR "\\"
#else
@ -1208,6 +1199,7 @@ EXTERN char_u e_dirnotf[] INIT(= N_(
"E919: Directory not found in '%s': \"%s\""));
EXTERN char_u e_unsupportedoption[] INIT(= N_("E519: Option not supported"));
EXTERN char_u e_fnametoolong[] INIT(= N_("E856: Filename too long"));
EXTERN char_u e_float_as_string[] INIT(= N_("E806: using Float as a String"));
EXTERN char top_bot_msg[] INIT(= N_("search hit TOP, continuing at BOTTOM"));
@ -1226,11 +1218,6 @@ EXTERN FILE *time_fd INIT(= NULL); /* where to write startup timing */
EXTERN int ignored;
EXTERN char *ignoredp;
EXTERN bool in_free_unref_items INIT(= false);
// Used for checking if local variables or arguments used in a lambda.
EXTERN int *eval_lavars_used INIT(= NULL);
// If a msgpack-rpc channel should be started over stdin/stdout
EXTERN bool embedded_mode INIT(= false);

View File

@ -369,7 +369,6 @@ static void prt_get_attr(int hl_id, prt_text_attr_T *pattr, int modec)
{
int colorindex;
uint32_t fg_color;
char *color;
pattr->bold = (highlight_has_attr(hl_id, HL_BOLD, modec) != NULL);
pattr->italic = (highlight_has_attr(hl_id, HL_ITALIC, modec) != NULL);
@ -377,11 +376,12 @@ static void prt_get_attr(int hl_id, prt_text_attr_T *pattr, int modec)
pattr->undercurl = (highlight_has_attr(hl_id, HL_UNDERCURL, modec) != NULL);
{
color = (char *)highlight_color(hl_id, (char_u *)"fg", modec);
if (color == NULL)
const char *color = highlight_color(hl_id, "fg", modec);
if (color == NULL) {
colorindex = 0;
else
} else {
colorindex = atoi(color);
}
if (colorindex >= 0 && colorindex < t_colors)
fg_color = prt_get_term_color(colorindex);

View File

@ -82,7 +82,7 @@ void hash_clear_all(hashtab_T *ht, unsigned int off)
/// used for that key.
/// WARNING: Returned pointer becomes invalid as soon as the hash table
/// is changed in any way.
hashitem_T *hash_find(hashtab_T *ht, const char_u *key)
hashitem_T *hash_find(const hashtab_T *const ht, const char_u *const key)
{
return hash_lookup(ht, (const char *)key, STRLEN(key), hash_hash(key));
}
@ -99,7 +99,8 @@ hashitem_T *hash_find(hashtab_T *ht, const char_u *key)
///
/// @warning Returned pointer becomes invalid as soon as the hash table
/// is changed in any way.
hashitem_T *hash_find_len(hashtab_T *ht, const char *key, const size_t len)
hashitem_T *hash_find_len(const hashtab_T *const ht, const char *const key,
const size_t len)
{
return hash_lookup(ht, key, len, hash_hash_len(key, len));
}
@ -115,7 +116,7 @@ hashitem_T *hash_find_len(hashtab_T *ht, const char *key, const size_t len)
/// used for that key.
/// WARNING: Returned pointer becomes invalid as soon as the hash table
/// is changed in any way.
hashitem_T *hash_lookup(hashtab_T *const ht,
hashitem_T *hash_lookup(const hashtab_T *const ht,
const char *const key, const size_t key_len,
const hash_T hash)
{

View File

@ -70,6 +70,25 @@ typedef struct hashtable_S {
hashitem_T ht_smallarray[HT_INIT_SIZE]; /// initial array
} hashtab_T;
/// Iterate over a hashtab
///
/// @param[in] ht Hashtab to iterate over.
/// @param hi Name of the variable with current hashtab entry.
/// @param code Cycle body.
#define HASHTAB_ITER(ht, hi, code) \
do { \
hashtab_T *const hi##ht_ = (ht); \
size_t hi##todo_ = hi##ht_->ht_used; \
for (hashitem_T *hi = hi##ht_->ht_array; hi##todo_; hi++) { \
if (!HASHITEM_EMPTY(hi)) { \
{ \
code \
} \
hi##todo_--; \
} \
} \
} while (0)
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "hashtab.h.generated.h"
#endif

View File

@ -140,34 +140,33 @@ char_u *get_cscope_name(expand_T *xp, int idx)
/*
* Handle command line completion for :cscope command.
*/
void set_context_in_cscope_cmd(expand_T *xp, char_u *arg, cmdidx_T cmdidx)
void set_context_in_cscope_cmd(expand_T *xp, const char *arg, cmdidx_T cmdidx)
{
char_u *p;
/* Default: expand subcommands */
// Default: expand subcommands.
xp->xp_context = EXPAND_CSCOPE;
xp->xp_pattern = arg;
expand_what = (cmdidx == CMD_scscope)
? EXP_SCSCOPE_SUBCMD : EXP_CSCOPE_SUBCMD;
xp->xp_pattern = (char_u *)arg;
expand_what = ((cmdidx == CMD_scscope)
? EXP_SCSCOPE_SUBCMD : EXP_CSCOPE_SUBCMD);
/* (part of) subcommand already typed */
if (*arg != NUL) {
p = skiptowhite(arg);
if (*p != NUL) { /* past first word */
xp->xp_pattern = skipwhite(p);
if (*skiptowhite(xp->xp_pattern) != NUL)
const char *p = (const char *)skiptowhite((const char_u *)arg);
if (*p != NUL) { // Past first word.
xp->xp_pattern = skipwhite((const char_u *)p);
if (*skiptowhite(xp->xp_pattern) != NUL) {
xp->xp_context = EXPAND_NOTHING;
else if (STRNICMP(arg, "add", p - arg) == 0)
} else if (STRNICMP(arg, "add", p - arg) == 0) {
xp->xp_context = EXPAND_FILES;
else if (STRNICMP(arg, "kill", p - arg) == 0)
} else if (STRNICMP(arg, "kill", p - arg) == 0) {
expand_what = EXP_CSCOPE_KILL;
else if (STRNICMP(arg, "find", p - arg) == 0)
} else if (STRNICMP(arg, "find", p - arg) == 0) {
expand_what = EXP_CSCOPE_FIND;
else
} else {
xp->xp_context = EXPAND_NOTHING;
}
}
}
}
/*

View File

@ -174,7 +174,7 @@ static char_u *skip_string(char_u *p)
char_u *paren = vim_strchr(delim, '(');
if (paren != NULL) {
ptrdiff_t delim_len = paren - delim;
const ptrdiff_t delim_len = paren - delim;
for (p += 3; *p; ++p)
if (p[0] == ')' && STRNCMP(p + 1, delim, delim_len) == 0

View File

@ -19,6 +19,15 @@
# define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
#endif
/// String with length
///
/// For use in functions which accept (char *s, size_t len) pair in arguments.
///
/// @param[in] s Static string.
///
/// @return `s, sizeof(s) - 1`
#define S_LEN(s) (s), (sizeof(s) - 1)
/*
* Position comparisons
*/

View File

@ -391,9 +391,10 @@ int main(int argc, char **argv)
shada_read_everything(NULL, false, true);
TIME_MSG("reading ShaDa");
}
/* It's better to make v:oldfiles an empty list than NULL. */
if (get_vim_var_list(VV_OLDFILES) == NULL)
set_vim_var_list(VV_OLDFILES, list_alloc());
// It's better to make v:oldfiles an empty list than NULL.
if (get_vim_var_list(VV_OLDFILES) == NULL) {
set_vim_var_list(VV_OLDFILES, tv_list_alloc());
}
/*
* "-q errorfile": Load the error file now.
@ -802,17 +803,18 @@ static void command_line_scan(mparm_T *parmp)
argv_idx = -1; /* skip to next argument */
break;
case 'A': /* "-A" start in Arabic mode */
set_option_value((char_u *)"arabic", 1L, NULL, 0);
case 'A': { // "-A" start in Arabic mode.
set_option_value("arabic", 1L, NULL, 0);
break;
case 'b': /* "-b" binary mode */
/* Needs to be effective before expanding file names, because
* for Win32 this makes us edit a shortcut file itself,
* instead of the file it links to. */
}
case 'b': { // "-b" binary mode.
// Needs to be effective before expanding file names, because
// for Win32 this makes us edit a shortcut file itself,
// instead of the file it links to.
set_options_bin(curbuf->b_p_bin, 1, 0);
curbuf->b_p_bin = 1; /* binary file I/O */
curbuf->b_p_bin = 1; // Binary file I/O.
break;
}
case 'e': /* "-e" Ex mode */
exmode_active = EXMODE_NORMAL;
@ -829,24 +831,27 @@ static void command_line_scan(mparm_T *parmp)
main_start_gui();
break;
case 'F': /* "-F" start in Farsi mode: rl + fkmap set */
p_fkmap = TRUE;
set_option_value((char_u *)"rl", 1L, NULL, 0);
case 'F': { // "-F" start in Farsi mode: rl + fkmap set.
p_fkmap = true;
set_option_value("rl", 1L, NULL, 0);
break;
}
case 'h': /* "-h" give help message */
usage();
mch_exit(0);
case 'H': /* "-H" start in Hebrew mode: rl + hkmap set */
p_hkmap = TRUE;
set_option_value((char_u *)"rl", 1L, NULL, 0);
case 'H': { // "-H" start in Hebrew mode: rl + hkmap set.
p_hkmap = true;
set_option_value("rl", 1L, NULL, 0);
break;
}
case 'l': /* "-l" lisp mode, 'lisp' and 'showmatch' on */
set_option_value((char_u *)"lisp", 1L, NULL, 0);
p_sm = TRUE;
case 'l': { // "-l" lisp mode, 'lisp' and 'showmatch' on.
set_option_value("lisp", 1L, NULL, 0);
p_sm = true;
break;
}
case 'M': /* "-M" no changes or writing of files */
reset_modifiable();
@ -945,8 +950,7 @@ static void command_line_scan(mparm_T *parmp)
/* default is 10: a little bit verbose */
p_verbose = get_number_arg(argv[0], &argv_idx, 10);
if (argv[0][argv_idx] != NUL) {
set_option_value((char_u *)"verbosefile", 0L,
(char_u *)argv[0] + argv_idx, 0);
set_option_value("verbosefile", 0L, argv[0] + argv_idx, 0);
argv_idx = (int)STRLEN(argv[0]);
}
break;
@ -955,7 +959,7 @@ static void command_line_scan(mparm_T *parmp)
/* "-w {scriptout}" write to script */
if (ascii_isdigit(((char_u *)argv[0])[argv_idx])) {
n = get_number_arg(argv[0], &argv_idx, 10);
set_option_value((char_u *)"window", n, NULL, 0);
set_option_value("window", n, NULL, 0);
break;
}
want_argument = TRUE;
@ -1087,7 +1091,7 @@ scripterror:
if (ascii_isdigit(*((char_u *)argv[0]))) {
argv_idx = 0;
n = get_number_arg(argv[0], &argv_idx, 10);
set_option_value((char_u *)"window", n, NULL, 0);
set_option_value("window", n, NULL, 0);
argv_idx = -1;
break;
}

View File

@ -62,7 +62,7 @@ int setmark(int c)
/// Free fmark_T item
void free_fmark(fmark_T fm)
{
dict_unref(fm.additional_data);
tv_dict_unref(fm.additional_data);
}
/// Free xfmark_T item
@ -1431,3 +1431,26 @@ void free_all_marks(void)
memset(&namedfm[0], 0, sizeof(namedfm));
}
#endif
/// Adjust position to point to the first byte of a multi-byte character
///
/// If it points to a tail byte it is move backwards to the head byte.
///
/// @param[in] buf Buffer to adjust position in.
/// @param[out] lp Position to adjust.
void mark_mb_adjustpos(buf_T *buf, pos_T *lp)
FUNC_ATTR_NONNULL_ALL
{
if (lp->col > 0 || lp->coladd > 1) {
const char_u *const p = ml_get_buf(buf, lp->lnum, false);
lp->col -= (*mb_head_off)(p, p + lp->col);
// Reset "coladd" when the cursor would be on the right half of a
// double-wide character.
if (lp->coladd == 1
&& p[lp->col] != TAB
&& vim_isprintc((*mb_ptr2char)(p + lp->col))
&& ptr2cells(p + lp->col) > 1) {
lp->coladd = 0;
}
}
}

View File

@ -3,7 +3,7 @@
#include "nvim/pos.h"
#include "nvim/os/time.h"
#include "nvim/eval_defs.h"
#include "nvim/eval/typval.h"
/*
* marks: positions in a file

View File

@ -50,6 +50,7 @@
#include "nvim/strings.h"
#include "nvim/os/os.h"
#include "nvim/arabic.h"
#include "nvim/mark.h"
typedef struct {
int rangeStart;
@ -375,16 +376,18 @@ void remove_bom(char_u *s)
*/
int mb_get_class(const char_u *p)
{
return mb_get_class_buf(p, curbuf);
return mb_get_class_tab(p, curbuf->b_chartab);
}
int mb_get_class_buf(const char_u *p, buf_T *buf)
int mb_get_class_tab(const char_u *p, const uint64_t *const chartab)
{
if (MB_BYTE2LEN(p[0]) == 1) {
if (p[0] == NUL || ascii_iswhite(p[0]))
if (p[0] == NUL || ascii_iswhite(p[0])) {
return 0;
if (vim_iswordc_buf(p[0], buf))
}
if (vim_iswordc_tab(p[0], chartab)) {
return 2;
}
return 1;
}
return utf_class(utf_ptr2char(p));
@ -580,7 +583,7 @@ int utf_ptr2char(const char_u *p)
* If byte sequence is illegal or incomplete, returns -1 and does not advance
* "s".
*/
static int utf_safe_read_char_adv(char_u **s, size_t *n)
static int utf_safe_read_char_adv(const char_u **s, size_t *n)
{
int c;
@ -622,7 +625,7 @@ static int utf_safe_read_char_adv(char_u **s, size_t *n)
* Get character at **pp and advance *pp to the next character.
* Note: composing characters are skipped!
*/
int mb_ptr2char_adv(char_u **pp)
int mb_ptr2char_adv(const char_u **const pp)
{
int c;
@ -635,7 +638,7 @@ int mb_ptr2char_adv(char_u **pp)
* Get character at **pp and advance *pp to the next character.
* Note: composing characters are returned as separate characters.
*/
int mb_cptr2char_adv(char_u **pp)
int mb_cptr2char_adv(const char_u **pp)
{
int c;
@ -1230,7 +1233,8 @@ bool utf_isupper(int a)
return utf_tolower(a) != a;
}
static int utf_strnicmp(char_u *s1, char_u *s2, size_t n1, size_t n2)
static int utf_strnicmp(const char_u *s1, const char_u *s2, size_t n1,
size_t n2)
{
int c1, c2, cdiff;
char_u buffer[6];
@ -1389,19 +1393,26 @@ int utf16_to_utf8(const WCHAR *strw, char **str)
* Returns zero if s1 and s2 are equal (ignoring case), the difference between
* two characters otherwise.
*/
int mb_strnicmp(char_u *s1, char_u *s2, size_t nn)
int mb_strnicmp(const char_u *s1, const char_u *s2, const size_t nn)
{
return utf_strnicmp(s1, s2, nn, nn);
}
/* We need to call mb_stricmp() even when we aren't dealing with a multi-byte
* encoding because mb_stricmp() takes care of all ascii and non-ascii
* encodings, including characters with umlauts in latin1, etc., while
* STRICMP() only handles the system locale version, which often does not
* handle non-ascii properly. */
int mb_stricmp(char_u *s1, char_u *s2)
/// Compare strings case-insensitively
///
/// @note We need to call mb_stricmp() even when we aren't dealing with
/// a multi-byte encoding because mb_stricmp() takes care of all ASCII and
/// non-ascii encodings, including characters with umlauts in latin1,
/// etc., while STRICMP() only handles the system locale version, which
/// often does not handle non-ascii properly.
///
/// @param[in] s1 First string to compare, not more then #MAXCOL characters.
/// @param[in] s2 Second string to compare, not more then #MAXCOL characters.
///
/// @return 0 if strings are equal, <0 if s1 < s2, >0 if s1 > s2.
int mb_stricmp(const char *s1, const char *s2)
{
return mb_strnicmp(s1, s2, MAXCOL);
return mb_strnicmp((const char_u *)s1, (const char_u *)s2, MAXCOL);
}
/*
@ -1639,38 +1650,16 @@ theend:
*/
void mb_adjust_cursor(void)
{
mb_adjustpos(curbuf, &curwin->w_cursor);
}
/*
* Adjust position "*lp" to point to the first byte of a multi-byte character.
* If it points to a tail byte it's moved backwards to the head byte.
*/
void mb_adjustpos(buf_T *buf, pos_T *lp)
{
char_u *p;
if (lp->col > 0
|| lp->coladd > 1
) {
p = ml_get_buf(buf, lp->lnum, FALSE);
lp->col -= (*mb_head_off)(p, p + lp->col);
/* Reset "coladd" when the cursor would be on the right half of a
* double-wide character. */
if (lp->coladd == 1
&& p[lp->col] != TAB
&& vim_isprintc((*mb_ptr2char)(p + lp->col))
&& ptr2cells(p + lp->col) > 1)
lp->coladd = 0;
}
mark_mb_adjustpos(curbuf, &curwin->w_cursor);
}
/// Checks and adjusts cursor column. Not mode-dependent.
/// @see check_cursor_col_win
///
/// @param win Places cursor on a valid column for this window.
void mb_check_adjust_col(win_T *win)
/// @param win_ Places cursor on a valid column for this window.
void mb_check_adjust_col(void *win_)
{
win_T *win = (win_T *)win_;
colnr_T oldcol = win->w_cursor.col;
// Column 0 is always valid.
@ -2039,8 +2028,8 @@ void * my_iconv_open(char_u *to, char_u *from)
* Returns the converted string in allocated memory. NULL for an error.
* If resultlenp is not NULL, sets it to the result length in bytes.
*/
static char_u * iconv_string(vimconv_T *vcp, char_u *str, size_t slen,
size_t *unconvlenp, size_t *resultlenp)
static char_u *iconv_string(const vimconv_T *const vcp, char_u *str,
size_t slen, size_t *unconvlenp, size_t *resultlenp)
{
const char *from;
size_t fromlen;
@ -2325,7 +2314,7 @@ int convert_setup_ext(vimconv_T *vcp, char_u *from, bool from_unicode_is_utf8,
* Illegal chars are often changed to "?", unless vcp->vc_fail is set.
* When something goes wrong, NULL is returned and "*lenp" is unchanged.
*/
char_u * string_convert(vimconv_T *vcp, char_u *ptr, size_t *lenp)
char_u *string_convert(const vimconv_T *const vcp, char_u *ptr, size_t *lenp)
{
return string_convert_ext(vcp, ptr, lenp, NULL);
}
@ -2335,7 +2324,7 @@ char_u * string_convert(vimconv_T *vcp, char_u *ptr, size_t *lenp)
* an incomplete sequence at the end it is not converted and "*unconvlenp" is
* set to the number of remaining bytes.
*/
char_u * string_convert_ext(vimconv_T *vcp, char_u *ptr,
char_u * string_convert_ext(const vimconv_T *const vcp, char_u *ptr,
size_t *lenp, size_t *unconvlenp)
{
char_u *retval = NULL;

View File

@ -2,6 +2,11 @@
#define NVIM_MBYTE_H
#include <stdbool.h>
#include <string.h>
#include "nvim/iconv.h"
#include "nvim/func_attr.h"
#include "nvim/os/os_defs.h" // For WCHAR, indirect
/*
* Return byte length of character that starts with byte "b".
@ -40,7 +45,41 @@
#define mb_ptr2char utf_ptr2char
#define mb_head_off utf_head_off
/// Flags for vimconv_T
typedef enum {
CONV_NONE = 0,
CONV_TO_UTF8 = 1,
CONV_9_TO_UTF8 = 2,
CONV_TO_LATIN1 = 3,
CONV_TO_LATIN9 = 4,
CONV_ICONV = 5,
} ConvFlags;
/// Structure used for string conversions
typedef struct {
int vc_type; ///< Zero or more ConvFlags.
int vc_factor; ///< Maximal expansion factor.
# ifdef USE_ICONV
iconv_t vc_fd; ///< Value for CONV_ICONV.
# endif
bool vc_fail; ///< What to do with invalid characters: if true, fail,
///< otherwise use '?'.
} vimconv_T;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "mbyte.h.generated.h"
#endif
static inline int mb_strcmp_ic(bool ic, const char *s1, const char *s2)
REAL_FATTR_NONNULL_ALL REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
/// Compare strings
///
/// @param[in] ic True if case is to be ignored.
///
/// @return 0 if s1 == s2, <0 if s1 < s2, >0 if s1 > s2.
static inline int mb_strcmp_ic(bool ic, const char *s1, const char *s2)
{
return (ic ? mb_stricmp(s1, s2) : strcmp(s1, s2));
}
#endif // NVIM_MBYTE_H

View File

@ -992,7 +992,7 @@ void ml_recover(void)
if (b0_ff != 0)
set_fileformat(b0_ff - 1, OPT_LOCAL);
if (b0_fenc != NULL) {
set_option_value((char_u *)"fenc", 0L, b0_fenc, OPT_LOCAL);
set_option_value("fenc", 0L, (char *)b0_fenc, OPT_LOCAL);
xfree(b0_fenc);
}
unchanged(curbuf, TRUE);

View File

@ -430,6 +430,19 @@ char *xstrdup(const char *str)
return xmemdupz(str, strlen(str));
}
/// strdup() wrapper
///
/// Unlike xstrdup() allocates a new empty string if it receives NULL.
char *xstrdupnul(const char *const str)
FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET
{
if (str == NULL) {
return xmallocz(0);
} else {
return xstrdup(str);
}
}
/// A version of memchr that starts the search at `src + len`.
///
/// Based on glibc's memrchr.

View File

@ -718,7 +718,7 @@ int delete_first_msg(void)
void ex_messages(void *const eap_p)
FUNC_ATTR_NONNULL_ALL
{
exarg_T *eap = (exarg_T *)eap_p;
const exarg_T *const eap = (const exarg_T *)eap_p;
struct msg_hist *p;
int c = 0;
@ -1562,13 +1562,17 @@ void msg_puts_attr(const char *const s, const int attr)
msg_puts_attr_len(s, -1, attr);
}
/// Like msg_puts_attr(), but with a maximum length "maxlen" (in bytes).
/// When "maxlen" is -1 there is no maximum length.
/// When "maxlen" is >= 0 the message is not put in the history.
void msg_puts_attr_len(const char *str, const ptrdiff_t maxlen, int attr)
/// Write a message with highlight attributes
///
/// @param[in] str NUL-terminated message string.
/// @param[in] len Length of the string or -1.
/// @param[in] attr Highlight attribute.
void msg_puts_attr_len(const char *const str, const ptrdiff_t len, int attr)
FUNC_ATTR_NONNULL_ALL
{
assert(len < 0 || memchr(str, 0, len) == NULL);
// If redirection is on, also write to the redirection file.
redir_write(str, maxlen);
redir_write(str, len);
// Don't print anything when using ":silent cmd".
if (msg_silent != 0) {
@ -1576,8 +1580,8 @@ void msg_puts_attr_len(const char *str, const ptrdiff_t maxlen, int attr)
}
// if MSG_HIST flag set, add message to history
if ((attr & MSG_HIST) && maxlen < 0) {
add_msg_hist(str, -1, attr);
if (attr & MSG_HIST) {
add_msg_hist(str, (int)len, attr);
attr &= ~MSG_HIST;
}
@ -1596,9 +1600,9 @@ void msg_puts_attr_len(const char *str, const ptrdiff_t maxlen, int attr)
// different, e.g. for Win32 console) or we just don't know where the
// cursor is.
if (msg_use_printf()) {
msg_puts_printf(str, maxlen);
msg_puts_printf(str, len);
} else {
msg_puts_display((const char_u *)str, maxlen, attr, false);
msg_puts_display((const char_u *)str, len, attr, false);
}
}

View File

@ -2211,39 +2211,44 @@ change_warning (
}
}
/*
* Ask for a reply from the user, a 'y' or a 'n'.
* No other characters are accepted, the message is repeated until a valid
* reply is entered or CTRL-C is hit.
* If direct is TRUE, don't use vgetc() but ui_inchar(), don't get characters
* from any buffers but directly from the user.
*
* return the 'y' or 'n'
*/
int ask_yesno(const char *str, bool direct)
/// Ask for a reply from the user, 'y' or 'n'
///
/// No other characters are accepted, the message is repeated until a valid
/// reply is entered or <C-c> is hit.
///
/// @param[in] str Prompt: question to ask user. Is always followed by
/// " (y/n)?".
/// @param[in] direct Determines what function to use to get user input. If
/// true then ui_inchar() will be used, otherwise vgetc().
/// I.e. when direct is true then characters are obtained
/// directly from the user without buffers involved.
///
/// @return 'y' or 'n'. Last is also what will be returned in case of interrupt.
int ask_yesno(const char *const str, const bool direct)
{
int r = ' ';
int save_State = State;
const int save_State = State;
no_wait_return++;
State = CONFIRM; // mouse behaves like with :confirm
setmouse(); // disables mouse for xterm
State = CONFIRM; // Mouse behaves like with :confirm.
setmouse(); // Disable mouse in xterm.
no_mapping++;
int r = ' ';
while (r != 'y' && r != 'n') {
/* same highlighting as for wait_return */
smsg_attr(hl_attr(HLF_R),
"%s (y/n)?", str);
if (direct)
// Same highlighting as for wait_return.
smsg_attr(hl_attr(HLF_R), "%s (y/n)?", str);
if (direct) {
r = get_keystroke();
else
} else {
r = plain_vgetc();
if (r == Ctrl_C || r == ESC)
}
if (r == Ctrl_C || r == ESC) {
r = 'n';
msg_putchar(r); /* show what you typed */
}
msg_putchar(r); // Show what you typed.
ui_flush();
}
--no_wait_return;
no_wait_return--;
State = save_State;
setmouse();
no_mapping--;

View File

@ -0,0 +1,10 @@
source-file=/home/zyx/a.a/Proj/c/neovim/src/nvim/move.c
i-file=/home/zyx/a.a/Proj/c/neovim/src/nvim/move.i
language=C
skip-cl-exe=yes
preprocessor=gcc
platform=linux64
lic-file=/home/zyx/a.a/Proj/c/neovim/build/../PVS-Studio.lic
output-file=/home/zyx/a.a/Proj/c/neovim/build/../PVS-Studio.log.x
analysis-mode=4

View File

@ -147,7 +147,7 @@ void channel_from_connection(SocketWatcher *watcher)
/// @param name The event name, an arbitrary string
/// @param args Array with event arguments
/// @return True if the event was sent successfully, false otherwise.
bool channel_send_event(uint64_t id, char *name, Array args)
bool channel_send_event(uint64_t id, const char *name, Array args)
{
Channel *channel = NULL;
@ -160,7 +160,7 @@ bool channel_send_event(uint64_t id, char *name, Array args)
if (channel) {
if (channel->pending_requests) {
// Pending request, queue the notification for later sending.
String method = cstr_as_string(name);
const String method = cstr_as_string((char *)name);
WBuffer *buffer = serialize_request(id, 0, method, args, &out_buffer, 1);
kv_push(channel->delayed_notifications, buffer);
} else {
@ -182,7 +182,7 @@ bool channel_send_event(uint64_t id, char *name, Array args)
/// @param[out] error True if the return value is an error
/// @return Whatever the remote method returned
Object channel_send_call(uint64_t id,
char *method_name,
const char *method_name,
Array args,
Error *err)
{
@ -519,10 +519,10 @@ static void send_error(Channel *channel, uint64_t id, char *err)
static void send_request(Channel *channel,
uint64_t id,
char *name,
const char *name,
Array args)
{
String method = {.size = strlen(name), .data = name};
const String method = cstr_as_string((char *)name);
channel_write(channel, serialize_request(channel->id,
id,
method,
@ -532,10 +532,10 @@ static void send_request(Channel *channel,
}
static void send_event(Channel *channel,
char *name,
const char *name,
Array args)
{
String method = {.size = strlen(name), .data = name};
const String method = cstr_as_string((char *)name);
channel_write(channel, serialize_request(channel->id,
0,
method,
@ -544,7 +544,7 @@ static void send_event(Channel *channel,
1));
}
static void broadcast_event(char *name, Array args)
static void broadcast_event(const char *name, Array args)
{
kvec_t(Channel *) subscribed = KV_INITIAL_VALUE;
Channel *channel;
@ -560,7 +560,7 @@ static void broadcast_event(char *name, Array args)
goto end;
}
String method = {.size = strlen(name), .data = name};
const String method = cstr_as_string((char *)name);
WBuffer *buffer = serialize_request(0,
0,
method,
@ -728,7 +728,7 @@ static void call_set_error(Channel *channel, char *msg)
static WBuffer *serialize_request(uint64_t channel_id,
uint64_t request_id,
String method,
const String method,
Array args,
msgpack_sbuffer *sbuffer,
size_t refcount)

View File

@ -322,7 +322,7 @@ void msgpack_rpc_from_float(Float result, msgpack_packer *res)
msgpack_pack_double(res, result);
}
void msgpack_rpc_from_string(String result, msgpack_packer *res)
void msgpack_rpc_from_string(const String result, msgpack_packer *res)
FUNC_ATTR_NONNULL_ARG(2)
{
msgpack_pack_str(res, result.size);
@ -478,7 +478,7 @@ Object msgpack_rpc_handle_invalid_arguments(uint64_t channel_id,
/// Serializes a msgpack-rpc request or notification(id == 0)
void msgpack_rpc_serialize_request(uint64_t request_id,
String method,
const String method,
Array args,
msgpack_packer *pac)
FUNC_ATTR_NONNULL_ARG(4)

View File

@ -1155,7 +1155,7 @@ static void normal_check_stuff_buffer(NormalState *s)
if (need_start_insertmode && goto_im() && !VIsual_active) {
need_start_insertmode = false;
stuffReadbuff((uint8_t *)"i"); // start insert mode next
stuffReadbuff("i"); // start insert mode next
// skip the fileinfo message now, because it would be shown
// after insert mode finishes!
need_fileinfo = false;
@ -1469,8 +1469,9 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
* If 'cpoptions' does not contain 'r', insert the search
* pattern to really repeat the same command.
*/
if (vim_strchr(p_cpo, CPO_REDO) == NULL)
if (vim_strchr(p_cpo, CPO_REDO) == NULL) {
AppendToRedobuffLit(cap->searchbuf, -1);
}
AppendToRedobuff(NL_STR);
} else if (cap->cmdchar == ':') {
/* do_cmdline() has stored the first typed line in
@ -1853,10 +1854,11 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
break;
case OP_FILTER:
if (vim_strchr(p_cpo, CPO_FILTER) != NULL)
AppendToRedobuff((char_u *)"!\r"); /* use any last used !cmd */
else
bangredo = true; /* do_bang() will put cmd in redo buffer */
if (vim_strchr(p_cpo, CPO_FILTER) != NULL) {
AppendToRedobuff("!\r"); // Use any last used !cmd.
} else {
bangredo = true; // do_bang() will put cmd in redo buffer.
}
case OP_INDENT:
case OP_COLON:
@ -2026,43 +2028,44 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
static void op_colon(oparg_T *oap)
{
stuffcharReadbuff(':');
if (oap->is_VIsual)
stuffReadbuff((char_u *)"'<,'>");
else {
/*
* Make the range look nice, so it can be repeated.
*/
if (oap->start.lnum == curwin->w_cursor.lnum)
if (oap->is_VIsual) {
stuffReadbuff("'<,'>");
} else {
// Make the range look nice, so it can be repeated.
if (oap->start.lnum == curwin->w_cursor.lnum) {
stuffcharReadbuff('.');
else
} else {
stuffnumReadbuff((long)oap->start.lnum);
}
if (oap->end.lnum != oap->start.lnum) {
stuffcharReadbuff(',');
if (oap->end.lnum == curwin->w_cursor.lnum)
if (oap->end.lnum == curwin->w_cursor.lnum) {
stuffcharReadbuff('.');
else if (oap->end.lnum == curbuf->b_ml.ml_line_count)
} else if (oap->end.lnum == curbuf->b_ml.ml_line_count) {
stuffcharReadbuff('$');
else if (oap->start.lnum == curwin->w_cursor.lnum) {
stuffReadbuff((char_u *)".+");
} else if (oap->start.lnum == curwin->w_cursor.lnum) {
stuffReadbuff(".+");
stuffnumReadbuff(oap->line_count - 1);
} else
} else {
stuffnumReadbuff((long)oap->end.lnum);
}
}
if (oap->op_type != OP_COLON)
stuffReadbuff((char_u *)"!");
}
if (oap->op_type != OP_COLON) {
stuffReadbuff("!");
}
if (oap->op_type == OP_INDENT) {
stuffReadbuff(get_equalprg());
stuffReadbuff((char_u *)"\n");
stuffReadbuff((const char *)get_equalprg());
stuffReadbuff("\n");
} else if (oap->op_type == OP_FORMAT) {
if (*curbuf->b_p_fp != NUL) {
stuffReadbuff(curbuf->b_p_fp);
stuffReadbuff((const char *)curbuf->b_p_fp);
} else if (*p_fp != NUL) {
stuffReadbuff(p_fp);
stuffReadbuff((const char *)p_fp);
} else {
stuffReadbuff((char_u *)"fmt");
stuffReadbuff("fmt");
}
stuffReadbuff((char_u *)"\n']");
stuffReadbuff("\n']");
}
/*
@ -2075,7 +2078,6 @@ static void op_colon(oparg_T *oap)
*/
static void op_function(oparg_T *oap)
{
char_u *(argv[1]);
int save_virtual_op = virtual_op;
if (*p_opfunc == NUL)
@ -2089,16 +2091,16 @@ static void op_function(oparg_T *oap)
decl(&curbuf->b_op_end);
}
if (oap->motion_type == kMTBlockWise) {
argv[0] = (char_u *)"block";
} else if (oap->motion_type == kMTLineWise) {
argv[0] = (char_u *)"line";
} else {
argv[0] = (char_u *)"char";
}
const char_u *const argv[1] = {
(const char_u *)(((const char *const[]) {
[kMTBlockWise] = "block",
[kMTLineWise] = "line",
[kMTCharWise] = "char",
})[oap->motion_type]),
};
/* Reset virtual_op so that 'virtualedit' can be changed in the
* function. */
// Reset virtual_op so that 'virtualedit' can be changed in the
// function.
virtual_op = MAYBE;
(void)call_func_retnr(p_opfunc, 1, argv, false);
@ -2305,7 +2307,7 @@ do_mouse (
if (VIsual_active) {
if (VIsual_select) {
stuffcharReadbuff(Ctrl_G);
stuffReadbuff((char_u *)"\"+p");
stuffReadbuff("\"+p");
} else {
stuffcharReadbuff('y');
stuffcharReadbuff(K_MIDDLEMOUSE);
@ -2465,7 +2467,7 @@ do_mouse (
&rettv, ARRAY_SIZE(argv), argv, NULL,
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
&doesrange, true, NULL, NULL);
clear_tv(&rettv);
tv_clear(&rettv);
break;
}
}
@ -4477,7 +4479,7 @@ static void nv_colon(cmdarg_T *cap)
/* translate "count:" into ":.,.+(count - 1)" */
stuffcharReadbuff('.');
if (cap->count0 > 1) {
stuffReadbuff((char_u *)",.+");
stuffReadbuff(",.+");
stuffnumReadbuff(cap->count0 - 1L);
}
}
@ -4757,7 +4759,7 @@ static void nv_ident(cmdarg_T *cap)
ptr = vim_strnsave(ptr, n);
if (kp_ex) {
// Escape the argument properly for an Ex command
p = vim_strsave_fnameescape(ptr, false);
p = (char_u *)vim_strsave_fnameescape((const char *)ptr, false);
} else {
// Escape the argument properly for a shell command
p = vim_strsave_shellescape(ptr, true, true);
@ -6157,17 +6159,15 @@ static void nv_abbrev(cmdarg_T *cap)
*/
static void nv_optrans(cmdarg_T *cap)
{
static char_u *(ar[8]) = {(char_u *)"dl", (char_u *)"dh",
(char_u *)"d$", (char_u *)"c$",
(char_u *)"cl", (char_u *)"cc",
(char_u *)"yy", (char_u *)":s\r"};
static char_u *str = (char_u *)"xXDCsSY&";
static const char *(ar[]) = { "dl", "dh", "d$", "c$", "cl", "cc", "yy",
":s\r" };
static const char *str = "xXDCsSY&";
if (!checkclearopq(cap->oap)) {
if (cap->count0) {
stuffnumReadbuff(cap->count0);
}
stuffReadbuff(ar[(int)(vim_strchr(str, cap->cmdchar) - str)]);
stuffReadbuff(ar[strchr(str, (char)cap->cmdchar) - str]);
}
cap->opcount = 0;
}
@ -7290,11 +7290,11 @@ static bool unadjust_for_sel(void)
pp = &curwin->w_cursor;
else
pp = &VIsual;
if (pp->coladd > 0)
--pp->coladd;
else if (pp->col > 0) {
--pp->col;
mb_adjustpos(curbuf, pp);
if (pp->coladd > 0) {
pp->coladd--;
} else if (pp->col > 0) {
pp->col--;
mark_mb_adjustpos(curbuf, pp);
} else if (pp->lnum > 1) {
--pp->lnum;
pp->col = (colnr_T)STRLEN(ml_get(pp->lnum));
@ -7829,7 +7829,7 @@ static void get_op_vcol(
// prevent from moving onto a trail byte
if (has_mbyte) {
mb_adjustpos(curwin->w_buffer, &oap->end);
mark_mb_adjustpos(curwin->w_buffer, &oap->end);
}
getvvcol(curwin, &(oap->start), &oap->start_vcol, NULL, &oap->end_vcol);

View File

@ -14,8 +14,10 @@
#include "nvim/buffer.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
#include "nvim/assert.h"
#include "nvim/edit.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds2.h"
#include "nvim/ex_getln.h"
@ -41,6 +43,7 @@
#include "nvim/terminal.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/macros.h"
#include "nvim/window.h"
#include "nvim/os/input.h"
#include "nvim/os/time.h"
@ -888,7 +891,7 @@ static void set_yreg_additional_data(yankreg_T *reg, dict_T *additional_data)
if (reg->additional_data == additional_data) {
return;
}
dict_unref(reg->additional_data);
tv_dict_unref(reg->additional_data);
reg->additional_data = additional_data;
}
@ -1106,7 +1109,6 @@ int insert_reg(
)
{
int retval = OK;
char_u *arg;
int allocated;
/*
@ -1122,21 +1124,24 @@ int insert_reg(
if (regname != NUL && !valid_yank_reg(regname, false))
return FAIL;
if (regname == '.') /* insert last inserted text */
retval = stuff_inserted(NUL, 1L, TRUE);
else if (get_spec_reg(regname, &arg, &allocated, TRUE)) {
if (arg == NULL)
char_u *arg;
if (regname == '.') { // Insert last inserted text.
retval = stuff_inserted(NUL, 1L, true);
} else if (get_spec_reg(regname, &arg, &allocated, true)) {
if (arg == NULL) {
return FAIL;
stuffescaped(arg, literally);
if (allocated)
}
stuffescaped((const char *)arg, literally);
if (allocated) {
xfree(arg);
} else { /* name or number register */
}
} else { // Name or number register.
yankreg_T *reg = get_yank_register(regname, YREG_PASTE);
if (reg->y_array == NULL) {
retval = FAIL;
} else {
for (size_t i = 0; i < reg->y_size; i++) {
stuffescaped(reg->y_array[i], literally);
stuffescaped((const char *)reg->y_array[i], literally);
// Insert a newline between lines and after last line if
// y_type is kMTLineWise.
if (reg->y_type == kMTLineWise || i < reg->y_size - 1) {
@ -1153,29 +1158,29 @@ int insert_reg(
* Stuff a string into the typeahead buffer, such that edit() will insert it
* literally ("literally" TRUE) or interpret is as typed characters.
*/
static void stuffescaped(char_u *arg, int literally)
static void stuffescaped(const char *arg, int literally)
{
int c;
char_u *start;
while (*arg != NUL) {
/* Stuff a sequence of normal ASCII characters, that's fast. Also
* stuff K_SPECIAL to get the effect of a special key when "literally"
* is TRUE. */
start = arg;
while ((*arg >= ' ' && *arg < DEL) || (*arg == K_SPECIAL && !literally))
++arg;
if (arg > start)
// Stuff a sequence of normal ASCII characters, that's fast. Also
// stuff K_SPECIAL to get the effect of a special key when "literally"
// is TRUE.
const char *const start = arg;
while ((*arg >= ' ' && *arg < DEL) || ((uint8_t)(*arg) == K_SPECIAL
&& !literally)) {
arg++;
}
if (arg > start) {
stuffReadbuffLen(start, (long)(arg - start));
}
/* stuff a single special character */
if (*arg != NUL) {
if (has_mbyte)
c = mb_cptr2char_adv(&arg);
else
c = *arg++;
if (literally && ((c < ' ' && c != TAB) || c == DEL))
const int c = (has_mbyte
? mb_cptr2char_adv((const char_u **)&arg)
: (uint8_t)(*arg++));
if (literally && ((c < ' ' && c != TAB) || c == DEL)) {
stuffcharReadbuff(Ctrl_V);
}
stuffcharReadbuff(c);
}
}
@ -2555,33 +2560,33 @@ static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg)
dict_T *dict = get_vim_var_dict(VV_EVENT);
// the yanked text
list_T *list = list_alloc();
list_T *list = tv_list_alloc();
for (size_t i = 0; i < reg->y_size; i++) {
list_append_string(list, reg->y_array[i], -1);
tv_list_append_string(list, (const char *)reg->y_array[i], -1);
}
list->lv_lock = VAR_FIXED;
dict_add_list(dict, "regcontents", list);
tv_dict_add_list(dict, S_LEN("regcontents"), list);
// the register type
char buf[NUMBUFLEN+2];
format_reg_type(reg->y_type, reg->y_width, buf, ARRAY_SIZE(buf));
dict_add_nr_str(dict, "regtype", 0, (char_u *)buf);
tv_dict_add_str(dict, S_LEN("regtype"), buf);
// name of requested register or the empty string for an unnamed operation.
buf[0] = (char)oap->regname;
buf[1] = NUL;
dict_add_nr_str(dict, "regname", 0, (char_u *)buf);
tv_dict_add_str(dict, S_LEN("regname"), buf);
// kind of operation (yank/delete/change)
buf[0] = (char)get_op_char(oap->op_type);
buf[1] = NUL;
dict_add_nr_str(dict, "operator", 0, (char_u *)buf);
tv_dict_add_str(dict, S_LEN("operator"), buf);
dict_set_keys_readonly(dict);
tv_dict_set_keys_readonly(dict);
textlock++;
apply_autocmds(EVENT_TEXTYANKPOST, NULL, NULL, false, curbuf);
textlock--;
dict_clear(dict);
tv_dict_clear(dict);
recursive = false;
}
@ -2660,7 +2665,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
// back to the previous line in the case of 'noautoindent' and
// 'backspace' includes "eol". So we insert a dummy space for Ctrl_U
// to consume.
stuffReadbuff((char_u *)"\n ");
stuffReadbuff("\n ");
stuffcharReadbuff(Ctrl_U);
}
}
@ -2672,7 +2677,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
// character. Simulate it with motion commands after the insert.
if (flags & PUT_CURSEND) {
if (flags & PUT_LINE) {
stuffReadbuff((char_u *)"j0");
stuffReadbuff("j0");
} else {
// Avoid ringing the bell from attempting to move into the space after
// the current line. We can stuff the readbuffer with "l" if:
@ -2702,7 +2707,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
}
}
} else if (flags & PUT_LINE) {
stuffReadbuff((char_u *)"g'[");
stuffReadbuff("g'[");
}
// So the 'u' command restores cursor position after ".p, save the cursor
@ -4844,8 +4849,8 @@ static void *get_reg_wrap_one_line(char_u *s, int flags)
if (!(flags & kGRegList)) {
return s;
}
list_T *list = list_alloc();
list_append_string(list, NULL, -1);
list_T *list = tv_list_alloc();
tv_list_append_string(list, NULL, 0);
list->lv_first->li_tv.vval.v_string = s;
return list;
}
@ -4895,9 +4900,9 @@ void *get_reg_contents(int regname, int flags)
return NULL;
if (flags & kGRegList) {
list_T *list = list_alloc();
list_T *list = tv_list_alloc();
for (size_t i = 0; i < reg->y_size; i++) {
list_append_string(list, reg->y_array[i], -1);
tv_list_append_string(list, (const char *)reg->y_array[i], -1);
}
return list;
@ -4978,7 +4983,7 @@ void write_reg_contents(int name, const char_u *str, ssize_t len,
write_reg_contents_ex(name, str, len, must_append, kMTUnknown, 0L);
}
void write_reg_contents_lst(int name, char_u **strings, int maxlen,
void write_reg_contents_lst(int name, char_u **strings,
bool must_append, MotionType yank_type,
colnr_T block_len)
{
@ -5482,16 +5487,18 @@ void cursor_pos_info(dict_T *dict)
if (dict != NULL) {
// Don't shorten this message, the user asked for it.
dict_add_nr_str(dict, "words", word_count, NULL);
dict_add_nr_str(dict, "chars", char_count, NULL);
dict_add_nr_str(dict, "bytes", byte_count + bom_count, NULL);
tv_dict_add_nr(dict, S_LEN("words"), (varnumber_T)word_count);
tv_dict_add_nr(dict, S_LEN("chars"), (varnumber_T)char_count);
tv_dict_add_nr(dict, S_LEN("bytes"), (varnumber_T)(byte_count + bom_count));
dict_add_nr_str(dict, l_VIsual_active ? "visual_bytes" : "cursor_bytes",
byte_count_cursor, NULL);
dict_add_nr_str(dict, l_VIsual_active ? "visual_chars" : "cursor_chars",
char_count_cursor, NULL);
dict_add_nr_str(dict, l_VIsual_active ? "visual_words" : "cursor_words",
word_count_cursor, NULL);
STATIC_ASSERT(sizeof("visual") == sizeof("cursor"),
"key_len argument in tv_dict_add_nr is wrong");
tv_dict_add_nr(dict, l_VIsual_active ? "visual_bytes" : "cursor_bytes",
sizeof("visual_bytes") - 1, (varnumber_T)byte_count_cursor);
tv_dict_add_nr(dict, l_VIsual_active ? "visual_chars" : "cursor_chars",
sizeof("visual_chars") - 1, (varnumber_T)char_count_cursor);
tv_dict_add_nr(dict, l_VIsual_active ? "visual_words" : "cursor_words",
sizeof("visual_words") - 1, (varnumber_T)word_count_cursor);
}
}
@ -5570,9 +5577,9 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
}
free_register(reg);
list_T *args = list_alloc();
char_u regname = (char_u)name;
list_append_string(args, &regname, 1);
list_T *const args = tv_list_alloc();
const char regname = (char)name;
tv_list_append_string(args, &regname, 1);
typval_T result = eval_call_provider("clipboard", "get", args);
@ -5584,7 +5591,8 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
goto err;
}
list_T *res = result.vval.v_list, *lines = NULL;
list_T *res = result.vval.v_list;
list_T *lines = NULL;
if (res->lv_len == 2 && res->lv_first->li_tv.v_type == VAR_LIST) {
lines = res->lv_first->li_tv.vval.v_list;
if (res->lv_last->li_tv.v_type != VAR_STRING) {
@ -5628,7 +5636,7 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
if (li->li_tv.v_type != VAR_STRING) {
goto err;
}
reg->y_array[i++] = (uint8_t *)xstrdup((char *)li->li_tv.vval.v_string);
reg->y_array[i++] = (char_u *)xstrdupnul((char *)li->li_tv.vval.v_string);
}
if (reg->y_size > 0 && strlen((char*)reg->y_array[reg->y_size-1]) == 0) {
@ -5686,35 +5694,39 @@ static void set_clipboard(int name, yankreg_T *reg)
return;
}
list_T *lines = list_alloc();
list_T *lines = tv_list_alloc();
for (size_t i = 0; i < reg->y_size; i++) {
list_append_string(lines, reg->y_array[i], -1);
tv_list_append_string(lines, (const char *)reg->y_array[i], -1);
}
list_T *args = list_alloc();
list_append_list(args, lines);
list_T *args = tv_list_alloc();
tv_list_append_list(args, lines);
char_u regtype;
char regtype;
switch (reg->y_type) {
case kMTLineWise:
case kMTLineWise: {
regtype = 'V';
list_append_string(lines, (char_u*)"", 0);
tv_list_append_string(lines, NULL, 0);
break;
case kMTCharWise:
}
case kMTCharWise: {
regtype = 'v';
break;
case kMTBlockWise:
}
case kMTBlockWise: {
regtype = 'b';
list_append_string(lines, (char_u*)"", 0);
tv_list_append_string(lines, NULL, 0);
break;
case kMTUnknown:
}
case kMTUnknown: {
assert(false);
}
list_append_string(args, &regtype, 1);
}
tv_list_append_string(args, &regtype, 1);
char_u regname = (char_u)name;
list_append_string(args, &regname, 1);
const char regname = (char)name;
tv_list_append_string(args, &regname, 1);
(void)eval_call_provider("clipboard", "set", args);
}

View File

@ -6,7 +6,7 @@
#include "nvim/macros.h"
#include "nvim/ascii.h"
#include "nvim/types.h"
#include "nvim/eval_defs.h"
#include "nvim/eval/typval.h"
#include "nvim/os/time.h"
typedef int (*Indenter)(void);

View File

@ -25,6 +25,7 @@
#include <limits.h>
#include "nvim/vim.h"
#include "nvim/macros.h"
#include "nvim/ascii.h"
#include "nvim/edit.h"
#include "nvim/option.h"
@ -34,6 +35,7 @@
#include "nvim/diff.h"
#include "nvim/digraph.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
#include "nvim/ex_cmds2.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
@ -604,7 +606,7 @@ void set_init_1(void)
/*
* 'maxmemtot' and 'maxmem' may have to be adjusted for available memory
*/
opt_idx = findoption((char_u *)"maxmemtot");
opt_idx = findoption("maxmemtot");
if (opt_idx >= 0) {
{
/* Use half of amount of memory available to Vim. */
@ -614,7 +616,7 @@ void set_init_1(void)
? UINTPTR_MAX
: (uintptr_t)(available_kib /2);
options[opt_idx].def_val[VI_DEFAULT] = (char_u *)n;
opt_idx = findoption((char_u *)"maxmem");
opt_idx = findoption("maxmem");
if (opt_idx >= 0) {
options[opt_idx].def_val[VI_DEFAULT] = (char_u *)n;
}
@ -645,7 +647,7 @@ void set_init_1(void)
}
}
buf[j] = NUL;
opt_idx = findoption((char_u *)"cdpath");
opt_idx = findoption("cdpath");
if (opt_idx >= 0) {
options[opt_idx].def_val[VI_DEFAULT] = buf;
options[opt_idx].flags |= P_DEF_ALLOCED;
@ -764,8 +766,9 @@ void set_init_1(void)
* NOTE: mlterm's author is being asked to 'set' a variable
* instead of an environment variable due to inheritance.
*/
if (os_env_exists("MLTERM"))
set_option_value((char_u *)"tbidi", 1L, NULL, 0);
if (os_env_exists("MLTERM")) {
set_option_value("tbidi", 1L, NULL, 0);
}
didset_options2();
@ -775,7 +778,7 @@ void set_init_1(void)
char_u *p = enc_locale();
if (p == NULL) {
// use utf-8 as 'default' if locale encoding can't be detected.
p = vim_strsave((char_u *)"utf-8");
p = (char_u *)xmemdupz(S_LEN("utf-8"));
}
fenc_default = p;
@ -882,7 +885,7 @@ set_options_default (
static void set_string_default(const char *name, char *val, bool allocated)
FUNC_ATTR_NONNULL_ALL
{
int opt_idx = findoption((char_u *)name);
int opt_idx = findoption(name);
if (opt_idx >= 0) {
if (options[opt_idx].flags & P_DEF_ALLOCED) {
xfree(options[opt_idx].def_val[VI_DEFAULT]);
@ -904,10 +907,11 @@ void set_number_default(char *name, long val)
{
int opt_idx;
opt_idx = findoption((char_u *)name);
if (opt_idx >= 0)
opt_idx = findoption(name);
if (opt_idx >= 0) {
options[opt_idx].def_val[VI_DEFAULT] = (char_u *)val;
}
}
#if defined(EXITFREE)
/*
@ -947,17 +951,19 @@ void set_init_2(void)
* wrong when the window height changes.
*/
set_number_default("scroll", Rows / 2);
idx = findoption((char_u *)"scroll");
if (idx >= 0 && !(options[idx].flags & P_WAS_SET))
idx = findoption("scroll");
if (idx >= 0 && !(options[idx].flags & P_WAS_SET)) {
set_option_default(idx, OPT_LOCAL, p_cp);
}
comp_col();
/*
* 'window' is only for backwards compatibility with Vi.
* Default is Rows - 1.
*/
if (!option_was_set((char_u *)"window"))
if (!option_was_set("window")) {
p_window = Rows - 1;
}
set_number_default("window", Rows - 1);
parse_shape_opt(SHAPE_CURSOR); /* set cursor shapes from 'guicursor' */
(void)parse_printoptions(); /* parse 'printoptions' default value */
@ -976,16 +982,18 @@ void set_init_3(void)
int idx_sp;
int do_sp;
idx_srr = findoption((char_u *)"srr");
if (idx_srr < 0)
do_srr = FALSE;
else
idx_srr = findoption("srr");
if (idx_srr < 0) {
do_srr = false;
} else {
do_srr = !(options[idx_srr].flags & P_WAS_SET);
idx_sp = findoption((char_u *)"sp");
if (idx_sp < 0)
do_sp = FALSE;
else
}
idx_sp = findoption("sp");
if (idx_sp < 0) {
do_sp = false;
} else {
do_sp = !(options[idx_sp].flags & P_WAS_SET);
}
size_t len = 0;
char_u *p = (char_u *)invocation_path_tail(p_sh, &len);
@ -1029,7 +1037,7 @@ void set_init_3(void)
}
if (bufempty()) {
int idx_ffs = findoption((char_u *)"ffs");
int idx_ffs = findoption_len(S_LEN("ffs"));
// Apply the first entry of 'fileformats' to the initial buffer.
if (idx_ffs >= 0 && (options[idx_ffs].flags & P_WAS_SET)) {
@ -1048,14 +1056,16 @@ void set_helplang_default(const char *lang)
{
int idx;
if (lang == NULL || STRLEN(lang) < 2) /* safety check */
const size_t lang_len = strlen(lang);
if (lang == NULL || lang_len < 2) { // safety check
return;
idx = findoption((char_u *)"hlg");
}
idx = findoption("hlg");
if (idx >= 0 && !(options[idx].flags & P_WAS_SET)) {
if (options[idx].flags & P_ALLOCED)
free_string_option(p_hlg);
p_hlg = (char_u *)xstrdup(lang);
/* zh_CN becomes "cn", zh_TW becomes "tw". */
p_hlg = (char_u *)xmemdupz(lang, lang_len);
// zh_CN becomes "cn", zh_TW becomes "tw".
if (STRNICMP(p_hlg, "zh_", 3) == 0 && STRLEN(p_hlg) >= 5) {
p_hlg[0] = (char_u)TOLOWER_ASC(p_hlg[3]);
p_hlg[1] = (char_u)TOLOWER_ASC(p_hlg[4]);
@ -1082,12 +1092,12 @@ void set_title_defaults(void)
* icon name. Saves a bit of time, because the X11 display server does
* not need to be contacted.
*/
idx1 = findoption((char_u *)"title");
idx1 = findoption("title");
if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET)) {
options[idx1].def_val[VI_DEFAULT] = (char_u *)(intptr_t)0;
p_title = 0;
}
idx1 = findoption((char_u *)"icon");
idx1 = findoption("icon");
if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET)) {
options[idx1].def_val[VI_DEFAULT] = (char_u *)(intptr_t)0;
p_icon = 0;
@ -1193,7 +1203,7 @@ do_set (
goto skip;
}
if (arg[1] == 't' && arg[2] == '_') { // could be term code
opt_idx = findoption_len(arg + 1, (size_t) (len - 1));
opt_idx = findoption_len((const char *)arg + 1, (size_t)(len - 1));
}
len++;
if (opt_idx == -1) {
@ -1209,7 +1219,7 @@ do_set (
len++;
}
}
opt_idx = findoption_len(arg, (size_t) len);
opt_idx = findoption_len((const char *)arg, (size_t)len);
if (opt_idx == -1) {
key = find_key_option(arg);
}
@ -1391,11 +1401,10 @@ do_set (
value = prefix;
}
errmsg = set_bool_option(opt_idx, varp, (int)value,
errmsg = (char_u *)set_bool_option(opt_idx, varp, (int)value,
opt_flags);
} else { /* numeric or string */
if (vim_strchr((char_u *)"=:&<", nextchar) == NULL
|| prefix != 1) {
} else { // Numeric or string.
if (strchr("=:&<", nextchar) == NULL || prefix != 1) {
errmsg = e_invarg;
goto skip;
}
@ -1448,15 +1457,19 @@ do_set (
goto skip;
}
if (adding)
if (adding) {
value = *(long *)varp + value;
if (prepending)
}
if (prepending) {
value = *(long *)varp * value;
if (removing)
}
if (removing) {
value = *(long *)varp - value;
errmsg = set_num_option(opt_idx, varp, value,
errbuf, sizeof(errbuf), opt_flags);
} else if (opt_idx >= 0) { /* string */
}
errmsg = (char_u *)set_num_option(opt_idx, varp, value,
errbuf, sizeof(errbuf),
opt_flags);
} else if (opt_idx >= 0) { // String.
char_u *save_arg = NULL;
char_u *s = NULL;
char_u *oldval = NULL; // previous value if *varp
@ -2221,7 +2234,7 @@ static void check_string_option(char_u **pp)
*/
int was_set_insecurely(char_u *opt, int opt_flags)
{
int idx = findoption(opt);
int idx = findoption((const char *)opt);
if (idx >= 0) {
uint32_t *flagp = insecure_flag(idx, opt_flags);
@ -2283,9 +2296,9 @@ set_string_option_direct (
int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
int idx = opt_idx;
if (idx == -1) { /* use name */
idx = findoption(name);
if (idx < 0) { /* not found (should not happen) */
if (idx == -1) { // Use name.
idx = findoption((const char *)name);
if (idx < 0) { // Not found (should not happen).
EMSG2(_(e_intern2), "set_string_option_direct()");
EMSG2(_("For option %s"), name);
return;
@ -2569,7 +2582,7 @@ did_set_string_option (
// The color scheme must have set 'background' back to another
// value, that's not what we want here. Disable the color
// scheme and set the colors again.
do_unlet((char_u *)"g:colors_name", true);
do_unlet(S_LEN("g:colors_name"), true);
free_string_option(p_bg);
p_bg = vim_strsave((char_u *)(dark ? "dark" : "light"));
check_string_option(&p_bg);
@ -2765,7 +2778,7 @@ did_set_string_option (
// option.
opt_idx = ((options[opt_idx].fullname[0] == 'v')
? (shada_idx == -1
? ((shada_idx = findoption((char_u *) "shada")))
? ((shada_idx = findoption("shada")))
: shada_idx)
: opt_idx);
// Update free_oldval now that we have the opt_idx for 'shada', otherwise
@ -3406,16 +3419,19 @@ static char_u *set_chars_option(char_u **varp)
&& p[len] == ':'
&& p[len + 1] != NUL) {
s = p + len + 1;
c1 = mb_ptr2char_adv(&s);
if (mb_char2cells(c1) > 1)
c1 = mb_ptr2char_adv((const char_u **)&s);
if (mb_char2cells(c1) > 1) {
continue;
}
if (tab[i].cp == &lcs_tab2) {
if (*s == NUL)
if (*s == NUL) {
continue;
c2 = mb_ptr2char_adv(&s);
if (mb_char2cells(c2) > 1)
}
c2 = mb_ptr2char_adv((const char_u **)&s);
if (mb_char2cells(c2) > 1) {
continue;
}
}
if (*s == ',' || *s == NUL) {
if (round) {
if (tab[i].cp == &lcs_tab2) {
@ -3575,24 +3591,24 @@ static void set_option_scriptID_idx(int opt_idx, int opt_flags, int id)
}
}
/*
* Set the value of a boolean option, and take care of side effects.
* Returns NULL for success, or an error message for an error.
*/
static char_u *
set_bool_option (
int opt_idx, /* index in options[] table */
char_u *varp, /* pointer to the option variable */
int value, /* new value */
int opt_flags /* OPT_LOCAL and/or OPT_GLOBAL */
)
/// Set the value of a boolean option, taking care of side effects
///
/// @param[in] opt_idx Option index in options[] table.
/// @param[out] varp Pointer to the option variable.
/// @param[in] value New value.
/// @param[in] opt_flags OPT_LOCAL and/or OPT_GLOBAL.
///
/// @return NULL on success, error message on error.
static char *set_bool_option(const int opt_idx, char_u *const varp,
const int value,
const int opt_flags)
{
int old_value = *(int *)varp;
/* Disallow changing some options from secure mode */
if ((secure || sandbox != 0)
&& (options[opt_idx].flags & P_SECURE)) {
return e_secure;
return (char *)e_secure;
}
*(int *)varp = value; /* set the new value */
@ -3605,20 +3621,18 @@ set_bool_option (
*(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) = value;
// Ensure that options set to p_force_on cannot be disabled.
if ((int *)varp == &p_force_on && p_force_on == FALSE) {
p_force_on = TRUE;
return e_unsupportedoption;
}
if ((int *)varp == &p_force_on && p_force_on == false) {
p_force_on = true;
return (char *)e_unsupportedoption;
// Ensure that options set to p_force_off cannot be enabled.
else if ((int *)varp == &p_force_off && p_force_off == TRUE) {
p_force_off = FALSE;
return e_unsupportedoption;
}
/* 'undofile' */
else if ((int *)varp == &curbuf->b_p_udf || (int *)varp == &p_udf) {
/* Only take action when the option was set. When reset we do not
* delete the undo file, the option may be set again without making
* any changes in between. */
} else if ((int *)varp == &p_force_off && p_force_off == true) {
p_force_off = false;
return (char *)e_unsupportedoption;
// 'undofile'
} else if ((int *)varp == &curbuf->b_p_udf || (int *)varp == &p_udf) {
// Only take action when the option was set. When reset we do not
// delete the undo file, the option may be set again without making
// any changes in between.
if (curbuf->b_p_udf || p_udf) {
char_u hash[UNDO_HASH_SIZE];
buf_T *save_curbuf = curbuf;
@ -3740,8 +3754,8 @@ set_bool_option (
if (curwin->w_p_pvw) {
FOR_ALL_WINDOWS_IN_TAB(win, curtab) {
if (win->w_p_pvw && win != curwin) {
curwin->w_p_pvw = FALSE;
return (char_u *)N_("E590: A preview window already exists");
curwin->w_p_pvw = false;
return N_("E590: A preview window already exists");
}
}
}
@ -3889,9 +3903,8 @@ set_bool_option (
/* set 'delcombine' */
p_deco = TRUE;
/* Force-set the necessary keymap for arabic */
set_option_value((char_u *)"keymap", 0L, (char_u *)"arabic",
OPT_LOCAL);
// Force-set the necessary keymap for arabic.
set_option_value("keymap", 0L, "arabic", OPT_LOCAL);
p_altkeymap = 0;
p_hkmap = 0;
p_fkmap = 0;
@ -3957,20 +3970,18 @@ set_bool_option (
return NULL;
}
/*
* Set the value of a number option, and take care of side effects.
* Returns NULL for success, or an error message for an error.
*/
static char_u *
set_num_option (
int opt_idx, /* index in options[] table */
char_u *varp, /* pointer to the option variable */
long value, /* new value */
char_u *errbuf, /* buffer for error messages */
size_t errbuflen, /* length of "errbuf" */
int opt_flags /* OPT_LOCAL, OPT_GLOBAL and
OPT_MODELINE */
)
/// Set the value of a number option, taking care of side effects
///
/// @param[in] opt_idx Option index in options[] table.
/// @param[out] varp Pointer to the option variable.
/// @param[in] value New value.
/// @param errbuf Buffer for error messages.
/// @param[in] errbuflen Length of `errbuf`.
/// @param[in] opt_flags OPT_LOCAL, OPT_GLOBAL or OPT_MODELINE.
///
/// @return NULL on success, error message on error.
static char *set_num_option(int opt_idx, char_u *varp, long value,
char_u *errbuf, size_t errbuflen, int opt_flags)
{
char_u *errmsg = NULL;
long old_value = *(long *)varp;
@ -3981,7 +3992,7 @@ set_num_option (
/* Disallow changing some options from secure mode. */
if ((secure || sandbox != 0)
&& (options[opt_idx].flags & P_SECURE)) {
return e_secure;
return (char *)e_secure;
}
*pp = value;
@ -4251,9 +4262,10 @@ set_num_option (
cmdline_row = (int)(Rows - p_ch);
}
}
if (p_window >= Rows || !option_was_set((char_u *)"window"))
if (p_window >= Rows || !option_was_set("window")) {
p_window = Rows - 1;
}
}
if (curbuf->b_p_ts <= 0) {
errmsg = e_positive;
@ -4357,7 +4369,7 @@ set_num_option (
curwin->w_set_curswant = TRUE;
check_redraw(options[opt_idx].flags);
return errmsg;
return (char *)errmsg;
}
/*
@ -4395,39 +4407,36 @@ static void check_redraw(uint32_t flags)
/// @param[in] len Length of the option.
///
/// @return Index of the option or -1 if option was not found.
int findoption_len(const char_u *const arg, const size_t len)
int findoption_len(const char *const arg, const size_t len)
{
char *s, *p;
const char *s;
const char *p;
static int quick_tab[27] = { 0, 0 }; // quick access table
int is_term_opt;
/*
* For first call: Initialize the quick-access table.
* It contains the index for the first option that starts with a certain
* letter. There are 26 letters, plus the first "t_" option.
*/
// For first call: Initialize the quick-access table.
// It contains the index for the first option that starts with a certain
// letter. There are 26 letters, plus the first "t_" option.
if (quick_tab[1] == 0) {
p = options[0].fullname;
for (short int i = 1; (s = options[i].fullname) != NULL; i++) {
if (s[0] != p[0]) {
if (s[0] == 't' && s[1] == '_')
if (s[0] == 't' && s[1] == '_') {
quick_tab[26] = i;
else
} else {
quick_tab[CharOrdLow(s[0])] = i;
}
}
p = s;
}
}
/*
* Check for name starting with an illegal character.
*/
// Check for name starting with an illegal character.
if (len == 0 || arg[0] < 'a' || arg[0] > 'z') {
return -1;
}
int opt_idx;
is_term_opt = (len > 2 && arg[0] == 't' && arg[1] == '_');
const bool is_term_opt = (len > 2 && arg[0] == 't' && arg[1] == '_');
if (is_term_opt) {
opt_idx = quick_tab[26];
} else {
@ -4435,7 +4444,7 @@ int findoption_len(const char_u *const arg, const size_t len)
}
// Match full name
for (; (s = options[opt_idx].fullname) != NULL; opt_idx++) {
if (STRNCMP(arg, s, len) == 0 && s[len] == NUL) {
if (strncmp(arg, s, len) == 0 && s[len] == NUL) {
break;
}
}
@ -4444,20 +4453,22 @@ int findoption_len(const char_u *const arg, const size_t len)
// Match short name
for (; options[opt_idx].fullname != NULL; opt_idx++) {
s = options[opt_idx].shortname;
if (s != NULL && STRNCMP(arg, s, len) == 0 && s[len] == NUL) {
if (s != NULL && strncmp(arg, s, len) == 0 && s[len] == NUL) {
break;
}
s = NULL;
}
}
if (s == NULL)
if (s == NULL) {
opt_idx = -1;
}
return opt_idx;
}
bool is_tty_option(char *name)
bool is_tty_option(const char *name)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
return (name[0] == 't' && name[1] == '_') || !strcmp((char *)name, "term");
return (name[0] == 't' && name[1] == '_') || strcmp(name, "term") == 0;
}
#define TCO_BUFFER_SIZE 8
@ -4493,7 +4504,7 @@ bool get_tty_option(char *name, char **value)
return false;
}
bool set_tty_option(char *name, char *value)
bool set_tty_option(const char *name, const char *value)
{
if (!strcmp(name, "t_Co")) {
int colors = atoi(value);
@ -4504,23 +4515,24 @@ bool set_tty_option(char *name, char *value)
if (colors != t_colors) {
t_colors = colors;
// We now have a different color setup, initialize it again.
init_highlight(TRUE, FALSE);
init_highlight(true, false);
}
return true;
}
return is_tty_option(name) || !strcmp(name, "term")
|| !strcmp(name, "ttytype");
return (is_tty_option(name) || !strcmp(name, "term")
|| !strcmp(name, "ttytype"));
}
/*
* Find index for option 'arg'.
* Return -1 if not found.
*/
static int findoption(char_u *arg)
/// Find index for an option
///
/// @param[in] arg Option name.
///
/// @return Option index or -1 if option was not found.
static int findoption(const char *const arg)
{
return findoption_len(arg, STRLEN(arg));
return findoption_len(arg, strlen(arg));
}
/*
@ -4548,9 +4560,10 @@ get_option_value (
int opt_idx;
char_u *varp;
opt_idx = findoption(name);
if (opt_idx < 0) /* unknown option */
opt_idx = findoption((const char *)name);
if (opt_idx < 0) { // Unknown option.
return -3;
}
varp = get_varp_scope(&(options[opt_idx]), opt_flags);
@ -4608,7 +4621,7 @@ int get_option_value_strict(char *name,
char_u *varp = NULL;
vimoption_T *p;
int rv = 0;
int opt_idx = findoption((uint8_t *)name);
int opt_idx = findoption(name);
if (opt_idx < 0) {
return 0;
}
@ -4702,21 +4715,19 @@ int get_option_value_strict(char *name,
return rv;
}
/*
* Set the value of option "name".
* Use "string" for string options, use "number" for other options.
*
* Returns NULL on success or error message on error.
*/
char_u *
set_option_value (
char_u *name,
long number,
char_u *string,
int opt_flags /* OPT_LOCAL or 0 (both) */
)
/// Set the value of an option
///
/// @param[in] name Option name.
/// @param[in] number New value for the number or boolean option.
/// @param[in] string New value for string option.
/// @param[in] opt_flags Flags: OPT_LOCAL or 0 (both).
///
/// @return NULL on success, error message on error.
char *set_option_value(const char *const name, const long number,
const char *const string, const int opt_flags)
FUNC_ATTR_NONNULL_ARG(1)
{
if (set_tty_option((char *)name, (char *)string)) {
if (set_tty_option(name, string)) {
return NULL;
}
@ -4724,9 +4735,9 @@ set_option_value (
char_u *varp;
opt_idx = findoption(name);
if (opt_idx < 0)
if (opt_idx < 0) {
EMSG2(_("E355: Unknown option: %s"), name);
else {
} else {
uint32_t flags = options[opt_idx].flags;
// Disallow changing some options in the sandbox
if (sandbox > 0 && (flags & P_SECURE)) {
@ -4734,11 +4745,11 @@ set_option_value (
return NULL;
}
if (flags & P_STRING) {
const char *s = (const char *)string;
const char *s = string;
if (s == NULL) {
s = "";
}
return (char_u *)set_string_option(opt_idx, s, opt_flags);
return set_string_option(opt_idx, s, opt_flags);
} else {
varp = get_varp_scope(&(options[opt_idx]), opt_flags);
if (varp != NULL) { /* hidden option is not changed */
@ -4757,12 +4768,11 @@ set_option_value (
return NULL; // do nothing as we hit an error
}
}
if (flags & P_NUM)
return set_num_option(opt_idx, varp, number,
NULL, 0, opt_flags);
else
return set_bool_option(opt_idx, varp, (int)number,
opt_flags);
if (flags & P_NUM) {
return set_num_option(opt_idx, varp, number, NULL, 0, opt_flags);
} else {
return set_bool_option(opt_idx, varp, (int)number, opt_flags);
}
}
}
}
@ -4773,9 +4783,10 @@ char_u *get_highlight_default(void)
{
int i;
i = findoption((char_u *)"hl");
if (i >= 0)
i = findoption("hl");
if (i >= 0) {
return options[i].def_val[VI_DEFAULT];
}
return (char_u *)NULL;
}
@ -5212,7 +5223,7 @@ void unset_global_local_option(char *name, void *from)
vimoption_T *p;
buf_T *buf = (buf_T *)from;
int opt_idx = findoption((uint8_t *)name);
int opt_idx = findoption(name);
if (opt_idx < 0) {
EMSG2(_("E355: Unknown option: %s"), name);
return;
@ -5775,11 +5786,12 @@ void reset_modifiable(void)
{
int opt_idx;
curbuf->b_p_ma = FALSE;
p_ma = FALSE;
opt_idx = findoption((char_u *)"ma");
if (opt_idx >= 0)
options[opt_idx].def_val[VI_DEFAULT] = FALSE;
curbuf->b_p_ma = false;
p_ma = false;
opt_idx = findoption("ma");
if (opt_idx >= 0) {
options[opt_idx].def_val[VI_DEFAULT] = false;
}
}
/*
@ -5877,15 +5889,15 @@ set_context_in_set_cmd (
expand_option_name[2] = p[-2];
expand_option_name[3] = p[-1];
} else {
/* Allow * wildcard */
while (ASCII_ISALNUM(*p) || *p == '_' || *p == '*')
// Allow * wildcard.
while (ASCII_ISALNUM(*p) || *p == '_' || *p == '*') {
p++;
if (*p == NUL)
}
if (*p == NUL) {
return;
}
nextchar = *p;
*p = NUL;
opt_idx = findoption(arg);
*p = nextchar;
opt_idx = findoption_len((const char *)arg, (size_t)(p - arg));
if (opt_idx == -1 || options[opt_idx].var == NULL) {
xp->xp_context = EXPAND_NOTHING;
return;
@ -6047,7 +6059,7 @@ void ExpandOldSetting(int *num_file, char_u ***file)
* For a terminal key code expand_option_idx is < 0.
*/
if (expand_option_idx < 0) {
expand_option_idx = findoption(expand_option_name);
expand_option_idx = findoption((const char *)expand_option_name);
}
if (expand_option_idx >= 0) {
@ -6447,20 +6459,22 @@ void vimrc_found(char_u *fname, char_u *envname)
}
}
/*
* Return TRUE when option "name" has been set.
* Only works correctly for global options.
*/
int option_was_set(char_u *name)
/// Check whether global option has been set
///
/// @param[in] name Option name.
///
/// @return True if it was set.
static bool option_was_set(const char *name)
{
int idx;
idx = findoption(name);
if (idx < 0) /* unknown option */
return FALSE;
if (options[idx].flags & P_WAS_SET)
return TRUE;
return FALSE;
if (idx < 0) { // Unknown option.
return false;
} else if (options[idx].flags & P_WAS_SET) {
return true;
}
return false;
}
/*
@ -6876,8 +6890,8 @@ void set_fileformat(int eol_style, int opt_flags)
need_maketitle = true; // Set window title later.
}
/// Skip to next part of an option argument: Skip space and comma.
char_u *skip_to_option_part(char_u *p)
/// Skip to next part of an option argument: skip space and comma
char_u *skip_to_option_part(const char_u *p)
{
if (*p == ',') {
p++;
@ -6885,7 +6899,7 @@ char_u *skip_to_option_part(char_u *p)
while (*p == ' ') {
p++;
}
return p;
return (char_u *)p;
}
/// Isolate one part of a string option separated by `sep_chars`.
@ -6945,10 +6959,11 @@ bool signcolumn_on(win_T *wp)
return wp->w_buffer->b_signlist != NULL;
}
/// Get window or buffer local options.
dict_T * get_winbuf_options(int bufopt)
/// Get window or buffer local options
dict_T *get_winbuf_options(const int bufopt)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC
{
dict_T *d = dict_alloc();
dict_T *const d = tv_dict_alloc();
for (int opt_idx = 0; options[opt_idx].fullname; opt_idx++) {
struct vimoption *opt = &options[opt_idx];
@ -6959,9 +6974,10 @@ dict_T * get_winbuf_options(int bufopt)
if (varp != NULL) {
if (opt->flags & P_STRING) {
dict_add_nr_str(d, opt->fullname, 0L, *(char_u **)varp);
tv_dict_add_str(d, opt->fullname, strlen(opt->fullname),
*(const char **)varp);
} else {
dict_add_nr_str(d, opt->fullname, *varp, NULL);
tv_dict_add_nr(d, opt->fullname, strlen(opt->fullname), *varp);
}
}
}

View File

@ -91,11 +91,11 @@ int os_dirname(char_u *buf, size_t len)
/// Check if the given path is a directory and not a symlink to a directory.
/// @return `true` if `name` is a directory and NOT a symlink to a directory.
/// `false` if `name` is not a directory or if an error occurred.
bool os_isrealdir(const char_u *name)
bool os_isrealdir(const char *name)
FUNC_ATTR_NONNULL_ALL
{
uv_fs_t request;
if (uv_fs_lstat(&fs_loop, &request, (char *)name, NULL) != kLibuvSuccess) {
if (uv_fs_lstat(&fs_loop, &request, name, NULL) != kLibuvSuccess) {
return false;
}
if (S_ISLNK(request.statbuf.st_mode)) {
@ -111,7 +111,7 @@ bool os_isrealdir(const char_u *name)
bool os_isdir(const char_u *name)
FUNC_ATTR_NONNULL_ALL
{
int32_t mode = os_getperm(name);
int32_t mode = os_getperm((const char *)name);
if (mode < 0) {
return false;
}
@ -236,7 +236,8 @@ bool os_can_exe(const char_u *name, char_u **abspath, bool use_path)
pathext);
#else
// Must have path separator, cannot execute files in the current directory.
bool ok = gettail_dir(name) != name && is_executable((char *)name);
const bool ok = ((const char_u *)gettail_dir((const char *)name) != name
&& is_executable((char *)name));
#endif
if (ok) {
if (abspath != NULL) {
@ -254,7 +255,7 @@ bool os_can_exe(const char_u *name, char_u **abspath, bool use_path)
static bool is_executable(const char *name)
FUNC_ATTR_NONNULL_ALL
{
int32_t mode = os_getperm((char_u *)name);
int32_t mode = os_getperm((const char *)name);
if (mode < 0) {
return false;
@ -606,11 +607,11 @@ static int os_stat(const char *name, uv_stat_t *statbuf)
/// Get the file permissions for a given file.
///
/// @return libuv error code on error.
int32_t os_getperm(const char_u *name)
int32_t os_getperm(const char *name)
FUNC_ATTR_NONNULL_ALL
{
uv_stat_t statbuf;
int stat_result = os_stat((char *)name, &statbuf);
int stat_result = os_stat(name, &statbuf);
if (stat_result == kLibuvSuccess) {
return (int32_t)statbuf.st_mode;
} else {
@ -621,11 +622,11 @@ int32_t os_getperm(const char_u *name)
/// Set the permission of a file.
///
/// @return `OK` for success, `FAIL` for failure.
int os_setperm(const char_u *name, int perm)
int os_setperm(const char *const name, int perm)
FUNC_ATTR_NONNULL_ALL
{
int r;
RUN_UV_FS_FUNC(r, uv_fs_chmod, (const char *)name, perm, NULL);
RUN_UV_FS_FUNC(r, uv_fs_chmod, name, perm, NULL);
return (r == kLibuvSuccess ? OK : FAIL);
}
@ -979,13 +980,13 @@ bool os_fileid_equal_fileinfo(const FileID *file_id,
/// When "fname" is the name of a shortcut (*.lnk) resolve the file it points
/// to and return that name in allocated memory.
/// Otherwise NULL is returned.
char *os_resolve_shortcut(char_u *fname)
char *os_resolve_shortcut(const char *fname)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC
{
HRESULT hr;
IPersistFile *ppf = NULL;
OLECHAR wsz[MAX_PATH];
char *rfname = NULL;
int len;
IShellLinkW *pslw = NULL;
WIN32_FIND_DATAW ffdw;
@ -994,7 +995,7 @@ char *os_resolve_shortcut(char_u *fname)
if (fname == NULL) {
return rfname;
}
len = (int)STRLEN(fname);
const size_t len = strlen(fname);
if (len <= 4 || STRNICMP(fname + len - 4, ".lnk", 4) != 0) {
return rfname;
}
@ -1006,7 +1007,7 @@ char *os_resolve_shortcut(char_u *fname)
&IID_IShellLinkW, (void **)&pslw);
if (hr == S_OK) {
WCHAR *p;
int conversion_result = utf8_to_utf16((char *)fname, &p);
const int conversion_result = utf8_to_utf16(fname, &p);
if (conversion_result != 0) {
EMSG2("utf8_to_utf16 failed: %s", uv_strerror(conversion_result));
}
@ -1036,7 +1037,7 @@ char *os_resolve_shortcut(char_u *fname)
ZeroMemory(wsz, MAX_PATH * sizeof(WCHAR));
hr = pslw->lpVtbl->GetPath(pslw, wsz, MAX_PATH, &ffdw, 0);
if (hr == S_OK && wsz[0] != NUL) {
int conversion_result = utf16_to_utf8(wsz, &rfname);
const int conversion_result = utf16_to_utf8(wsz, &rfname);
if (conversion_result != 0) {
EMSG2("utf16_to_utf8 failed: %s", uv_strerror(conversion_result));
}

View File

@ -12,8 +12,9 @@ typedef struct pty_process {
#define pty_process_spawn(job) libuv_process_spawn((LibuvProcess *)job)
#define pty_process_close(job) libuv_process_close((LibuvProcess *)job)
#define pty_process_close_master(job) libuv_process_close((LibuvProcess *)job)
#define pty_process_resize(job, width, height)
#define pty_process_teardown(loop)
#define pty_process_resize(job, width, height) ( \
(void)job, (void)width, (void)height, 0)
#define pty_process_teardown(loop) ((void)loop, 0)
static inline PtyProcess pty_process_init(Loop *loop, void *data)
{

View File

@ -110,14 +110,14 @@ void mch_copy_sec(char_u *from_file, char_u *to_file)
// Return a pointer to the ACL of file "fname" in allocated memory.
// Return NULL if the ACL is not available for whatever reason.
vim_acl_T mch_get_acl(char_u *fname)
vim_acl_T mch_get_acl(const char_u *fname)
{
vim_acl_T ret = NULL;
return ret;
}
// Set the ACL of file "fname" to "acl" (unless it's NULL).
void mch_set_acl(char_u *fname, vim_acl_T aclent)
void mch_set_acl(const char_u *fname, vim_acl_T aclent)
{
if (aclent == NULL)
return;

View File

@ -159,7 +159,7 @@ const char_u *invocation_path_tail(const char_u *invocation, size_t *len)
/// @param fname A file path. (Must be != NULL.)
/// @return Pointer to first found path separator + 1.
/// An empty string, if `fname` doesn't contain a path separator,
char_u *path_next_component(char_u *fname)
const char *path_next_component(const char *fname)
{
assert(fname != NULL);
while (*fname != NUL && !vim_ispathsep(*fname)) {
@ -282,48 +282,63 @@ bool dir_of_file_exists(char_u *fname)
return retval;
}
/*
* Versions of fnamecmp() and fnamencmp() that handle '/' and '\' equally
* and deal with 'fileignorecase'.
*/
int vim_fnamecmp(char_u *x, char_u *y)
/// Compare two file names
///
/// Handles '/' and '\\' correctly and deals with &fileignorecase option.
///
/// @param[in] fname1 First file name.
/// @param[in] fname2 Second file name.
///
/// @return 0 if they are equal, non-zero otherwise.
int path_fnamecmp(const char *fname1, const char *fname2)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
#ifdef BACKSLASH_IN_FILENAME
return vim_fnamencmp(x, y, MAXPATHL);
const size_t len1 = strlen(fname1);
const size_t len2 = strlen(fname2);
return path_fnamencmp(fname1, fname2, MAX(len1, len2));
#else
if (p_fic)
return mb_stricmp(x, y);
return STRCMP(x, y);
return mb_strcmp_ic((bool)p_fic, fname1, fname2);
#endif
}
int vim_fnamencmp(char_u *x, char_u *y, size_t len)
/// Compare two file names
///
/// Handles '/' and '\\' correctly and deals with &fileignorecase option.
///
/// @param[in] fname1 First file name.
/// @param[in] fname2 Second file name.
/// @param[in] len Compare at most len bytes.
///
/// @return 0 if they are equal, non-zero otherwise.
int path_fnamencmp(const char *const fname1, const char *const fname2,
size_t len)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
#ifdef BACKSLASH_IN_FILENAME
char_u *px = x;
char_u *py = y;
int cx = NUL;
int cy = NUL;
int c1 = NUL;
int c2 = NUL;
const char *p1 = fname1;
const char *p2 = fname2;
while (len > 0) {
cx = PTR2CHAR(px);
cy = PTR2CHAR(py);
if (cx == NUL || cy == NUL
|| ((p_fic ? vim_tolower(cx) != vim_tolower(cy) : cx != cy)
&& !(cx == '/' && cy == '\\')
&& !(cx == '\\' && cy == '/')))
c1 = PTR2CHAR((const char_u *)p1);
c2 = PTR2CHAR((const char_u *)p2);
if ((c1 == NUL || c2 == NUL
|| (!((c1 == '/' || c1 == '\\') && (c2 == '\\' || c2 == '/'))))
&& (p_fic ? (c1 != c2 && CH_FOLD(c1) != CH_FOLD(c2)) : c1 != c2)) {
break;
len -= MB_PTR2LEN(px);
px += MB_PTR2LEN(px);
py += MB_PTR2LEN(py);
}
if (len == 0)
return 0;
return cx - cy;
len -= MB_PTR2LEN((const char_u *)p1);
p1 += MB_PTR2LEN((const char_u *)p1);
p2 += MB_PTR2LEN((const char_u *)p2);
}
return c1 - c2;
#else
if (p_fic)
return mb_strnicmp(x, y, len);
return STRNCMP(x, y, len);
if (p_fic) {
return mb_strnicmp((const char_u *)fname1, (const char_u *)fname2, len);
}
return strncmp(fname1, fname2, len);
#endif
}
@ -416,7 +431,7 @@ bool add_pathsep(char *p)
///
/// @return [allocated] Copy of absolute path to `fname` or NULL when
/// `fname` is NULL.
char *FullName_save(char *fname, bool force)
char *FullName_save(const char *fname, bool force)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC
{
if (fname == NULL) {
@ -804,7 +819,7 @@ static void expand_path_option(char_u *curdir, garray_T *gap)
}
STRMOVE(buf + len + 1, buf);
STRCPY(buf, curdir);
buf[len] = PATHSEP;
buf[len] = (char_u)PATHSEP;
simplify_filename(buf);
}
@ -893,7 +908,7 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
for (int i = 0; i < gap->ga_len && !got_int; i++) {
char_u *path = fnames[i];
int is_in_curdir;
char_u *dir_end = gettail_dir(path);
char_u *dir_end = (char_u *)gettail_dir((const char *)path);
char_u *pathsep_p;
char_u *path_cutoff;
@ -995,18 +1010,22 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
ga_remove_duplicate_strings(gap);
}
/// Return the end of the directory name, on the first path
/// separator:
/// Find end of the directory name
///
/// @param[in] fname File name to process.
///
/// @return end of the directory name, on the first path separator:
///
/// "/path/file", "/path/dir/", "/path//dir", "/file"
/// ^ ^ ^ ^
char_u *gettail_dir(const char_u *fname)
const char *gettail_dir(const char *const fname)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
const char_u *dir_end = fname;
const char_u *next_dir_end = fname;
const char *dir_end = fname;
const char *next_dir_end = fname;
bool look_for_sep = true;
const char_u *p;
for (p = fname; *p != NUL; ) {
for (const char *p = fname; *p != NUL; ) {
if (vim_ispathsep(*p)) {
if (look_for_sep) {
next_dir_end = p;
@ -1019,7 +1038,7 @@ char_u *gettail_dir(const char_u *fname)
}
mb_ptr_adv(p);
}
return (char_u *)dir_end;
return dir_end;
}
@ -1314,12 +1333,12 @@ static int expand_backtick(
/// When the path looks like a URL leave it unmodified.
void slash_adjust(char_u *p)
{
if (path_with_url(p)) {
if (path_with_url((const char *)p)) {
return;
}
while (*p) {
if (*p == psepcN) {
*p = psepc;
if (*p == (char_u)psepcN) {
*p = (char_u)psepc;
}
mb_ptr_adv(p);
}
@ -1538,8 +1557,8 @@ void simplify_filename(char_u *filename)
p = tail; /* skip to char after ".." or "../" */
}
} else {
++components; /* simple path component */
p = path_next_component(p);
components++; // Simple path component.
p = (char_u *)path_next_component((const char *)p);
}
} while (*p != NUL);
}

View File

@ -610,13 +610,10 @@ static int pum_set_selected(int n, int repeat)
if (res == OK) {
// Edit a new, empty buffer. Set options for a "wipeout"
// buffer.
set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL);
set_option_value((char_u *)"bt", 0L,
(char_u *)"nofile", OPT_LOCAL);
set_option_value((char_u *)"bh", 0L,
(char_u *)"wipe", OPT_LOCAL);
set_option_value((char_u *)"diff", 0L,
NULL, OPT_LOCAL);
set_option_value("swf", 0L, NULL, OPT_LOCAL);
set_option_value("bt", 0L, "nofile", OPT_LOCAL);
set_option_value("bh", 0L, "wipe", OPT_LOCAL);
set_option_value("diff", 0L, NULL, OPT_LOCAL);
}
}

View File

@ -1236,7 +1236,7 @@ static int qf_add_entry(qf_info_T *qi, char_u *dir, char_u *fname, int bufnum,
qfp->qf_nr = nr;
if (type != 1 && !vim_isprintc(type)) /* only printable chars allowed */
type = 0;
qfp->qf_type = type;
qfp->qf_type = (char_u)type;
qfp->qf_valid = valid;
lastp = &qi->qf_lists[qi->qf_curlist].qf_last;
@ -2581,15 +2581,13 @@ void ex_copen(exarg_T *eap)
else {
/* Create a new quickfix buffer */
(void)do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, oldwin);
/* switch off 'swapfile' */
set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL);
set_option_value((char_u *)"bt", 0L, (char_u *)"quickfix",
OPT_LOCAL);
set_option_value((char_u *)"bh", 0L, (char_u *)"wipe", OPT_LOCAL);
// Switch off 'swapfile'.
set_option_value("swf", 0L, NULL, OPT_LOCAL);
set_option_value("bt", 0L, "quickfix", OPT_LOCAL);
set_option_value("bh", 0L, "wipe", OPT_LOCAL);
RESET_BINDING(curwin);
curwin->w_p_diff = FALSE;
set_option_value((char_u *)"fdm", 0L, (char_u *)"manual",
OPT_LOCAL);
curwin->w_p_diff = false;
set_option_value("fdm", 0L, "manual", OPT_LOCAL);
}
/* Only set the height when still in the same tab page and there is no
@ -2901,14 +2899,14 @@ static void qf_fill_buffer(qf_info_T *qi, buf_T *buf, qfline_T *old_last)
}
}
/* correct cursor position */
check_lnums(TRUE);
// Correct cursor position.
check_lnums(true);
if (old_last == NULL) {
// Set the 'filetype' to "qf" each time after filling the buffer. This
// resembles reading a file into a buffer, it's more logical when using
// autocommands.
set_option_value((char_u *)"ft", 0L, (char_u *)"qf", OPT_LOCAL);
set_option_value("ft", 0L, "qf", OPT_LOCAL);
curbuf->b_p_ma = false;
keep_filetype = true; // don't detect 'filetype'
@ -3974,7 +3972,6 @@ static void unload_dummy_buffer(buf_T *buf, char_u *dirname_start)
int get_errorlist(win_T *wp, int qf_idx, list_T *list)
{
qf_info_T *qi = &ql_info;
dict_T *dict;
char_u buf[2];
qfline_T *qfp;
int i;
@ -4002,23 +3999,34 @@ int get_errorlist(win_T *wp, int qf_idx, list_T *list)
if (bufnum != 0 && (buflist_findnr(bufnum) == NULL))
bufnum = 0;
dict = dict_alloc();
list_append_dict(list, dict);
dict_T *const dict = tv_dict_alloc();
tv_list_append_dict(list, dict);
buf[0] = qfp->qf_type;
buf[1] = NUL;
if ( dict_add_nr_str(dict, "bufnr", (long)bufnum, NULL) == FAIL
|| dict_add_nr_str(dict, "lnum", (long)qfp->qf_lnum, NULL) == FAIL
|| dict_add_nr_str(dict, "col", (long)qfp->qf_col, NULL) == FAIL
|| dict_add_nr_str(dict, "vcol", (long)qfp->qf_viscol, NULL) == FAIL
|| dict_add_nr_str(dict, "nr", (long)qfp->qf_nr, NULL) == FAIL
|| dict_add_nr_str(dict, "pattern", 0L,
qfp->qf_pattern == NULL ? (char_u *)"" : qfp->qf_pattern) == FAIL
|| dict_add_nr_str(dict, "text", 0L,
qfp->qf_text == NULL ? (char_u *)"" : qfp->qf_text) == FAIL
|| dict_add_nr_str(dict, "type", 0L, buf) == FAIL
|| dict_add_nr_str(dict, "valid", (long)qfp->qf_valid, NULL) == FAIL)
return FAIL;
if (tv_dict_add_nr(dict, S_LEN("bufnr"), (varnumber_T)bufnum) == FAIL
|| (tv_dict_add_nr(dict, S_LEN("lnum"), (varnumber_T)qfp->qf_lnum)
== FAIL)
|| (tv_dict_add_nr(dict, S_LEN("col"), (varnumber_T)qfp->qf_col)
== FAIL)
|| (tv_dict_add_nr(dict, S_LEN("vcol"), (varnumber_T)qfp->qf_viscol)
== FAIL)
|| (tv_dict_add_nr(dict, S_LEN("nr"), (varnumber_T)qfp->qf_nr) == FAIL)
|| tv_dict_add_str(dict, S_LEN("pattern"),
(qfp->qf_pattern == NULL
? ""
: (const char *)qfp->qf_pattern)) == FAIL
|| tv_dict_add_str(dict, S_LEN("text"),
(qfp->qf_text == NULL
? ""
: (const char *)qfp->qf_text)) == FAIL
|| tv_dict_add_str(dict, S_LEN("type"), (const char *)buf) == FAIL
|| (tv_dict_add_nr(dict, S_LEN("valid"), (varnumber_T)qfp->qf_valid)
== FAIL)) {
// tv_dict_add* fail only if key already exist, but this is a newly
// allocated dictionary which is thus guaranteed to have no existing keys.
assert(false);
}
qfp = qfp->qf_next;
if (qfp == NULL) {
@ -4057,7 +4065,7 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
int flags = QF_GETLIST_NONE;
int qf_idx = qi->qf_curlist; // default is the current list
if ((di = dict_find(what, (char_u *)"nr", -1)) != NULL) {
if ((di = tv_dict_find(what, S_LEN("nr"))) != NULL) {
// Use the specified quickfix/location list
if (di->di_tv.v_type == VAR_NUMBER) {
qf_idx = di->di_tv.vval.v_number - 1;
@ -4070,15 +4078,15 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
}
}
if (dict_find(what, (char_u *)"all", -1) != NULL) {
if (tv_dict_find(what, S_LEN("all")) != NULL) {
flags |= QF_GETLIST_ALL;
}
if (dict_find(what, (char_u *)"title", -1) != NULL) {
if (tv_dict_find(what, S_LEN("title")) != NULL) {
flags |= QF_GETLIST_TITLE;
}
if (dict_find(what, (char_u *)"winid", -1) != NULL) {
if (tv_dict_find(what, S_LEN("winid")) != NULL) {
flags |= QF_GETLIST_WINID;
}
@ -4087,15 +4095,15 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
if (t == NULL) {
t = (char_u *)"";
}
status = dict_add_nr_str(retdict, "title", 0L, t);
status = tv_dict_add_str(retdict, S_LEN("title"), (const char *)t);
}
if ((status == OK) && (flags & QF_GETLIST_NR)) {
status = dict_add_nr_str(retdict, "nr", qf_idx + 1, NULL);
status = tv_dict_add_nr(retdict, S_LEN("nr"), qf_idx + 1);
}
if ((status == OK) && (flags & QF_GETLIST_WINID)) {
win_T *win = qf_find_win(qi);
if (win != NULL) {
status = dict_add_nr_str(retdict, "winid", win->handle, NULL);
status = tv_dict_add_nr(retdict, S_LEN("winid"), win->handle);
}
}
@ -4132,17 +4140,18 @@ static int qf_add_entries(qf_info_T *qi, list_T *list, char_u *title,
if (d == NULL)
continue;
char_u *filename = get_dict_string(d, "filename", true);
int bufnum = (int)get_dict_number(d, "bufnr");
long lnum = get_dict_number(d, "lnum");
int col = (int)get_dict_number(d, "col");
char_u vcol = (char_u)get_dict_number(d, "vcol");
int nr = (int)get_dict_number(d, "nr");
char_u *type = get_dict_string(d, "type", true);
char_u *pattern = get_dict_string(d, "pattern", true);
char_u *text = get_dict_string(d, "text", true);
char *const filename = tv_dict_get_string(d, "filename", true);
int bufnum = (int)tv_dict_get_number(d, "bufnr");
long lnum = tv_dict_get_number(d, "lnum");
int col = (int)tv_dict_get_number(d, "col");
char_u vcol = (char_u)tv_dict_get_number(d, "vcol");
int nr = (int)tv_dict_get_number(d, "nr");
const char *type_str = tv_dict_get_string(d, "type", false);
const char_u type = (char_u)(uint8_t)(type_str == NULL ? NUL : *type_str);
char *const pattern = tv_dict_get_string(d, "pattern", true);
char *text = tv_dict_get_string(d, "text", true);
if (text == NULL) {
text = vim_strsave((char_u *)"");
text = xcalloc(1, 1);
}
bool valid = true;
if ((filename == NULL && bufnum == 0) || (lnum == 0 && pattern == NULL)) {
@ -4162,21 +4171,20 @@ static int qf_add_entries(qf_info_T *qi, list_T *list, char_u *title,
int status = qf_add_entry(qi,
NULL, // dir
filename,
(char_u *)filename,
bufnum,
text,
(char_u *)text,
lnum,
col,
vcol, // vis_col
pattern, // search pattern
(char_u *)pattern, // search pattern
nr,
(char_u)(type == NULL ? NUL : *type),
type,
valid);
xfree(filename);
xfree(pattern);
xfree(text);
xfree(type);
if (status == FAIL) {
retval = FAIL;
@ -4213,7 +4221,7 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action)
newlist = true;
}
int qf_idx = qi->qf_curlist; // default is the current list
if ((di = dict_find(what, (char_u *)"nr", -1)) != NULL) {
if ((di = tv_dict_find(what, S_LEN("nr"))) != NULL) {
// Use the specified quickfix/location list
if (di->di_tv.v_type == VAR_NUMBER) {
qf_idx = di->di_tv.vval.v_number - 1;
@ -4231,10 +4239,11 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action)
qf_idx = qi->qf_curlist;
}
if ((di = dict_find(what, (char_u *)"title", -1)) != NULL) {
if ((di = tv_dict_find(what, S_LEN("title"))) != NULL) {
if (di->di_tv.v_type == VAR_STRING) {
xfree(qi->qf_lists[qf_idx].qf_title);
qi->qf_lists[qf_idx].qf_title = get_dict_string(what, "title", true);
qi->qf_lists[qf_idx].qf_title = (char_u *)tv_dict_get_string(
what, "title", true);
if (qf_idx == qi->qf_curlist) {
qf_update_win_titlevar(qi);
}
@ -4363,7 +4372,6 @@ void ex_cbuffer(exarg_T *eap)
*/
void ex_cexpr(exarg_T *eap)
{
typval_T *tv;
qf_info_T *qi = &ql_info;
const char *au_name = NULL;
@ -4403,11 +4411,11 @@ void ex_cexpr(exarg_T *eap)
/* Evaluate the expression. When the result is a string or a list we can
* use it to fill the errorlist. */
tv = eval_expr(eap->arg, NULL);
if (tv != NULL) {
if ((tv->v_type == VAR_STRING && tv->vval.v_string != NULL)
|| (tv->v_type == VAR_LIST && tv->vval.v_list != NULL)) {
if (qf_init_ext(qi, NULL, NULL, tv, p_efm,
typval_T tv;
if (eval0(eap->arg, &tv, NULL, true) != FAIL) {
if ((tv.v_type == VAR_STRING && tv.vval.v_string != NULL)
|| (tv.v_type == VAR_LIST && tv.vval.v_list != NULL)) {
if (qf_init_ext(qi, NULL, NULL, &tv, p_efm,
(eap->cmdidx != CMD_caddexpr
&& eap->cmdidx != CMD_laddexpr),
(linenr_T)0, (linenr_T)0, *eap->cmdlinep) > 0) {
@ -4422,7 +4430,7 @@ void ex_cexpr(exarg_T *eap)
} else {
EMSG(_("E777: String or List expected"));
}
free_tv(tv);
tv_clear(&tv);
}
}

View File

@ -2221,11 +2221,12 @@ collection:
if (*regparse == '[')
endc = get_coll_element(&regparse);
if (endc == 0) {
if (has_mbyte)
endc = mb_ptr2char_adv(&regparse);
else
if (has_mbyte) {
endc = mb_ptr2char_adv((const char_u **)&regparse);
} else {
endc = *regparse++;
}
}
/* Handle \o40, \x20 and \u20AC style sequences */
if (endc == '\\' && !reg_cpo_lit)
@ -3650,9 +3651,11 @@ static long regtry(bt_regprog_T *prog, colnr_T col)
*/
static int reg_prev_class(void)
{
if (reginput > regline)
return mb_get_class_buf(reginput - 1
- (*mb_head_off)(regline, reginput - 1), reg_buf);
if (reginput > regline) {
return mb_get_class_tab(reginput - 1 - (*mb_head_off)(regline,
reginput - 1),
reg_buf->b_chartab);
}
return -1;
}
@ -3918,12 +3921,13 @@ regmatch (
else if (has_mbyte) {
int this_class;
/* Get class of current and previous char (if it exists). */
this_class = mb_get_class_buf(reginput, reg_buf);
if (this_class <= 1)
status = RA_NOMATCH; /* not on a word at all */
else if (reg_prev_class() == this_class)
status = RA_NOMATCH; /* previous char is in same word */
// Get class of current and previous char (if it exists).
this_class = mb_get_class_tab(reginput, reg_buf->b_chartab);
if (this_class <= 1) {
status = RA_NOMATCH; // Not on a word at all.
} else if (reg_prev_class() == this_class) {
status = RA_NOMATCH; // Previous char is in same word.
}
} else {
if (!vim_iswordc_buf(c, reg_buf) || (reginput > regline
&& vim_iswordc_buf(reginput[-1
@ -3938,8 +3942,8 @@ regmatch (
else if (has_mbyte) {
int this_class, prev_class;
/* Get class of current and previous char (if it exists). */
this_class = mb_get_class_buf(reginput, reg_buf);
// Get class of current and previous char (if it exists).
this_class = mb_get_class_tab(reginput, reg_buf->b_chartab);
prev_class = reg_prev_class();
if (this_class == prev_class
|| prev_class == 0 || prev_class == 1)
@ -6268,8 +6272,8 @@ static int cstrncmp(char_u *s1, char_u *s2, int *n)
str2 = s2;
c1 = c2 = 0;
while ((int)(str1 - s1) < *n) {
c1 = mb_ptr2char_adv(&str1);
c2 = mb_ptr2char_adv(&str2);
c1 = mb_ptr2char_adv((const char_u **)&str1);
c2 = mb_ptr2char_adv((const char_u **)&str2);
/* decompose the character if necessary, into 'base' characters
* because I don't care about Arabic, I will hard-code the Hebrew
@ -6583,7 +6587,6 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest,
if (expr != NULL) {
typval_T argv[2];
int dummy;
char_u buf[NUMBUFLEN];
typval_T rettv;
staticList10_T matchList;
@ -6613,11 +6616,12 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest,
clear_submatch_list(&matchList);
}
}
eval_result = get_tv_string_buf_chk(&rettv, buf);
char buf[NUMBUFLEN];
eval_result = (char_u *)tv_get_string_buf_chk(&rettv, buf);
if (eval_result != NULL) {
eval_result = vim_strsave(eval_result);
}
clear_tv(&rettv);
tv_clear(&rettv);
} else {
eval_result = eval_to_string(source + 2, NULL, true);
}
@ -6976,7 +6980,7 @@ list_T *reg_submatch_list(int no)
linenr_T slnum;
linenr_T elnum;
list_T *list;
char_u *s;
const char *s;
if (submatch_match == NULL) {
slnum = submatch_mmatch->startpos[no].lnum;
@ -6988,27 +6992,27 @@ list_T *reg_submatch_list(int no)
colnr_T scol = submatch_mmatch->startpos[no].col;
colnr_T ecol = submatch_mmatch->endpos[no].col;
list = list_alloc();
list = tv_list_alloc();
s = reg_getline_submatch(slnum) + scol;
s = (const char *)reg_getline_submatch(slnum) + scol;
if (slnum == elnum) {
list_append_string(list, s, ecol - scol);
tv_list_append_string(list, s, ecol - scol);
} else {
list_append_string(list, s, -1);
tv_list_append_string(list, s, -1);
for (int i = 1; i < elnum - slnum; i++) {
s = reg_getline_submatch(slnum + i);
list_append_string(list, s, -1);
s = (const char *)reg_getline_submatch(slnum + i);
tv_list_append_string(list, s, -1);
}
s = reg_getline_submatch(elnum);
list_append_string(list, s, ecol);
s = (const char *)reg_getline_submatch(elnum);
tv_list_append_string(list, s, ecol);
}
} else {
s = submatch_match->startp[no];
s = (const char *)submatch_match->startp[no];
if (s == NULL || submatch_match->endp[no] == NULL) {
return NULL;
}
list = list_alloc();
list_append_string(list, s, (int)(submatch_match->endp[no] - s));
list = tv_list_alloc();
tv_list_append_string(list, s, (const char *)submatch_match->endp[no] - s);
}
return list;

View File

@ -5410,7 +5410,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
int this_class;
// Get class of current and previous char (if it exists).
this_class = mb_get_class_buf(reginput, reg_buf);
this_class = mb_get_class_tab(reginput, reg_buf->b_chartab);
if (this_class <= 1) {
result = false;
} else if (reg_prev_class() == this_class) {
@ -5435,7 +5435,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
int this_class, prev_class;
// Get class of current and previous char (if it exists).
this_class = mb_get_class_buf(reginput, reg_buf);
this_class = mb_get_class_tab(reginput, reg_buf->b_chartab);
prev_class = reg_prev_class();
if (this_class == prev_class
|| prev_class == 0 || prev_class == 1) {

View File

@ -3141,7 +3141,7 @@ win_line (
p_extra = extra;
c = *p_extra;
mb_c = mb_ptr2char_adv(&p_extra);
mb_c = mb_ptr2char_adv((const char_u **)&p_extra);
mb_utf8 = (c >= 0x80);
n_extra = (int)STRLEN(p_extra);
c_extra = NUL;

View File

@ -282,7 +282,7 @@ void restore_search_patterns(void)
static inline void free_spat(struct spat *const spat)
{
xfree(spat->pat);
dict_unref(spat->additional_data);
tv_dict_unref(spat->additional_data);
}
#if defined(EXITFREE)
@ -356,9 +356,10 @@ int pat_has_uppercase(char_u *pat)
return FALSE;
}
char_u *last_csearch(void)
const char *last_csearch(void)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
return lastc_bytes;
return (const char *)lastc_bytes;
}
int last_csearch_forward(void)
@ -1290,10 +1291,11 @@ int search_for_exact_line(buf_T *buf, pos_T *pos, int dir, char_u *pat)
* ignored because we are interested in the next line -- Acevedo */
if ((compl_cont_status & CONT_ADDING)
&& !(compl_cont_status & CONT_SOL)) {
if ((p_ic ? mb_stricmp(p, pat) : STRCMP(p, pat)) == 0)
if (mb_strcmp_ic((bool)p_ic, (const char *)p, (const char *)pat) == 0) {
return OK;
} else if (*p != NUL) { /* ignore empty lines */
/* expanding lines or words */
}
} else if (*p != NUL) { // Ignore empty lines.
// Expanding lines or words.
assert(compl_length >= 0);
if ((p_ic ? mb_strnicmp(p, pat, (size_t)compl_length)
: STRNCMP(p, pat, compl_length)) == 0)

View File

@ -259,11 +259,11 @@ void sha256_finish(context_sha256_T *ctx, char_u digest[SHA256_SUM_SIZE])
///
/// @returns hex digest of "buf[buf_len]" in a static array.
/// if "salt" is not NULL also do "salt[salt_len]".
char_u *sha256_bytes(const char_u *restrict buf, size_t buf_len,
const char_u *restrict salt, size_t salt_len)
const char *sha256_bytes(const uint8_t *restrict buf, size_t buf_len,
const uint8_t *restrict salt, size_t salt_len)
{
char_u sha256sum[SHA256_SUM_SIZE];
static char_u hexit[SHA256_BUFFER_SIZE + 1]; // buf size + NULL
static char hexit[SHA256_BUFFER_SIZE + 1]; // buf size + NULL
context_sha256_T ctx;
sha256_self_test();
@ -277,7 +277,7 @@ char_u *sha256_bytes(const char_u *restrict buf, size_t buf_len,
sha256_finish(&ctx, sha256sum);
for (size_t j = 0; j < SHA256_SUM_SIZE; j++) {
snprintf((char *) hexit + j * SHA_STEP, SHA_STEP+1, "%02x", sha256sum[j]);
snprintf(hexit + j * SHA_STEP, SHA_STEP + 1, "%02x", sha256sum[j]);
}
hexit[sizeof(hexit) - 1] = '\0';
return hexit;
@ -308,7 +308,7 @@ bool sha256_self_test(void)
context_sha256_T ctx;
char_u buf[1000];
char_u sha256sum[SHA256_SUM_SIZE];
char_u *hexit;
const char *hexit;
static bool sha256_self_tested = false;
static bool failures = false;
@ -320,8 +320,8 @@ bool sha256_self_test(void)
for (size_t i = 0; i < 3; i++) {
if (i < 2) {
hexit = sha256_bytes((char_u *) sha_self_test_msg[i],
STRLEN(sha_self_test_msg[i]),
hexit = sha256_bytes((uint8_t *)sha_self_test_msg[i],
strlen(sha_self_test_msg[i]),
NULL, 0);
STRCPY(output, hexit);
} else {

View File

@ -30,7 +30,7 @@
#include "nvim/ex_getln.h"
#include "nvim/search.h"
#include "nvim/regexp.h"
#include "nvim/eval_defs.h"
#include "nvim/eval/typval.h"
#include "nvim/version.h"
#include "nvim/path.h"
#include "nvim/fileio.h"
@ -82,8 +82,6 @@ KHASH_SET_INIT_STR(strset)
(buflist_new((char_u *)ffname, (char_u *)sfname, __VA_ARGS__))
#define convert_setup(vcp, from, to) \
(convert_setup(vcp, (char_u *)from, (char_u *)to))
#define os_getperm(f) \
(os_getperm((char_u *) f))
#define os_isdir(f) (os_isdir((char_u *) f))
#define regtilde(s, m) ((char *) regtilde((char_u *) s, m))
#define path_tail_with_sep(f) ((char *) path_tail_with_sep((char_u *)f))
@ -1223,7 +1221,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
khash_t(fnamebufs) fname_bufs = KHASH_EMPTY_TABLE(fnamebufs);
khash_t(strset) oldfiles_set = KHASH_EMPTY_TABLE(strset);
if (get_old_files && (oldfiles_list == NULL || force)) {
oldfiles_list = list_alloc();
oldfiles_list = tv_list_alloc();
set_vim_var_list(VV_OLDFILES, oldfiles_list);
}
ShaDaReadResult srni_ret;
@ -1436,7 +1434,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
}
int kh_ret;
(void)kh_put(strset, &oldfiles_set, fname, &kh_ret);
list_append_allocated_string(oldfiles_list, fname);
tv_list_append_allocated_string(oldfiles_list, fname);
if (!want_marks) {
// Avoid free because this string was already used.
cur_entry.data.filemark.fname = NULL;
@ -1573,7 +1571,9 @@ static char *shada_filename(const char *file)
do { \
const String s_ = (s); \
msgpack_pack_str(spacker, s_.size); \
if (s_.size) { \
msgpack_pack_str_body(spacker, s_.data, s_.size); \
} \
} while (0)
#define PACK_BIN(s) \
do { \
@ -1621,7 +1621,7 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
for (const hashitem_T *hi= d->dv_hashtab.ht_array; todo; hi++) { \
if (!HASHITEM_EMPTY(hi)) { \
todo--; \
dictitem_T *const di = HI2DI(hi); \
dictitem_T *const di = TV_DICT_HI2DI(hi); \
const size_t key_len = strlen((const char *)hi->hi_key); \
msgpack_pack_str(spacker, key_len); \
msgpack_pack_str_body(spacker, (const char *)hi->hi_key, key_len); \
@ -1965,7 +1965,7 @@ static ShaDaWriteResult shada_pack_encoded_entry(msgpack_packer *const packer,
typval_T tgttv;
var_item_copy(sd_conv, &entry.data.data.global_var.value, &tgttv,
true, 0);
clear_tv(&entry.data.data.global_var.value);
tv_clear(&entry.data.data.global_var.value);
entry.data.data.global_var.value = tgttv;
}
ret = shada_pack_entry(packer, entry.data, max_kbyte);
@ -2559,7 +2559,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer,
if (sd_writer->sd_conv.vc_type != CONV_NONE) {
var_item_copy(&sd_writer->sd_conv, &vartv, &tgttv, true, 0);
} else {
copy_tv(&vartv, &tgttv);
tv_copy(&vartv, &tgttv);
}
ShaDaWriteResult spe_ret;
if ((spe_ret = shada_pack_entry(packer, (ShadaEntry) {
@ -2573,13 +2573,13 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer,
}
}
}, max_kbyte)) == kSDWriteFailed) {
clear_tv(&vartv);
clear_tv(&tgttv);
tv_clear(&vartv);
tv_clear(&tgttv);
ret = kSDWriteFailed;
goto shada_write_exit;
}
clear_tv(&vartv);
clear_tv(&tgttv);
tv_clear(&vartv);
tv_clear(&tgttv);
if (spe_ret == kSDWriteSuccessfull) {
int kh_ret;
(void) kh_put(strset, &wms->dumped_variables, name, &kh_ret);
@ -3154,17 +3154,17 @@ static void shada_free_shada_entry(ShadaEntry *const entry)
case kSDItemJump:
case kSDItemGlobalMark:
case kSDItemLocalMark: {
dict_unref(entry->data.filemark.additional_data);
tv_dict_unref(entry->data.filemark.additional_data);
xfree(entry->data.filemark.fname);
break;
}
case kSDItemSearchPattern: {
dict_unref(entry->data.search_pattern.additional_data);
tv_dict_unref(entry->data.search_pattern.additional_data);
xfree(entry->data.search_pattern.pat);
break;
}
case kSDItemRegister: {
dict_unref(entry->data.reg.additional_data);
tv_dict_unref(entry->data.reg.additional_data);
for (size_t i = 0; i < entry->data.reg.contents_size; i++) {
xfree(entry->data.reg.contents[i]);
}
@ -3172,25 +3172,25 @@ static void shada_free_shada_entry(ShadaEntry *const entry)
break;
}
case kSDItemHistoryEntry: {
list_unref(entry->data.history_item.additional_elements);
tv_list_unref(entry->data.history_item.additional_elements);
xfree(entry->data.history_item.string);
break;
}
case kSDItemVariable: {
list_unref(entry->data.global_var.additional_elements);
tv_list_unref(entry->data.global_var.additional_elements);
xfree(entry->data.global_var.name);
clear_tv(&entry->data.global_var.value);
tv_clear(&entry->data.global_var.value);
break;
}
case kSDItemSubString: {
list_unref(entry->data.sub_string.additional_elements);
tv_list_unref(entry->data.sub_string.additional_elements);
xfree(entry->data.sub_string.sub);
break;
}
case kSDItemBufferList: {
for (size_t i = 0; i < entry->data.buffer_list.size; i++) {
xfree(entry->data.buffer_list.buffers[i].fname);
dict_unref(entry->data.buffer_list.buffers[i].additional_data);
tv_dict_unref(entry->data.buffer_list.buffers[i].additional_data);
}
xfree(entry->data.buffer_list.buffers);
break;
@ -3451,7 +3451,7 @@ static inline char *get_converted_string(const vimconv_T *const sd_conv,
"cannot be converted to a VimL dictionary")), \
initial_fpos); \
ga_clear(&ad_ga); \
clear_tv(&adtv); \
tv_clear(&adtv); \
goto shada_read_next_item_error; \
} \
tgt = adtv.vval.v_dict; \
@ -3474,7 +3474,7 @@ static inline char *get_converted_string(const vimconv_T *const sd_conv,
if (msgpack_to_vim(obj, &aetv) == FAIL) { \
emsgf(_(READERR(name, "cannot be converted to a VimL list")), \
initial_fpos); \
clear_tv(&aetv); \
tv_clear(&aetv); \
goto shada_read_next_item_error; \
} \
assert(aetv.v_type == VAR_LIST); \
@ -3866,7 +3866,7 @@ shada_read_next_item_hist_no_conv:
&tgttv,
true,
0);
clear_tv(&entry->data.global_var.value);
tv_clear(&entry->data.global_var.value);
entry->data.global_var.value = tgttv;
}
SET_ADDITIONAL_ELEMENTS(unpacked.data.via.array, 2,

View File

@ -2309,10 +2309,11 @@ int captype(char_u *word, char_u *end)
for (p = word; !spell_iswordp_nmw(p, curwin); mb_ptr_adv(p))
if (end == NULL ? *p == NUL : p >= end)
return 0; // only non-word characters, illegal word
if (has_mbyte)
c = mb_ptr2char_adv(&p);
else
if (has_mbyte) {
c = mb_ptr2char_adv((const char_u **)&p);
} else {
c = *p++;
}
firstcap = allcap = SPELL_ISUPPER(c);
// Need to check all letters to find a word with mixed upper/lower.
@ -2607,14 +2608,15 @@ static bool spell_iswordp(char_u *p, win_T *wp)
// Returns true if "p" points to a word character.
// Unlike spell_iswordp() this doesn't check for "midword" characters.
bool spell_iswordp_nmw(char_u *p, win_T *wp)
bool spell_iswordp_nmw(const char_u *p, win_T *wp)
{
int c;
if (has_mbyte) {
c = mb_ptr2char(p);
if (c > 255)
if (c > 255) {
return spell_mb_isword_class(mb_get_class(p), wp);
}
return spelltab.st_isw[c];
}
return spelltab.st_isw[*p];
@ -2675,7 +2677,7 @@ int spell_casefold(char_u *str, int len, char_u *buf, int buflen)
buf[outi] = NUL;
return FAIL;
}
c = mb_cptr2char_adv(&p);
c = mb_cptr2char_adv((const char_u **)&p);
outi += mb_char2bytes(SPELL_TOFOLD(c), buf + outi);
}
buf[outi] = NUL;
@ -2937,7 +2939,7 @@ void spell_suggest(int count)
// For redo we use a change-word command.
ResetRedobuff();
AppendToRedobuff((char_u *)"ciw");
AppendToRedobuff("ciw");
AppendToRedobuffLit(p + c,
stp->st_wordlen + sug.su_badlen - stp->st_orglen);
AppendCharToRedobuff(ESC);
@ -3232,7 +3234,7 @@ static void spell_suggest_expr(suginfo_T *su, char_u *expr)
list_T *list;
listitem_T *li;
int score;
char_u *p;
const char *p;
// The work is split up in a few parts to avoid having to export
// suginfo_T.
@ -3244,11 +3246,12 @@ static void spell_suggest_expr(suginfo_T *su, char_u *expr)
if (li->li_tv.v_type == VAR_LIST) {
// Get the word and the score from the items.
score = get_spellword(li->li_tv.vval.v_list, &p);
if (score >= 0 && score <= su->su_maxscore)
add_suggestion(su, &su->su_ga, p, su->su_badlen,
if (score >= 0 && score <= su->su_maxscore) {
add_suggestion(su, &su->su_ga, (const char_u *)p, su->su_badlen,
score, 0, true, su->su_sallang, false);
}
list_unref(list);
}
tv_list_unref(list);
}
// Remove bogus suggestions, sort and truncate at "maxcount".
@ -3405,17 +3408,19 @@ void onecap_copy(char_u *word, char_u *wcopy, bool upper)
int l;
p = word;
if (has_mbyte)
c = mb_cptr2char_adv(&p);
else
if (has_mbyte) {
c = mb_cptr2char_adv((const char_u **)&p);
} else {
c = *p++;
if (upper)
}
if (upper) {
c = SPELL_TOUPPER(c);
else
} else {
c = SPELL_TOFOLD(c);
if (has_mbyte)
}
if (has_mbyte) {
l = mb_char2bytes(c, wcopy);
else {
} else {
l = 1;
wcopy[0] = c;
}
@ -3432,10 +3437,11 @@ static void allcap_copy(char_u *word, char_u *wcopy)
d = wcopy;
for (s = word; *s != NUL; ) {
if (has_mbyte)
c = mb_cptr2char_adv(&s);
else
if (has_mbyte) {
c = mb_cptr2char_adv((const char_u **)&s);
} else {
c = *s++;
}
if (c == 0xdf) {
c = 'S';
@ -5616,7 +5622,7 @@ static void
add_suggestion (
suginfo_T *su,
garray_T *gap, // either su_ga or su_sga
char_u *goodword,
const char_u *goodword,
int badlenarg, // len of bad word replaced with "goodword"
int score,
int altscore,
@ -5630,13 +5636,11 @@ add_suggestion (
int badlen; // len of bad word changed
suggest_T *stp;
suggest_T new_sug;
int i;
char_u *pgood, *pbad;
// Minimize "badlen" for consistency. Avoids that changing "the the" to
// "thee the" is added next to changing the first "the" the "thee".
pgood = goodword + STRLEN(goodword);
pbad = su->su_badptr + badlenarg;
const char_u *pgood = goodword + STRLEN(goodword);
char_u *pbad = su->su_badptr + badlenarg;
for (;; ) {
goodlen = (int)(pgood - goodword);
badlen = (int)(pbad - su->su_badptr);
@ -5656,9 +5660,10 @@ add_suggestion (
// the first "the" to itself.
return;
if (GA_EMPTY(gap))
int i;
if (GA_EMPTY(gap)) {
i = -1;
else {
} else {
// Check if the word is already there. Also check the length that is
// being replaced "thes," -> "these" is a different suggestion from
// "thes" -> "these".
@ -5857,27 +5862,31 @@ cleanup_suggestions (
return maxscore;
}
// Soundfold a string, for soundfold().
// Result is in allocated memory, NULL for an error.
char_u *eval_soundfold(char_u *word)
/// Soundfold a string, for soundfold()
///
/// @param[in] word Word to soundfold.
///
/// @return [allocated] soundfolded string or NULL in case of error. May return
/// copy of the input string if soundfolding is not
/// supported by any of the languages in &spellang.
char *eval_soundfold(const char *const word)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
{
langp_T *lp;
char_u sound[MAXWLEN];
if (curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL) {
// Use the sound-folding of the first language that supports it.
for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) {
lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; lpi++) {
langp_T *const lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
if (!GA_EMPTY(&lp->lp_slang->sl_sal)) {
// soundfold the word
spell_soundfold(lp->lp_slang, word, false, sound);
return vim_strsave(sound);
char_u sound[MAXWLEN];
spell_soundfold(lp->lp_slang, (char_u *)word, false, sound);
return xstrdup((const char *)sound);
}
}
}
// No language with sound folding, return word as-is.
return vim_strsave(word);
return xstrdup(word);
}
/// Turn "inword" into its sound-a-like equivalent in "res[MAXWLEN]".
@ -5934,12 +5943,12 @@ static void spell_soundfold_sofo(slang_T *slang, char_u *inword, char_u *res)
// The sl_sal_first[] table contains the translation for chars up to
// 255, sl_sal the rest.
for (s = inword; *s != NUL; ) {
c = mb_cptr2char_adv(&s);
if (enc_utf8 ? utf_class(c) == 0 : ascii_iswhite(c))
c = mb_cptr2char_adv((const char_u **)&s);
if (enc_utf8 ? utf_class(c) == 0 : ascii_iswhite(c)) {
c = ' ';
else if (c < 256)
} else if (c < 256) {
c = slang->sl_sal_first[c];
else {
} else {
ip = ((int **)slang->sl_sal.ga_data)[c & 0xff];
if (ip == NULL) // empty list, can't match
c = NUL;
@ -6224,9 +6233,7 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
int word[MAXWLEN];
int wres[MAXWLEN];
int l;
char_u *s;
int *ws;
char_u *t;
int *pf;
int i, j, z;
int reslen;
@ -6246,9 +6253,9 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
// Remove accents, if wanted. We actually remove all non-word characters.
// But keep white space.
wordlen = 0;
for (s = inword; *s != NUL; ) {
t = s;
c = mb_cptr2char_adv(&s);
for (const char_u *s = inword; *s != NUL; ) {
const char_u *t = s;
c = mb_cptr2char_adv((const char_u **)&s);
if (slang->sl_rem_accents) {
if (enc_utf8 ? utf_class(c) == 0 : ascii_iswhite(c)) {
if (did_white)
@ -6257,10 +6264,11 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
did_white = true;
} else {
did_white = false;
if (!spell_iswordp_nmw(t, curwin))
if (!spell_iswordp_nmw(t, curwin)) {
continue;
}
}
}
word[wordlen++] = c;
}
word[wordlen] = NUL;
@ -6305,7 +6313,7 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
continue;
++k;
}
s = smp[n].sm_rules;
char_u *s = smp[n].sm_rules;
pri = 5; // default priority
p0 = *s;
@ -6705,24 +6713,29 @@ soundalike_score (
static int spell_edit_score(slang_T *slang, char_u *badword, char_u *goodword)
{
int *cnt;
int badlen, goodlen; // lengths including NUL
int j, i;
int t;
int bc, gc;
int pbc, pgc;
char_u *p;
int wbadword[MAXWLEN];
int wgoodword[MAXWLEN];
const bool l_has_mbyte = has_mbyte;
// Lengths with NUL.
int badlen;
int goodlen;
if (l_has_mbyte) {
// Get the characters from the multi-byte strings and put them in an
// int array for easy access.
for (p = badword, badlen = 0; *p != NUL; )
badlen = 0;
for (const char_u *p = badword; *p != NUL; ) {
wbadword[badlen++] = mb_cptr2char_adv(&p);
}
wbadword[badlen++] = 0;
for (p = goodword, goodlen = 0; *p != NUL; )
goodlen = 0;
for (const char_u *p = goodword; *p != NUL; ) {
wgoodword[goodlen++] = mb_cptr2char_adv(&p);
}
wgoodword[goodlen++] = 0;
} else {
badlen = (int)STRLEN(badword) + 1;
@ -6956,19 +6969,20 @@ static int spell_edit_score_limit_w(slang_T *slang, char_u *badword, char_u *goo
int score_off;
int minscore;
int round;
char_u *p;
int wbadword[MAXWLEN];
int wgoodword[MAXWLEN];
// Get the characters from the multi-byte strings and put them in an
// int array for easy access.
bi = 0;
for (p = badword; *p != NUL; )
for (const char_u *p = badword; *p != NUL; ) {
wbadword[bi++] = mb_cptr2char_adv(&p);
}
wbadword[bi++] = 0;
gi = 0;
for (p = goodword; *p != NUL; )
for (const char_u *p = goodword; *p != NUL; ) {
wgoodword[gi++] = mb_cptr2char_adv(&p);
}
wgoodword[gi++] = 0;
// The idea is to go from start to end over the words. So long as
@ -7134,16 +7148,17 @@ void ex_spelldump(exarg_T *eap)
char_u *spl;
long dummy;
if (no_spell_checking(curwin))
if (no_spell_checking(curwin)) {
return;
}
get_option_value((char_u *)"spl", &dummy, &spl, OPT_LOCAL);
// Create a new empty buffer in a new window.
do_cmdline_cmd("new");
// enable spelling locally in the new window
set_option_value((char_u*)"spell", true, (char_u*)"", OPT_LOCAL);
set_option_value((char_u*)"spl", dummy, spl, OPT_LOCAL);
set_option_value("spell", true, "", OPT_LOCAL);
set_option_value("spl", dummy, (char *)spl, OPT_LOCAL);
xfree(spl);
if (!bufempty()) {

View File

@ -1435,7 +1435,7 @@ static int set_sofo(slang_T *lp, char_u *from, char_u *to)
// First count the number of items for each list. Temporarily use
// sl_sal_first[] for this.
for (p = from, s = to; *p != NUL && *s != NUL; ) {
c = mb_cptr2char_adv(&p);
c = mb_cptr2char_adv((const char_u **)&p);
mb_cptr_adv(s);
if (c >= 256)
++lp->sl_sal_first[c & 0xff];
@ -1455,8 +1455,8 @@ static int set_sofo(slang_T *lp, char_u *from, char_u *to)
// list.
memset(lp->sl_sal_first, 0, sizeof(salfirst_T) * 256);
for (p = from, s = to; *p != NUL && *s != NUL; ) {
c = mb_cptr2char_adv(&p);
i = mb_cptr2char_adv(&s);
c = mb_cptr2char_adv((const char_u **)&p);
i = mb_cptr2char_adv((const char_u **)&s);
if (c >= 256) {
// Append the from-to chars at the end of the list with
// the low byte.
@ -1542,8 +1542,9 @@ static int *mb_str2wide(char_u *s)
int i = 0;
int *res = xmalloc((mb_charlen(s) + 1) * sizeof(int));
for (char_u *p = s; *p != NUL; )
res[i++] = mb_ptr2char_adv(&p);
for (char_u *p = s; *p != NUL; ) {
res[i++] = mb_ptr2char_adv((const char_u **)&p);
}
res[i] = NUL;
return res;
@ -2486,14 +2487,15 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
// Check that every character appears only once.
for (p = items[1]; *p != NUL; ) {
c = mb_ptr2char_adv(&p);
c = mb_ptr2char_adv((const char_u **)&p);
if ((!GA_EMPTY(&spin->si_map)
&& vim_strchr(spin->si_map.ga_data, c)
!= NULL)
|| vim_strchr(p, c) != NULL)
|| vim_strchr(p, c) != NULL) {
smsg(_("Duplicate character in MAP in %s line %d"),
fname, lnum);
}
}
// We simply concatenate all the MAP strings, separated by
// slashes.
@ -2717,12 +2719,12 @@ static unsigned get_affitem(int flagtype, char_u **pp)
}
res = getdigits_int(pp);
} else {
res = mb_ptr2char_adv(pp);
res = mb_ptr2char_adv((const char_u **)pp);
if (flagtype == AFT_LONG || (flagtype == AFT_CAPLONG
&& res >= 'A' && res <= 'Z')) {
if (**pp == NUL)
return 0;
res = mb_ptr2char_adv(pp) + (res << 16);
res = mb_ptr2char_adv((const char_u **)pp) + (res << 16);
}
}
return res;
@ -2823,13 +2825,15 @@ static bool flag_in_afflist(int flagtype, char_u *afflist, unsigned flag)
case AFT_CAPLONG:
case AFT_LONG:
for (p = afflist; *p != NUL; ) {
n = mb_ptr2char_adv(&p);
n = mb_ptr2char_adv((const char_u **)&p);
if ((flagtype == AFT_LONG || (n >= 'A' && n <= 'Z'))
&& *p != NUL)
n = mb_ptr2char_adv(&p) + (n << 16);
if (n == flag)
&& *p != NUL) {
n = mb_ptr2char_adv((const char_u **)&p) + (n << 16);
}
if (n == flag) {
return true;
}
}
break;
case AFT_NUM:
@ -5436,10 +5440,11 @@ static void init_spellfile(void)
fname = LANGP_ENTRY(curwin->w_s->b_langp, 0)
->lp_slang->sl_fname;
vim_snprintf((char *)buf + l, MAXPATHL - l, ".%s.add",
fname != NULL
&& strstr((char *)path_tail(fname), ".ascii.") != NULL
? (char_u *)"ascii" : spell_enc());
set_option_value((char_u *)"spellfile", 0L, buf, OPT_LOCAL);
((fname != NULL
&& strstr((char *)path_tail(fname), ".ascii.") != NULL)
? "ascii"
: (const char *)spell_enc()));
set_option_value("spellfile", 0L, (const char *)buf, OPT_LOCAL);
break;
}
aspath = false;
@ -5465,9 +5470,9 @@ static int set_spell_chartab(char_u *fol, char_u *low, char_u *upp)
EMSG(_(e_affform));
return FAIL;
}
f = mb_ptr2char_adv(&pf);
l = mb_ptr2char_adv(&pl);
u = mb_ptr2char_adv(&pu);
f = mb_ptr2char_adv((const char_u **)&pf);
l = mb_ptr2char_adv((const char_u **)&pl);
u = mb_ptr2char_adv((const char_u **)&pu);
// Every character that appears is a word character.
if (f < 256)
new_st.st_isw[f] = true;
@ -5532,7 +5537,7 @@ set_spell_charflags (
}
if (*p != NUL) {
c = mb_ptr2char_adv(&p);
c = mb_ptr2char_adv((const char_u **)&p);
new_st.st_fold[i + 128] = c;
if (i + 128 != c && new_st.st_isu[i + 128] && c < 256)
new_st.st_upper[c] = i + 128;
@ -5619,12 +5624,13 @@ static void set_map_str(slang_T *lp, char_u *map)
// "aaa/bbb/ccc/". Fill sl_map_array[c] with the character before c and
// before the same slash. For characters above 255 sl_map_hash is used.
for (p = map; *p != NUL; ) {
c = mb_cptr2char_adv(&p);
if (c == '/')
c = mb_cptr2char_adv((const char_u **)&p);
if (c == '/') {
headc = 0;
else {
if (headc == 0)
} else {
if (headc == 0) {
headc = c;
}
// Characters above 255 don't fit in sl_map_array[], put them in
// the hash table. Each entry is the char, a NUL the headchar and

View File

@ -291,30 +291,33 @@ void vim_strup(char_u *p)
}
}
/*
* Make string "s" all upper-case and return it in allocated memory.
* Handles multi-byte characters as well as possible.
*/
char_u *strup_save(const char_u *orig)
/// Make given string all upper-case
///
/// Handels multi-byte characters as good as possible.
///
/// @param[in] orig Input string.
///
/// @return [allocated] upper-cased string.
char *strup_save(const char *const orig)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
{
char_u *res = vim_strsave(orig);
char *res = xstrdup(orig);
char_u *p = res;
char *p = res;
while (*p != NUL) {
int l;
if (enc_utf8) {
int c = utf_ptr2char(p);
int c = utf_ptr2char((const char_u *)p);
int uc = utf_toupper(c);
/* Reallocate string when byte count changes. This is rare,
* thus it's OK to do another malloc()/free(). */
l = utf_ptr2len(p);
// Reallocate string when byte count changes. This is rare,
// thus it's OK to do another malloc()/free().
l = utf_ptr2len((const char_u *)p);
int newl = utf_char2len(uc);
if (newl != l) {
// TODO(philix): use xrealloc() in strup_save()
char_u *s = xmalloc(STRLEN(res) + (size_t)(1 + newl - l));
char *s = xmalloc(STRLEN(res) + (size_t)(1 + newl - l));
memcpy(s, res, (size_t)(p - res));
STRCPY(s + (p - res) + newl, p + l);
p = s + (p - res);
@ -322,12 +325,13 @@ char_u *strup_save(const char_u *orig)
res = s;
}
utf_char2bytes(uc, p);
utf_char2bytes(uc, (char_u *)p);
p += newl;
} else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1)
p += l; /* skip multi-byte character */
else {
*p = (char_u) TOUPPER_LOC(*p); // note that toupper() can be a macro
} else if (has_mbyte && (l = (*mb_ptr2len)((const char_u *)p)) > 1) {
p += l; // Skip multi-byte character.
} else {
// note that toupper() can be a macro
*p = (char)(uint8_t)TOUPPER_LOC(*p);
p++;
}
}
@ -571,8 +575,8 @@ static varnumber_T tv_nr(typval_T *tvs, int *idxp)
EMSG(_(e_printf));
} else {
(*idxp)++;
int err = false;
n = (varnumber_T)get_tv_number_chk(&tvs[idx], &err);
bool err = false;
n = tv_get_number_chk(&tvs[idx], &err);
if (err) {
n = 0;
}
@ -594,22 +598,21 @@ static varnumber_T tv_nr(typval_T *tvs, int *idxp)
/// free "*tofree".
///
/// @return String value or NULL in case of error.
static char *tv_str(typval_T *tvs, int *idxp, char ** const tofree)
static const char *tv_str(typval_T *tvs, int *idxp, char **const tofree)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
int idx = *idxp - 1;
char *s = NULL;
const char *s = NULL;
if (tvs[idx].v_type == VAR_UNKNOWN) {
EMSG(_(e_printf));
} else {
(*idxp)++;
if (tvs[idx].v_type == VAR_STRING || tvs[idx].v_type == VAR_NUMBER) {
s = (char *)get_tv_string_chk(&tvs[idx]);
s = tv_get_string_chk(&tvs[idx]);
*tofree = NULL;
} else {
s = encode_tv2echo(&tvs[idx], NULL);
*tofree = s;
s = *tofree = encode_tv2echo(&tvs[idx], NULL);
}
}
return s;
@ -949,7 +952,7 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap,
case 's':
case 'S':
str_arg = tvs ? tv_str(tvs, &arg_idx, &tofree)
: va_arg(ap, char *);
: va_arg(ap, const char *);
if (!str_arg) {
str_arg = "[NULL]";
str_arg_l = 6;

View File

@ -5,7 +5,7 @@
#include <stdarg.h>
#include "nvim/types.h"
#include "nvim/eval_defs.h"
#include "nvim/eval/typval.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "strings.h.generated.h"

View File

@ -1406,16 +1406,16 @@ static int syn_stack_equal(synstate_T *sp)
/* If the pointer is different it can still be the
* same text. Compare the strings, ignore case when
* the start item has the sp_ic flag set. */
if (bsx->matches[j] == NULL
|| six->matches[j] == NULL)
if (bsx->matches[j] == NULL || six->matches[j] == NULL) {
break;
if ((SYN_ITEMS(syn_block)[CUR_STATE(i).si_idx]).sp_ic
? mb_stricmp(bsx->matches[j],
six->matches[j]) != 0
: STRCMP(bsx->matches[j], six->matches[j]) != 0)
}
if (mb_strcmp_ic((SYN_ITEMS(syn_block)[CUR_STATE(i).si_idx]).sp_ic,
(const char *)bsx->matches[j],
(const char *)six->matches[j]) != 0) {
break;
}
}
}
if (j != NSUBEXP)
break;
}
@ -3259,9 +3259,10 @@ static void syn_cmd_clear(exarg_T *eap, int syncing)
syntax_sync_clear();
else {
syntax_clear(curwin->w_s);
if (curwin->w_s == &curwin->w_buffer->b_s)
do_unlet((char_u *)"b:current_syntax", TRUE);
do_unlet((char_u *)"w:current_syntax", TRUE);
if (curwin->w_s == &curwin->w_buffer->b_s) {
do_unlet(S_LEN("b:current_syntax"), true);
}
do_unlet(S_LEN("w:current_syntax"), true);
}
} else {
/*
@ -3337,7 +3338,7 @@ static void syn_cmd_enable(exarg_T *eap, int syncing)
{
set_internal_string_var((char_u *)"syntax_cmd", (char_u *)"enable");
syn_cmd_onoff(eap, "syntax");
do_unlet((char_u *)"g:syntax_cmd", TRUE);
do_unlet(S_LEN("g:syntax_cmd"), true);
}
/*
@ -3350,7 +3351,7 @@ static void syn_cmd_reset(exarg_T *eap, int syncing)
if (!eap->skip) {
set_internal_string_var((char_u *)"syntax_cmd", (char_u *)"reset");
do_cmdline_cmd("runtime! syntax/syncolor.vim");
do_unlet((char_u *)"g:syntax_cmd", TRUE);
do_unlet(S_LEN("g:syntax_cmd"), true);
}
}
@ -5537,10 +5538,10 @@ void ex_ownsyntax(exarg_T *eap)
set_internal_string_var((char_u *)"w:current_syntax", new_value);
}
/* restore value of b:current_syntax */
if (old_value == NULL)
do_unlet((char_u *)"b:current_syntax", TRUE);
else {
// Restore value of b:current_syntax.
if (old_value == NULL) {
do_unlet(S_LEN("b:current_syntax"), true);
} else {
set_internal_string_var((char_u *)"b:current_syntax", old_value);
xfree(old_value);
}
@ -5573,46 +5574,45 @@ void reset_expand_highlight(void)
* Handle command line completion for :match and :echohl command: Add "None"
* as highlight group.
*/
void set_context_in_echohl_cmd(expand_T *xp, char_u *arg)
void set_context_in_echohl_cmd(expand_T *xp, const char *arg)
{
xp->xp_context = EXPAND_HIGHLIGHT;
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
include_none = 1;
}
/*
* Handle command line completion for :syntax command.
*/
void set_context_in_syntax_cmd(expand_T *xp, char_u *arg)
void set_context_in_syntax_cmd(expand_T *xp, const char *arg)
{
char_u *p;
/* Default: expand subcommands */
// Default: expand subcommands.
xp->xp_context = EXPAND_SYNTAX;
expand_what = EXP_SUBCMD;
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
include_link = 0;
include_default = 0;
/* (part of) subcommand already typed */
if (*arg != NUL) {
p = skiptowhite(arg);
if (*p != NUL) { /* past first word */
xp->xp_pattern = skipwhite(p);
if (*skiptowhite(xp->xp_pattern) != NUL)
const char *p = (const char *)skiptowhite((const char_u *)arg);
if (*p != NUL) { // Past first word.
xp->xp_pattern = skipwhite((const char_u *)p);
if (*skiptowhite(xp->xp_pattern) != NUL) {
xp->xp_context = EXPAND_NOTHING;
else if (STRNICMP(arg, "case", p - arg) == 0)
} else if (STRNICMP(arg, "case", p - arg) == 0) {
expand_what = EXP_CASE;
else if ( STRNICMP(arg, "keyword", p - arg) == 0
} else if (STRNICMP(arg, "keyword", p - arg) == 0
|| STRNICMP(arg, "region", p - arg) == 0
|| STRNICMP(arg, "match", p - arg) == 0
|| STRNICMP(arg, "list", p - arg) == 0)
|| STRNICMP(arg, "list", p - arg) == 0) {
xp->xp_context = EXPAND_HIGHLIGHT;
else
} else {
xp->xp_context = EXPAND_NOTHING;
}
}
}
}
static char *(case_args[]) = {"match", "ignore", NULL};
@ -6231,7 +6231,7 @@ do_highlight (
*/
line = linep;
if (ends_excmd(*line)) {
do_unlet((char_u *)"colors_name", TRUE);
do_unlet(S_LEN("colors_name"), true);
restore_cterm_colors();
/*
@ -6510,16 +6510,16 @@ do_highlight (
if (!ui_rgb_attached()) {
must_redraw = CLEAR;
if (color >= 0) {
if (t_colors < 16)
if (t_colors < 16) {
i = (color == 0 || color == 4);
else
} else {
i = (color < 7 || color == 8);
/* Set the 'background' option if the value is
* wrong. */
if (i != (*p_bg == 'd'))
set_option_value((char_u *)"bg", 0L,
i ? (char_u *)"dark"
: (char_u *)"light", 0);
}
// Set the 'background' option if the value is
// wrong.
if (i != (*p_bg == 'd')) {
set_option_value("bg", 0L, (i ? "dark" : "light"), 0);
}
}
}
}
@ -6930,21 +6930,21 @@ static int highlight_list_arg(int id, int didh, int type, int iarg, char_u *sarg
return didh;
}
/*
* Return "1" if highlight group "id" has attribute "flag".
* Return NULL otherwise.
*/
char_u *
highlight_has_attr (
int id,
int flag,
int modec // 'g' for GUI, 'c' for cterm
)
/// Check whether highlight group has attribute
///
/// @param[in] id Highilght group to check.
/// @param[in] flag Attribute to check.
/// @param[in] modec 'g' for GUI, 'c' for term.
///
/// @return "1" if highlight group has attribute, NULL otherwise.
const char *highlight_has_attr(const int id, const int flag, const int modec)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
{
int attr;
if (id <= 0 || id > highlight_ga.ga_len)
if (id <= 0 || id > highlight_ga.ga_len) {
return NULL;
}
if (modec == 'g') {
attr = HL_TABLE()[id - 1].sg_gui;
@ -6952,39 +6952,42 @@ highlight_has_attr (
attr = HL_TABLE()[id - 1].sg_cterm;
}
if (attr & flag)
return (char_u *)"1";
return (attr & flag) ? "1" : NULL;
}
/// Return color name of the given highlight group
///
/// @param[in] id Highlight group to work with.
/// @param[in] what What to return: one of "font", "fg", "bg", "sp", "fg#",
/// "bg#" or "sp#".
/// @param[in] modec 'g' for GUI, 'c' for cterm and 't' for term.
///
/// @return color name, possibly in a static buffer. Buffer will be overwritten
/// on next highlight_color() call. May return NULL.
const char *highlight_color(const int id, const char *const what,
const int modec)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
static char name[20];
int n;
bool fg = false;
bool sp = false;
bool font = false;
if (id <= 0 || id > highlight_ga.ga_len) {
return NULL;
}
/*
* Return color name of highlight group "id".
*/
char_u *
highlight_color (
int id,
char_u *what, /* "font", "fg", "bg", "sp", "fg#", "bg#" or "sp#" */
int modec /* 'g' for GUI, 'c' for cterm, 't' for term */
)
{
static char_u name[20];
int n;
int fg = FALSE;
int sp = FALSE;
int font = FALSE;
if (id <= 0 || id > highlight_ga.ga_len)
return NULL;
if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'g')
fg = TRUE;
else if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'o'
&& TOLOWER_ASC(what[2]) == 'n' && TOLOWER_ASC(what[3]) == 't')
font = TRUE;
else if (TOLOWER_ASC(what[0]) == 's' && TOLOWER_ASC(what[1]) == 'p')
sp = TRUE;
else if (!(TOLOWER_ASC(what[0]) == 'b' && TOLOWER_ASC(what[1]) == 'g'))
if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'g') {
fg = true;
} else if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'o'
&& TOLOWER_ASC(what[2]) == 'n' && TOLOWER_ASC(what[3]) == 't') {
font = true;
} else if (TOLOWER_ASC(what[0]) == 's' && TOLOWER_ASC(what[1]) == 'p') {
sp = true;
} else if (!(TOLOWER_ASC(what[0]) == 'b' && TOLOWER_ASC(what[1]) == 'g')) {
return NULL;
}
if (modec == 'g') {
if (what[2] == '#' && ui_rgb_attached()) {
if (fg) {
@ -6997,19 +7000,20 @@ highlight_color (
if (n < 0 || n > 0xffffff) {
return NULL;
}
snprintf((char *)name, sizeof(name), "#%06x", n);
snprintf(name, sizeof(name), "#%06x", n);
return name;
}
if (fg) {
return HL_TABLE()[id - 1].sg_rgb_fg_name;
return (const char *)HL_TABLE()[id - 1].sg_rgb_fg_name;
}
if (sp) {
return HL_TABLE()[id - 1].sg_rgb_sp_name;
return (const char *)HL_TABLE()[id - 1].sg_rgb_sp_name;
}
return HL_TABLE()[id - 1].sg_rgb_bg_name;
return (const char *)HL_TABLE()[id - 1].sg_rgb_bg_name;
}
if (font || sp)
if (font || sp) {
return NULL;
}
if (modec == 'c') {
if (fg) {
n = HL_TABLE()[id - 1].sg_cterm_fg - 1;
@ -7019,10 +7023,10 @@ highlight_color (
if (n < 0) {
return NULL;
}
snprintf((char *)name, sizeof(name), "%d", n);
snprintf(name, sizeof(name), "%d", n);
return name;
}
/* term doesn't have color */
// term doesn't have color.
return NULL;
}
@ -7113,7 +7117,7 @@ set_hl_attr (
* Lookup a highlight group name and return it's ID.
* If it is not found, 0 is returned.
*/
int syn_name2id(char_u *name)
int syn_name2id(const char_u *name)
{
int i;
char_u name_u[200];
@ -7133,7 +7137,7 @@ int syn_name2id(char_u *name)
/*
* Return TRUE if highlight group "name" exists.
*/
int highlight_exists(char_u *name)
int highlight_exists(const char_u *name)
{
return syn_name2id(name) > 0;
}
@ -7469,45 +7473,45 @@ int highlight_changed(void)
/*
* Handle command line completion for :highlight command.
*/
void set_context_in_highlight_cmd(expand_T *xp, char_u *arg)
void set_context_in_highlight_cmd(expand_T *xp, const char *arg)
{
char_u *p;
/* Default: expand group names */
// Default: expand group names.
xp->xp_context = EXPAND_HIGHLIGHT;
xp->xp_pattern = arg;
xp->xp_pattern = (char_u *)arg;
include_link = 2;
include_default = 1;
/* (part of) subcommand already typed */
if (*arg != NUL) {
p = skiptowhite(arg);
if (*p != NUL) { /* past "default" or group name */
const char *p = (const char *)skiptowhite((const char_u *)arg);
if (*p != NUL) { // Past "default" or group name.
include_default = 0;
if (STRNCMP("default", arg, p - arg) == 0) {
arg = skipwhite(p);
xp->xp_pattern = arg;
p = skiptowhite(arg);
if (strncmp("default", arg, p - arg) == 0) {
arg = (const char *)skipwhite((const char_u *)p);
xp->xp_pattern = (char_u *)arg;
p = (const char *)skiptowhite((const char_u *)arg);
}
if (*p != NUL) { /* past group name */
include_link = 0;
if (arg[1] == 'i' && arg[0] == 'N')
if (arg[1] == 'i' && arg[0] == 'N') {
highlight_list();
if (STRNCMP("link", arg, p - arg) == 0
|| STRNCMP("clear", arg, p - arg) == 0) {
xp->xp_pattern = skipwhite(p);
p = skiptowhite(xp->xp_pattern);
if (*p != NUL) { /* past first group name */
xp->xp_pattern = skipwhite(p);
p = skiptowhite(xp->xp_pattern);
}
if (strncmp("link", arg, p - arg) == 0
|| strncmp("clear", arg, p - arg) == 0) {
xp->xp_pattern = skipwhite((const char_u *)p);
p = (const char *)skiptowhite(xp->xp_pattern);
if (*p != NUL) { // Past first group name.
xp->xp_pattern = skipwhite((const char_u *)p);
p = (const char *)skiptowhite(xp->xp_pattern);
}
}
if (*p != NUL) /* past group name(s) */
if (*p != NUL) { // Past group name(s).
xp->xp_context = EXPAND_NOTHING;
}
}
}
}
}
/*
* List highlighting matches in a nice way.

View File

@ -674,7 +674,7 @@ do_tag (
fname = xmalloc(MAXPATHL + 1);
cmd = xmalloc(CMDBUFFSIZE + 1);
list = list_alloc();
list = tv_list_alloc();
for (i = 0; i < num_matches; ++i) {
int len, cmd_len;
@ -773,20 +773,21 @@ do_tag (
cmd[len] = NUL;
}
dict = dict_alloc();
list_append_dict(list, dict);
dict = tv_dict_alloc();
tv_list_append_dict(list, dict);
dict_add_nr_str(dict, "text", 0L, tag_name);
dict_add_nr_str(dict, "filename", 0L, fname);
dict_add_nr_str(dict, "lnum", lnum, NULL);
if (lnum == 0)
dict_add_nr_str(dict, "pattern", 0L, cmd);
tv_dict_add_str(dict, S_LEN("text"), (const char *)tag_name);
tv_dict_add_str(dict, S_LEN("filename"), (const char *)fname);
tv_dict_add_nr(dict, S_LEN("lnum"), lnum);
if (lnum == 0) {
tv_dict_add_str(dict, S_LEN("pattern"), (const char *)cmd);
}
}
vim_snprintf((char *)IObuff, IOSIZE, "ltag %s", tag);
set_errorlist(curwin, list, ' ', IObuff, NULL);
list_free(list);
tv_list_free(list);
xfree(fname);
xfree(cmd);
@ -2203,7 +2204,7 @@ parse_tag_line (
* Return TRUE if it is a static tag and adjust *tagname to the real tag.
* Return FALSE if it is not a static tag.
*/
static int test_for_static(tagptrs_T *tagp)
static bool test_for_static(tagptrs_T *tagp)
{
char_u *p;
@ -2768,8 +2769,8 @@ add_tag_field (
int len = 0;
int retval;
/* check that the field name doesn't exist yet */
if (dict_find(dict, (char_u *)field_name, -1) != NULL) {
// Check that the field name doesn't exist yet.
if (tv_dict_find(dict, field_name, -1) != NULL) {
if (p_verbose > 0) {
verbose_enter();
smsg(_("Duplicate field name: %s"), field_name);
@ -2790,7 +2791,8 @@ add_tag_field (
STRLCPY(buf, start, len + 1);
}
buf[len] = NUL;
retval = dict_add_nr_str(dict, field_name, 0L, buf);
retval = tv_dict_add_str(dict, field_name, STRLEN(field_name),
(const char *)buf);
xfree(buf);
return retval;
}
@ -2806,7 +2808,7 @@ int get_tags(list_T *list, char_u *pat)
char_u *full_fname;
dict_T *dict;
tagptrs_T tp;
long is_static;
bool is_static;
ret = find_tags(pat, &num_matches, &matches,
TAG_REGEXP | TAG_NOIC, (int)MAXCOL, NULL);
@ -2824,19 +2826,18 @@ int get_tags(list_T *list, char_u *pat)
if (STRNCMP(tp.tagname, "!_TAG_", 6) == 0)
continue;
dict = dict_alloc();
list_append_dict(list, dict);
dict = tv_dict_alloc();
tv_list_append_dict(list, dict);
full_fname = tag_full_fname(&tp);
if (add_tag_field(dict, "name", tp.tagname, tp.tagname_end) == FAIL
|| add_tag_field(dict, "filename", full_fname,
NULL) == FAIL
|| add_tag_field(dict, "cmd", tp.command,
tp.command_end) == FAIL
|| add_tag_field(dict, "filename", full_fname, NULL) == FAIL
|| add_tag_field(dict, "cmd", tp.command, tp.command_end) == FAIL
|| add_tag_field(dict, "kind", tp.tagkind,
tp.tagkind ? tp.tagkind_end : NULL) == FAIL
|| dict_add_nr_str(dict, "static", is_static, NULL) == FAIL)
|| tv_dict_add_nr(dict, S_LEN("static"), is_static) == FAIL) {
ret = FAIL;
}
xfree(full_fname);

View File

@ -226,17 +226,17 @@ Terminal *terminal_open(TerminalOptions opts)
rv->invalid_start = 0;
rv->invalid_end = opts.height;
refresh_screen(rv, curbuf);
set_option_value((uint8_t *)"buftype", 0, (uint8_t *)"terminal", OPT_LOCAL);
set_option_value("buftype", 0, "terminal", OPT_LOCAL);
// Default settings for terminal buffers
curbuf->b_p_ma = false; // 'nomodifiable'
curbuf->b_p_ul = -1; // 'undolevels'
curbuf->b_p_scbk = p_scbk; // 'scrollback'
curbuf->b_p_tw = 0; // 'textwidth'
set_option_value((uint8_t *)"wrap", false, NULL, OPT_LOCAL);
set_option_value((uint8_t *)"number", false, NULL, OPT_LOCAL);
set_option_value((uint8_t *)"relativenumber", false, NULL, OPT_LOCAL);
set_option_value((uint8_t *)"list", false, NULL, OPT_LOCAL);
set_option_value("wrap", false, NULL, OPT_LOCAL);
set_option_value("number", false, NULL, OPT_LOCAL);
set_option_value("relativenumber", false, NULL, OPT_LOCAL);
set_option_value("list", false, NULL, OPT_LOCAL);
buf_set_term_title(curbuf, (char *)curbuf->b_ffname);
RESET_BINDING(curwin);
// Reset cursor in current window.

View File

@ -1015,7 +1015,7 @@ static const char *tui_tk_ti_getstr(const char *name, const char *value,
ILOG("libtermkey:kdch1=%s", value);
// Vim: "If <BS> and <DEL> are now the same, redefine <DEL>."
if (stty_erase != NULL && value != NULL && strcmp(stty_erase, value) == 0) {
return stty_erase[0] == DEL ? (char *)CTRL_H_STR : (char *)DEL_STR;
return stty_erase[0] == DEL ? CTRL_H_STR : DEL_STR;
}
}

View File

@ -82,6 +82,7 @@
#include "nvim/vim.h"
#include "nvim/ascii.h"
#include "nvim/undo.h"
#include "nvim/macros.h"
#include "nvim/cursor.h"
#include "nvim/edit.h"
#include "nvim/eval.h"
@ -317,7 +318,7 @@ static long get_undolevel(void)
static inline void zero_fmark_additional_data(fmark_T *fmarks)
{
for (size_t i = 0; i < NMARKS; i++) {
dict_unref(fmarks[i].additional_data);
tv_dict_unref(fmarks[i].additional_data);
fmarks[i].additional_data = NULL;
}
}
@ -1080,7 +1081,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
*/
perm = 0600;
if (buf->b_ffname != NULL) {
perm = os_getperm(buf->b_ffname);
perm = os_getperm((const char *)buf->b_ffname);
if (perm < 0) {
perm = 0600;
}
@ -1139,7 +1140,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
EMSG2(_(e_not_open), file_name);
goto theend;
}
(void)os_setperm((char_u *)file_name, perm);
(void)os_setperm(file_name, perm);
if (p_verbose > 0) {
verbose_enter();
smsg(_("Writing undo file: %s"), file_name);
@ -1164,7 +1165,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
&& os_fileinfo(file_name, &file_info_new)
&& file_info_old.stat.st_gid != file_info_new.stat.st_gid
&& os_fchown(fd, (uv_uid_t)-1, (uv_gid_t)file_info_old.stat.st_gid)) {
os_setperm((char_u *)file_name, (perm & 0707) | ((perm & 07) << 3));
os_setperm(file_name, (perm & 0707) | ((perm & 07) << 3));
}
# ifdef HAVE_SELINUX
if (buf->b_ffname != NULL)
@ -2941,25 +2942,28 @@ void u_eval_tree(u_header_T *first_uhp, list_T *list)
dict_T *dict;
while (uhp != NULL) {
dict = dict_alloc();
dict_add_nr_str(dict, "seq", uhp->uh_seq, NULL);
dict_add_nr_str(dict, "time", (long)uhp->uh_time, NULL);
if (uhp == curbuf->b_u_newhead)
dict_add_nr_str(dict, "newhead", 1, NULL);
if (uhp == curbuf->b_u_curhead)
dict_add_nr_str(dict, "curhead", 1, NULL);
if (uhp->uh_save_nr > 0)
dict_add_nr_str(dict, "save", uhp->uh_save_nr, NULL);
if (uhp->uh_alt_next.ptr != NULL) {
list_T *alt_list = list_alloc();
/* Recursive call to add alternate undo tree. */
u_eval_tree(uhp->uh_alt_next.ptr, alt_list);
dict_add_list(dict, "alt", alt_list);
dict = tv_dict_alloc();
tv_dict_add_nr(dict, S_LEN("seq"), (varnumber_T)uhp->uh_seq);
tv_dict_add_nr(dict, S_LEN("time"), (varnumber_T)uhp->uh_time);
if (uhp == curbuf->b_u_newhead) {
tv_dict_add_nr(dict, S_LEN("newhead"), 1);
}
if (uhp == curbuf->b_u_curhead) {
tv_dict_add_nr(dict, S_LEN("curhead"), 1);
}
if (uhp->uh_save_nr > 0) {
tv_dict_add_nr(dict, S_LEN("save"), (varnumber_T)uhp->uh_save_nr);
}
list_append_dict(list, dict);
if (uhp->uh_alt_next.ptr != NULL) {
list_T *alt_list = tv_list_alloc();
// Recursive call to add alternate undo tree.
u_eval_tree(uhp->uh_alt_next.ptr, alt_list);
tv_dict_add_list(dict, S_LEN("alt"), alt_list);
}
tv_list_append_dict(list, dict);
uhp = uhp->uh_prev.ptr;
}
}

View File

@ -73,7 +73,7 @@ static char *features[] = {
};
// clang-format off
static int included_patches[] = {
static const int included_patches[] = {
// 2367,NA
// 2366 NA
// 2365 NA
@ -2461,10 +2461,10 @@ static char *(extra_patches[]) = {
/// @param version Version string like "1.3.42"
///
/// @return true if Nvim is at or above the version.
bool has_nvim_version(char *version_str)
FUNC_ATTR_NONNULL_ALL
bool has_nvim_version(const char *const version_str)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
char *p = version_str;
const char *p = version_str;
int major = 0;
int minor = 0;
int patch = 0;

View File

@ -30,7 +30,7 @@ Error: configure did not run properly.Check auto/config.log.
#include "nvim/os/os_defs.h" /* bring lots of system header files */
/// length of a buffer to store a number in ASCII (64 bits binary + NUL)
#define NUMBUFLEN 65
enum { NUMBUFLEN = 65 };
// flags for vim_str2nr()
#define STR2NR_BIN 1
@ -51,22 +51,7 @@ Error: configure did not run properly.Check auto/config.log.
/* ================ end of the header file puzzle =============== */
#ifdef HAVE_WORKING_LIBINTL
# include <libintl.h>
# define _(x) gettext((char *)(x))
// XXX do we actually need this?
# ifdef gettext_noop
# define N_(x) gettext_noop(x)
# else
# define N_(x) x
# endif
#else
# define _(x) ((char *)(x))
# define N_(x) x
# define bindtextdomain(x, y) /* empty */
# define bind_textdomain_codeset(x, y) /* empty */
# define textdomain(x) /* empty */
#endif
#include "nvim/gettext.h"
/* special attribute addition: Put message in history */
#define MSG_HIST 0x1000
@ -109,11 +94,14 @@ Error: configure did not run properly.Check auto/config.log.
// all mode bits used for mapping
#define MAP_ALL_MODES (0x3f | SELECTMODE | TERM_FOCUS)
/* directions */
#define FORWARD 1
#define BACKWARD (-1)
#define FORWARD_FILE 3
#define BACKWARD_FILE (-3)
/// Directions.
typedef enum {
kDirectionNotSet = 0,
FORWARD = 1,
BACKWARD = (-1),
FORWARD_FILE = 3,
BACKWARD_FILE = (-3),
} Direction;
/* return values for functions */
#if !(defined(OK) && (OK == 1))
@ -282,14 +270,21 @@ enum {
#define SHOWCMD_COLS 10 /* columns needed by shown command */
#define STL_MAX_ITEM 80 /* max nr of %<flag> in statusline */
/*
* fnamecmp() is used to compare file names.
* On some systems case in a file name does not matter, on others it does.
* (this does not account for maximum name lengths and things like "../dir",
* thus it is not 100% accurate!)
*/
#define fnamecmp(x, y) vim_fnamecmp((char_u *)(x), (char_u *)(y))
#define fnamencmp(x, y, n) vim_fnamencmp((char_u *)(x), (char_u *)(y), \
/// Compare file names
///
/// On some systems case in a file name does not matter, on others it does.
///
/// @note Does not account for maximum name lengths and things like "../dir",
/// thus it is not 100% accurate. OS may also use different algorythm for
/// case-insensitive comparison.
///
/// @param[in] x First file name to compare.
/// @param[in] y Second file name to compare.
///
/// @return 0 for equal file names, non-zero otherwise.
#define fnamecmp(x, y) path_fnamecmp((const char *)(x), (const char *)(y))
#define fnamencmp(x, y, n) path_fnamencmp((const char *)(x), \
(const char *)(y), \
(size_t)(n))
/*

View File

@ -2983,8 +2983,8 @@ static tabpage_T *alloc_tabpage(void)
tp->handle = ++last_tp_handle;
handle_register_tabpage(tp);
/* init t: variables */
tp->tp_vars = dict_alloc();
// Init t: variables.
tp->tp_vars = tv_dict_alloc();
init_var_dict(tp->tp_vars, &tp->tp_winvar, VAR_SCOPE);
tp->tp_diff_invalid = TRUE;
tp->tp_ch_used = p_ch;
@ -3811,8 +3811,8 @@ static win_T *win_alloc(win_T *after, int hidden)
new_wp->handle = ++last_win_id;
handle_register_window(new_wp);
/* init w: variables */
new_wp->w_vars = dict_alloc();
// Init w: variables.
new_wp->w_vars = tv_dict_alloc();
init_var_dict(new_wp->w_vars, &new_wp->w_winvar, VAR_SCOPE);
/* Don't execute autocommands while the window is not properly
@ -5504,9 +5504,9 @@ void restore_buffer(bufref_T *save_curbuf)
// Optionally, a desired ID 'id' can be specified (greater than or equal to 1).
// If no particular ID is desired, -1 must be specified for 'id'.
// Return ID of added match, -1 on failure.
int match_add(win_T *wp, char_u *grp, char_u *pat,
int match_add(win_T *wp, const char *const grp, const char *const pat,
int prio, int id, list_T *pos_list,
char_u *conceal_char)
const char *const conceal_char)
{
matchitem_T *cur;
matchitem_T *prev;
@ -5534,11 +5534,11 @@ int match_add(win_T *wp, char_u *grp, char_u *pat,
cur = cur->next;
}
}
if ((hlg_id = syn_namen2id(grp, (int)STRLEN(grp))) == 0) {
if ((hlg_id = syn_name2id((const char_u *)grp)) == 0) {
EMSG2(_(e_nogroup), grp);
return -1;
}
if (pat != NULL && (regprog = vim_regcomp(pat, RE_MAGIC)) == NULL) {
if (pat != NULL && (regprog = vim_regcomp((char_u *)pat, RE_MAGIC)) == NULL) {
EMSG2(_(e_invarg2), pat);
return -1;
}
@ -5557,14 +5557,14 @@ int match_add(win_T *wp, char_u *grp, char_u *pat,
m = xcalloc(1, sizeof(matchitem_T));
m->id = id;
m->priority = prio;
m->pattern = pat == NULL ? NULL: vim_strsave(pat);
m->pattern = pat == NULL ? NULL: (char_u *)xstrdup(pat);
m->hlg_id = hlg_id;
m->match.regprog = regprog;
m->match.rmm_ic = FALSE;
m->match.rmm_maxcol = 0;
m->conceal_char = 0;
if (conceal_char != NULL) {
m->conceal_char = (*mb_ptr2char)(conceal_char);
m->conceal_char = (*mb_ptr2char)((const char_u *)conceal_char);
}
// Set up position matches
@ -5582,7 +5582,7 @@ int match_add(win_T *wp, char_u *grp, char_u *pat,
int len = 1;
list_T *subl;
listitem_T *subli;
int error = false;
bool error = false;
if (li->li_tv.v_type == VAR_LIST) {
subl = li->li_tv.vval.v_list;
@ -5593,8 +5593,8 @@ int match_add(win_T *wp, char_u *grp, char_u *pat,
if (subli == NULL) {
goto fail;
}
lnum = get_tv_number_chk(&subli->li_tv, &error);
if (error == true) {
lnum = tv_get_number_chk(&subli->li_tv, &error);
if (error) {
goto fail;
}
if (lnum == 0) {
@ -5604,13 +5604,14 @@ int match_add(win_T *wp, char_u *grp, char_u *pat,
m->pos.pos[i].lnum = lnum;
subli = subli->li_next;
if (subli != NULL) {
col = get_tv_number_chk(&subli->li_tv, &error);
if (error == true)
col = tv_get_number_chk(&subli->li_tv, &error);
if (error) {
goto fail;
}
subli = subli->li_next;
if (subli != NULL) {
len = get_tv_number_chk(&subli->li_tv, &error);
if (error == true) {
len = tv_get_number_chk(&subli->li_tv, &error);
if (error) {
goto fail;
}
}
@ -5809,14 +5810,14 @@ int win_getid(typval_T *argvars)
if (argvars[0].v_type == VAR_UNKNOWN) {
return curwin->handle;
}
int winnr = get_tv_number(&argvars[0]);
int winnr = tv_get_number(&argvars[0]);
win_T *wp;
if (winnr > 0) {
if (argvars[1].v_type == VAR_UNKNOWN) {
wp = firstwin;
} else {
tabpage_T *tp = NULL;
int tabnr = get_tv_number(&argvars[1]);
int tabnr = tv_get_number(&argvars[1]);
FOR_ALL_TABS(tp2) {
if (--tabnr == 0) {
tp = tp2;
@ -5843,7 +5844,7 @@ int win_getid(typval_T *argvars)
int win_gotoid(typval_T *argvars)
{
int id = get_tv_number(&argvars[0]);
int id = tv_get_number(&argvars[0]);
FOR_ALL_TAB_WINDOWS(tp, wp) {
if (wp->handle == id) {
@ -5878,16 +5879,16 @@ void win_id2tabwin(typval_T *argvars, list_T *list)
{
int winnr = 1;
int tabnr = 1;
int id = get_tv_number(&argvars[0]);
handle_T id = (handle_T)tv_get_number(&argvars[0]);
win_get_tabwin(id, &tabnr, &winnr);
list_append_number(list, tabnr);
list_append_number(list, winnr);
tv_list_append_number(list, tabnr);
tv_list_append_number(list, winnr);
}
win_T * win_id2wp(typval_T *argvars)
{
int id = get_tv_number(&argvars[0]);
int id = tv_get_number(&argvars[0]);
FOR_ALL_TAB_WINDOWS(tp, wp) {
if (wp->handle == id) {
@ -5901,7 +5902,7 @@ win_T * win_id2wp(typval_T *argvars)
int win_id2win(typval_T *argvars)
{
int nr = 1;
int id = get_tv_number(&argvars[0]);
int id = tv_get_number(&argvars[0]);
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->handle == id) {
@ -5914,11 +5915,11 @@ int win_id2win(typval_T *argvars)
void win_findbuf(typval_T *argvars, list_T *list)
{
int bufnr = get_tv_number(&argvars[0]);
int bufnr = tv_get_number(&argvars[0]);
FOR_ALL_TAB_WINDOWS(tp, wp) {
if (wp->w_buffer->b_fnum == bufnr) {
list_append_number(list, wp->handle);
tv_list_append_number(list, wp->handle);
}
}
}

View File

@ -0,0 +1,302 @@
local helpers = require('test.functional.helpers')(after_each)
local lfs = require('lfs')
local eq = helpers.eq
local clear = helpers.clear
local funcs = helpers.funcs
local meths = helpers.meths
local command = helpers.command
local exc_exec = helpers.exc_exec
local bufmeths = helpers.bufmeths
local winmeths = helpers.winmeths
local curbufmeths = helpers.curbufmeths
local curwinmeths = helpers.curwinmeths
local curtabmeths = helpers.curtabmeths
local get_pathsep = helpers.get_pathsep
local fname = 'Xtest-functional-eval-buf_functions'
local fname2 = fname .. '.2'
local dirname = fname .. '.d'
before_each(clear)
for _, func in ipairs({'bufname(%s)', 'bufnr(%s)', 'bufwinnr(%s)',
'getbufline(%s, 1)', 'getbufvar(%s, "changedtick")',
'setbufvar(%s, "f", 0)'}) do
local funcname = func:match('%w+')
describe(funcname .. '() function', function()
it('errors out when receives v:true/v:false/v:null', function()
-- Not compatible with Vim: in Vim it always results in buffer not found
-- without any error messages.
for _, var in ipairs({'v:true', 'v:false', 'v:null'}) do
eq('Vim(call):E5300: Expected a Number or a String',
exc_exec('call ' .. func:format(var)))
end
end)
it('errors out when receives invalid argument', function()
eq('Vim(call):E745: Expected a Number or a String, List found',
exc_exec('call ' .. func:format('[]')))
eq('Vim(call):E728: Expected a Number or a String, Dictionary found',
exc_exec('call ' .. func:format('{}')))
eq('Vim(call):E805: Expected a Number or a String, Float found',
exc_exec('call ' .. func:format('0.0')))
eq('Vim(call):E703: Expected a Number or a String, Funcref found',
exc_exec('call ' .. func:format('function("tr")')))
end)
end)
end
describe('bufname() function', function()
it('returns empty string when buffer was not found', function()
command('file ' .. fname)
eq('', funcs.bufname(2))
eq('', funcs.bufname('non-existent-buffer'))
eq('', funcs.bufname('#'))
command('edit ' .. fname2)
eq(2, funcs.bufnr('%'))
eq('', funcs.bufname('X'))
end)
before_each(function()
lfs.mkdir(dirname)
end)
after_each(function()
lfs.rmdir(dirname)
end)
it('returns expected buffer name', function()
eq('', funcs.bufname('%')) -- Buffer has no name yet
command('file ' .. fname)
local wd = lfs.currentdir()
local sep = get_pathsep()
local curdirname = funcs.fnamemodify(wd, ':t')
for _, arg in ipairs({'%', 1, 'X', wd}) do
eq(fname, funcs.bufname(arg))
meths.set_current_dir('..')
eq(curdirname .. sep .. fname, funcs.bufname(arg))
meths.set_current_dir(curdirname)
meths.set_current_dir(dirname)
eq(wd .. sep .. fname, funcs.bufname(arg))
meths.set_current_dir('..')
eq(fname, funcs.bufname(arg))
command('enew')
end
eq('', funcs.bufname('%'))
eq('', funcs.bufname('$'))
eq(2, funcs.bufnr('%'))
end)
end)
describe('bufnr() function', function()
it('returns -1 when buffer was not found', function()
command('file ' .. fname)
eq(-1, funcs.bufnr(2))
eq(-1, funcs.bufnr('non-existent-buffer'))
eq(-1, funcs.bufnr('#'))
command('edit ' .. fname2)
eq(2, funcs.bufnr('%'))
eq(-1, funcs.bufnr('X'))
end)
it('returns expected buffer number', function()
eq(1, funcs.bufnr('%'))
command('file ' .. fname)
local wd = lfs.currentdir()
local curdirname = funcs.fnamemodify(wd, ':t')
eq(1, funcs.bufnr(fname))
eq(1, funcs.bufnr(wd))
eq(1, funcs.bufnr(curdirname))
eq(1, funcs.bufnr('X'))
end)
it('returns number of last buffer with "$"', function()
eq(1, funcs.bufnr('$'))
command('new')
eq(2, funcs.bufnr('$'))
command('new')
eq(3, funcs.bufnr('$'))
command('only')
eq(3, funcs.bufnr('$'))
eq(3, funcs.bufnr('%'))
command('buffer 1')
eq(3, funcs.bufnr('$'))
eq(1, funcs.bufnr('%'))
command('bwipeout 2')
eq(3, funcs.bufnr('$'))
eq(1, funcs.bufnr('%'))
command('bwipeout 3')
eq(1, funcs.bufnr('$'))
eq(1, funcs.bufnr('%'))
command('new')
eq(4, funcs.bufnr('$'))
end)
end)
describe('bufwinnr() function', function()
it('returns -1 when buffer was not found', function()
command('file ' .. fname)
eq(-1, funcs.bufwinnr(2))
eq(-1, funcs.bufwinnr('non-existent-buffer'))
eq(-1, funcs.bufwinnr('#'))
command('split ' .. fname2) -- It would be OK if there was one window
eq(2, funcs.bufnr('%'))
eq(-1, funcs.bufwinnr('X'))
end)
before_each(function()
lfs.mkdir(dirname)
end)
after_each(function()
lfs.rmdir(dirname)
end)
it('returns expected window number', function()
eq(1, funcs.bufwinnr('%'))
command('file ' .. fname)
command('vsplit')
command('split ' .. fname2)
eq(2, funcs.bufwinnr(fname))
eq(1, funcs.bufwinnr(fname2))
eq(-1, funcs.bufwinnr(fname:sub(1, #fname - 1)))
meths.set_current_dir(dirname)
eq(2, funcs.bufwinnr(fname))
eq(1, funcs.bufwinnr(fname2))
eq(-1, funcs.bufwinnr(fname:sub(1, #fname - 1)))
eq(1, funcs.bufwinnr('%'))
eq(2, funcs.bufwinnr(1))
eq(1, funcs.bufwinnr(2))
eq(-1, funcs.bufwinnr(3))
eq(1, funcs.bufwinnr('$'))
end)
end)
describe('getbufline() function', function()
it('returns empty list when buffer was not found', function()
command('file ' .. fname)
eq({}, funcs.getbufline(2, 1))
eq({}, funcs.getbufline('non-existent-buffer', 1))
eq({}, funcs.getbufline('#', 1))
command('edit ' .. fname2)
eq(2, funcs.bufnr('%'))
eq({}, funcs.getbufline('X', 1))
end)
it('returns empty list when range is invalid', function()
eq({}, funcs.getbufline(1, 0))
curbufmeths.set_lines(0, 1, false, {'foo', 'bar', 'baz'})
eq({}, funcs.getbufline(1, 2, 1))
eq({}, funcs.getbufline(1, -10, -20))
eq({}, funcs.getbufline(1, -2, -1))
eq({}, funcs.getbufline(1, -1, 9999))
end)
it('returns expected lines', function()
meths.set_option('hidden', true)
command('file ' .. fname)
curbufmeths.set_lines(0, 1, false, {'foo\0', '\0bar', 'baz'})
command('edit ' .. fname2)
curbufmeths.set_lines(0, 1, false, {'abc\0', '\0def', 'ghi'})
eq({'foo\n', '\nbar', 'baz'}, funcs.getbufline(1, 1, 9999))
eq({'abc\n', '\ndef', 'ghi'}, funcs.getbufline(2, 1, 9999))
eq({'foo\n', '\nbar', 'baz'}, funcs.getbufline(1, 1, '$'))
eq({'baz'}, funcs.getbufline(1, '$', '$'))
eq({'baz'}, funcs.getbufline(1, '$', 9999))
end)
end)
describe('getbufvar() function', function()
it('returns empty list when buffer was not found', function()
command('file ' .. fname)
eq('', funcs.getbufvar(2, '&autoindent'))
eq('', funcs.getbufvar('non-existent-buffer', '&autoindent'))
eq('', funcs.getbufvar('#', '&autoindent'))
command('edit ' .. fname2)
eq(2, funcs.bufnr('%'))
eq('', funcs.getbufvar('X', '&autoindent'))
end)
it('returns empty list when variable/option/etc was not found', function()
command('file ' .. fname)
eq('', funcs.getbufvar(1, '&autondent'))
eq('', funcs.getbufvar(1, 'changedtic'))
end)
it('returns expected option value', function()
eq(0, funcs.getbufvar(1, '&autoindent'))
eq(0, funcs.getbufvar(1, '&l:autoindent'))
eq(0, funcs.getbufvar(1, '&g:autoindent'))
-- Also works with global-only options
eq(0, funcs.getbufvar(1, '&hidden'))
eq(0, funcs.getbufvar(1, '&l:hidden'))
eq(0, funcs.getbufvar(1, '&g:hidden'))
-- Also works with window-local options
eq(0, funcs.getbufvar(1, '&number'))
eq(0, funcs.getbufvar(1, '&l:number'))
eq(0, funcs.getbufvar(1, '&g:number'))
command('new')
-- But with window-local options it probably does not what you expect
curwinmeths.set_option('number', true)
-- (note that current windows buffer is 2, but getbufvar() receives 1)
eq(2, bufmeths.get_number(curwinmeths.get_buf()))
eq(1, funcs.getbufvar(1, '&number'))
eq(1, funcs.getbufvar(1, '&l:number'))
-- You can get global value though, if you find this useful.
eq(0, funcs.getbufvar(1, '&g:number'))
end)
it('returns expected variable value', function()
eq(2, funcs.getbufvar(1, 'changedtick'))
curbufmeths.set_lines(0, 1, false, {'abc\0', '\0def', 'ghi'})
eq(3, funcs.getbufvar(1, 'changedtick'))
curbufmeths.set_var('test', true)
eq(true, funcs.getbufvar(1, 'test'))
eq({test=true, changedtick=3}, funcs.getbufvar(1, ''))
command('new')
eq(3, funcs.getbufvar(1, 'changedtick'))
eq(true, funcs.getbufvar(1, 'test'))
eq({test=true, changedtick=3}, funcs.getbufvar(1, ''))
end)
end)
describe('setbufvar() function', function()
it('throws the error or ignores the input when buffer was not found', function()
command('file ' .. fname)
eq(0,
exc_exec('call setbufvar(2, "&autoindent", 0)'))
eq('Vim(call):E94: No matching buffer for non-existent-buffer',
exc_exec('call setbufvar("non-existent-buffer", "&autoindent", 0)'))
eq(0,
exc_exec('call setbufvar("#", "&autoindent", 0)'))
command('edit ' .. fname2)
eq(2, funcs.bufnr('%'))
eq('Vim(call):E93: More than one match for X',
exc_exec('call setbufvar("X", "&autoindent", 0)'))
end)
it('may set options, including window-local and global values', function()
local buf1 = meths.get_current_buf()
eq(false, curwinmeths.get_option('number'))
command('split')
command('new')
eq(2, bufmeths.get_number(curwinmeths.get_buf()))
funcs.setbufvar(1, '&number', true)
local windows = curtabmeths.list_wins()
eq(false, winmeths.get_option(windows[1], 'number'))
eq(true, winmeths.get_option(windows[2], 'number'))
eq(false, winmeths.get_option(windows[3], 'number'))
eq(false, winmeths.get_option(meths.get_current_win(), 'number'))
eq(false, meths.get_option('hidden'))
funcs.setbufvar(1, '&hidden', true)
eq(true, meths.get_option('hidden'))
eq(false, bufmeths.get_option(buf1, 'autoindent'))
funcs.setbufvar(1, '&autoindent', true)
eq(true, bufmeths.get_option(buf1, 'autoindent'))
eq('Vim(call):E355: Unknown option: xxx',
exc_exec('call setbufvar(1, "&xxx", 0)'))
end)
it('may set variables', function()
local buf1 = meths.get_current_buf()
command('split')
command('new')
eq(2, curbufmeths.get_number())
funcs.setbufvar(1, 'number', true)
eq(true, bufmeths.get_var(buf1, 'number'))
eq('Vim(call):E461: Illegal variable name: b:',
exc_exec('call setbufvar(1, "", 0)'))
eq(true, bufmeths.get_var(buf1, 'number'))
funcs.setbufvar(1, 'changedtick', true)
-- eq(true, bufmeths.get_var(buf1, 'changedtick'))
eq(2, funcs.getbufvar(1, 'changedtick'))
end)
end)

View File

@ -0,0 +1,24 @@
local helpers = require('test.functional.helpers')(after_each)
local eq = helpers.eq
local eval = helpers.eval
local meths = helpers.meths
local clear = helpers.clear
before_each(clear)
describe('extend()', function()
it('suceeds to extend list with itself', function()
meths.set_var('l', {1, {}})
eq({1, {}, 1, {}}, eval('extend(l, l)'))
eq({1, {}, 1, {}}, meths.get_var('l'))
meths.set_var('l', {1, {}})
eq({1, {}, 1, {}}, eval('extend(l, l, 0)'))
eq({1, {}, 1, {}}, meths.get_var('l'))
meths.set_var('l', {1, {}})
eq({1, 1, {}, {}}, eval('extend(l, l, 1)'))
eq({1, 1, {}, {}}, meths.get_var('l'))
end)
end)

View File

@ -0,0 +1,38 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local feed = helpers.feed
local clear = helpers.clear
local command = helpers.command
local screen
before_each(function()
clear()
screen = Screen.new(25, 5)
screen:attach()
end)
describe('input()', function()
it('works correctly with multiline prompts', function()
feed([[:call input("Test\nFoo")<CR>]])
screen:expect([[
{1:~ }|
{1:~ }|
{1:~ }|
Test |
Foo^ |
]], {{bold=true, foreground=Screen.colors.Blue}})
end)
it('works correctly with multiline prompts and :echohl', function()
command('hi Test ctermfg=Red guifg=Red term=bold')
feed([[:echohl Test | call input("Test\nFoo")<CR>]])
screen:expect([[
{1:~ }|
{1:~ }|
{1:~ }|
{2:Test} |
{2:Foo}^ |
]], {{bold=true, foreground=Screen.colors.Blue}, {foreground=Screen.colors.Red}})
end)
end)

View File

@ -0,0 +1,61 @@
local helpers = require('test.functional.helpers')(after_each)
local eq = helpers.eq
local clear = helpers.clear
local funcs = helpers.funcs
local command = helpers.command
before_each(clear)
describe('setmatches()', function()
it('correctly handles case when both group and pattern entries are numbers',
function()
command('hi def link 1 PreProc')
eq(0, funcs.setmatches({{group=1, pattern=2, id=3, priority=4}}))
eq({{
group='1',
pattern='2',
id=3,
priority=4,
}}, funcs.getmatches())
eq(0, funcs.setmatches({{group=1, pattern=2, id=3, priority=4, conceal=5}}))
eq({{
group='1',
pattern='2',
id=3,
priority=4,
conceal='5',
}}, funcs.getmatches())
eq(0, funcs.setmatches({{group=1, pos1={2}, pos2={6}, id=3, priority=4, conceal=5}}))
eq({{
group='1',
pos1={2},
pos2={6},
id=3,
priority=4,
conceal='5',
}}, funcs.getmatches())
end)
it('fails with -1 if highlight group is not defined', function()
eq(-1, funcs.setmatches({{group=1, pattern=2, id=3, priority=4}}))
eq({}, funcs.getmatches())
eq(-1, funcs.setmatches({{group=1, pos1={2}, pos2={6}, id=3, priority=4, conceal=5}}))
eq({}, funcs.getmatches())
end)
end)
describe('matchadd()', function()
it('correctly works when first two arguments and conceal are numbers at once',
function()
command('hi def link 1 PreProc')
eq(4, funcs.matchadd(1, 2, 3, 4, {conceal=5}))
eq({{
group='1',
pattern='2',
priority=3,
id=4,
conceal='5',
}}, funcs.getmatches())
end)
end)

View File

@ -0,0 +1,51 @@
local helpers = require('test.functional.helpers')(after_each)
local eq = helpers.eq
local eval = helpers.eval
local clear = helpers.clear
local funcs = helpers.funcs
local redir_exec = helpers.redir_exec
before_each(clear)
for _, func in ipairs({'min', 'max'}) do
describe(func .. '()', function()
it('gives a single error message when multiple values failed conversions',
function()
eq('\nE745: Using a List as a Number\n0',
redir_exec('echo ' .. func .. '([-5, [], [], [], 5])'))
eq('\nE745: Using a List as a Number\n0',
redir_exec('echo ' .. func .. '({1:-5, 2:[], 3:[], 4:[], 5:5})'))
for errmsg, errinput in pairs({
['E745: Using a List as a Number'] = '[]',
['E805: Using a Float as a Number'] = '0.0',
['E703: Using a Funcref as a Number'] = 'function("tr")',
['E728: Using a Dictionary as a Number'] = '{}',
}) do
eq('\n' .. errmsg .. '\n0',
redir_exec('echo ' .. func .. '([' .. errinput .. '])'))
eq('\n' .. errmsg .. '\n0',
redir_exec('echo ' .. func .. '({1:' .. errinput .. '})'))
end
end)
it('works with arrays/dictionaries with zero items', function()
eq(0, funcs[func]({}))
eq(0, eval(func .. '({})'))
end)
it('works with arrays/dictionaries with one item', function()
eq(5, funcs[func]({5}))
eq(5, funcs[func]({test=5}))
end)
it('works with NULL arrays/dictionaries', function()
eq(0, eval(func .. '(v:_null_list)'))
eq(0, eval(func .. '(v:_null_dict)'))
end)
it('errors out for invalid types', function()
for _, errinput in ipairs({'1', 'v:true', 'v:false', 'v:null',
'function("tr")', '""'}) do
eq(('\nE712: Argument of %s() must be a List or Dictionary\n0'):format(
func),
redir_exec('echo ' .. func .. '(' .. errinput .. ')'))
end
end)
end)
end

View File

@ -0,0 +1,138 @@
local helpers = require('test.functional.helpers')(after_each)
local curbufmeths = helpers.curbufmeths
local redir_exec = helpers.redir_exec
local exc_exec = helpers.exc_exec
local command = helpers.command
local clear = helpers.clear
local meths = helpers.meths
local funcs = helpers.funcs
local eq = helpers.eq
describe('NULL', function()
before_each(function()
clear()
command('let L = v:_null_list')
command('let D = v:_null_dict')
command('let S = $XXX_NONEXISTENT_VAR_XXX')
end)
local tmpfname = 'Xtest-functional-viml-null'
after_each(function()
os.remove(tmpfname)
end)
local null_test = function(name, cmd, err)
it(name, function()
eq(err, exc_exec(cmd))
end)
end
local null_expr_test = function(name, expr, err, val, after)
it(name, function()
eq((err == 0) and ('') or ('\n' .. err),
redir_exec('let g:_var = ' .. expr))
if val == nil then
eq(0, funcs.exists('g:_var'))
else
eq(val, meths.get_var('_var'))
end
if after ~= nil then
after()
end
end)
end
describe('list', function()
-- Incorrect behaviour
-- FIXME map() should not return 0 without error
null_expr_test('does not crash map()', 'map(L, "v:val")', 0, 0)
-- FIXME map() should not return 0 without error
null_expr_test('does not crash filter()', 'filter(L, "1")', 0, 0)
-- FIXME map() should at least return L
null_expr_test('makes map() return v:_null_list', 'map(L, "v:val") is# L', 0, 0)
-- FIXME filter() should at least return L
null_expr_test('makes filter() return v:_null_list', 'map(L, "1") is# L', 0, 0)
-- FIXME add() should not return 1 at all
null_expr_test('does not crash add()', 'add(L, 0)', 0, 1)
null_expr_test('does not crash extend()', 'extend(L, [1])', 'E742: Cannot change value of extend() argument', 0)
null_expr_test('does not crash extend() (second position)', 'extend([1], L)', 0, {1})
-- FIXME should be accepted by inputlist()
null_expr_test('is accepted as an empty list by inputlist()',
'[feedkeys("\\n"), inputlist(L)]', 'E686: Argument of inputlist() must be a List', {0, 0})
-- FIXME should be accepted by writefile(), return {0, {}}
null_expr_test('is accepted as an empty list by writefile()',
('[writefile(L, "%s"), readfile("%s")]'):format(tmpfname, tmpfname),
'E484: Can\'t open file ' .. tmpfname, {0, {}})
-- FIXME should give error message
null_expr_test('does not crash remove()', 'remove(L, 0)', 0, 0)
-- FIXME should return 0
null_expr_test('is accepted by setqflist()', 'setqflist(L)', 0, -1)
-- FIXME should return 0
null_expr_test('is accepted by setloclist()', 'setloclist(1, L)', 0, -1)
-- FIXME should return 0
null_expr_test('is accepted by setmatches()', 'setmatches(L)', 0, -1)
-- FIXME should return empty list or error out
null_expr_test('is accepted by sort()', 'sort(L)', 0, 0)
-- FIXME Should return 1
null_expr_test('is accepted by sort()', 'sort(L) is L', 0, 0)
-- FIXME should not error out
null_test('is accepted by :cexpr', 'cexpr L', 'Vim(cexpr):E777: String or List expected')
-- FIXME should not error out
null_test('is accepted by :lexpr', 'lexpr L', 'Vim(lexpr):E777: String or List expected')
null_test('is accepted by :for', 'for x in L|throw x|endfor', 0)
-- Subjectable behaviour
-- FIXME Should return 1
null_expr_test('is equal to empty list', 'L == []', 0, 0)
-- FIXME Should return 1
null_expr_test('is equal to empty list (reverse order)', '[] == L', 0, 0)
-- FIXME Should return 1
null_expr_test('is not locked', 'islocked("v:_null_list")', 0, 0)
-- Crashes
-- null_expr_test('does not crash setreg', 'setreg("x", L)', 0, 0)
-- null_expr_test('does not crash setline', 'setline(1, L)', 0, 0)
-- null_expr_test('does not crash system()', 'system("cat", L)', 0, '')
-- null_expr_test('does not crash systemlist()', 'systemlist("cat", L)', 0, {})
-- Correct behaviour
null_expr_test('does not crash append()', 'append(1, L)', 0, 0, function()
eq({''}, curbufmeths.get_lines(0, -1, false))
end)
null_expr_test('is identical to itself', 'L is L', 0, 1)
null_expr_test('can be sliced', 'L[:]', 0, {})
null_expr_test('can be copied', 'copy(L)', 0, {})
null_expr_test('can be deepcopied', 'deepcopy(L)', 0, {})
null_expr_test('does not crash when indexed', 'L[1]',
'E684: list index out of range: 1\nE15: Invalid expression: L[1]', nil)
null_expr_test('does not crash call()', 'call("arglistid", L)', 0, 0)
null_expr_test('does not crash col()', 'col(L)', 0, 0)
null_expr_test('does not crash virtcol()', 'virtcol(L)', 0, 0)
null_expr_test('does not crash line()', 'line(L)', 0, 0)
null_expr_test('does not crash count()', 'count(L, 1)', 0, 0)
null_expr_test('does not crash cursor()', 'cursor(L)', 'E474: Invalid argument', -1)
null_expr_test('is empty', 'empty(L)', 0, 1)
null_expr_test('does not crash get()', 'get(L, 1, 10)', 0, 10)
null_expr_test('has zero length', 'len(L)', 0, 0)
null_expr_test('is accepted as an empty list by max()', 'max(L)', 0, 0)
null_expr_test('is accepted as an empty list by min()', 'min(L)', 0, 0)
null_expr_test('is stringified correctly', 'string(L)', 0, '[]')
null_expr_test('is JSON encoded correctly', 'json_encode(L)', 0, '[]')
null_test('does not crash lockvar', 'lockvar! L', 0)
null_expr_test('can be added to itself', '(L + L)', 0, {})
null_expr_test('can be added to itself', '(L + L) is L', 0, 1)
null_expr_test('can be added to non-empty list', '([1] + L)', 0, {1})
null_expr_test('can be added to non-empty list (reversed)', '(L + [1])', 0, {1})
null_expr_test('is equal to itself', 'L == L', 0, 1)
null_expr_test('is not not equal to itself', 'L != L', 0, 0)
null_expr_test('counts correctly', 'count([L], L)', 0, 1)
end)
describe('dict', function()
it('does not crash when indexing NULL dict', function()
eq('\nE716: Key not present in Dictionary: test\nE15: Invalid expression: v:_null_dict.test',
redir_exec('echo v:_null_dict.test'))
end)
null_expr_test('makes extend error out', 'extend(D, {})', 'E742: Cannot change value of extend() argument', 0)
null_expr_test('makes extend do nothing', 'extend({1: 2}, D)', 0, {['1']=2})
end)
end)

View File

@ -0,0 +1,41 @@
local helpers = require('test.functional.helpers')(after_each)
local eq = helpers.eq
local NIL = helpers.NIL
local eval = helpers.eval
local clear = helpers.clear
local meths = helpers.meths
local funcs = helpers.funcs
local command = helpers.command
local exc_exec = helpers.exc_exec
before_each(clear)
describe('sort()', function()
it('errors out when sorting special values', function()
eq('Vim(call):E907: Using a special value as a Float',
exc_exec('call sort([v:true, v:false], "f")'))
end)
it('sorts “wrong” values between -0.0001 and 0.0001, preserving order',
function()
meths.set_var('list', {true, false, NIL, {}, {a=42}, 'check',
0.0001, -0.0001})
command('call insert(g:list, function("tr"))')
local error_lines = funcs.split(
funcs.execute('silent! call sort(g:list, "f")'), '\n')
local errors = {}
for _, err in ipairs(error_lines) do
errors[err] = true
end
eq({
['E891: Using a Funcref as a Float']=true,
['E892: Using a String as a Float']=true,
['E893: Using a List as a Float']=true,
['E894: Using a Dictionary as a Float']=true,
['E907: Using a special value as a Float']=true,
}, errors)
eq('[-1.0e-4, function(\'tr\'), v:true, v:false, v:null, [], {\'a\': 42}, \'check\', 1.0e-4]',
eval('string(g:list)'))
end)
end)

View File

@ -7,7 +7,6 @@ local eval = helpers.eval
local exc_exec = helpers.exc_exec
local redir_exec = helpers.redir_exec
local funcs = helpers.funcs
local write_file = helpers.write_file
local NIL = helpers.NIL
local source = helpers.source
local dedent = helpers.dedent
@ -105,10 +104,8 @@ describe('string() function', function()
end)
describe('used to represent funcrefs', function()
local fname = 'Xtest-functional-eval-string_spec-fref-script.vim'
before_each(function()
write_file(fname, [[
source([[
function Test1()
endfunction
@ -120,11 +117,6 @@ describe('string() function', function()
let g:Test2_f = function('s:Test2')
]])
command('source ' .. fname)
end)
after_each(function()
os.remove(fname)
end)
it('dumps references to built-in functions', function()

View File

@ -49,7 +49,7 @@ describe('timers', function()
it('works with zero timeout', function()
-- timer_start does still not invoke the callback immediately
eq(0,eval("[timer_start(0, 'MyHandler', {'repeat': 1000}), g:val][1]"))
run(nil, nil, nil, 300)
run(nil, nil, nil, 400)
eq(1000,eval("g:val"))
end)

Some files were not shown because too many files have changed in this diff Show More