aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/CMakeLists.txt47
-rw-r--r--src/nvim/charset.c10
-rw-r--r--src/nvim/edit.c11
-rw-r--r--src/nvim/eval.c1356
-rw-r--r--src/nvim/ex_cmds.c38
-rw-r--r--src/nvim/ex_cmds2.c4
-rw-r--r--src/nvim/ex_docmd.c74
-rw-r--r--src/nvim/ex_eval.c20
-rw-r--r--src/nvim/ex_getln.c65
-rw-r--r--src/nvim/farsi.c4
-rw-r--r--src/nvim/file_search.c26
-rw-r--r--src/nvim/fileio.c181
-rw-r--r--src/nvim/getchar.c64
-rw-r--r--src/nvim/globals.h9
-rw-r--r--src/nvim/hashtab.c77
-rw-r--r--src/nvim/if_cscope.c5
-rw-r--r--src/nvim/keymap.c4
-rw-r--r--src/nvim/memline.c4
-rw-r--r--src/nvim/menu.c9
-rw-r--r--src/nvim/message.c1229
-rw-r--r--src/nvim/message.h13
-rw-r--r--src/nvim/misc1.c4
-rw-r--r--src/nvim/normal.c4
-rw-r--r--src/nvim/ops.c7
-rw-r--r--src/nvim/option.c13
-rw-r--r--src/nvim/option_defs.h1
-rw-r--r--src/nvim/options.lua7
-rw-r--r--src/nvim/pos.h2
-rw-r--r--src/nvim/quickfix.c15
-rw-r--r--src/nvim/screen.c16
-rw-r--r--src/nvim/search.c12
-rw-r--r--src/nvim/spell.c64
-rw-r--r--src/nvim/strings.c848
-rw-r--r--src/nvim/strings.h5
-rw-r--r--src/nvim/syntax.c138
-rw-r--r--src/nvim/tag.c21
-rw-r--r--src/nvim/tui/tui.c2
-rw-r--r--src/nvim/undo.c11
-rw-r--r--src/nvim/version.c2
39 files changed, 2321 insertions, 2101 deletions
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index 5a658691ce..b19a951d5b 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -299,25 +299,6 @@ if(WIN32)
install(DIRECTORY ${PROJECT_BINARY_DIR}/windows_runtime_deps/
DESTINATION ${CMAKE_INSTALL_BINDIR})
- foreach(BIN win32yank.exe)
- unset(BIN_PATH CACHE)
- find_program(BIN_PATH ${BIN})
- if(NOT BIN_PATH)
- message(FATAL_ERROR "Unable to find external dependency ${BIN}")
- endif()
-
- add_custom_target(external_${BIN}
- COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/windows_runtime_deps
- COMMAND ${CMAKE_COMMAND}
- "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}"
- -DBINARY="${BIN_PATH}"
- -DDST=${PROJECT_BINARY_DIR}/windows_runtime_deps
- -P ${PROJECT_SOURCE_DIR}/cmake/WindowsDllCopy.cmake
- COMMAND ${CMAKE_COMMAND} -E copy ${BIN_PATH} ${PROJECT_BINARY_DIR}/windows_runtime_deps/
- COMMENT "${BIN_PATH}")
- add_dependencies(nvim_runtime_deps "external_${BIN}")
- endforeach()
-
add_custom_target(nvim_dll_deps DEPENDS nvim
COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/windows_runtime_deps
COMMAND ${CMAKE_COMMAND}
@@ -326,6 +307,34 @@ if(WIN32)
-DDST=${PROJECT_BINARY_DIR}/windows_runtime_deps
-P ${PROJECT_SOURCE_DIR}/cmake/WindowsDllCopy.cmake)
add_dependencies(nvim_runtime_deps nvim_dll_deps)
+
+ add_custom_target(external_blobs
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/windows_runtime_deps/platforms
+
+ COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/ca-bundle.crt" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
+ COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/curl.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
+ COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/diff.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
+ COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/tee.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
+ COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/tidy.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
+ COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/win32yank.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
+
+ COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/D3Dcompiler_47.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
+ COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libEGL.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
+ COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libgcc_s_dw2-1.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
+ COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libGLESV2.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
+ COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libstdc++-6.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
+ COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libwinpthread-1.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
+ COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/nvim-qt.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
+ COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/Qt5Core.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
+ COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/Qt5Gui.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
+ COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/Qt5Network.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
+ COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/Qt5Svg.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
+ COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/Qt5Widgets.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
+
+ COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/platforms/qwindows.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/platforms/
+ )
+
+ add_dependencies(nvim_runtime_deps external_blobs)
endif()
if(CLANG_ASAN_UBSAN)
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index 4d150c3230..e33e002787 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -1373,17 +1373,17 @@ void getvcols(win_T *wp, pos_T *pos1, pos_T *pos2, colnr_T *left,
/// skipwhite: skip over ' ' and '\t'.
///
-/// @param q
+/// @param[in] q String to skip in.
///
/// @return Pointer to character after the skipped whitespace.
-char_u* skipwhite(char_u *q)
+char_u *skipwhite(const char_u *q)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- char_u *p = q;
+ const char_u *p = q;
while (ascii_iswhite(*p)) {
- // skip to next non-white
p++;
}
- return p;
+ return (char_u *)p;
}
/// skip over digits
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 53540d21d4..9a8ff21263 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -1859,8 +1859,9 @@ static bool check_compl_option(bool dict_opt)
: (*curbuf->b_p_tsr == NUL && *p_tsr == NUL)) {
ctrl_x_mode = 0;
edit_submode = NULL;
- msg_attr(dict_opt ? (char_u *)_("'dictionary' option is empty")
- : (char_u *)_("'thesaurus' option is empty"), hl_attr(HLF_E));
+ msg_attr((dict_opt
+ ? _("'dictionary' option is empty")
+ : _("'thesaurus' option is empty")), hl_attr(HLF_E));
if (emsg_silent == 0) {
vim_beep(BO_COMPL);
setcursor();
@@ -4801,9 +4802,9 @@ static int ins_complete(int c, bool enable_pum)
if (!shortmess(SHM_COMPLETIONMENU)) {
if (edit_submode_extra != NULL) {
if (!p_smd) {
- msg_attr(edit_submode_extra,
- edit_submode_highl < HLF_COUNT
- ? hl_attr(edit_submode_highl) : 0);
+ msg_attr((const char *)edit_submode_extra,
+ (edit_submode_highl < HLF_COUNT
+ ? hl_attr(edit_submode_highl) : 0));
}
} else {
msg_clr_cmdline(); // necessary for "noshowmode"
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 49ce9f3144..57c2368523 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -1422,13 +1422,13 @@ void ex_let(exarg_T *eap)
if (*expr != '=' && !(vim_strchr((char_u *)"+-.", *expr) != NULL
&& expr[1] == '=')) {
// ":let" without "=": list variables
- if (*arg == '[')
+ if (*arg == '[') {
EMSG(_(e_invarg));
- else if (!ends_excmd(*arg))
- /* ":let var1 var2" */
- arg = list_arg_vars(eap, arg, &first);
- else if (!eap->skip) {
- /* ":let" */
+ } else if (!ends_excmd(*arg)) {
+ // ":let var1 var2"
+ arg = (char_u *)list_arg_vars(eap, (const char *)arg, &first);
+ } else if (!eap->skip) {
+ // ":let"
list_glob_vars(&first);
list_buf_vars(&first);
list_win_vars(&first);
@@ -1612,7 +1612,8 @@ static char_u *skip_var_one(char_u *arg)
* List variables for hashtab "ht" with prefix "prefix".
* If "empty" is TRUE also list NULL strings as empty strings.
*/
-static void list_hashtable_vars(hashtab_T *ht, char_u *prefix, int empty, int *first)
+static void list_hashtable_vars(hashtab_T *ht, const char *prefix, int empty,
+ int *first)
{
hashitem_T *hi;
dictitem_T *di;
@@ -1621,11 +1622,12 @@ static void list_hashtable_vars(hashtab_T *ht, char_u *prefix, int empty, int *f
todo = (int)ht->ht_used;
for (hi = ht->ht_array; todo > 0 && !got_int; ++hi) {
if (!HASHITEM_EMPTY(hi)) {
- --todo;
+ todo--;
di = HI2DI(hi);
if (empty || di->di_tv.v_type != VAR_STRING
- || di->di_tv.vval.v_string != NULL)
+ || di->di_tv.vval.v_string != NULL) {
list_one_var(di, prefix, first);
+ }
}
}
}
@@ -1635,7 +1637,7 @@ static void list_hashtable_vars(hashtab_T *ht, char_u *prefix, int empty, int *f
*/
static void list_glob_vars(int *first)
{
- list_hashtable_vars(&globvarht, (char_u *)"", TRUE, first);
+ list_hashtable_vars(&globvarht, "", true, first);
}
/*
@@ -1643,14 +1645,13 @@ static void list_glob_vars(int *first)
*/
static void list_buf_vars(int *first)
{
- char_u numbuf[NUMBUFLEN];
+ char numbuf[NUMBUFLEN];
- list_hashtable_vars(&curbuf->b_vars->dv_hashtab, (char_u *)"b:",
- TRUE, first);
+ list_hashtable_vars(&curbuf->b_vars->dv_hashtab, "b:", true, first);
- sprintf((char *)numbuf, "%" PRId64, (int64_t)curbuf->b_changedtick);
- list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER,
- numbuf, first);
+ snprintf(numbuf, sizeof(numbuf), "%d", curbuf->b_changedtick);
+ list_one_var_a("b:", "changedtick", sizeof("changedtick") - 1, VAR_NUMBER,
+ numbuf, first);
}
/*
@@ -1658,8 +1659,7 @@ static void list_buf_vars(int *first)
*/
static void list_win_vars(int *first)
{
- list_hashtable_vars(&curwin->w_vars->dv_hashtab,
- (char_u *)"w:", TRUE, first);
+ list_hashtable_vars(&curwin->w_vars->dv_hashtab, "w:", true, first);
}
/*
@@ -1667,8 +1667,7 @@ static void list_win_vars(int *first)
*/
static void list_tab_vars(int *first)
{
- list_hashtable_vars(&curtab->tp_vars->dv_hashtab,
- (char_u *)"t:", TRUE, first);
+ list_hashtable_vars(&curtab->tp_vars->dv_hashtab, "t:", true, first);
}
/*
@@ -1676,7 +1675,7 @@ static void list_tab_vars(int *first)
*/
static void list_vim_vars(int *first)
{
- list_hashtable_vars(&vimvarht, (char_u *)"v:", FALSE, first);
+ list_hashtable_vars(&vimvarht, "v:", false, first);
}
/*
@@ -1684,9 +1683,9 @@ static void list_vim_vars(int *first)
*/
static void list_script_vars(int *first)
{
- if (current_SID > 0 && current_SID <= ga_scripts.ga_len)
- list_hashtable_vars(&SCRIPT_VARS(current_SID),
- (char_u *)"s:", FALSE, first);
+ if (current_SID > 0 && current_SID <= ga_scripts.ga_len) {
+ list_hashtable_vars(&SCRIPT_VARS(current_SID), "s:", false, first);
+ }
}
/*
@@ -1694,36 +1693,37 @@ static void list_script_vars(int *first)
*/
static void list_func_vars(int *first)
{
- if (current_funccal != NULL)
- list_hashtable_vars(&current_funccal->l_vars.dv_hashtab,
- (char_u *)"l:", FALSE, first);
+ if (current_funccal != NULL) {
+ list_hashtable_vars(&current_funccal->l_vars.dv_hashtab, "l:", false,
+ first);
+ }
}
/*
* List variables in "arg".
*/
-static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first)
+static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first)
{
int error = FALSE;
int len;
- char_u *name;
- char_u *name_start;
- char_u *arg_subsc;
- char_u *tofree;
+ const char *name;
+ const char *name_start;
typval_T tv;
while (!ends_excmd(*arg) && !got_int) {
if (error || eap->skip) {
- arg = find_name_end(arg, NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
+ arg = (const char *)find_name_end((char_u *)arg, NULL, NULL,
+ FNE_INCL_BR | FNE_CHECK_START);
if (!ascii_iswhite(*arg) && !ends_excmd(*arg)) {
emsg_severe = TRUE;
EMSG(_(e_trailing));
break;
}
} else {
- /* get_name_len() takes care of expanding curly braces */
+ // get_name_len() takes care of expanding curly braces
name_start = name = arg;
- len = get_name_len(&arg, &tofree, TRUE, TRUE);
+ char *tofree;
+ len = get_name_len(&arg, &tofree, true, true);
if (len <= 0) {
/* This is mainly to keep test 49 working: when expanding
* curly braces fails overrule the exception error message. */
@@ -1737,14 +1737,15 @@ static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first)
if (tofree != NULL) {
name = tofree;
}
- if (get_var_tv(name, len, &tv, NULL, true, false) == FAIL) {
+ if (get_var_tv((const char *)name, len, &tv, NULL, true, false)
+ == FAIL) {
error = true;
} else {
// handle d.key, l[idx], f(expr)
- arg_subsc = arg;
- if (handle_subscript(&arg, &tv, TRUE, TRUE) == FAIL)
- error = TRUE;
- else {
+ const char *const arg_subsc = arg;
+ if (handle_subscript(&arg, &tv, true, true) == FAIL) {
+ error = true;
+ } else {
if (arg == arg_subsc && len == 2 && name[1] == ':') {
switch (*name) {
case 'g': list_glob_vars(first); break;
@@ -1758,17 +1759,15 @@ static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first)
EMSG2(_("E738: Can't list variables for %s"), name);
}
} else {
- int c;
-
- char_u *s = (char_u *) encode_tv2echo(&tv, NULL);
- c = *arg;
- *arg = NUL;
- list_one_var_a((char_u *)"",
- arg == arg_subsc ? name : name_start,
- tv.v_type,
- s == NULL ? (char_u *)"" : s,
- first);
- *arg = c;
+ char *const s = encode_tv2echo(&tv, NULL);
+ const char *const used_name = (arg == arg_subsc
+ ? name
+ : name_start);
+ const ptrdiff_t name_size = (used_name == tofree
+ ? (ptrdiff_t)strlen(used_name)
+ : (arg - used_name));
+ list_one_var_a("", used_name, name_size,
+ tv.v_type, s == NULL ? "" : s, first);
xfree(s);
}
clear_tv(&tv);
@@ -1779,7 +1778,7 @@ static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first)
xfree(tofree);
}
- arg = skipwhite(arg);
+ arg = (const char *)skipwhite((const char_u *)arg);
}
return arg;
@@ -1799,9 +1798,7 @@ ex_let_one (
char_u *op /* "+", "-", "." or NULL*/
)
{
- int c1;
char_u *name;
- char_u *p;
char_u *arg_end = NULL;
int len;
int opt_flags;
@@ -1815,18 +1812,18 @@ ex_let_one (
++arg;
name = arg;
len = get_env_len(&arg);
- if (len == 0)
+ if (len == 0) {
EMSG2(_(e_invarg2), name - 1);
- else {
- if (op != NULL && (*op == '+' || *op == '-'))
+ } else {
+ if (op != NULL && (*op == '+' || *op == '-')) {
EMSG2(_(e_letwrong), op);
- else if (endchars != NULL
- && vim_strchr(endchars, *skipwhite(arg)) == NULL)
+ } else if (endchars != NULL
+ && vim_strchr(endchars, *skipwhite(arg)) == NULL) {
EMSG(_(e_letunexp));
- else if (!check_secure()) {
- c1 = name[len];
+ } else if (!check_secure()) {
+ const char_u c1 = name[len];
name[len] = NUL;
- p = get_tv_string_chk(tv);
+ char_u *p = get_tv_string_chk(tv);
if (p != NULL && op != NULL && *op == '.') {
char *s = vim_getenv((char *)name);
@@ -1850,43 +1847,41 @@ ex_let_one (
xfree(tofree);
}
}
- }
- /*
- * ":let &option = expr": Set option value.
- * ":let &l:option = expr": Set local option value.
- * ":let &g:option = expr": Set global option value.
- */
- else if (*arg == '&') {
- /* Find the end of the name. */
- p = find_option_end(&arg, &opt_flags);
- if (p == NULL || (endchars != NULL
- && vim_strchr(endchars, *skipwhite(p)) == NULL))
+ // ":let &option = expr": Set option value.
+ // ":let &l:option = expr": Set local option value.
+ // ":let &g:option = expr": Set global option value.
+ } else if (*arg == '&') {
+ // Find the end of the name.
+ char *const p = (char *)find_option_end((const char **)&arg, &opt_flags);
+ if (p == NULL
+ || (endchars != NULL
+ && vim_strchr(endchars, *skipwhite((const char_u *)p)) == NULL)) {
EMSG(_(e_letunexp));
- else {
+ } else {
long n;
int opt_type;
long numval;
- char_u *stringval = NULL;
- char_u *s;
+ char_u *stringval = NULL;
+ char_u *s;
- c1 = *p;
+ const char c1 = *p;
*p = NUL;
n = get_tv_number(tv);
s = get_tv_string_chk(tv); /* != NULL if number or string */
if (s != NULL && op != NULL && *op != '=') {
- opt_type = get_option_value(arg, &numval,
- &stringval, opt_flags);
+ opt_type = get_option_value(arg, &numval, &stringval, opt_flags);
if ((opt_type == 1 && *op == '.')
- || (opt_type == 0 && *op != '.'))
+ || (opt_type == 0 && *op != '.')) {
EMSG2(_(e_letwrong), op);
- else {
- if (opt_type == 1) { /* number */
- if (*op == '+')
+ } else {
+ if (opt_type == 1) { // number
+ if (*op == '+') {
n = numval + n;
- else
+ } else {
n = numval - n;
- } else if (opt_type == 0 && stringval != NULL) { /* string */
+ }
+ } else if (opt_type == 0 && stringval != NULL) { // string
s = concat_str(stringval, s);
xfree(stringval);
stringval = s;
@@ -1895,7 +1890,7 @@ ex_let_one (
}
if (s != NULL) {
set_option_value(arg, n, s, opt_flags);
- arg_end = p;
+ arg_end = (char_u *)p;
}
*p = c1;
xfree(stringval);
@@ -1915,7 +1910,7 @@ ex_let_one (
char_u *ptofree = NULL;
char_u *s;
- p = get_tv_string_chk(tv);
+ char_u *p = get_tv_string_chk(tv);
if (p != NULL && op != NULL && *op == '.') {
s = get_reg_contents(*arg == '@' ? '"' : *arg, kGRegExprSrc);
if (s != NULL) {
@@ -1937,7 +1932,7 @@ ex_let_one (
else if (eval_isnamec1(*arg) || *arg == '{') {
lval_T lv;
- p = get_lval(arg, tv, &lv, FALSE, FALSE, 0, FNE_CHECK_START);
+ char_u *const p = get_lval(arg, tv, &lv, false, false, 0, FNE_CHECK_START);
if (p != NULL && lv.ll_name != NULL) {
if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL)
EMSG(_(e_letunexp));
@@ -2047,9 +2042,11 @@ get_lval (
cc = *p;
*p = NUL;
- v = find_var(lp->ll_name, &ht, flags & GLV_NO_AUTOLOAD);
- if (v == NULL && !quiet)
+ v = find_var((const char *)lp->ll_name, STRLEN(lp->ll_name), &ht,
+ flags & GLV_NO_AUTOLOAD);
+ if (v == NULL && !quiet) {
EMSG2(_(e_undefvar), lp->ll_name);
+ }
*p = cc;
if (v == NULL)
return NULL;
@@ -2309,7 +2306,7 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, ch
// handle +=, -= and .=
di = NULL;
- if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name),
+ if (get_var_tv((const char *)lp->ll_name, (int)STRLEN(lp->ll_name),
&tv, &di, true, false) == OK) {
if ((di == NULL
|| (!var_check_ro(di->di_flags, lp->ll_name, false)
@@ -2785,7 +2782,7 @@ void ex_call(exarg_T *eap)
// contents. For VAR_PARTIAL get its partial, unless we already have one
// from trans_function_name().
len = (int)STRLEN(tofree);
- name = deref_func_name(tofree, &len,
+ name = deref_func_name((const char *)tofree, &len,
partial != NULL ? NULL : &partial, false);
/* Skip white space to allow ":call func ()". Not good, but required for
@@ -2823,9 +2820,10 @@ void ex_call(exarg_T *eap)
break;
}
- /* Handle a function returning a Funcref, Dictionary or List. */
- if (handle_subscript(&arg, &rettv, !eap->skip, TRUE) == FAIL) {
- failed = TRUE;
+ // Handle a function returning a Funcref, Dictionary or List.
+ if (handle_subscript((const char **)&arg, &rettv, !eap->skip, true)
+ == FAIL) {
+ failed = true;
break;
}
@@ -3014,7 +3012,8 @@ int do_unlet(char_u *name, int forceit)
dict_T *d;
dictitem_T *di;
dict_T *dict;
- ht = find_var_ht_dict(name, &varname, &dict);
+ ht = find_var_ht_dict((const char *)name, STRLEN(name),
+ (const char **)&varname, &dict);
if (ht != NULL && *varname != NUL) {
if (ht == &globvarht) {
@@ -3025,7 +3024,7 @@ int do_unlet(char_u *name, int forceit)
} else if (ht == &compat_hashtab) {
d = &vimvardict;
} else {
- di = find_var_in_ht(ht, *name, (char_u *)"", false);
+ di = find_var_in_ht(ht, *name, "", 0, false);
d = di->di_tv.vval.v_dict;
}
if (d == NULL) {
@@ -3034,7 +3033,7 @@ int do_unlet(char_u *name, int forceit)
}
hi = hash_find(ht, varname);
if (HASHITEM_EMPTY(hi)) {
- hi = find_hi_in_scoped_ht(name, &ht);
+ hi = find_hi_in_scoped_ht((const char *)name, &ht);
}
if (hi != NULL && !HASHITEM_EMPTY(hi)) {
di = HI2DI(hi);
@@ -3088,18 +3087,19 @@ static int do_lock_var(lval_T *lp, char_u *name_end, int deep, int lock)
cc = *name_end;
*name_end = NUL;
- /* Normal name or expanded name. */
- if (check_changedtick(lp->ll_name))
+ // Normal name or expanded name.
+ if (check_changedtick(lp->ll_name)) {
ret = FAIL;
- else {
- di = find_var(lp->ll_name, NULL, TRUE);
- if (di == NULL)
+ } else {
+ di = find_var((const char *)lp->ll_name, STRLEN(lp->ll_name), NULL, true);
+ if (di == NULL) {
ret = FAIL;
- else {
- if (lock)
+ } else {
+ if (lock) {
di->di_flags |= DI_FLAGS_LOCK;
- else
+ } else {
di->di_flags &= ~DI_FLAGS_LOCK;
+ }
item_lock(&di->di_tv, deep, lock);
}
}
@@ -4280,9 +4280,10 @@ static int eval7(
break;
// Option value: &name
- case '&': ret = get_option_tv(arg, rettv, evaluate);
+ case '&': {
+ ret = get_option_tv((const char **)arg, rettv, evaluate);
break;
-
+ }
// Environment variable: $VAR.
case '$': ret = get_env_tv(arg, rettv, evaluate);
break;
@@ -4318,7 +4319,7 @@ static int eval7(
// Must be a variable or function name.
// Can also be a curly-braces kind of name: {expr}.
s = *arg;
- len = get_name_len(arg, &alias, evaluate, true);
+ len = get_name_len((const char **)arg, (char **)&alias, evaluate, true);
if (alias != NULL) {
s = alias;
}
@@ -4330,12 +4331,12 @@ static int eval7(
partial_T *partial;
if (!evaluate) {
- check_vars(s, len);
+ check_vars((const char *)s, len);
}
// If "s" is the name of a variable of type VAR_FUNC
// use its contents.
- s = deref_func_name(s, &len, &partial, !evaluate);
+ s = deref_func_name((const char *)s, &len, &partial, !evaluate);
// Invoke the function.
ret = get_func_tv(s, len, rettv, arg,
@@ -4360,9 +4361,9 @@ static int eval7(
ret = FAIL;
}
} else if (evaluate) {
- ret = get_var_tv(s, len, rettv, NULL, true, false);
+ ret = get_var_tv((const char *)s, len, rettv, NULL, true, false);
} else {
- check_vars(s, len);
+ check_vars((const char *)s, len);
ret = OK;
}
}
@@ -4374,7 +4375,7 @@ static int eval7(
// Handle following '[', '(' and '.' for expr[expr], expr.name,
// expr(expr).
if (ret == OK) {
- ret = handle_subscript(arg, rettv, evaluate, true);
+ ret = handle_subscript((const char **)arg, rettv, evaluate, true);
}
// Apply logical NOT and unary '-', from right to left, ignore '+'.
@@ -4675,35 +4676,32 @@ eval_index (
return OK;
}
-/*
- * Get an option value.
- * "arg" points to the '&' or '+' before the option name.
- * "arg" is advanced to character after the option name.
- * Return OK or FAIL.
- */
-static int
-get_option_tv (
- char_u **arg,
- typval_T *rettv, /* when NULL, only check if option exists */
- int evaluate
-)
+/// Get an option value
+///
+/// @param[in,out] arg Points to the '&' or '+' before the option name. Is
+/// advanced to the character after the option name.
+/// @param[out] rettv Location where result is saved.
+/// @param[in] evaluate If not true, rettv is not populated.
+///
+/// @return OK or FAIL.
+static int get_option_tv(const char **const arg, typval_T *const rettv,
+ const bool evaluate)
+ FUNC_ATTR_NONNULL_ARG(1)
{
- char_u *option_end;
long numval;
char_u *stringval;
int opt_type;
int c;
- int working = (**arg == '+'); /* has("+option") */
+ bool working = (**arg == '+'); // has("+option")
int ret = OK;
int opt_flags;
- /*
- * Isolate the option name and find its value.
- */
- option_end = find_option_end(arg, &opt_flags);
+ // Isolate the option name and find its value.
+ char *option_end = (char *)find_option_end(arg, &opt_flags);
if (option_end == NULL) {
- if (rettv != NULL)
+ if (rettv != NULL) {
EMSG2(_("E112: Option name missing: %s"), *arg);
+ }
return FAIL;
}
@@ -4714,8 +4712,8 @@ get_option_tv (
c = *option_end;
*option_end = NUL;
- opt_type = get_option_value(*arg, &numval,
- rettv == NULL ? NULL : &stringval, opt_flags);
+ opt_type = get_option_value((char_u *)(*arg), &numval,
+ rettv == NULL ? NULL : &stringval, opt_flags);
if (opt_type == -3) { /* invalid name */
if (rettv != NULL)
@@ -7266,53 +7264,55 @@ static VimLFuncDef *find_internal_func(const char *const name)
return find_internal_func_gperf(name, len);
}
-/// Check if "name" is a variable of type VAR_FUNC. If so, return the function
-/// name it contains, otherwise return "name".
-/// If "partialp" is not NULL, and "name" is of type VAR_PARTIAL also set
-/// "partialp".
-static char_u *deref_func_name(
- char_u *name, int *lenp,
- partial_T **partialp, bool no_autoload
-)
+/// Return name of the function corresponding to `name`
+///
+/// If `name` points to variable that is either a function or partial then
+/// corresponding function name is returned. Otherwise it returns `name` itself.
+///
+/// @param[in] name Function name to check.
+/// @param[in,out] lenp Location where length of the returned name is stored.
+/// Must be set to the length of the `name` argument.
+/// @param[out] partialp Location where partial will be stored if found
+/// function appears to be a partial. May be NULL if this
+/// is not needed.
+/// @param[in] no_autoload If true, do not source autoload scripts if function
+/// was not found.
+///
+/// @return name of the function.
+static char_u *deref_func_name(const char *name, int *lenp,
+ partial_T **const partialp, bool no_autoload)
+ FUNC_ATTR_NONNULL_ARG(1, 2)
{
- dictitem_T *v;
- int cc;
- char_u *s;
-
if (partialp != NULL) {
*partialp = NULL;
}
- cc = name[*lenp];
- name[*lenp] = NUL;
- v = find_var(name, NULL, no_autoload);
- name[*lenp] = cc;
+ dictitem_T *const v = find_var(name, (size_t)(*lenp), NULL, no_autoload);
if (v != NULL && v->di_tv.v_type == VAR_FUNC) {
- if (v->di_tv.vval.v_string == NULL) {
+ if (v->di_tv.vval.v_string == NULL) { // just in case
*lenp = 0;
- return (char_u *)""; /* just in case */
+ return (char_u *)"";
}
- s = v->di_tv.vval.v_string;
- *lenp = (int)STRLEN(s);
- return s;
+ *lenp = (int)STRLEN(v->di_tv.vval.v_string);
+ return v->di_tv.vval.v_string;
}
if (v != NULL && v->di_tv.v_type == VAR_PARTIAL) {
- partial_T *pt = v->di_tv.vval.v_partial;
+ partial_T *const pt = v->di_tv.vval.v_partial;
- if (pt == NULL) {
+ if (pt == NULL) { // just in case
*lenp = 0;
- return (char_u *)""; // just in case
+ return (char_u *)"";
}
if (partialp != NULL) {
*partialp = pt;
}
- s = partial_name(pt);
+ char_u *s = partial_name(pt);
*lenp = (int)STRLEN(s);
return s;
}
- return name;
+ return (char_u *)name;
}
/*
@@ -7394,34 +7394,49 @@ get_func_tv (
return ret;
}
-#define ERROR_UNKNOWN 0
-#define ERROR_TOOMANY 1
-#define ERROR_TOOFEW 2
-#define ERROR_SCRIPT 3
-#define ERROR_DICT 4
-#define ERROR_NONE 5
-#define ERROR_OTHER 6
-#define ERROR_BOTH 7
-#define ERROR_DELETED 8
+typedef enum {
+ ERROR_UNKNOWN = 0,
+ ERROR_TOOMANY,
+ ERROR_TOOFEW,
+ ERROR_SCRIPT,
+ ERROR_DICT,
+ ERROR_NONE,
+ ERROR_OTHER,
+ ERROR_BOTH,
+ ERROR_DELETED,
+} FnameTransError;
+
#define FLEN_FIXED 40
-/// In a script change <SID>name() and s:name() to K_SNR 123_name().
-/// Change <SNR>123_name() to K_SNR 123_name().
-/// Use "fname_buf[FLEN_FIXED + 1]" when it fits, otherwise allocate memory
-/// (slow).
-static char_u *
-fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error) {
- int llen;
+/// In a script transform script-local names into actually used names
+///
+/// Transforms "<SID>" and "s:" prefixes to `K_SNR {N}` (e.g. K_SNR "123") and
+/// "<SNR>" prefix to `K_SNR`. Uses `fname_buf` buffer that is supposed to have
+/// #FLEN_FIXED + 1 length when it fits, otherwise it allocates memory.
+///
+/// @param[in] name Name to transform.
+/// @param fname_buf Buffer to save resulting function name to, if it fits.
+/// Must have at least #FLEN_FIXED + 1 length.
+/// @param[out] tofree Location where pointer to an allocated memory is saved
+/// in case result does not fit into fname_buf.
+/// @param[out] error Location where error type is saved, @see
+/// FnameTransError.
+///
+/// @return transformed name: either `fname_buf` or a pointer to an allocated
+/// memory.
+static char_u *fname_trans_sid(const char_u *const name,
+ char_u *const fname_buf,
+ char_u **const tofree, int *const error)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+{
char_u *fname;
- int i;
-
- llen = eval_fname_script(name);
+ const int llen = eval_fname_script((const char *)name);
if (llen > 0) {
fname_buf[0] = K_SPECIAL;
fname_buf[1] = KS_EXTRA;
fname_buf[2] = (int)KE_SNR;
- i = 3;
- if (eval_fname_sid(name)) { // "<SID>" or "s:"
+ int i = 3;
+ if (eval_fname_sid((const char *)name)) { // "<SID>" or "s:"
if (current_SID <= 0) {
*error = ERROR_SCRIPT;
} else {
@@ -7444,7 +7459,7 @@ fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error) {
}
}
} else {
- fname = name;
+ fname = (char_u *)name;
}
return fname;
@@ -7564,7 +7579,7 @@ call_func(
rettv->vval.v_number = 0;
error = ERROR_UNKNOWN;
- if (!builtin_function(rfname, -1)) {
+ if (!builtin_function((const char *)rfname, -1)) {
// User defined function.
if (partial != NULL && partial->pt_func != NULL) {
fp = partial->pt_func;
@@ -7579,9 +7594,10 @@ call_func(
/* executed an autocommand, search for the function again */
fp = find_func(rfname);
}
- /* Try loading a package. */
- if (fp == NULL && script_autoload(rfname, TRUE) && !aborting()) {
- /* loaded a package, search for the function again */
+ // Try loading a package.
+ if (fp == NULL && script_autoload((const char *)rfname, STRLEN(rfname),
+ true) && !aborting()) {
+ // Loaded a package, search for the function again.
fp = find_func(rfname);
}
@@ -7609,7 +7625,7 @@ call_func(
}
} else {
// Find the function name in the table, call its implementation.
- VimLFuncDef *const fdef = find_internal_func((char *)fname);
+ VimLFuncDef *const fdef = find_internal_func((const char *)fname);
if (fdef != NULL) {
if (argcount < fdef->min_argc) {
error = ERROR_TOOFEW;
@@ -8292,17 +8308,17 @@ static buf_T *get_buf_tv(typval_T *tv, int curtab_only)
*/
static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- buf_T *buf;
-
- (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
- ++emsg_off;
- buf = get_buf_tv(&argvars[0], FALSE);
rettv->v_type = VAR_STRING;
- if (buf != NULL && buf->b_fname != NULL)
- rettv->vval.v_string = vim_strsave(buf->b_fname);
- else
- rettv->vval.v_string = NULL;
- --emsg_off;
+ rettv->vval.v_string = NULL;
+ if (!tv_check_str_or_nr(&argvars[0])) {
+ return;
+ }
+ emsg_off++;
+ const buf_T *const buf = get_buf_tv(&argvars[0], false);
+ emsg_off--;
+ if (buf != NULL && buf->b_fname != NULL) {
+ rettv->vval.v_string = (char_u *)xstrdup((char *)buf->b_fname);
+ }
}
/*
@@ -8310,36 +8326,36 @@ static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_bufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- buf_T *buf;
- int error = FALSE;
- char_u *name;
+ int error = false;
+ char_u *name;
- (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
- ++emsg_off;
- buf = get_buf_tv(&argvars[0], FALSE);
- --emsg_off;
+ rettv->vval.v_number = -1;
+ if (!tv_check_str_or_nr(&argvars[0])) {
+ return;
+ }
+ emsg_off++;
+ const buf_T *buf = get_buf_tv(&argvars[0], false);
+ emsg_off--;
- /* If the buffer isn't found and the second argument is not zero create a
- * new buffer. */
+ // If the buffer isn't found and the second argument is not zero create a
+ // new buffer.
if (buf == NULL
&& argvars[1].v_type != VAR_UNKNOWN
&& get_tv_number_chk(&argvars[1], &error) != 0
&& !error
&& (name = get_tv_string_chk(&argvars[0])) != NULL
- && !error)
+ && !error) {
buf = buflist_new(name, NULL, (linenr_T)1, 0);
+ }
- if (buf != NULL)
+ if (buf != NULL) {
rettv->vval.v_number = buf->b_fnum;
- else
- rettv->vval.v_number = -1;
+ }
}
static void buf_win_common(typval_T *argvars, typval_T *rettv, bool get_nr)
{
- int error = false;
- (void)get_tv_number_chk(&argvars[0], &error); // issue errmsg if type error
- if (error) { // the argument has an invalid type
+ if (!tv_check_str_or_nr(&argvars[0])) {
rettv->vval.v_number = -1;
return;
}
@@ -8383,14 +8399,13 @@ static void f_bufwinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_byte2line(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- long boff = 0;
-
- boff = get_tv_number(&argvars[0]) - 1; /* boff gets -1 on type error */
- if (boff < 0)
+ long boff = get_tv_number(&argvars[0]) - 1;
+ if (boff < 0) {
rettv->vval.v_number = -1;
- else
- rettv->vval.v_number = ml_find_line_or_offset(curbuf,
- (linenr_T)0, &boff);
+ } else {
+ rettv->vval.v_number = (varnumber_T)ml_find_line_or_offset(curbuf, 0,
+ &boff);
+ }
}
static void byteidx(typval_T *argvars, typval_T *rettv, int comp)
@@ -9250,54 +9265,55 @@ static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- char_u *p;
- char_u *name;
- int n = FALSE;
+ int n = false;
int len = 0;
- p = get_tv_string(&argvars[0]);
- if (*p == '$') { /* environment variable */
- /* first try "normal" environment variables (fast) */
- if (os_getenv((char *)(p + 1)) != NULL)
- n = TRUE;
- else {
- /* try expanding things like $VIM and ${HOME} */
- p = expand_env_save(p);
- if (p != NULL && *p != '$')
- n = TRUE;
+ char *p = (char *)get_tv_string(&argvars[0]);
+ if (*p == '$') { // Environment variable.
+ // First try "normal" environment variables (fast).
+ if (os_getenv(p + 1) != NULL) {
+ n = true;
+ } else {
+ // Try expanding things like $VIM and ${HOME}.
+ p = (char *)expand_env_save((char_u *)p);
+ if (p != NULL && *p != '$') {
+ n = true;
+ }
xfree(p);
}
- } else if (*p == '&' || *p == '+') { // option
- n = (get_option_tv(&p, NULL, true) == OK);
- if (*skipwhite(p) != NUL) {
- n = false; // trailing garbage
+ } else if (*p == '&' || *p == '+') { // Option.
+ n = (get_option_tv((const char **)&p, NULL, true) == OK);
+ if (*skipwhite((const char_u *)p) != NUL) {
+ n = false; // Trailing garbage.
}
- } else if (*p == '*') { // internal or user defined function
+ } else if (*p == '*') { // Internal or user defined function.
n = function_exists(p + 1, false);
} else if (*p == ':') {
n = cmd_exists(p + 1);
} else if (*p == '#') {
- if (p[1] == '#')
+ if (p[1] == '#') {
n = autocmd_supported(p + 2);
- else
+ } else {
n = au_exists(p + 1);
- } else { /* internal variable */
- char_u *tofree;
+ }
+ } else { // Internal variable.
typval_T tv;
- /* get_name_len() takes care of expanding curly braces */
- name = p;
- len = get_name_len(&p, &tofree, TRUE, FALSE);
+ // get_name_len() takes care of expanding curly braces
+ const char *name = p;
+ char *tofree;
+ len = get_name_len((const char **)&p, &tofree, true, false);
if (len > 0) {
if (tofree != NULL) {
name = tofree;
}
n = (get_var_tv(name, len, &tv, NULL, false, true) == OK);
if (n) {
- /* handle d.key, l[idx], f(expr) */
- n = (handle_subscript(&p, &tv, TRUE, FALSE) == OK);
- if (n)
+ // Handle d.key, l[idx], f(expr).
+ n = (handle_subscript((const char **)&p, &tv, true, false) == OK);
+ if (n) {
clear_tv(&tv);
+ }
}
}
if (*p != NUL)
@@ -10055,7 +10071,7 @@ static void common_function(typval_T *argvars, typval_T *rettv,
// Don't check an autoload name for existence here.
} else if (trans_name != NULL
&& (is_funcref ? find_func(trans_name) == NULL
- : !translated_function_exists(trans_name))) {
+ : !translated_function_exists((const char *)trans_name))) {
EMSG2(_("E700: Unknown function: %s"), s);
} else {
int dict_idx = 0;
@@ -10451,20 +10467,22 @@ static void f_getbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T lnum;
linenr_T end;
- buf_T *buf;
+ buf_T *buf = NULL;
- (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
- ++emsg_off;
- buf = get_buf_tv(&argvars[0], FALSE);
- --emsg_off;
+ if (tv_check_str_or_nr(&argvars[0])) {
+ emsg_off++;
+ buf = get_buf_tv(&argvars[0], false);
+ emsg_off--;
+ }
lnum = get_tv_lnum_buf(&argvars[1], buf);
- if (argvars[2].v_type == VAR_UNKNOWN)
+ if (argvars[2].v_type == VAR_UNKNOWN) {
end = lnum;
- else
+ } else {
end = get_tv_lnum_buf(&argvars[2], buf);
+ }
- get_buffer_lines(buf, lnum, end, TRUE, rettv);
+ get_buffer_lines(buf, lnum, end, true, rettv);
}
/*
@@ -10472,26 +10490,25 @@ static void f_getbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- buf_T *buf;
- buf_T *save_curbuf;
- char_u *varname;
- dictitem_T *v;
- int done = FALSE;
-
- (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
- varname = get_tv_string_chk(&argvars[1]);
- ++emsg_off;
- buf = get_buf_tv(&argvars[0], FALSE);
+ bool done = false;
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
+ if (!tv_check_str_or_nr(&argvars[0])) {
+ goto f_getbufvar_end;
+ }
+
+ const char *varname = (const char *)get_tv_string_chk(&argvars[1]);
+ emsg_off++;
+ buf_T *const buf = get_buf_tv(&argvars[0], false);
+
if (buf != NULL && varname != NULL) {
- /* set curbuf to be our buf, temporarily */
- save_curbuf = curbuf;
+ // set curbuf to be our buf, temporarily
+ buf_T *const save_curbuf = curbuf;
curbuf = buf;
- if (*varname == '&') { // buffer-local-option
+ if (*varname == '&') { // buffer-local-option
if (varname[1] == NUL) {
// get all buffer-local options in a dict
dict_T *opts = get_winbuf_options(true);
@@ -10511,25 +10528,26 @@ static void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = curbuf->b_changedtick;
done = true;
} else {
- /* Look up the variable. */
- /* Let getbufvar({nr}, "") return the "b:" dictionary. */
- v = find_var_in_ht(&curbuf->b_vars->dv_hashtab,
- 'b', varname, FALSE);
+ // Look up the variable.
+ // Let getbufvar({nr}, "") return the "b:" dictionary.
+ dictitem_T *const v = find_var_in_ht(&curbuf->b_vars->dv_hashtab, 'b',
+ varname, strlen(varname), false);
if (v != NULL) {
copy_tv(&v->di_tv, rettv);
- done = TRUE;
+ done = true;
}
}
- /* restore previous notion of curbuf */
+ // restore previous notion of curbuf
curbuf = save_curbuf;
}
+ emsg_off--;
- if (!done && argvars[2].v_type != VAR_UNKNOWN)
- /* use the default value */
+f_getbufvar_end:
+ if (!done && argvars[2].v_type != VAR_UNKNOWN) {
+ // use the default value
copy_tv(&argvars[2], rettv);
-
- --emsg_off;
+ }
}
/*
@@ -11297,13 +11315,12 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
win_T *oldcurwin;
tabpage_T *tp, *oldtabpage;
dictitem_T *v;
- char_u *varname;
bool done = false;
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
- varname = get_tv_string_chk(&argvars[1]);
+ const char *const varname = (const char *)get_tv_string_chk(&argvars[1]);
tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL));
if (tp != NULL && varname != NULL) {
// Set tp to be our tabpage, temporarily. Also set the window to the
@@ -11312,7 +11329,8 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (switch_win(&oldcurwin, &oldtabpage, window, tp, true) == OK) {
// look up the variable
// Let gettabvar({nr}, "") return the "t:" dictionary.
- v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't', varname, FALSE);
+ v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't',
+ varname, strlen(varname), false);
if (v != NULL) {
copy_tv(&v->di_tv, rettv);
done = true;
@@ -11491,7 +11509,6 @@ getwinvar (
)
{
win_T *win, *oldcurwin;
- char_u *varname;
dictitem_T *v;
tabpage_T *tp = NULL;
tabpage_T *oldtabpage = NULL;
@@ -11502,12 +11519,13 @@ getwinvar (
else
tp = curtab;
win = find_win_by_nr(&argvars[off], tp);
- varname = get_tv_string_chk(&argvars[off + 1]);
- ++emsg_off;
+ const char *varname = (const char *)get_tv_string_chk(
+ &argvars[off + 1]);
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
+ emsg_off++;
if (win != NULL && varname != NULL) {
// Set curwin to be our win, temporarily. Also set the tabpage,
// otherwise the window is not valid. Only do this when needed,
@@ -11533,7 +11551,8 @@ getwinvar (
} else {
// Look up the variable.
// Let getwinvar({nr}, "") return the "w:" dictionary.
- v = find_var_in_ht(&win->w_vars->dv_hashtab, 'w', varname, FALSE);
+ v = find_var_in_ht(&win->w_vars->dv_hashtab, 'w', varname,
+ strlen(varname), false);
if (v != NULL) {
copy_tv(&v->di_tv, rettv);
done = true;
@@ -11546,12 +11565,12 @@ getwinvar (
restore_win(oldcurwin, oldtabpage, true);
}
}
+ emsg_off--;
- if (!done && argvars[off + 2].v_type != VAR_UNKNOWN)
- /* use the default return value */
+ if (!done && argvars[off + 2].v_type != VAR_UNKNOWN) {
+ // use the default return value
copy_tv(&argvars[off + 2], rettv);
-
- --emsg_off;
+ }
}
/*
@@ -11821,6 +11840,10 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr)
#endif
} else if (STRICMP(name, "syntax_items") == 0) {
n = syntax_present(curwin);
+#ifdef UNIX
+ } else if (STRICMP(name, "unnamedplus") == 0) {
+ n = eval_has_provider("clipboard");
+#endif
}
}
@@ -12217,8 +12240,8 @@ static void get_user_input(typval_T *argvars, typval_T *rettv, int inputdialog)
*p = NUL;
msg_start();
msg_clr_eos();
- msg_puts_attr(prompt, echo_attr);
- msg_didout = FALSE;
+ msg_puts_attr((const char *)prompt, echo_attr);
+ msg_didout = false;
msg_starthere();
*p = c;
}
@@ -12310,7 +12333,7 @@ static void f_inputlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
msg_clr_eos();
for (li = argvars[0].vval.v_list->lv_first; li != NULL; li = li->li_next) {
- msg_puts(get_tv_string(&li->li_tv));
+ msg_puts((const char *)get_tv_string(&li->li_tv));
msg_putchar('\n');
}
@@ -12435,10 +12458,11 @@ static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr)
EMSG(_(e_trailing));
else {
if (lv.ll_tv == NULL) {
- if (check_changedtick(lv.ll_name))
- rettv->vval.v_number = 1; /* always locked */
- else {
- di = find_var(lv.ll_name, NULL, TRUE);
+ if (check_changedtick(lv.ll_name)) {
+ rettv->vval.v_number = 1; // Always locked.
+ } else {
+ di = find_var((const char *)lv.ll_name, STRLEN(lv.ll_name), NULL,
+ true);
if (di != NULL) {
/* Consider a variable locked when:
* 1. the variable itself is locked
@@ -13279,9 +13303,9 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
rettv_dict_alloc(rettv);
if (rhs != NULL) {
// Return a dictionary.
- char_u *lhs = str2special_save(mp->m_keys, TRUE);
- char_u *mapmode = map_mode_to_chars(mp->m_mode);
- dict_T *dict = rettv->vval.v_dict;
+ char_u *lhs = str2special_save(mp->m_keys, true);
+ char *const mapmode = map_mode_to_chars(mp->m_mode);
+ dict_T *dict = rettv->vval.v_dict;
dict_add_nr_str(dict, "lhs", 0L, lhs);
dict_add_nr_str(dict, "rhs", 0L, mp->m_orig_str);
@@ -13291,7 +13315,7 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
dict_add_nr_str(dict, "sid", (long)mp->m_script_ID, NULL);
dict_add_nr_str(dict, "buffer", (long)buffer_local, NULL);
dict_add_nr_str(dict, "nowait", mp->m_nowait ? 1L : 0L, NULL);
- dict_add_nr_str(dict, "mode", 0L, mapmode);
+ dict_add_nr_str(dict, "mode", 0L, (char_u *)mapmode);
xfree(lhs);
xfree(mapmode);
@@ -15508,44 +15532,45 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_setbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- buf_T *buf;
- char_u *varname, *bufvarname;
- typval_T *varp;
char_u nbuf[NUMBUFLEN];
- if (check_restricted() || check_secure())
+ if (check_restricted()
+ || check_secure()
+ || !tv_check_str_or_nr(&argvars[0])) {
return;
- (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
- varname = get_tv_string_chk(&argvars[1]);
- buf = get_buf_tv(&argvars[0], FALSE);
- varp = &argvars[2];
+ }
+ const char *varname = (const char *)get_tv_string_chk(&argvars[1]);
+ buf_T *const buf = get_buf_tv(&argvars[0], false);
+ typval_T *varp = &argvars[2];
if (buf != NULL && varname != NULL && varp != NULL) {
if (*varname == '&') {
long numval;
- char_u *strval;
+ char_u *strval;
int error = false;
- aco_save_T aco;
+ aco_save_T aco;
// set curbuf to be our buf, temporarily
aucmd_prepbuf(&aco, buf);
- ++varname;
+ varname++;
numval = get_tv_number_chk(varp, &error);
strval = get_tv_string_buf_chk(varp, nbuf);
- if (!error && strval != NULL)
- set_option_value(varname, numval, strval, OPT_LOCAL);
+ if (!error && strval != NULL) {
+ set_option_value((char_u *)varname, numval, strval, OPT_LOCAL);
+ }
// reset notion of buffer
aucmd_restbuf(&aco);
} else {
buf_T *save_curbuf = curbuf;
- bufvarname = xmalloc(STRLEN(varname) + 3);
+ const size_t varname_len = STRLEN(varname);
+ char_u *const bufvarname = xmalloc(STRLEN(varname) + 3);
curbuf = buf;
- STRCPY(bufvarname, "b:");
- STRCPY(bufvarname + 2, varname);
- set_var(bufvarname, varp, TRUE);
+ memcpy(bufvarname, "b:", 2);
+ memcpy(bufvarname + 2, varname, varname_len + 1);
+ set_var(bufvarname, varp, true);
xfree(bufvarname);
curbuf = save_curbuf;
}
@@ -17232,8 +17257,8 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
p = highlight_has_attr(id, HL_ITALIC, modec);
break;
- case 'n': /* name */
- p = get_highlight_name(NULL, id - 1);
+ case 'n': // name
+ p = (char_u *)get_highlight_name(NULL, id - 1);
break;
case 'r': /* reverse */
@@ -18802,11 +18827,12 @@ static int get_env_len(char_u **arg)
// Get the length of the name of a function or internal variable.
// "arg" is advanced to the first non-white character after the name.
// Return 0 if something is wrong.
-static int get_id_len(char_u **arg) {
- char_u *p;
+static int get_id_len(const char **const arg)
+{
int len;
// Find the end of the name.
+ const char *p;
for (p = *arg; eval_isnamec(*p); p++) {
if (*p == ':') {
// "s:" is start of "s:var", but "n:" is not and can be used in
@@ -18823,7 +18849,7 @@ static int get_id_len(char_u **arg) {
}
len = (int)(p - *arg);
- *arg = skipwhite(p);
+ *arg = (const char *)skipwhite((const char_u *)p);
return len;
}
@@ -18837,18 +18863,20 @@ static int get_id_len(char_u **arg) {
* If the name contains 'magic' {}'s, expand them and return the
* expanded name in an allocated string via 'alias' - caller must free.
*/
-static int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose)
+static int get_name_len(const char **const arg,
+ char **alias,
+ int evaluate,
+ int verbose)
{
int len;
- char_u *p;
char_u *expr_start;
char_u *expr_end;
*alias = NULL; /* default to no alias */
- if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA
- && (*arg)[2] == (int)KE_SNR) {
- /* hard coded <SNR>, already translated */
+ if ((*arg)[0] == (char)K_SPECIAL && (*arg)[1] == (char)KS_EXTRA
+ && (*arg)[2] == (char)KE_SNR) {
+ // Hard coded <SNR>, already translated.
*arg += 3;
return get_id_len(arg) + 3;
}
@@ -18861,14 +18889,14 @@ static int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose)
/*
* Find the end of the name; check for {} construction.
*/
- p = find_name_end(*arg, &expr_start, &expr_end,
- len > 0 ? 0 : FNE_CHECK_START);
+ const char *p = (const char *)find_name_end((char_u *)(*arg),
+ &expr_start,
+ &expr_end,
+ len > 0 ? 0 : FNE_CHECK_START);
if (expr_start != NULL) {
- char_u *temp_string;
-
if (!evaluate) {
len += (int)(p - *arg);
- *arg = skipwhite(p);
+ *arg = (const char *)skipwhite((const char_u *)p);
return len;
}
@@ -18876,11 +18904,13 @@ static int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose)
* Include any <SID> etc in the expanded string:
* Thus the -len here.
*/
- temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p);
- if (temp_string == NULL)
+ char_u *temp_string = make_expanded_name((char_u *)(*arg) - len, expr_start,
+ expr_end, (char_u *)p);
+ if (temp_string == NULL) {
return -1;
- *alias = temp_string;
- *arg = skipwhite(p);
+ }
+ *alias = (char *)temp_string;
+ *arg = (const char *)skipwhite((const char_u *)p);
return (int)STRLEN(temp_string);
}
@@ -19294,9 +19324,8 @@ char_u *set_cmdarg(exarg_T *eap, char_u *oldarg)
* Get the value of internal variable "name".
* Return OK or FAIL.
*/
-static int
-get_var_tv (
- char_u *name,
+static int get_var_tv(
+ const char *name,
int len, // length of "name"
typval_T *rettv, // NULL when only checking existence
dictitem_T **dip, // non-NULL when typval's dict item is needed
@@ -19308,25 +19337,16 @@ get_var_tv (
typval_T *tv = NULL;
typval_T atv;
dictitem_T *v;
- int cc;
- /* truncate the name, so that we can use strcmp() */
- cc = name[len];
- name[len] = NUL;
-
- /*
- * Check for "b:changedtick".
- */
- if (STRCMP(name, "b:changedtick") == 0) {
+ // Check for "b:changedtick".
+ if (sizeof("b:changedtick") - 1 == len
+ && STRNCMP(name, "b:changedtick", len) == 0) {
atv.v_type = VAR_NUMBER;
atv.vval.v_number = curbuf->b_changedtick;
tv = &atv;
- }
- /*
- * Check for user-defined variables.
- */
- else {
- v = find_var(name, NULL, no_autoload);
+ } else {
+ // Check for user-defined variables.
+ v = find_var(name, (size_t)len, NULL, no_autoload);
if (v != NULL) {
tv = &v->di_tv;
if (dip != NULL) {
@@ -19336,41 +19356,33 @@ get_var_tv (
}
if (tv == NULL) {
- if (rettv != NULL && verbose)
- EMSG2(_(e_undefvar), name);
+ if (rettv != NULL && verbose) {
+ emsgf(_("E121: Undefined variable: %.*s"), len, name);
+ }
ret = FAIL;
- } else if (rettv != NULL)
+ } else if (rettv != NULL) {
copy_tv(tv, rettv);
-
- name[len] = cc;
+ }
return ret;
}
/// Check if variable "name[len]" is a local variable or an argument.
/// If so, "*eval_lavars_used" is set to TRUE.
-static void check_vars(char_u *name, int len)
+static void check_vars(const char *name, size_t len)
{
- int cc;
- char_u *varname;
- hashtab_T *ht;
-
if (eval_lavars_used == NULL) {
return;
}
- // truncate the name, so that we can use strcmp()
- cc = name[len];
- name[len] = NUL;
+ const char *varname;
+ hashtab_T *ht = find_var_ht(name, len, &varname);
- ht = find_var_ht(name, &varname);
if (ht == get_funccal_local_ht() || ht == get_funccal_args_ht()) {
- if (find_var(name, NULL, true) != NULL) {
+ if (find_var(name, len, NULL, true) != NULL) {
*eval_lavars_used = true;
}
}
-
- name[len] = cc;
}
/// Handle expr[expr], expr[expr:expr] subscript and .name lookup.
@@ -19378,7 +19390,7 @@ static void check_vars(char_u *name, int len)
/// Can all be combined: dict.func(expr)[idx]['func'](expr)
static int
handle_subscript(
- char_u **arg,
+ const char **const arg,
typval_T *rettv,
int evaluate, /* do more than finding the end */
int verbose /* give error messages */
@@ -19413,7 +19425,7 @@ handle_subscript(
} else {
s = (char_u *)"";
}
- ret = get_func_tv(s, (int)STRLEN(s), rettv, arg,
+ ret = get_func_tv(s, (int)STRLEN(s), rettv, (char_u **)arg,
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
&len, evaluate, pt, selfdict);
@@ -19440,7 +19452,7 @@ handle_subscript(
++selfdict->dv_refcount;
} else
selfdict = NULL;
- if (eval_index(arg, rettv, evaluate, verbose) == FAIL) {
+ if (eval_index((char_u **)arg, rettv, evaluate, verbose) == FAIL) {
clear_tv(rettv);
ret = FAIL;
}
@@ -19813,6 +19825,53 @@ static void init_tv(typval_T *varp)
memset(varp, 0, sizeof(typval_T));
}
+/// Check that given value is a number or string
+///
+/// Error messages are compatible with get_tv_number() previously used for the
+/// same purpose in buf*() functions. Special values are not accepted (previous
+/// behaviour: silently fail to find buffer).
+///
+/// @param[in] tv Value to check.
+///
+/// @return true if everything is OK, false otherwise.
+bool tv_check_str_or_nr(const typval_T *const tv)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE
+{
+ switch (tv->v_type) {
+ case VAR_NUMBER:
+ case VAR_STRING: {
+ return true;
+ }
+ case VAR_FLOAT: {
+ EMSG(_("E805: Expected a Number or a String, Float found"));
+ return false;
+ }
+ case VAR_PARTIAL:
+ case VAR_FUNC: {
+ EMSG(_("E703: Expected a Number or a String, Funcref found"));
+ return false;
+ }
+ case VAR_LIST: {
+ EMSG(_("E745: Expected a Number or a String, List found"));
+ return false;
+ }
+ case VAR_DICT: {
+ EMSG(_("E728: Expected a Number or a String, Dictionary found"));
+ return false;
+ }
+ case VAR_SPECIAL: {
+ EMSG(_("E5300: Expected a Number or a String"));
+ return false;
+ }
+ case VAR_UNKNOWN: {
+ EMSG2(_(e_intern2), "tv_check_str_or_nr(UNKNOWN)");
+ return false;
+ }
+ }
+ assert(false);
+ return false;
+}
+
/*
* Get the number value of a variable.
* If it is a String variable, uses vim_str2nr().
@@ -20017,67 +20076,82 @@ char_u *get_tv_string_buf_chk(const typval_T *varp, char_u *buf)
* When "htp" is not NULL we are writing to the variable, set "htp" to the
* hashtab_T used.
*/
-static dictitem_T *find_var(char_u *name, hashtab_T **htp, int no_autoload)
+static dictitem_T *find_var(const char *const name, const size_t name_len,
+ hashtab_T **htp, int no_autoload)
{
- char_u *varname;
- hashtab_T *ht;
- dictitem_T *ret = NULL;
-
- ht = find_var_ht(name, &varname);
+ const char *varname;
+ hashtab_T *ht = find_var_ht(name, name_len, &varname);
if (htp != NULL) {
*htp = ht;
}
if (ht == NULL) {
return NULL;
}
- ret = find_var_in_ht(ht, *name, varname, no_autoload || htp != NULL);
+ dictitem_T *ret = find_var_in_ht(ht, *name,
+ varname, name_len - (size_t)(varname - name),
+ no_autoload || htp != NULL);
if (ret != NULL) {
return ret;
}
// Search in parent scope for lambda
- return find_var_in_scoped_ht(name, no_autoload || htp != NULL);
+ return find_var_in_scoped_ht(name, name_len, no_autoload || htp != NULL);
}
-/// Find variable "varname" in hashtab "ht" with name "htname".
-/// Returns NULL if not found.
-dictitem_T *find_var_in_ht(hashtab_T *ht, int htname,
- char_u *varname, bool no_autoload)
+/// Find variable in hashtab
+///
+/// @param[in] ht Hashtab to find variable in.
+/// @param[in] htname Hashtab name (first character).
+/// @param[in] varname Variable name.
+/// @param[in] varname_len Variable name length.
+/// @param[in] no_autoload If true then autoload scripts will not be sourced
+/// if autoload variable was not found.
+///
+/// @return pointer to the dictionary item with the found variable or NULL if it
+/// was not found.
+static dictitem_T *find_var_in_ht(hashtab_T *const ht,
+ int htname,
+ const char *const varname,
+ const size_t varname_len,
+ int no_autoload)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
hashitem_T *hi;
- if (*varname == NUL) {
- /* Must be something like "s:", otherwise "ht" would be NULL. */
+ if (varname_len == 0) {
+ // Must be something like "s:", otherwise "ht" would be NULL.
switch (htname) {
- case 's': return &SCRIPT_SV(current_SID)->sv_var;
- case 'g': return &globvars_var;
- case 'v': return &vimvars_var;
- case 'b': return &curbuf->b_bufvar;
- case 'w': return &curwin->w_winvar;
- case 't': return &curtab->tp_winvar;
- case 'l': return current_funccal == NULL
- ? NULL : &current_funccal->l_vars_var;
- case 'a': return current_funccal == NULL
- ? NULL : &current_funccal->l_avars_var;
+ case 's': return (dictitem_T *)&SCRIPT_SV(current_SID)->sv_var;
+ case 'g': return (dictitem_T *)&globvars_var;
+ case 'v': return (dictitem_T *)&vimvars_var;
+ case 'b': return (dictitem_T *)&curbuf->b_bufvar;
+ case 'w': return (dictitem_T *)&curwin->w_winvar;
+ case 't': return (dictitem_T *)&curtab->tp_winvar;
+ case 'l': return (current_funccal == NULL
+ ? NULL : (dictitem_T *)&current_funccal->l_vars_var);
+ case 'a': return (current_funccal == NULL
+ ? NULL : (dictitem_T *)&current_funccal->l_avars_var);
}
return NULL;
}
- hi = hash_find(ht, varname);
+ hi = hash_find_len(ht, varname, varname_len);
if (HASHITEM_EMPTY(hi)) {
- /* For global variables we may try auto-loading the script. If it
- * worked find the variable again. Don't auto-load a script if it was
- * loaded already, otherwise it would be loaded every time when
- * checking if a function name is a Funcref variable. */
+ // For global variables we may try auto-loading the script. If it
+ // worked find the variable again. Don't auto-load a script if it was
+ // loaded already, otherwise it would be loaded every time when
+ // checking if a function name is a Funcref variable.
if (ht == &globvarht && !no_autoload) {
- /* Note: script_autoload() may make "hi" invalid. It must either
- * be obtained again or not used. */
- if (!script_autoload(varname, FALSE) || aborting())
+ // Note: script_autoload() may make "hi" invalid. It must either
+ // be obtained again or not used.
+ if (!script_autoload(varname, varname_len, false) || aborting()) {
return NULL;
- hi = hash_find(ht, varname);
+ }
+ hi = hash_find_len(ht, varname, varname_len);
}
- if (HASHITEM_EMPTY(hi))
+ if (HASHITEM_EMPTY(hi)) {
return NULL;
+ }
}
return HI2DI(hi);
}
@@ -20103,7 +20177,7 @@ static funccall_T *get_funccal(void)
/// Return the hashtable used for argument in the current funccal.
/// Return NULL if there is no current funccal.
-hashtab_T *get_funccal_args_ht(void)
+static hashtab_T *get_funccal_args_ht(void)
{
if (current_funccal == NULL) {
return NULL;
@@ -20113,7 +20187,7 @@ hashtab_T *get_funccal_args_ht(void)
/// Return the hashtable used for local variables in the current funccal.
/// Return NULL if there is no current funccal.
-hashtab_T *get_funccal_local_ht(void)
+static hashtab_T *get_funccal_local_ht(void)
{
if (current_funccal == NULL) {
return NULL;
@@ -20121,17 +20195,25 @@ hashtab_T *get_funccal_local_ht(void)
return &get_funccal()->l_vars.dv_hashtab;
}
-// Find the dict and hashtable used for a variable name. Set "varname" to the
-// start of name without ':'.
-static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d)
+/// Find the dict and hashtable used for a variable
+///
+/// @param[in] name Variable name, possibly with scope prefix.
+/// @param[in] name_len Variable name length.
+/// @param[out] varname Will be set to the start of the name without scope
+/// prefix.
+/// @param[out] d Scope dictionary.
+///
+/// @return Scope hashtab, NULL if name is not valid.
+static hashtab_T *find_var_ht_dict(const char *name, const size_t name_len,
+ const char **varname, dict_T **d)
{
- hashitem_T *hi;
+ hashitem_T *hi;
*d = NULL;
- if (name[0] == NUL) {
+ if (name_len == 0) {
return NULL;
}
- if (name[1] != ':') {
+ if (name_len == 1 || (name_len >= 2 && name[1] != ':')) {
// name has implicit scope
if (name[0] == ':' || name[0] == AUTOLOAD_CHAR) {
// The name must not start with a colon or #.
@@ -20140,7 +20222,7 @@ static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d)
*varname = name;
// "version" is "v:version" in all scopes
- hi = hash_find(&compat_hashtab, name);
+ hi = hash_find_len(&compat_hashtab, name, name_len);
if (!HASHITEM_EMPTY(hi)) {
return &compat_hashtab;
}
@@ -20156,26 +20238,27 @@ static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d)
*varname = name + 2;
if (*name == 'g') { // global variable
*d = &globvardict;
- } else if (vim_strchr(name + 2, ':') != NULL
- || vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL) {
+ } else if (name_len > 2
+ && (memchr(name + 2, ':', name_len - 2) != NULL
+ || memchr(name + 2, AUTOLOAD_CHAR, name_len - 2) != NULL)) {
// There must be no ':' or '#' in the rest of the name if g: was not used
return NULL;
}
- if (*name == 'b') { // buffer variable
+ if (*name == 'b') { // buffer variable
*d = curbuf->b_vars;
- } else if (*name == 'w') { // window variable
+ } else if (*name == 'w') { // window variable
*d = curwin->w_vars;
- } else if (*name == 't') { // tab page variable
+ } else if (*name == 't') { // tab page variable
*d = curtab->tp_vars;
- } else if (*name == 'v') { // v: variable
+ } else if (*name == 'v') { // v: variable
*d = &vimvardict;
} else if (*name == 'a' && current_funccal != NULL) { // function argument
*d = &get_funccal()->l_avars;
} else if (*name == 'l' && current_funccal != NULL) { // local variable
*d = &get_funccal()->l_vars;
- } else if (*name == 's' // script variable
- && current_SID > 0 && current_SID <= ga_scripts.ga_len) {
+ } else if (*name == 's' // script variable
+ && current_SID > 0 && current_SID <= ga_scripts.ga_len) {
*d = &SCRIPT_SV(current_SID)->sv_dict;
}
@@ -20183,13 +20266,19 @@ end:
return *d ? &(*d)->dv_hashtab : NULL;
}
-// Find the hashtab used for a variable name.
-// Return NULL if the name is not valid.
-// Set "varname" to the start of name without ':'.
-static hashtab_T *find_var_ht(uint8_t *name, uint8_t **varname)
+/// Find the hashtable used for a variable
+///
+/// @param[in] name Variable name, possibly with scope prefix.
+/// @param[in] name_len Variable name length.
+/// @param[out] varname Will be set to the start of the name without scope
+/// prefix.
+///
+/// @return Scope hashtab, NULL if name is not valid.
+static hashtab_T *find_var_ht(const char *name, const size_t name_len,
+ const char **varname)
{
dict_T *d;
- return find_var_ht_dict(name, varname, &d);
+ return find_var_ht_dict(name, name_len, varname, &d);
}
/*
@@ -20197,13 +20286,14 @@ static hashtab_T *find_var_ht(uint8_t *name, uint8_t **varname)
* Note: see get_tv_string() for how long the pointer remains valid.
* Returns NULL when it doesn't exist.
*/
-char_u *get_var_value(char_u *name)
+char_u *get_var_value(const char *const name)
{
dictitem_T *v;
- v = find_var(name, NULL, FALSE);
- if (v == NULL)
+ v = find_var(name, strlen(name), NULL, false);
+ if (v == NULL) {
return NULL;
+ }
return get_tv_string(&v->di_tv);
}
@@ -20324,28 +20414,27 @@ static void delete_var(hashtab_T *ht, hashitem_T *hi)
/*
* List the value of one internal variable.
*/
-static void list_one_var(dictitem_T *v, char_u *prefix, int *first)
+static void list_one_var(dictitem_T *v, const char *prefix, int *first)
{
- char_u *s = (char_u *) encode_tv2echo(&v->di_tv, NULL);
- list_one_var_a(prefix, v->di_key, v->di_tv.v_type,
- s == NULL ? (char_u *)"" : s, first);
+ char *const s = encode_tv2echo(&v->di_tv, NULL);
+ list_one_var_a(prefix, (const char *)v->di_key, STRLEN(v->di_key),
+ v->di_tv.v_type, (s == NULL ? "" : s), first);
xfree(s);
}
-static void
-list_one_var_a (
- char_u *prefix,
- char_u *name,
- int type,
- char_u *string,
- int *first /* when TRUE clear rest of screen and set to FALSE */
-)
+/// @param[in] name_len Length of the name. May be -1, in this case strlen()
+/// will be used.
+/// @param[in,out] first When true clear rest of screen and set to false.
+static void list_one_var_a(const char *prefix, const char *name,
+ const ptrdiff_t name_len, const int type,
+ const char *string, int *first)
{
- /* don't use msg() or msg_attr() to avoid overwriting "v:statusmsg" */
+ // don't use msg() or msg_attr() to avoid overwriting "v:statusmsg"
msg_start();
msg_puts(prefix);
- if (name != NULL) /* "a:" vars don't have a name stored */
- msg_puts(name);
+ if (name != NULL) { // "a:" vars don't have a name stored
+ msg_puts_attr_len(name, name_len, 0);
+ }
msg_putchar(' ');
msg_advance(22);
if (type == VAR_NUMBER) {
@@ -20363,10 +20452,10 @@ list_one_var_a (
} else
msg_putchar(' ');
- msg_outtrans(string);
+ msg_outtrans((char_u *)string);
if (type == VAR_FUNC || type == VAR_PARTIAL) {
- msg_puts((char_u *)"()");
+ msg_puts("()");
}
if (*first) {
msg_clr_eos();
@@ -20387,12 +20476,14 @@ set_var (
)
{
dictitem_T *v;
- char_u *varname;
hashtab_T *ht;
typval_T oldtv;
dict_T *dict;
- ht = find_var_ht_dict(name, &varname, &dict);
+ const size_t name_len = STRLEN(name);
+ char_u *varname;
+ ht = find_var_ht_dict((const char *)name, name_len, (const char **)&varname,
+ &dict);
bool watched = is_watched(dict);
if (watched) {
@@ -20403,11 +20494,13 @@ set_var (
EMSG2(_(e_illvar), name);
return;
}
- v = find_var_in_ht(ht, 0, varname, true);
+ v = find_var_in_ht(ht, 0,
+ (const char *)varname, name_len - (size_t)(varname - name),
+ true);
// Search in parent scope which is possible to reference from lambda
if (v == NULL) {
- v = find_var_in_scoped_ht(name, true);
+ v = find_var_in_scoped_ht((const char *)name, name_len, true);
}
if ((tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL)
@@ -20538,12 +20631,12 @@ var_check_func_name (
// Don't allow hiding a function. When "v" is not NULL we might be
// assigning another function to the same var, the type is checked
// below.
- if (new_var && function_exists(name, false)) {
+ if (new_var && function_exists((const char *)name, false)) {
EMSG2(_("E705: Variable name conflicts with existing function: %s"),
- name);
- return TRUE;
+ name);
+ return true;
}
- return FALSE;
+ return false;
}
/*
@@ -20738,7 +20831,6 @@ void ex_echo(exarg_T *eap)
{
char_u *arg = eap->arg;
typval_T rettv;
- char_u *p;
bool needclr = true;
bool atstart = true;
@@ -20749,19 +20841,20 @@ void ex_echo(exarg_T *eap)
* still need to be cleared. E.g., "echo 22,44". */
need_clr_eos = needclr;
- p = arg;
- if (eval1(&arg, &rettv, !eap->skip) == FAIL) {
- /*
- * Report the invalid expression unless the expression evaluation
- * has been cancelled due to an aborting error, an interrupt, or an
- * exception.
- */
- if (!aborting())
- EMSG2(_(e_invexpr2), p);
- need_clr_eos = FALSE;
- break;
+ {
+ char_u *p = arg;
+ if (eval1(&arg, &rettv, !eap->skip) == FAIL) {
+ // Report the invalid expression unless the expression evaluation
+ // has been cancelled due to an aborting error, an interrupt, or an
+ // exception.
+ if (!aborting()) {
+ EMSG2(_(e_invexpr2), p);
+ }
+ need_clr_eos = false;
+ break;
+ }
+ need_clr_eos = false;
}
- need_clr_eos = FALSE;
if (!eap->skip) {
if (atstart) {
@@ -20775,9 +20868,11 @@ void ex_echo(exarg_T *eap)
msg_sb_eol();
msg_start();
}
- } else if (eap->cmdidx == CMD_echo)
- msg_puts_attr((char_u *)" ", echo_attr);
- char_u *tofree = p = (char_u *) encode_tv2echo(&rettv, NULL);
+ } else if (eap->cmdidx == CMD_echo) {
+ msg_puts_attr(" ", echo_attr);
+ }
+ char *tofree = encode_tv2echo(&rettv, NULL);
+ const char *p = tofree;
if (p != NULL) {
for (; *p != NUL && !got_int; ++p) {
if (*p == '\n' || *p == '\r' || *p == TAB) {
@@ -20786,15 +20881,16 @@ void ex_echo(exarg_T *eap)
msg_clr_eos();
needclr = false;
}
- msg_putchar_attr(*p, echo_attr);
+ msg_putchar_attr((uint8_t)(*p), echo_attr);
} else {
if (has_mbyte) {
- int i = (*mb_ptr2len)(p);
+ int i = (*mb_ptr2len)((const char_u *)p);
- (void)msg_outtrans_len_attr(p, i, echo_attr);
+ (void)msg_outtrans_len_attr((char_u *)p, i, echo_attr);
p += i - 1;
- } else
- (void)msg_outtrans_len_attr(p, 1, echo_attr);
+ } else {
+ (void)msg_outtrans_len_attr((char_u *)p, 1, echo_attr);
+ }
}
}
}
@@ -20908,9 +21004,9 @@ void ex_execute(exarg_T *eap)
* Returns NULL when no option name found. Otherwise pointer to the char
* after the option name.
*/
-static char_u *find_option_end(char_u **arg, int *opt_flags)
+static const char *find_option_end(const char **const arg, int *const opt_flags)
{
- char_u *p = *arg;
+ const char *p = *arg;
++p;
if (*p == 'g' && p[1] == ':') {
@@ -21086,7 +21182,7 @@ void ex_function(exarg_T *eap)
}
if (!got_int) {
msg_putchar('\n');
- msg_puts((char_u *)" endfunction");
+ msg_puts(" endfunction");
}
} else
emsg_funcname(N_("E123: Undefined function: %s"), name);
@@ -21263,7 +21359,7 @@ void ex_function(exarg_T *eap)
if (*p == '!') {
p = skipwhite(p + 1);
}
- p += eval_fname_script(p);
+ p += eval_fname_script((const char *)p);
xfree(trans_function_name(&p, true, 0, NULL, NULL));
if (*skipwhite(p) == '(') {
nesting++;
@@ -21338,7 +21434,7 @@ void ex_function(exarg_T *eap)
* If there are no errors, add the function
*/
if (fudi.fd_dict == NULL) {
- v = find_var(name, &ht, FALSE);
+ v = find_var((const char *)name, STRLEN(name), &ht, false);
if (v != NULL && v->di_tv.v_type == VAR_FUNC) {
emsg_funcname(N_("E707: Function name conflicts with variable: %s"),
name);
@@ -21404,7 +21500,7 @@ void ex_function(exarg_T *eap)
/* Check that the autoload name matches the script name. */
int j = FAIL;
if (sourcing_name != NULL) {
- scriptname = autoload_name(name);
+ scriptname = (char_u *)autoload_name((const char *)name, STRLEN(name));
p = vim_strchr(scriptname, '/');
plen = (int)STRLEN(p);
slen = (int)STRLEN(sourcing_name);
@@ -21521,15 +21617,16 @@ trans_function_name(
if ((*pp)[0] == K_SPECIAL && (*pp)[1] == KS_EXTRA
&& (*pp)[2] == (int)KE_SNR) {
*pp += 3;
- len = get_id_len(pp) + 3;
- return vim_strnsave(start, len);
+ len = get_id_len((const char **)pp) + 3;
+ return (char_u *)xmemdupz(start, len);
}
/* A name starting with "<SID>" or "<SNR>" is local to a script. But
* don't skip over "s:", get_lval() needs it for "s:dict.func". */
- lead = eval_fname_script(start);
- if (lead > 2)
+ lead = eval_fname_script((const char *)start);
+ if (lead > 2) {
start += lead;
+ }
/* Note that TFN_ flags use the same values as GLV_ flags. */
end = get_lval(start, NULL, &lv, FALSE, skip, flags,
@@ -21592,14 +21689,15 @@ trans_function_name(
/* Check if the name is a Funcref. If so, use the value. */
if (lv.ll_exp_name != NULL) {
len = (int)STRLEN(lv.ll_exp_name);
- name = deref_func_name(lv.ll_exp_name, &len, partial,
+ name = deref_func_name((const char *)lv.ll_exp_name, &len, partial,
flags & TFN_NO_AUTOLOAD);
if (name == lv.ll_exp_name) {
name = NULL;
}
} else if (!(flags & TFN_NO_DEREF)) {
len = (int)(end - *pp);
- name = deref_func_name(*pp, &len, partial, flags & TFN_NO_AUTOLOAD);
+ name = deref_func_name((const char *)(*pp), &len, partial,
+ flags & TFN_NO_AUTOLOAD);
if (name == *pp) {
name = NULL;
}
@@ -21644,9 +21742,9 @@ trans_function_name(
lead = 0; /* do nothing */
else if (lead > 0) {
lead = 3;
- if ((lv.ll_exp_name != NULL && eval_fname_sid(lv.ll_exp_name))
- || eval_fname_sid(*pp)) {
- /* It's "s:" or "<SID>" */
+ if ((lv.ll_exp_name != NULL && eval_fname_sid((const char *)lv.ll_exp_name))
+ || eval_fname_sid((const char *)(*pp))) {
+ // It's "s:" or "<SID>".
if (current_SID <= 0) {
EMSG(_(e_usingsid));
goto theend;
@@ -21654,7 +21752,8 @@ trans_function_name(
sprintf((char *)sid_buf, "%" PRId64 "_", (int64_t)current_SID);
lead += (int)STRLEN(sid_buf);
}
- } else if (!(flags & TFN_INT) && builtin_function(lv.ll_name, len)) {
+ } else if (!(flags & TFN_INT)
+ && builtin_function((const char *)lv.ll_name, len)) {
EMSG2(_("E128: Function name must start with a capital or \"s:\": %s"),
start);
goto theend;
@@ -21691,12 +21790,13 @@ theend:
* Return 2 if "p" starts with "s:".
* Return 0 otherwise.
*/
-static int eval_fname_script(char_u *p)
+static int eval_fname_script(const char *const p)
{
// Use mb_stricmp() because in Turkish comparing the "I" may not work with
// the standard library function.
- if (p[0] == '<' && (mb_strnicmp(p + 1, (char_u *)"SID>", 4) == 0
- || mb_strnicmp(p + 1, (char_u *)"SNR>", 4) == 0)) {
+ if (p[0] == '<'
+ && (mb_strnicmp((char_u *)p + 1, (char_u *)"SID>", 4) == 0
+ || mb_strnicmp((char_u *)p + 1, (char_u *)"SNR>", 4) == 0)) {
return 5;
}
if (p[0] == 's' && p[1] == ':') {
@@ -21705,13 +21805,19 @@ static int eval_fname_script(char_u *p)
return 0;
}
-/*
- * Return TRUE if "p" starts with "<SID>" or "s:".
- * Only works if eval_fname_script() returned non-zero for "p"!
- */
-static int eval_fname_sid(char_u *p)
+/// Check whether function name starts with <SID> or s:
+///
+/// Only works for names previously checked by eval_fname_script(), if it
+/// returned non-zero.
+///
+/// @param[in] name Name to check.
+///
+/// @return true if it starts with <SID> or s:, false otherwise.
+static inline bool eval_fname_sid(const char *const name)
+ FUNC_ATTR_PURE FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT
+ FUNC_ATTR_NONNULL_ALL
{
- return *p == 's' || TOUPPER_ASC(p[2]) == 'I';
+ return *name == 's' || TOUPPER_ASC(name[2]) == 'I';
}
/*
@@ -21725,33 +21831,36 @@ static void list_func_head(ufunc_T *fp, int indent)
MSG_PUTS("function ");
if (fp->uf_name[0] == K_SPECIAL) {
MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8));
- msg_puts(fp->uf_name + 3);
- } else
- msg_puts(fp->uf_name);
+ msg_puts((const char *)fp->uf_name + 3);
+ } else {
+ msg_puts((const char *)fp->uf_name);
+ }
msg_putchar('(');
int j;
- for (j = 0; j < fp->uf_args.ga_len; ++j) {
- if (j)
- MSG_PUTS(", ");
- msg_puts(FUNCARG(fp, j));
+ for (j = 0; j < fp->uf_args.ga_len; j++) {
+ if (j) {
+ msg_puts(", ");
+ }
+ msg_puts((const char *)FUNCARG(fp, j));
}
if (fp->uf_varargs) {
- if (j)
- MSG_PUTS(", ");
- MSG_PUTS("...");
+ if (j) {
+ msg_puts(", ");
+ }
+ msg_puts("...");
}
msg_putchar(')');
if (fp->uf_flags & FC_ABORT) {
- MSG_PUTS(" abort");
+ msg_puts(" abort");
}
if (fp->uf_flags & FC_RANGE) {
- MSG_PUTS(" range");
+ msg_puts(" range");
}
if (fp->uf_flags & FC_DICT) {
- MSG_PUTS(" dict");
+ msg_puts(" dict");
}
if (fp->uf_flags & FC_CLOSURE) {
- MSG_PUTS(" closure");
+ msg_puts(" closure");
}
msg_clr_eos();
if (p_verbose > 0)
@@ -21760,7 +21869,7 @@ static void list_func_head(ufunc_T *fp, int indent)
/// Find a function by name, return pointer to it in ufuncs.
/// @return NULL for unknown function.
-ufunc_T *find_func(char_u *name)
+static ufunc_T *find_func(const char_u *name)
{
hashitem_T *hi;
@@ -21832,58 +21941,59 @@ void free_all_functions(void)
#endif
-int translated_function_exists(char_u *name)
+bool translated_function_exists(const char *name)
{
if (builtin_function(name, -1)) {
return find_internal_func((char *)name) != NULL;
}
- return find_func(name) != NULL;
+ return find_func((const char_u *)name) != NULL;
}
-/// Check if a function exists by name
+/// Check whether function with the given name exists
///
-/// @param[in] name The name of the function to check.
-/// @param[in] no_deref If true, do not dereference a Funcref.
+/// @param[in] name Function name.
+/// @param[in] no_deref Whether to dereference a Funcref.
///
-/// @return true if a function "name" exists.
-static int function_exists(char_u *name, bool no_deref)
+/// @return True if it exists, false otherwise.
+static bool function_exists(const char *const name, bool no_deref)
{
- char_u *nm = name;
- char_u *p;
- int n = false;
+ char_u *nm = (char_u *)name;
+ bool n = false;
int flag = TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD;
if (no_deref) {
flag |= TFN_NO_DEREF;
}
- p = trans_function_name(&nm, false, flag, NULL, NULL);
+ char *const p = (char *)trans_function_name(&nm, false, flag, NULL, NULL);
nm = skipwhite(nm);
/* Only accept "funcname", "funcname ", "funcname (..." and
* "funcname(...", not "funcname!...". */
- if (p != NULL && (*nm == NUL || *nm == '('))
+ if (p != NULL && (*nm == NUL || *nm == '(')) {
n = translated_function_exists(p);
+ }
xfree(p);
return n;
}
/// Checks if a builtin function with the given name exists.
///
-/// @param[in] name The name of the builtin function to check.
-/// @param[in] len The length of "name", or -1 for NUL terminated.
+/// @param[in] name name of the builtin function to check.
+/// @param[in] len length of "name", or -1 for NUL terminated.
///
/// @return true if "name" looks like a builtin function name: starts with a
/// lower case letter and doesn't contain AUTOLOAD_CHAR.
-static bool builtin_function(char_u *name, int len)
+static bool builtin_function(const char *name, int len)
{
if (!ASCII_ISLOWER(name[0])) {
- return FALSE;
+ return false;
}
- char_u *p = vim_strchr(name, AUTOLOAD_CHAR);
+ const char *p = (len == -1
+ ? strchr(name, AUTOLOAD_CHAR)
+ : memchr(name, AUTOLOAD_CHAR, (size_t)len));
- return p == NULL
- || (len > 0 && p > name + len);
+ return p == NULL;
}
/*
@@ -22049,44 +22159,45 @@ static int prof_self_cmp(const void *s1, const void *s2)
}
-/*
- * If "name" has a package name try autoloading the script for it.
- * Return TRUE if a package was loaded.
- */
-static int
-script_autoload (
- char_u *name,
- int reload /* load script again when already loaded */
-)
+/// If name has a package name try autoloading the script for it
+///
+/// @param[in] name Variable/function name.
+/// @param[in] name_len Name length.
+/// @param[in] reload If true, load script again when already loaded.
+///
+/// @return true if a package was loaded.
+static bool script_autoload(const char *const name, const size_t name_len,
+ const bool reload)
{
- char_u *p;
- char_u *scriptname, *tofree;
- int ret = FALSE;
- int i;
-
- /* If there is no '#' after name[0] there is no package name. */
- p = vim_strchr(name, AUTOLOAD_CHAR);
- if (p == NULL || p == name)
- return FALSE;
+ // If there is no '#' after name[0] there is no package name.
+ const char *p = memchr(name, AUTOLOAD_CHAR, name_len);
+ if (p == NULL || p == name) {
+ return false;
+ }
- tofree = scriptname = autoload_name(name);
+ bool ret = false;
+ char *tofree = autoload_name(name, name_len);
+ char *scriptname = tofree;
- /* Find the name in the list of previously loaded package names. Skip
- * "autoload/", it's always the same. */
- for (i = 0; i < ga_loaded.ga_len; ++i)
- if (STRCMP(((char_u **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0)
+ // Find the name in the list of previously loaded package names. Skip
+ // "autoload/", it's always the same.
+ int i = 0;
+ for (; i < ga_loaded.ga_len; i++) {
+ if (STRCMP(((char **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0) {
break;
- if (!reload && i < ga_loaded.ga_len)
- ret = FALSE; /* was loaded already */
- else {
- /* Remember the name if it wasn't loaded already. */
+ }
+ }
+ if (!reload && i < ga_loaded.ga_len) {
+ ret = false; // Was loaded already.
+ } else {
+ // Remember the name if it wasn't loaded already.
if (i == ga_loaded.ga_len) {
- GA_APPEND(char_u *, &ga_loaded, scriptname);
+ GA_APPEND(char *, &ga_loaded, scriptname);
tofree = NULL;
}
// Try loading the package from $VIMRUNTIME/autoload/<name>.vim
- if (source_runtime(scriptname, 0) == OK) {
+ if (source_runtime((char_u *)scriptname, 0) == OK) {
ret = true;
}
}
@@ -22095,21 +22206,29 @@ script_autoload (
return ret;
}
-/*
- * Return the autoload script name for a function or variable name.
- */
-static char_u *autoload_name(char_u *name)
+/// Return the autoload script name for a function or variable name
+///
+/// @param[in] name Variable/function name.
+/// @param[in] name_len Name length.
+///
+/// @return [allocated] autoload script name.
+static char *autoload_name(const char *const name, const size_t name_len)
+ FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT
{
- /* Get the script file name: replace '#' with '/', append ".vim". */
- char_u *scriptname = xmalloc(STRLEN(name) + 14);
- STRCPY(scriptname, "autoload/");
- STRCAT(scriptname, name);
- *vim_strrchr(scriptname, AUTOLOAD_CHAR) = NUL;
- STRCAT(scriptname, ".vim");
-
- char_u *p;
- while ((p = vim_strchr(scriptname, AUTOLOAD_CHAR)) != NULL)
- *p = '/';
+ // Get the script file name: replace '#' with '/', append ".vim".
+ char *const scriptname = xmalloc(name_len + sizeof("autoload/.vim"));
+ memcpy(scriptname, "autoload/", sizeof("autoload/") - 1);
+ memcpy(scriptname + sizeof("autoload/") - 1, name, name_len);
+ size_t auchar_idx = 0;
+ for (size_t i = sizeof("autoload/") - 1;
+ i - sizeof("autoload/") + 1 < name_len;
+ i++) {
+ if (scriptname[i] == AUTOLOAD_CHAR) {
+ scriptname[i] = '/';
+ auchar_idx = i;
+ }
+ }
+ memcpy(scriptname + auchar_idx, ".vim", sizeof(".vim"));
return scriptname;
}
@@ -22582,24 +22701,24 @@ call_user_func(
smsg(_("calling %s"), sourcing_name);
if (p_verbose >= 14) {
- char_u buf[MSG_BUF_LEN];
-
- msg_puts((char_u *)"(");
- for (int i = 0; i < argcount; ++i) {
+ msg_puts("(");
+ for (int i = 0; i < argcount; i++) {
if (i > 0) {
- msg_puts((char_u *)", ");
+ msg_puts(", ");
}
if (argvars[i].v_type == VAR_NUMBER) {
msg_outnum((long)argvars[i].vval.v_number);
} else {
// Do not want errors such as E724 here.
emsg_off++;
- char_u *s = (char_u *) encode_tv2string(&argvars[i], NULL);
- char_u *tofree = s;
+ char *tofree = encode_tv2string(&argvars[i], NULL);
+ char *s = tofree;
emsg_off--;
if (s != NULL) {
- if (vim_strsize(s) > MSG_BUF_CLEN) {
- trunc_string(s, buf, MSG_BUF_CLEN, MSG_BUF_LEN);
+ if (vim_strsize((char_u *)s) > MSG_BUF_CLEN) {
+ char buf[MSG_BUF_LEN];
+ trunc_string((char_u *)s, (char_u *)buf, MSG_BUF_CLEN,
+ sizeof(buf));
s = buf;
}
msg_puts(s);
@@ -22607,9 +22726,9 @@ call_user_func(
}
}
}
- msg_puts((char_u *)")");
+ msg_puts(")");
}
- msg_puts((char_u *)"\n"); /* don't overwrite this either */
+ msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
--no_wait_return;
@@ -22700,7 +22819,7 @@ call_user_func(
xfree(tofree);
}
}
- msg_puts((char_u *)"\n"); /* don't overwrite this either */
+ msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
--no_wait_return;
@@ -22718,7 +22837,7 @@ call_user_func(
verbose_enter_scroll();
smsg(_("continuing in %s"), sourcing_name);
- msg_puts((char_u *)"\n"); /* don't overwrite this either */
+ msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
--no_wait_return;
@@ -23172,23 +23291,23 @@ static var_flavour_T var_flavour(char_u *varname)
}
/// Search hashitem in parent scope.
-hashitem_T *find_hi_in_scoped_ht(char_u *name, hashtab_T **pht)
+hashitem_T *find_hi_in_scoped_ht(const char *name, hashtab_T **pht)
{
- funccall_T *old_current_funccal = current_funccal;
- hashtab_T *ht;
- hashitem_T *hi = NULL;
- char_u *varname;
-
if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL) {
return NULL;
}
+ funccall_T *old_current_funccal = current_funccal;
+ hashitem_T *hi = NULL;
+ const size_t namelen = strlen(name);
+ const char *varname;
+
// Search in parent scope which is possible to reference from lambda
current_funccal = current_funccal->func->uf_scoped;
while (current_funccal != NULL) {
- ht = find_var_ht(name, &varname);
+ hashtab_T *ht = find_var_ht(name, namelen, &varname);
if (ht != NULL && *varname != NUL) {
- hi = hash_find(ht, varname);
+ hi = hash_find_len(ht, varname, namelen - (varname - name));
if (!HASHITEM_EMPTY(hi)) {
*pht = ht;
break;
@@ -23205,23 +23324,24 @@ hashitem_T *find_hi_in_scoped_ht(char_u *name, hashtab_T **pht)
}
/// Search variable in parent scope.
-dictitem_T *find_var_in_scoped_ht(char_u *name, int no_autoload)
+dictitem_T *find_var_in_scoped_ht(const char *name, const size_t namelen,
+ int no_autoload)
{
- dictitem_T *v = NULL;
- funccall_T *old_current_funccal = current_funccal;
- hashtab_T *ht;
- char_u *varname;
-
if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL) {
return NULL;
}
+ dictitem_T *v = NULL;
+ funccall_T *old_current_funccal = current_funccal;
+ const char *varname;
+
// Search in parent scope which is possible to reference from lambda
current_funccal = current_funccal->func->uf_scoped;
while (current_funccal) {
- ht = find_var_ht(name, &varname);
+ hashtab_T *ht = find_var_ht(name, namelen, &varname);
if (ht != NULL && *varname != NUL) {
- v = find_var_in_ht(ht, *name, varname, no_autoload);
+ v = find_var_in_ht(ht, *name, varname,
+ namelen - (size_t)(varname - name), no_autoload);
if (v != NULL) {
break;
}
@@ -23230,7 +23350,7 @@ dictitem_T *find_var_in_scoped_ht(char_u *name, int no_autoload)
break;
}
current_funccal = current_funccal->func->uf_scoped;
- }
+ }
current_funccal = old_current_funccal;
return v;
@@ -24137,10 +24257,12 @@ bool eval_has_provider(char *name)
{
#define check_provider(name) \
if (has_##name == -1) { \
- has_##name = !!find_func((uint8_t *)"provider#" #name "#Call"); \
+ has_##name = !!find_func((char_u *)"provider#" #name "#Call"); \
if (!has_##name) { \
- script_autoload((uint8_t *)"provider#" #name "#Call", false); \
- has_##name = !!find_func((uint8_t *)"provider#" #name "#Call"); \
+ script_autoload("provider#" #name "#Call", \
+ sizeof("provider#" #name "#Call") - 1, \
+ false); \
+ has_##name = !!find_func((char_u *)"provider#" #name "#Call"); \
} \
}
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 4b3798794c..a03878dec2 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -1474,12 +1474,12 @@ void append_redir(char *const buf, const size_t buflen,
void print_line_no_prefix(linenr_T lnum, int use_number, int list)
{
- char_u numbuf[30];
+ char numbuf[30];
if (curwin->w_p_nu || use_number) {
- vim_snprintf((char *)numbuf, sizeof(numbuf),
- "%*ld ", number_width(curwin), (long)lnum);
- msg_puts_attr(numbuf, hl_attr(HLF_N)); /* Highlight line nrs */
+ vim_snprintf(numbuf, sizeof(numbuf), "%*" PRIdLINENR " ",
+ number_width(curwin), lnum);
+ msg_puts_attr(numbuf, hl_attr(HLF_N)); // Highlight line nrs.
}
msg_prt_line(ml_get(lnum), list);
}
@@ -5720,33 +5720,33 @@ void ex_sign(exarg_T *eap)
*/
static void sign_list_defined(sign_T *sp)
{
- char_u *p;
-
smsg("sign %s", sp->sn_name);
if (sp->sn_icon != NULL) {
- MSG_PUTS(" icon=");
+ msg_puts(" icon=");
msg_outtrans(sp->sn_icon);
- MSG_PUTS(_(" (not supported)"));
+ msg_puts(_(" (not supported)"));
}
if (sp->sn_text != NULL) {
- MSG_PUTS(" text=");
+ msg_puts(" text=");
msg_outtrans(sp->sn_text);
}
if (sp->sn_line_hl > 0) {
- MSG_PUTS(" linehl=");
- p = get_highlight_name(NULL, sp->sn_line_hl - 1);
- if (p == NULL)
- MSG_PUTS("NONE");
- else
+ msg_puts(" linehl=");
+ const char *const p = get_highlight_name(NULL, sp->sn_line_hl - 1);
+ if (p == NULL) {
+ msg_puts("NONE");
+ } else {
msg_puts(p);
+ }
}
if (sp->sn_text_hl > 0) {
- MSG_PUTS(" texthl=");
- p = get_highlight_name(NULL, sp->sn_text_hl - 1);
- if (p == NULL)
- MSG_PUTS("NONE");
- else
+ msg_puts(" texthl=");
+ const char *const p = get_highlight_name(NULL, sp->sn_text_hl - 1);
+ if (p == NULL) {
+ msg_puts("NONE");
+ } else {
msg_puts(p);
+ }
}
}
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index b4e57bc916..048323b137 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -2250,7 +2250,7 @@ void ex_compiler(exarg_T *eap)
// plugin will then skip the settings. Afterwards set
// "b:current_compiler" and restore "current_compiler".
// Explicitly prepend "g:" to make it work in a function.
- old_cur_comp = get_var_value((char_u *)"g:current_compiler");
+ old_cur_comp = get_var_value("g:current_compiler");
if (old_cur_comp != NULL) {
old_cur_comp = vim_strsave(old_cur_comp);
}
@@ -2268,7 +2268,7 @@ void ex_compiler(exarg_T *eap)
do_cmdline_cmd(":delcommand CompilerSet");
// Set "b:current_compiler" from "current_compiler".
- p = get_var_value((char_u *)"g:current_compiler");
+ p = get_var_value("g:current_compiler");
if (p != NULL) {
set_internal_string_var((char_u *)"b:current_compiler", p);
}
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index c5625d7882..03f943b1b1 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -583,10 +583,10 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline,
++no_wait_return;
verbose_enter_scroll();
- smsg(_("line %" PRId64 ": %s"),
- (int64_t)sourcing_lnum, cmdline_copy);
- if (msg_silent == 0)
- msg_puts((char_u *)"\n"); /* don't overwrite this */
+ smsg(_("line %" PRIdLINENR ": %s"), sourcing_lnum, cmdline_copy);
+ if (msg_silent == 0) {
+ msg_puts("\n"); // don't overwrite this either
+ }
verbose_leave_scroll();
--no_wait_return;
@@ -1815,9 +1815,9 @@ static char_u * do_one_cmd(char_u **cmdlinep,
errormsg = (char_u *)_("E493: Backwards range given");
goto doend;
}
- if (ask_yesno((char_u *)
- _("Backwards range given, OK to swap"), FALSE) != 'y')
+ if (ask_yesno(_("Backwards range given, OK to swap"), false) != 'y') {
goto doend;
+ }
}
lnum = ea.line1;
ea.line1 = ea.line2;
@@ -2582,27 +2582,29 @@ int modifier_len(char_u *cmd)
* Return 2 if there is an exact match.
* Return 3 if there is an ambiguous match.
*/
-int cmd_exists(char_u *name)
+int cmd_exists(const char *const name)
{
exarg_T ea;
- int full = FALSE;
- int i;
- int j;
char_u *p;
- /* Check command modifiers. */
- for (i = 0; i < (int)ARRAY_SIZE(cmdmods); ++i) {
- for (j = 0; name[j] != NUL; ++j)
- if (name[j] != cmdmods[i].name[j])
+ // Check command modifiers.
+ for (int i = 0; i < (int)ARRAY_SIZE(cmdmods); i++) {
+ int j;
+ for (j = 0; name[j] != NUL; j++) {
+ if (name[j] != (char)cmdmods[i].name[j]) {
break;
- if (name[j] == NUL && j >= cmdmods[i].minlen)
+ }
+ }
+ if (name[j] == NUL && j >= cmdmods[i].minlen) {
return cmdmods[i].name[j] == NUL ? 2 : 1;
+ }
}
/* Check built-in commands and user defined commands.
* For ":2match" and ":3match" we need to skip the number. */
- ea.cmd = (*name == '2' || *name == '3') ? name + 1 : name;
+ ea.cmd = (char_u *)((*name == '2' || *name == '3') ? name + 1 : name);
ea.cmdidx = (cmdidx_T)0;
+ int full = false;
p = find_command(&ea, &full);
if (p == NULL)
return 3;
@@ -3940,8 +3942,6 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp)
* Don't do this for:
* - replacement that already has been escaped: "##"
* - shell commands (may have to use quotes instead).
- * - non-unix systems when there is a single argument (spaces don't
- * separate arguments then).
*/
if (!eap->usefilter
&& !escaped
@@ -3952,9 +3952,7 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp)
&& eap->cmdidx != CMD_lgrep
&& eap->cmdidx != CMD_grepadd
&& eap->cmdidx != CMD_lgrepadd
-#ifndef UNIX
&& !(eap->argt & NOSPC)
-#endif
) {
char_u *l;
#ifdef BACKSLASH_IN_FILENAME
@@ -4016,28 +4014,6 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp)
}
}
- // Replace any other wildcards, remove backslashes.
-#ifdef UNIX
- /*
- * Only for Unix we check for more than one file name.
- * For other systems spaces are considered to be part
- * of the file name.
- * Only check here if there is no wildcard, otherwise
- * ExpandOne() will check for errors. This allows
- * ":e `ls ve*.c`" on Unix.
- */
- if (!has_wildcards)
- for (p = eap->arg; *p; ++p) {
- /* skip escaped characters */
- if (p[1] && (*p == '\\' || *p == Ctrl_V))
- ++p;
- else if (ascii_iswhite(*p)) {
- *errormsgp = (char_u *)_("E172: Only one file name allowed");
- return FAIL;
- }
- }
-#endif
-
/*
* Halve the number of backslashes (this is Vi compatible).
* For Unix, when wildcards are expanded, this is
@@ -8246,9 +8222,9 @@ eval_vars (
char_u *resultbuf = NULL;
size_t resultlen;
buf_T *buf;
- int valid = VALID_HEAD + VALID_PATH; /* assume valid result */
- int skip_mod = FALSE;
- char_u strbuf[30];
+ int valid = VALID_HEAD | VALID_PATH; // Assume valid result.
+ int skip_mod = false;
+ char strbuf[30];
*errormsg = NULL;
if (escaped != NULL)
@@ -8380,8 +8356,8 @@ eval_vars (
"E496: no autocommand buffer number to substitute for \"<abuf>\"");
return NULL;
}
- sprintf((char *)strbuf, "%d", autocmd_bufnr);
- result = strbuf;
+ snprintf(strbuf, sizeof(strbuf), "%d", autocmd_bufnr);
+ result = (char_u *)strbuf;
break;
case SPEC_AMATCH: /* match name for autocommand */
@@ -8406,8 +8382,8 @@ eval_vars (
*errormsg = (char_u *)_("E842: no line number to use for \"<slnum>\"");
return NULL;
}
- sprintf((char *)strbuf, "%" PRId64, (int64_t)sourcing_lnum);
- result = strbuf;
+ snprintf(strbuf, sizeof(strbuf), "%" PRIdLINENR, sourcing_lnum);
+ result = (char_u *)strbuf;
break;
default:
// should not happen
diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c
index f518fa0d66..4bb6f97035 100644
--- a/src/nvim/ex_eval.c
+++ b/src/nvim/ex_eval.c
@@ -482,7 +482,7 @@ static int throw_exception(void *value, int type, char_u *cmdname)
msg_scroll = TRUE; /* always scroll up, don't overwrite */
smsg(_("Exception thrown: %s"), excp->value);
- msg_puts((char_u *)"\n"); /* don't overwrite this either */
+ msg_puts("\n"); // don't overwrite this either
if (debug_break_level > 0 || *p_vfile == NUL)
cmdline_row = msg_row;
@@ -532,15 +532,17 @@ static void discard_exception(except_T *excp, int was_finished)
smsg(was_finished ? _("Exception finished: %s")
: _("Exception discarded: %s"),
excp->value);
- msg_puts((char_u *)"\n"); /* don't overwrite this either */
- if (debug_break_level > 0 || *p_vfile == NUL)
+ msg_puts("\n"); // don't overwrite this either
+ if (debug_break_level > 0 || *p_vfile == NUL) {
cmdline_row = msg_row;
- --no_wait_return;
- if (debug_break_level > 0)
+ }
+ no_wait_return--;
+ if (debug_break_level > 0) {
msg_silent = save_msg_silent;
- else
+ } else {
verbose_leave();
- STRCPY(IObuff, saved_IObuff);
+ }
+ xstrlcpy((char *)IObuff, (const char *)saved_IObuff, IOSIZE);
xfree(saved_IObuff);
}
if (excp->type != ET_INTERRUPT)
@@ -595,7 +597,7 @@ static void catch_exception(except_T *excp)
msg_scroll = TRUE; /* always scroll up, don't overwrite */
smsg(_("Exception caught: %s"), excp->value);
- msg_puts((char_u *)"\n"); /* don't overwrite this either */
+ msg_puts("\n"); // don't overwrite this either
if (debug_break_level > 0 || *p_vfile == NUL)
cmdline_row = msg_row;
@@ -714,7 +716,7 @@ static void report_pending(int action, int pending, void *value)
++no_wait_return;
msg_scroll = TRUE; /* always scroll up, don't overwrite */
smsg(mesg, s);
- msg_puts((char_u *)"\n"); /* don't overwrite this either */
+ msg_puts("\n"); // don't overwrite this either
cmdline_row = msg_row;
--no_wait_return;
if (debug_break_level > 0)
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 2555b64dfd..d99c8d02f7 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -1879,7 +1879,7 @@ getexmodeline (
vcol = indent;
while (indent >= 8) {
ga_append(&line_ga, TAB);
- msg_puts((char_u *)" ");
+ msg_puts(" ");
indent -= 8;
}
while (indent-- > 0) {
@@ -2608,7 +2608,7 @@ static void redrawcmdprompt(void)
if (ccline.cmdfirstc != NUL)
msg_putchar(ccline.cmdfirstc);
if (ccline.cmdprompt != NULL) {
- msg_puts_attr(ccline.cmdprompt, ccline.cmdattr);
+ msg_puts_attr((const char *)ccline.cmdprompt, ccline.cmdattr);
ccline.cmdindent = msg_col + (msg_row - cmdline_row) * Columns;
/* do the reverse of set_cmdspos() */
if (ccline.cmdfirstc != NUL)
@@ -3317,7 +3317,7 @@ static int showmatches(expand_T *xp, int wildmenu)
msg_outtrans_attr(files_found[k], hl_attr(HLF_D));
p = files_found[k] + STRLEN(files_found[k]) + 1;
msg_advance(maxlen + 1);
- msg_puts(p);
+ msg_puts((const char *)p);
msg_advance(maxlen + 3);
msg_puts_long_attr(p + 2, hl_attr(HLF_D));
break;
@@ -3759,6 +3759,8 @@ static void cleanup_help_tags(int num_file, char_u **file)
}
}
+typedef char_u *(*ExpandFunc)(expand_T *, int);
+
/*
* Do the expansion based on xp->xp_context and "pat".
*/
@@ -3898,39 +3900,38 @@ ExpandFromContext (
else {
static struct expgen {
int context;
- char_u *((*func)(expand_T *, int));
+ ExpandFunc func;
int ic;
int escaped;
- } tab[] =
- {
- {EXPAND_COMMANDS, get_command_name, FALSE, TRUE},
- {EXPAND_BEHAVE, get_behave_arg, TRUE, TRUE},
- {EXPAND_HISTORY, get_history_arg, TRUE, TRUE},
- {EXPAND_USER_COMMANDS, get_user_commands, FALSE, TRUE},
- {EXPAND_USER_ADDR_TYPE, get_user_cmd_addr_type, FALSE, TRUE},
- {EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, FALSE, TRUE},
- {EXPAND_USER_NARGS, get_user_cmd_nargs, FALSE, TRUE},
- {EXPAND_USER_COMPLETE, get_user_cmd_complete, FALSE, TRUE},
- {EXPAND_USER_VARS, get_user_var_name, FALSE, TRUE},
- {EXPAND_FUNCTIONS, get_function_name, FALSE, TRUE},
- {EXPAND_USER_FUNC, get_user_func_name, FALSE, TRUE},
- {EXPAND_EXPRESSION, get_expr_name, FALSE, TRUE},
- {EXPAND_MENUS, get_menu_name, FALSE, TRUE},
- {EXPAND_MENUNAMES, get_menu_names, FALSE, TRUE},
- {EXPAND_SYNTAX, get_syntax_name, TRUE, TRUE},
- {EXPAND_SYNTIME, get_syntime_arg, TRUE, TRUE},
- {EXPAND_HIGHLIGHT, get_highlight_name, TRUE, TRUE},
- {EXPAND_EVENTS, get_event_name, TRUE, TRUE},
- {EXPAND_AUGROUP, get_augroup_name, TRUE, TRUE},
- {EXPAND_CSCOPE, get_cscope_name, TRUE, TRUE},
- {EXPAND_SIGN, get_sign_name, TRUE, TRUE},
- {EXPAND_PROFILE, get_profile_name, TRUE, TRUE},
+ } tab[] = {
+ { EXPAND_COMMANDS, get_command_name, false, true },
+ { EXPAND_BEHAVE, get_behave_arg, true, true },
+ { EXPAND_HISTORY, get_history_arg, true, true },
+ { EXPAND_USER_COMMANDS, get_user_commands, false, true },
+ { EXPAND_USER_ADDR_TYPE, get_user_cmd_addr_type, false, true },
+ { EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, false, true },
+ { EXPAND_USER_NARGS, get_user_cmd_nargs, false, true },
+ { EXPAND_USER_COMPLETE, get_user_cmd_complete, false, true },
+ { EXPAND_USER_VARS, get_user_var_name, false, true },
+ { EXPAND_FUNCTIONS, get_function_name, false, true },
+ { EXPAND_USER_FUNC, get_user_func_name, false, true },
+ { EXPAND_EXPRESSION, get_expr_name, false, true },
+ { EXPAND_MENUS, get_menu_name, false, true },
+ { EXPAND_MENUNAMES, get_menu_names, false, true },
+ { EXPAND_SYNTAX, get_syntax_name, true, true },
+ { EXPAND_SYNTIME, get_syntime_arg, true, true },
+ { EXPAND_HIGHLIGHT, (ExpandFunc)get_highlight_name, true, true },
+ { EXPAND_EVENTS, get_event_name, true, true },
+ { EXPAND_AUGROUP, get_augroup_name, true, true },
+ { EXPAND_CSCOPE, get_cscope_name, true, true },
+ { EXPAND_SIGN, get_sign_name, true, true },
+ { EXPAND_PROFILE, get_profile_name, true, true },
#ifdef HAVE_WORKING_LIBINTL
- {EXPAND_LANGUAGE, get_lang_arg, TRUE, FALSE},
- {EXPAND_LOCALES, get_locales, TRUE, FALSE},
+ { EXPAND_LANGUAGE, get_lang_arg, true, false },
+ { EXPAND_LOCALES, get_locales, true, false },
#endif
- {EXPAND_ENV_VARS, get_env_name, TRUE, TRUE},
- {EXPAND_USER, get_users, TRUE, FALSE},
+ { EXPAND_ENV_VARS, get_env_name, true, true },
+ { EXPAND_USER, get_users, true, false },
};
int i;
diff --git a/src/nvim/farsi.c b/src/nvim/farsi.c
index eb22ad1428..678e6d2e14 100644
--- a/src/nvim/farsi.c
+++ b/src/nvim/farsi.c
@@ -1593,7 +1593,7 @@ void conv_to_pvim(void)
// Assume the screen has been messed up: clear it and redraw.
redraw_later(CLEAR);
- MSG_ATTR(farsi_text_1, hl_attr(HLF_S));
+ MSG_ATTR((const char *)farsi_text_1, hl_attr(HLF_S));
}
/// Convert the Farsi VIM into Farsi 3342 standard.
@@ -1614,7 +1614,7 @@ void conv_to_pstd(void)
// Assume the screen has been messed up: clear it and redraw.
redraw_later(CLEAR);
- MSG_ATTR(farsi_text_2, hl_attr(HLF_S));
+ msg_attr((const char *)farsi_text_2, hl_attr(HLF_S));
}
/// left-right swap the characters in buf[len].
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index d733ba311a..79a39c6503 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -636,9 +636,8 @@ char_u *vim_findfile(void *search_ctx_arg)
if (p_verbose >= 5) {
verbose_enter_scroll();
smsg("Already Searched: %s (%s)",
- stackp->ffs_fix_path, stackp->ffs_wc_path);
- /* don't overwrite this either */
- msg_puts((char_u *)"\n");
+ stackp->ffs_fix_path, stackp->ffs_wc_path);
+ msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
}
#endif
@@ -650,8 +649,7 @@ char_u *vim_findfile(void *search_ctx_arg)
verbose_enter_scroll();
smsg("Searching: %s (%s)",
stackp->ffs_fix_path, stackp->ffs_wc_path);
- /* don't overwrite this either */
- msg_puts((char_u *)"\n");
+ msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
}
#endif
@@ -809,10 +807,8 @@ char_u *vim_findfile(void *search_ctx_arg)
) == FAIL) {
if (p_verbose >= 5) {
verbose_enter_scroll();
- smsg("Already: %s",
- file_path);
- /* don't overwrite this either */
- msg_puts((char_u *)"\n");
+ smsg("Already: %s", file_path);
+ msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
}
continue;
@@ -837,8 +833,7 @@ char_u *vim_findfile(void *search_ctx_arg)
if (p_verbose >= 5) {
verbose_enter_scroll();
smsg("HIT: %s", file_path);
- /* don't overwrite this either */
- msg_puts((char_u *)"\n");
+ msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
}
#endif
@@ -999,10 +994,8 @@ static ff_visited_list_hdr_T *ff_get_visited_list(char_u *filename, ff_visited_l
#ifdef FF_VERBOSE
if (p_verbose >= 5) {
verbose_enter_scroll();
- smsg("ff_get_visited_list: FOUND list for %s",
- filename);
- /* don't overwrite this either */
- msg_puts((char_u *)"\n");
+ smsg("ff_get_visited_list: FOUND list for %s", filename);
+ msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
}
#endif
@@ -1016,8 +1009,7 @@ static ff_visited_list_hdr_T *ff_get_visited_list(char_u *filename, ff_visited_l
if (p_verbose >= 5) {
verbose_enter_scroll();
smsg("ff_get_visited_list: new list for %s", filename);
- /* don't overwrite this either */
- msg_puts((char_u *)"\n");
+ msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
}
#endif
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index cdb912ca94..4ea5121a91 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -3895,15 +3895,15 @@ static int check_mtime(buf_T *buf, FileInfo *file_info)
if (buf->b_mtime_read != 0
&& time_differs(file_info->stat.st_mtim.tv_sec,
buf->b_mtime_read)) {
- msg_scroll = TRUE; /* don't overwrite messages here */
- msg_silent = 0; /* must give this prompt */
- /* don't use emsg() here, don't want to flush the buffers */
- MSG_ATTR(_("WARNING: The file has been changed since reading it!!!"),
- hl_attr(HLF_E));
- if (ask_yesno((char_u *)_("Do you really want to write to it"),
- TRUE) == 'n')
+ msg_scroll = true; // Don't overwrite messages here.
+ msg_silent = 0; // Must give this prompt.
+ // Don't use emsg() here, don't want to flush the buffers.
+ msg_attr(_("WARNING: The file has been changed since reading it!!!"),
+ hl_attr(HLF_E));
+ if (ask_yesno(_("Do you really want to write to it"), true) == 'n') {
return FAIL;
- msg_scroll = FALSE; /* always overwrite the file message now */
+ }
+ msg_scroll = false; // Always overwrite the file message now.
}
return OK;
}
@@ -4778,8 +4778,8 @@ check_timestamps (
--no_wait_return;
need_check_timestamps = FALSE;
if (need_wait_return && didit == 2) {
- /* make sure msg isn't overwritten */
- msg_puts((char_u *)"\n");
+ // make sure msg isn't overwritten
+ msg_puts("\n");
ui_flush();
}
}
@@ -5006,10 +5006,9 @@ buf_check_timestamp (
} else {
if (!autocmd_busy) {
msg_start();
- msg_puts_attr((char_u *) tbuf, hl_attr(HLF_E) + MSG_HIST);
+ msg_puts_attr(tbuf, hl_attr(HLF_E) + MSG_HIST);
if (*mesg2 != NUL) {
- msg_puts_attr((char_u *)mesg2,
- hl_attr(HLF_W) + MSG_HIST);
+ msg_puts_attr(mesg2, hl_attr(HLF_W) + MSG_HIST);
}
msg_clr_eos();
(void)msg_end();
@@ -5385,13 +5384,9 @@ char_u *vim_tempname(void)
static AutoPatCmd *active_apc_list = NULL; /* stack of active autocommands */
-/*
- * augroups stores a list of autocmd group names.
- */
-static garray_T augroups = {0, 0, sizeof(char_u *), 10, NULL};
-#define AUGROUP_NAME(i) (((char_u **)augroups.ga_data)[i])
-// use get_deleted_augroup() to get this
-static char_u *deleted_augroup = NULL;
+/// List of autocmd group names
+static garray_T augroups = { 0, 0, sizeof(char_u *), 10, NULL };
+#define AUGROUP_NAME(i) (((char **)augroups.ga_data)[i])
/*
* The ID of the current group. Group 0 is the default one.
@@ -5406,10 +5401,14 @@ static event_T last_event;
static int last_group;
static int autocmd_blocked = 0; /* block all autocmds */
-static char_u *get_deleted_augroup(void)
+// use get_deleted_augroup() to get this
+static const char *deleted_augroup = NULL;
+
+static inline const char *get_deleted_augroup(void)
+ FUNC_ATTR_ALWAYS_INLINE
{
if (deleted_augroup == NULL) {
- deleted_augroup = (char_u *)_("--Deleted--");
+ deleted_augroup = _("--Deleted--");
}
return deleted_augroup;
}
@@ -5438,7 +5437,7 @@ static void show_autocmd(AutoPat *ap, event_T event)
} else {
msg_puts_attr(AUGROUP_NAME(ap->group), hl_attr(HLF_T));
}
- msg_puts((char_u *)" ");
+ msg_puts(" ");
}
msg_puts_attr(event_nr2name(event), hl_attr(HLF_T));
last_event = event;
@@ -5567,7 +5566,7 @@ void aubuflocal_remove(buf_T *buf)
if (p_verbose >= 6) {
verbose_enter();
smsg(_("auto-removing autocommand: %s <buffer=%d>"),
- event_nr2name(event), buf->b_fnum);
+ event_nr2name(event), buf->b_fnum);
verbose_leave();
}
}
@@ -5590,9 +5589,10 @@ static int au_new_group(char_u *name)
ga_grow(&augroups, 1);
}
- AUGROUP_NAME(i) = vim_strsave(name);
- if (i == augroups.ga_len)
- ++augroups.ga_len;
+ AUGROUP_NAME(i) = xstrdup((char *)name);
+ if (i == augroups.ga_len) {
+ augroups.ga_len++;
+ }
}
return i;
@@ -5626,7 +5626,7 @@ static void au_del_group(char_u *name)
}
xfree(AUGROUP_NAME(i));
if (in_use) {
- AUGROUP_NAME(i) = get_deleted_augroup();
+ AUGROUP_NAME(i) = (char *)get_deleted_augroup();
} else {
AUGROUP_NAME(i) = NULL;
}
@@ -5680,7 +5680,7 @@ void do_augroup(char_u *arg, int del_group)
for (int i = 0; i < augroups.ga_len; ++i) {
if (AUGROUP_NAME(i) != NULL) {
msg_puts(AUGROUP_NAME(i));
- msg_puts((char_u *)" ");
+ msg_puts(" ");
}
}
msg_clr_eos();
@@ -5691,23 +5691,19 @@ void do_augroup(char_u *arg, int del_group)
#if defined(EXITFREE)
void free_all_autocmds(void)
{
- int i;
- char_u *s;
-
for (current_augroup = -1; current_augroup < augroups.ga_len;
current_augroup++) {
do_autocmd((char_u *)"", true);
}
- for (i = 0; i < augroups.ga_len; i++) {
- s = ((char_u **)(augroups.ga_data))[i];
- if (s != get_deleted_augroup()) {
- xfree(s);
- }
+ for (int i = 0; i < augroups.ga_len; i++) {
+ char *const s = ((char **)(augroups.ga_data))[i];
+ if ((const char *)s != get_deleted_augroup()) {
+ xfree(s);
+ }
}
ga_clear(&augroups);
}
-
#endif
/*
@@ -5715,13 +5711,13 @@ void free_all_autocmds(void)
* Return NUM_EVENTS if the event name was not found.
* Return a pointer to the next event name in "end".
*/
-static event_T event_name2nr(char_u *start, char_u **end)
+static event_T event_name2nr(const char_u *start, char_u **end)
{
- char_u *p;
+ const char_u *p;
int i;
int len;
- // the event name ends with end of line, '|', a blank or a comma */
+ // the event name ends with end of line, '|', a blank or a comma
for (p = start; *p && !ascii_iswhite(*p) && *p != ',' && *p != '|'; p++) {
}
for (i = 0; event_names[i].name != NULL; i++) {
@@ -5730,25 +5726,32 @@ static event_T event_name2nr(char_u *start, char_u **end)
break;
}
}
- if (*p == ',')
- ++p;
- *end = p;
- if (event_names[i].name == NULL)
+ if (*p == ',') {
+ p++;
+ }
+ *end = (char_u *)p;
+ if (event_names[i].name == NULL) {
return NUM_EVENTS;
+ }
return event_names[i].event;
}
-/*
- * Return the name for event "event".
- */
-static char_u *event_nr2name(event_T event)
+/// Return the name for event
+///
+/// @param[in] event Event to return name for.
+///
+/// @return Event name, static string. Returns "Unknown" for unknown events.
+static const char *event_nr2name(event_T event)
+ FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_CONST
{
int i;
- for (i = 0; event_names[i].name != NULL; ++i)
- if (event_names[i].event == event)
- return (char_u *)event_names[i].name;
- return (char_u *)"Unknown";
+ for (i = 0; event_names[i].name != NULL; i++) {
+ if (event_names[i].event == event) {
+ return event_names[i].name;
+ }
+ }
+ return "Unknown";
}
/*
@@ -7013,7 +7016,6 @@ auto_next_pat (
{
AutoPat *ap;
AutoCmd *cp;
- char_u *name;
char *s;
xfree(sourcing_name);
@@ -7032,11 +7034,13 @@ auto_next_pat (
? match_file_pat(NULL, &ap->reg_prog, apc->fname, apc->sfname,
apc->tail, ap->allow_dirs)
: ap->buflocal_nr == apc->arg_bufnr) {
- name = event_nr2name(apc->event);
+ const char *const name = event_nr2name(apc->event);
s = _("%s Auto commands for \"%s\"");
- sourcing_name = xmalloc(STRLEN(s) + STRLEN(name) + ap->patlen + 1);
- sprintf((char *)sourcing_name, s,
- (char *)name, (char *)ap->pat);
+ const size_t sourcing_name_len = (STRLEN(s) + strlen(name) + ap->patlen
+ + 1);
+ sourcing_name = xmalloc(sourcing_name_len);
+ snprintf((char *)sourcing_name, sourcing_name_len, s, name,
+ (char *)ap->pat);
if (p_verbose >= 8) {
verbose_enter();
smsg(_("Executing %s"), sourcing_name);
@@ -7102,7 +7106,7 @@ char_u *getnextac(int c, void *cookie, int indent)
if (p_verbose >= 9) {
verbose_enter_scroll();
smsg(_("autocommand %s"), ac->cmd);
- msg_puts((char_u *)"\n"); /* don't overwrite this either */
+ msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
}
retval = vim_strsave(ac->cmd);
@@ -7168,15 +7172,17 @@ bool has_autocmd(event_T event, char_u *sfname, buf_T *buf)
*/
char_u *get_augroup_name(expand_T *xp, int idx)
{
- if (idx == augroups.ga_len) /* add "END" add the end */
+ if (idx == augroups.ga_len) { // add "END" add the end
return (char_u *)"END";
- if (idx >= augroups.ga_len) /* end of list */
+ }
+ if (idx >= augroups.ga_len) { // end of list
return NULL;
+ }
if (AUGROUP_NAME(idx) == NULL || AUGROUP_NAME(idx) == get_deleted_augroup()) {
// skip deleted entries
return (char_u *)"";
}
- return AUGROUP_NAME(idx); // return a name
+ return (char_u *)AUGROUP_NAME(idx);
}
static int include_groups = FALSE;
@@ -7238,18 +7244,22 @@ char_u *get_event_name(expand_T *xp, int idx)
|| AUGROUP_NAME(idx) == get_deleted_augroup()) {
return (char_u *)""; // skip deleted entries
}
- return AUGROUP_NAME(idx); // return a name
+ return (char_u *)AUGROUP_NAME(idx);
}
return (char_u *)event_names[idx - augroups.ga_len].name;
}
-/// Return true if autocmd "event" is supported.
-bool autocmd_supported(char_u *event)
+/// Check whether given autocommand is supported
+///
+/// @param[in] event Event to check.
+///
+/// @return True if it is, false otherwise.
+bool autocmd_supported(const char *const event)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
char_u *p;
-
- return event_name2nr(event, &p) != NUM_EVENTS;
+ return event_name2nr((const char_u *)event, &p) != NUM_EVENTS;
}
/// Return true if an autocommand is defined for a group, event and
@@ -7264,26 +7274,24 @@ bool autocmd_supported(char_u *event)
/// exists("#Event#pat")
///
/// @param arg autocommand string
-bool au_exists(const char_u *arg) FUNC_ATTR_WARN_UNUSED_RESULT
+bool au_exists(const char *const arg) FUNC_ATTR_WARN_UNUSED_RESULT
{
- char_u *arg_save;
- char_u *pattern = NULL;
- char_u *event_name;
- char_u *p;
event_T event;
AutoPat *ap;
buf_T *buflocal_buf = NULL;
int group;
bool retval = false;
- /* Make a copy so that we can change the '#' chars to a NUL. */
- arg_save = vim_strsave(arg);
- p = vim_strchr(arg_save, '#');
- if (p != NULL)
+ // Make a copy so that we can change the '#' chars to a NUL.
+ char *const arg_save = xstrdup(arg);
+ char *p = strchr(arg_save, '#');
+ if (p != NULL) {
*p++ = NUL;
+ }
- /* First, look for an autocmd group name */
- group = au_find_group(arg_save);
+ // First, look for an autocmd group name.
+ group = au_find_group((char_u *)arg_save);
+ char *event_name;
if (group == AUGROUP_ERROR) {
/* Didn't match a group name, assume the first argument is an event. */
group = AUGROUP_ALL;
@@ -7295,17 +7303,18 @@ bool au_exists(const char_u *arg) FUNC_ATTR_WARN_UNUSED_RESULT
goto theend;
}
- /* Must be "Group#Event" or "Group#Event#pat". */
+ // Must be "Group#Event" or "Group#Event#pat".
event_name = p;
- p = vim_strchr(event_name, '#');
- if (p != NULL)
- *p++ = NUL; /* "Group#Event#pat" */
+ p = strchr(event_name, '#');
+ if (p != NULL) {
+ *p++ = NUL; // "Group#Event#pat"
+ }
}
- pattern = p; /* "pattern" is NULL when there is no pattern */
+ char *pattern = p; // "pattern" is NULL when there is no pattern.
- /* find the index (enum) for the event name */
- event = event_name2nr(event_name, &p);
+ // Find the index (enum) for the event name.
+ event = event_name2nr((char_u *)event_name, (char_u **)&p);
/* return FALSE if the event name is not recognized */
if (event == NUM_EVENTS)
@@ -7331,7 +7340,7 @@ bool au_exists(const char_u *arg) FUNC_ATTR_WARN_UNUSED_RESULT
&& (group == AUGROUP_ALL || ap->group == group)
&& (pattern == NULL
|| (buflocal_buf == NULL
- ? fnamecmp(ap->pat, pattern) == 0
+ ? fnamecmp(ap->pat, (char_u *)pattern) == 0
: ap->buflocal_nr == buflocal_buf->b_fnum))) {
retval = true;
break;
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index fe889eb860..b7c6fd41f2 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -1913,17 +1913,13 @@ static int vgetorpeek(int advance)
if ((mp == NULL || max_mlen >= mp_match_len)
&& keylen != KEYLEN_PART_MAP) {
- /*
- * When no matching mapping found or found a
- * non-matching mapping that matches at least what the
- * matching mapping matched:
- * Check if we have a terminal code, when:
- * mapping is allowed,
- * keys have not been mapped,
- * and not an ESC sequence, not in insert mode or
- * p_ek is on,
- * and when not timed out,
- */
+ // When no matching mapping found or found a non-matching mapping
+ // that matches at least what the matching mapping matched:
+ // Check if we have a terminal code, when:
+ // mapping is allowed,
+ // keys have not been mapped,
+ // and not an ESC sequence, not in insert mode,
+ // and when not timed out.
if ((no_mapping == 0 || allow_keys != 0)
&& (typebuf.tb_maplen == 0
|| (p_remap && typebuf.tb_noremap[
@@ -3165,11 +3161,11 @@ map_clear_int (
}
}
-/*
- * Return characters to represent the map mode in an allocated string.
- * Returns NULL when out of memory.
- */
-char_u *map_mode_to_chars(int mode)
+/// Return characters to represent the map mode in an allocated string
+///
+/// @return [allocated] NUL-terminated string with characters.
+char *map_mode_to_chars(int mode)
+ FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_RET
{
garray_T mapmode;
@@ -3202,7 +3198,7 @@ char_u *map_mode_to_chars(int mode)
}
ga_append(&mapmode, NUL);
- return (char_u *)mapmode.ga_data;
+ return (char *)mapmode.ga_data;
}
static void
@@ -3211,8 +3207,7 @@ showmap (
int local /* TRUE for buffer-local map */
)
{
- int len = 1;
- char_u *mapchars;
+ size_t len = 1;
if (msg_didout || msg_silent != 0) {
msg_putchar('\n');
@@ -3220,29 +3215,30 @@ showmap (
return;
}
- mapchars = map_mode_to_chars(mp->m_mode);
- if (mapchars != NULL) {
+ {
+ char *const mapchars = map_mode_to_chars(mp->m_mode);
msg_puts(mapchars);
- len = (int)STRLEN(mapchars);
+ len = strlen(mapchars);
xfree(mapchars);
}
while (++len <= 3)
msg_putchar(' ');
- /* Display the LHS. Get length of what we write. */
- len = msg_outtrans_special(mp->m_keys, TRUE);
+ // Display the LHS. Get length of what we write.
+ len = (size_t)msg_outtrans_special(mp->m_keys, true);
do {
msg_putchar(' '); /* padd with blanks */
++len;
} while (len < 12);
- if (mp->m_noremap == REMAP_NONE)
- msg_puts_attr((char_u *)"*", hl_attr(HLF_8));
- else if (mp->m_noremap == REMAP_SCRIPT)
- msg_puts_attr((char_u *)"&", hl_attr(HLF_8));
- else
+ if (mp->m_noremap == REMAP_NONE) {
+ msg_puts_attr("*", hl_attr(HLF_8));
+ } else if (mp->m_noremap == REMAP_SCRIPT) {
+ msg_puts_attr("&", hl_attr(HLF_8));
+ } else {
msg_putchar(' ');
+ }
if (local)
msg_putchar('@');
@@ -3251,11 +3247,11 @@ showmap (
/* Use FALSE below if we only want things like <Up> to show up as such on
* the rhs, and not M-x etc, TRUE gets both -- webb */
- if (*mp->m_str == NUL)
- msg_puts_attr((char_u *)"<Nop>", hl_attr(HLF_8));
- else {
- /* Remove escaping of CSI, because "m_str" is in a format to be used
- * as typeahead. */
+ if (*mp->m_str == NUL) {
+ msg_puts_attr("<Nop>", hl_attr(HLF_8));
+ } else {
+ // Remove escaping of CSI, because "m_str" is in a format to be used
+ // as typeahead.
char_u *s = vim_strsave(mp->m_str);
vim_unescape_csi(s);
msg_outtrans_special(s, FALSE);
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index b00a7ac3c9..b141d40aa2 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -882,8 +882,13 @@ EXTERN int swap_exists_did_quit INIT(= FALSE);
EXTERN char_u IObuff[IOSIZE]; ///< Buffer for sprintf, I/O, etc.
EXTERN char_u NameBuff[MAXPATHL]; ///< Buffer for expanding file names
EXTERN char_u msg_buf[MSG_BUF_LEN]; ///< Small buffer for messages
-EXTERN char os_buf[MAX(MAXPATHL, IOSIZE)]; ///< Buffer for the os/ layer
-
+EXTERN char os_buf[ ///< Buffer for the os/ layer
+#if MAXPATHL > IOSIZE
+MAXPATHL
+#else
+IOSIZE
+#endif
+];
/* When non-zero, postpone redrawing. */
EXTERN int RedrawingDisabled INIT(= 0);
diff --git a/src/nvim/hashtab.c b/src/nvim/hashtab.c
index 376f33e23e..b14bb01c0e 100644
--- a/src/nvim/hashtab.c
+++ b/src/nvim/hashtab.c
@@ -82,22 +82,42 @@ 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, char_u *key)
+hashitem_T *hash_find(hashtab_T *ht, const char_u *key)
{
- return hash_lookup(ht, key, hash_hash(key));
+ return hash_lookup(ht, (const char *)key, STRLEN(key), hash_hash(key));
+}
+
+/// Like hash_find, but key is not NUL-terminated
+///
+/// @param[in] ht Hashtab to look in.
+/// @param[in] key Key of the looked-for item. Must not be NULL.
+/// @param[in] len Key length.
+///
+/// @return Pointer to the hash item corresponding to the given key.
+/// If not found, then return pointer to the empty item that would be
+/// used for that 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)
+{
+ return hash_lookup(ht, key, len, hash_hash_len(key, len));
}
/// Like hash_find(), but caller computes "hash".
///
-/// @param key The key of the looked-for item. Must not be NULL.
-/// @param hash The precomputed hash for the key.
+/// @param[in] key The key of the looked-for item. Must not be NULL.
+/// @param[in] key_len Key length.
+/// @param[in] hash The precomputed hash for the key.
///
/// @return Pointer to the hashitem corresponding to the given key.
/// If not found, then return pointer to the empty item that would be
/// 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 *ht, char_u *key, hash_T hash)
+hashitem_T *hash_lookup(hashtab_T *const ht,
+ const char *const key, const size_t key_len,
+ const hash_T hash)
{
#ifdef HT_DEBUG
hash_count_lookup++;
@@ -117,7 +137,9 @@ hashitem_T* hash_lookup(hashtab_T *ht, char_u *key, hash_T hash)
hashitem_T *freeitem = NULL;
if (hi->hi_key == HI_KEY_REMOVED) {
freeitem = hi;
- } else if ((hi->hi_hash == hash) && (STRCMP(hi->hi_key, key) == 0)) {
+ } else if ((hi->hi_hash == hash)
+ && (STRNCMP(hi->hi_key, key, key_len) == 0)
+ && hi->hi_key[key_len] == NUL) {
return hi;
}
@@ -142,7 +164,8 @@ hashitem_T* hash_lookup(hashtab_T *ht, char_u *key, hash_T hash)
if ((hi->hi_hash == hash)
&& (hi->hi_key != HI_KEY_REMOVED)
- && (STRCMP(hi->hi_key, key) == 0)) {
+ && (STRNCMP(hi->hi_key, key, key_len) == 0)
+ && hi->hi_key[key_len] == NUL) {
return hi;
}
@@ -179,7 +202,7 @@ void hash_debug_results(void)
int hash_add(hashtab_T *ht, char_u *key)
{
hash_T hash = hash_hash(key);
- hashitem_T *hi = hash_lookup(ht, key, hash);
+ hashitem_T *hi = hash_lookup(ht, (const char *)key, STRLEN(key), hash);
if (!HASHITEM_EMPTY(hi)) {
EMSG2(_(e_intern2), "hash_add()");
return FAIL;
@@ -359,13 +382,16 @@ static void hash_may_resize(hashtab_T *ht, size_t minitems)
ht->ht_filled = ht->ht_used;
}
+#define HASH_CYCLE_BODY(hash, p) \
+ hash = hash * 101 + *p++
+
/// Get the hash number for a key.
///
/// If you think you know a better hash function: Compile with HT_DEBUG set and
/// run a script that uses hashtables a lot. Vim will then print statistics
/// when exiting. Try that with the current hash algorithm and yours. The
/// lower the percentage the better.
-hash_T hash_hash(char_u *key)
+hash_T hash_hash(const char_u *key)
{
hash_T hash = *key;
@@ -375,14 +401,43 @@ hash_T hash_hash(char_u *key)
// A simplistic algorithm that appears to do very well.
// Suggested by George Reilly.
- char_u *p = key + 1;
+ const uint8_t *p = key + 1;
while (*p != NUL) {
- hash = hash * 101 + *p++;
+ HASH_CYCLE_BODY(hash, p);
}
return hash;
}
+/// Get the hash number for a key that is not a NUL-terminated string
+///
+/// @warning Function does not check whether key contains NUL. But you will not
+/// be able to get hash entry in this case.
+///
+/// @param[in] key Key.
+/// @param[in] len Key length.
+///
+/// @return Key hash.
+hash_T hash_hash_len(const char *key, const size_t len)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ if (len == 0) {
+ return 0;
+ }
+
+ hash_T hash = *(uint8_t *)key;
+ const uint8_t *end = (uint8_t *)key + len;
+
+ const uint8_t *p = (const uint8_t *)key + 1;
+ while (p < end) {
+ HASH_CYCLE_BODY(hash, p);
+ }
+
+ return hash;
+}
+
+#undef HASH_CYCLE_BODY
+
/// Function to get HI_KEY_REMOVED value
///
/// Used for testing because luajit ffi does not allow getting addresses of
diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c
index 9d50058257..a05ac5f877 100644
--- a/src/nvim/if_cscope.c
+++ b/src/nvim/if_cscope.c
@@ -2008,8 +2008,9 @@ static int cs_reset(exarg_T *eap)
xfree(pplist);
xfree(fllist);
- if (p_csverbose)
- MSG_ATTR(_("All cscope databases reset"), hl_attr(HLF_R) | MSG_HIST);
+ if (p_csverbose) {
+ msg_attr(_("All cscope databases reset"), hl_attr(HLF_R) | MSG_HIST);
+ }
return CSCOPE_SUCCESS;
} /* cs_reset */
diff --git a/src/nvim/keymap.c b/src/nvim/keymap.c
index 94bbaf4239..72b0d0aa40 100644
--- a/src/nvim/keymap.c
+++ b/src/nvim/keymap.c
@@ -843,10 +843,10 @@ char_u *replace_termcodes(const char_u *from, const size_t from_len,
// If "mapleader" or "maplocalleader" isn't set use a backslash.
if (end - src >= 7 && STRNICMP(src, "<Leader>", 8) == 0) {
len = 8;
- p = get_var_value((char_u *)"g:mapleader");
+ p = get_var_value("g:mapleader");
} else if (end - src >= 12 && STRNICMP(src, "<LocalLeader>", 13) == 0) {
len = 13;
- p = get_var_value((char_u *)"g:maplocalleader");
+ p = get_var_value("g:maplocalleader");
} else {
len = 0;
p = NULL;
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index b8891f6560..91dab16e27 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -1410,8 +1410,8 @@ recover_names (
for (int i = 0; i < num_files; ++i) {
/* print the swap file name */
msg_outnum((long)++file_count);
- MSG_PUTS(". ");
- msg_puts(path_tail(files[i]));
+ msg_puts(". ");
+ msg_puts((const char *)path_tail(files[i]));
msg_putchar('\n');
(void)swapfile_info(files[i]);
}
diff --git a/src/nvim/menu.c b/src/nvim/menu.c
index 7c0eee64dd..529978e3f0 100644
--- a/src/nvim/menu.c
+++ b/src/nvim/menu.c
@@ -755,10 +755,11 @@ static void show_menus_recursive(vimmenu_T *menu, int modes, int depth)
else
msg_putchar(' ');
MSG_PUTS(" ");
- if (*menu->strings[bit] == NUL)
- msg_puts_attr((char_u *)"<Nop>", hl_attr(HLF_8));
- else
- msg_outtrans_special(menu->strings[bit], FALSE);
+ if (*menu->strings[bit] == NUL) {
+ msg_puts_attr("<Nop>", hl_attr(HLF_8));
+ } else {
+ msg_outtrans_special(menu->strings[bit], false);
+ }
}
} else {
if (menu == NULL) {
diff --git a/src/nvim/message.c b/src/nvim/message.c
index ad1c63eeac..5427ae7793 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -7,7 +7,6 @@
#include <stdbool.h>
#include <stdarg.h>
#include <string.h>
-#include <math.h>
#include "nvim/vim.h"
#include "nvim/ascii.h"
@@ -129,9 +128,9 @@ int verb_msg(char_u *s)
return n;
}
-int msg_attr(char_u *s, int attr) FUNC_ATTR_NONNULL_ARG(1)
+int msg_attr(const char *s, const int attr) FUNC_ATTR_NONNULL_ARG(1)
{
- return msg_attr_keep(s, attr, FALSE);
+ return msg_attr_keep((char_u *)s, attr, false);
}
int
@@ -165,8 +164,9 @@ msg_attr_keep (
|| (*s != '<'
&& last_msg_hist != NULL
&& last_msg_hist->msg != NULL
- && STRCMP(s, last_msg_hist->msg)))
- add_msg_hist(s, -1, attr);
+ && STRCMP(s, last_msg_hist->msg))) {
+ add_msg_hist((const char *)s, -1, attr);
+ }
/* When displaying keep_msg, don't let msg_start() free it, caller must do
* that. */
@@ -348,7 +348,7 @@ int smsg_attr(int attr, char *s, ...)
va_start(arglist, s);
vim_vsnprintf((char *)IObuff, IOSIZE, s, arglist, NULL);
va_end(arglist);
- return msg_attr(IObuff, attr);
+ return msg_attr((const char *)IObuff, attr);
}
/*
@@ -382,39 +382,40 @@ static int other_sourcing_name(void)
return FALSE;
}
-/// Get the message about the source, as used for an error message.
-/// Returns an allocated string with room for one more character.
-/// Returns NULL when no message is to be given.
-static char_u *get_emsg_source(void)
+/// Get the message about the source, as used for an error message
+///
+/// @return [allocated] String with room for one more character. NULL when no
+/// message is to be given.
+static char *get_emsg_source(void)
+ FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT
{
if (sourcing_name != NULL && other_sourcing_name()) {
- char_u *p = (char_u *)_("Error detected while processing %s:");
- size_t len = STRLEN(sourcing_name) + STRLEN(p) + 1;
- char_u *buf = xmalloc(len);
- snprintf((char *)buf, len, (char *)p, sourcing_name);
+ const char *const p = _("Error detected while processing %s:");
+ const size_t buf_len = STRLEN(sourcing_name) + strlen(p) + 1;
+ char *const buf = xmalloc(buf_len);
+ snprintf(buf, buf_len, p, sourcing_name);
return buf;
}
return NULL;
}
-/*
- * Get the message about the source lnum, as used for an error message.
- * Returns an allocated string with room for one more character.
- * Returns NULL when no message is to be given.
- */
-static char_u *get_emsg_lnum(void)
+/// Get the message about the source lnum, as used for an error message.
+///
+/// @return [allocated] String with room for one more character. NULL when no
+/// message is to be given.
+static char *get_emsg_lnum(void)
+ FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT
{
- char_u *Buf, *p;
-
- /* lnum is 0 when executing a command from the command line
- * argument, we don't want a line number then */
+ // lnum is 0 when executing a command from the command line
+ // argument, we don't want a line number then
if (sourcing_name != NULL
&& (other_sourcing_name() || sourcing_lnum != last_sourcing_lnum)
&& sourcing_lnum != 0) {
- p = (char_u *)_("line %4ld:");
- Buf = xmalloc(STRLEN(p) + 20);
- sprintf((char *)Buf, (char *)p, (long)sourcing_lnum);
- return Buf;
+ const char *const p = _("line %4ld:");
+ const size_t buf_len = 20 + strlen(p);
+ char *const buf = xmalloc(buf_len);
+ snprintf(buf, buf_len, p, (long)sourcing_lnum);
+ return buf;
}
return NULL;
}
@@ -426,10 +427,8 @@ static char_u *get_emsg_lnum(void)
*/
void msg_source(int attr)
{
- char_u *p;
-
- ++no_wait_return;
- p = get_emsg_source();
+ no_wait_return++;
+ char *p = get_emsg_source();
if (p != NULL) {
msg_attr(p, attr);
xfree(p);
@@ -476,10 +475,10 @@ int emsg_not_now(void)
*
* return TRUE if wait_return not called
*/
-int emsg(char_u *s)
+int emsg(const char_u *s_)
{
+ const char *s = (const char *)s_;
int attr;
- char_u *p;
int ignore = false;
int severe;
@@ -506,7 +505,7 @@ int emsg(char_u *s)
* when the message should be ignored completely (used for the
* interrupt message).
*/
- if (cause_errthrow(s, severe, &ignore) == true) {
+ if (cause_errthrow((char_u *)s, severe, &ignore) == true) {
if (!ignore) {
did_emsg = true;
}
@@ -514,7 +513,7 @@ int emsg(char_u *s)
}
// set "v:errmsg", also when using ":silent! cmd"
- set_vim_var_string(VV_ERRMSG, (char *) s, -1);
+ set_vim_var_string(VV_ERRMSG, s, -1);
/*
* When using ":silent! cmd" ignore error messages.
@@ -523,19 +522,21 @@ int emsg(char_u *s)
if (emsg_silent != 0) {
if (!emsg_noredir) {
msg_start();
- p = get_emsg_source();
+ char *p = get_emsg_source();
if (p != NULL) {
- STRCAT(p, "\n");
- redir_write(p, STRLEN(p));
+ const size_t p_len = strlen(p);
+ p[p_len] = '\n';
+ redir_write(p, p_len + 1);
xfree(p);
}
p = get_emsg_lnum();
if (p != NULL) {
- STRCAT(p, "\n");
- redir_write(p, STRLEN(p));
+ const size_t p_len = strlen(p);
+ p[p_len] = '\n';
+ redir_write(p, p_len + 1);
xfree(p);
}
- redir_write(s, STRLEN(s));
+ redir_write(s, strlen(s));
}
return true;
}
@@ -570,10 +571,8 @@ int emsg(char_u *s)
*/
msg_source(attr);
- /*
- * Display the error message itself.
- */
- msg_nowait = FALSE; /* wait for this msg */
+ // Display the error message itself.
+ msg_nowait = false; // Wait for this msg.
return msg_attr(s, attr);
}
@@ -625,14 +624,14 @@ char_u *msg_trunc_attr(char_u *s, int force, int attr)
{
int n;
- /* Add message to history before truncating */
- add_msg_hist(s, -1, attr);
+ // Add message to history before truncating.
+ add_msg_hist((const char *)s, -1, attr);
s = msg_may_trunc(force, s);
- msg_hist_off = TRUE;
- n = msg_attr(s, attr);
- msg_hist_off = FALSE;
+ msg_hist_off = true;
+ n = msg_attr((const char *)s, attr);
+ msg_hist_off = false;
if (n)
return s;
@@ -671,12 +670,8 @@ char_u *msg_may_trunc(int force, char_u *s)
return s;
}
-static void
-add_msg_hist (
- char_u *s,
- int len, /* -1 for undetermined length */
- int attr
-)
+/// @param[in] len Length of s or -1.
+static void add_msg_hist(const char *s, int len, int attr)
{
if (msg_hist_off || msg_silent != 0)
return;
@@ -694,9 +689,10 @@ add_msg_hist (
++s;
--len;
}
- while (len > 0 && s[len - 1] == '\n')
- --len;
- p->msg = vim_strnsave(s, len);
+ while (len > 0 && s[len - 1] == '\n') {
+ len--;
+ }
+ p->msg = (char_u *)xmemdupz(s, (size_t)len);
p->next = NULL;
p->attr = attr;
if (last_msg_hist != NULL)
@@ -729,11 +725,11 @@ int delete_first_msg(void)
return OK;
}
-/*
- * ":messages" command.
- */
-void ex_messages(exarg_T *eap)
+/// :messages command implementation
+void ex_messages(void *const eap_p)
+ FUNC_ATTR_NONNULL_ALL
{
+ exarg_T *eap = (exarg_T *)eap_p;
struct msg_hist *p;
int c = 0;
@@ -771,7 +767,7 @@ void ex_messages(exarg_T *eap)
// Display what was not skipped.
for (; p != NULL && !got_int; p = p->next) {
if (p->msg != NULL) {
- msg_attr(p->msg, p->attr);
+ msg_attr((const char *)p->msg, p->attr);
}
}
@@ -1055,9 +1051,10 @@ void msg_start(void)
msg_didout = FALSE; /* no output on current line yet */
}
- /* when redirecting, may need to start a new line. */
- if (!did_return)
- redir_write((char_u *)"\n", -1);
+ // When redirecting, may need to start a new line.
+ if (!did_return) {
+ redir_write("\n", 1);
+ }
}
/*
@@ -1076,24 +1073,24 @@ void msg_putchar(int c)
void msg_putchar_attr(int c, int attr)
{
- char_u buf[MB_MAXBYTES + 1];
+ char buf[MB_MAXBYTES + 1];
if (IS_SPECIAL(c)) {
- buf[0] = K_SPECIAL;
- buf[1] = K_SECOND(c);
- buf[2] = K_THIRD(c);
+ buf[0] = (char)K_SPECIAL;
+ buf[1] = (char)K_SECOND(c);
+ buf[2] = (char)K_THIRD(c);
buf[3] = NUL;
} else {
- buf[(*mb_char2bytes)(c, buf)] = NUL;
+ buf[(*mb_char2bytes)(c, (char_u *)buf)] = NUL;
}
msg_puts_attr(buf, attr);
}
void msg_outnum(long n)
{
- char_u buf[20];
+ char buf[20];
- sprintf((char *)buf, "%" PRId64, (int64_t)n);
+ snprintf(buf, sizeof(buf), "%ld", n);
msg_puts(buf);
}
@@ -1149,16 +1146,16 @@ char_u *msg_outtrans_one(char_u *p, int attr)
msg_outtrans_len_attr(p, l, attr);
return p + l;
}
- msg_puts_attr(transchar_byte(*p), attr);
+ msg_puts_attr((const char *)transchar_byte(*p), attr);
return p + 1;
}
int msg_outtrans_len_attr(char_u *msgstr, int len, int attr)
{
int retval = 0;
- char_u *str = msgstr;
- char_u *plain_start = msgstr;
- char_u *s;
+ const char *str = (const char *)msgstr;
+ const char *plain_start = (const char *)msgstr;
+ char_u *s;
int mb_l;
int c;
@@ -1168,36 +1165,39 @@ int msg_outtrans_len_attr(char_u *msgstr, int len, int attr)
attr &= ~MSG_HIST;
}
- /* If the string starts with a composing character first draw a space on
- * which the composing char can be drawn. */
- if (enc_utf8 && utf_iscomposing(utf_ptr2char(msgstr)))
- msg_puts_attr((char_u *)" ", attr);
+ // If the string starts with a composing character first draw a space on
+ // which the composing char can be drawn.
+ if (enc_utf8 && utf_iscomposing(utf_ptr2char(msgstr))) {
+ msg_puts_attr(" ", attr);
+ }
/*
* Go over the string. Special characters are translated and printed.
* Normal characters are printed several at a time.
*/
while (--len >= 0) {
- if (enc_utf8)
- /* Don't include composing chars after the end. */
- mb_l = utfc_ptr2len_len(str, len + 1);
- else if (has_mbyte)
- mb_l = (*mb_ptr2len)(str);
- else
+ if (enc_utf8) {
+ // Don't include composing chars after the end.
+ mb_l = utfc_ptr2len_len((char_u *)str, len + 1);
+ } else if (has_mbyte) {
+ mb_l = (*mb_ptr2len)((char_u *)str);
+ } else {
mb_l = 1;
+ }
if (has_mbyte && mb_l > 1) {
- c = (*mb_ptr2char)(str);
- if (vim_isprintc(c))
- /* printable multi-byte char: count the cells. */
- retval += (*mb_ptr2cells)(str);
- else {
- /* unprintable multi-byte char: print the printable chars so
- * far and the translation of the unprintable char. */
- if (str > plain_start)
- msg_puts_attr_len(plain_start, (int)(str - plain_start),
- attr);
+ c = (*mb_ptr2char)((char_u *)str);
+ if (vim_isprintc(c)) {
+ // Printable multi-byte char: count the cells.
+ retval += (*mb_ptr2cells)((char_u *)str);
+ } else {
+ // Unprintable multi-byte char: print the printable chars so
+ // far and the translation of the unprintable char.
+ if (str > plain_start) {
+ msg_puts_attr_len(plain_start, str - plain_start, attr);
+ }
plain_start = str + mb_l;
- msg_puts_attr(transchar(c), attr == 0 ? hl_attr(HLF_8) : attr);
+ msg_puts_attr((const char *)transchar(c),
+ (attr == 0 ? hl_attr(HLF_8) : attr));
retval += char2cells(c);
}
len -= mb_l - 1;
@@ -1205,23 +1205,25 @@ int msg_outtrans_len_attr(char_u *msgstr, int len, int attr)
} else {
s = transchar_byte(*str);
if (s[1] != NUL) {
- /* unprintable char: print the printable chars so far and the
- * translation of the unprintable char. */
- if (str > plain_start)
- msg_puts_attr_len(plain_start, (int)(str - plain_start),
- attr);
+ // Unprintable char: print the printable chars so far and the
+ // translation of the unprintable char.
+ if (str > plain_start) {
+ msg_puts_attr_len(plain_start, str - plain_start, attr);
+ }
plain_start = str + 1;
- msg_puts_attr(s, attr == 0 ? hl_attr(HLF_8) : attr);
+ msg_puts_attr((const char *)s, attr == 0 ? hl_attr(HLF_8) : attr);
retval += (int)STRLEN(s);
- } else
- ++retval;
- ++str;
+ } else {
+ retval++;
+ }
+ str++;
}
}
- if (str > plain_start)
- /* print the printable chars at the end */
- msg_puts_attr_len(plain_start, (int)(str - plain_start), attr);
+ if (str > plain_start) {
+ // Print the printable chars at the end.
+ msg_puts_attr_len(plain_start, str - plain_start, attr);
+ }
return retval;
}
@@ -1264,23 +1266,23 @@ msg_outtrans_special (
{
char_u *str = strstart;
int retval = 0;
- char_u *string;
int attr;
- int len;
attr = hl_attr(HLF_8);
while (*str != NUL) {
- /* Leading and trailing spaces need to be displayed in <> form. */
+ const char *string;
+ // Leading and trailing spaces need to be displayed in <> form.
if ((str == strstart || str[1] == NUL) && *str == ' ') {
- string = (char_u *)"<Space>";
- ++str;
- } else
- string = str2special(&str, from);
- len = vim_strsize(string);
- /* Highlight special keys */
- msg_puts_attr(string, len > 1
- && (*mb_ptr2len)(string) <= 1
- ? attr : 0);
+ string = "<Space>";
+ str++;
+ } else {
+ string = (const char *)str2special((char_u **)&str, from);
+ }
+ const int len = vim_strsize((char_u *)string);
+ // Highlight special keys
+ msg_puts_attr(string, (len > 1
+ && (*mb_ptr2len)((char_u *)string) <= 1
+ ? attr : 0));
retval += len;
}
return retval;
@@ -1404,7 +1406,6 @@ void msg_prt_line(char_u *s, int list)
int attr = 0;
char_u *trail = NULL;
int l;
- char_u buf[MB_MAXBYTES + 1];
if (curwin->w_p_list)
list = TRUE;
@@ -1430,10 +1431,11 @@ void msg_prt_line(char_u *s, int list)
c = *p_extra++;
} else if (has_mbyte && (l = (*mb_ptr2len)(s)) > 1) {
col += (*mb_ptr2cells)(s);
+ char buf[MB_MAXBYTES + 1];
if (lcs_nbsp != NUL && list
&& (mb_ptr2char(s) == 160 || mb_ptr2char(s) == 0x202f)) {
- mb_char2bytes(lcs_nbsp, buf);
- buf[(*mb_ptr2len)(buf)] = NUL;
+ mb_char2bytes(lcs_nbsp, (char_u *)buf);
+ buf[(*mb_ptr2len)((char_u *)buf)] = NUL;
} else {
memmove(buf, s, (size_t)l);
buf[l] = NUL;
@@ -1530,12 +1532,12 @@ static char_u *screen_puts_mbyte(char_u *s, int l, int attr)
* Output a string to the screen at position msg_row, msg_col.
* Update msg_row and msg_col for the next message.
*/
-void msg_puts(char_u *s)
+void msg_puts(const char *s)
{
msg_puts_attr(s, 0);
}
-void msg_puts_title(char_u *s)
+void msg_puts_title(const char *s)
{
msg_puts_attr(s, hl_attr(HLF_T));
}
@@ -1559,7 +1561,7 @@ void msg_puts_long_len_attr(char_u *longstr, int len, int attr)
if (len > room && room >= 20) {
slen = (room - 3) / 2;
msg_outtrans_len_attr(longstr, slen, attr);
- msg_puts_attr((char_u *)"...", hl_attr(HLF_8));
+ msg_puts_attr("...", hl_attr(HLF_8));
}
msg_outtrans_len_attr(longstr + len - slen, slen, attr);
}
@@ -1567,7 +1569,7 @@ void msg_puts_long_len_attr(char_u *longstr, int len, int attr)
/*
* Basic function for writing a message with highlight attributes.
*/
-void msg_puts_attr(char_u *s, int attr)
+void msg_puts_attr(const char *const s, const int attr)
{
msg_puts_attr_len(s, -1, attr);
}
@@ -1575,7 +1577,7 @@ void msg_puts_attr(char_u *s, int 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.
-static void msg_puts_attr_len(char_u *str, int maxlen, int attr)
+void msg_puts_attr_len(const char *str, const ptrdiff_t maxlen, int attr)
{
// If redirection is on, also write to the redirection file.
redir_write(str, maxlen);
@@ -1606,9 +1608,9 @@ static void msg_puts_attr_len(char_u *str, int 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((char *)str, maxlen);
+ msg_puts_printf(str, maxlen);
} else {
- msg_puts_display(str, maxlen, attr, false);
+ msg_puts_display((const char_u *)str, maxlen, attr, false);
}
}
@@ -1616,14 +1618,15 @@ static void msg_puts_attr_len(char_u *str, int maxlen, int attr)
* The display part of msg_puts_attr_len().
* May be called recursively to display scroll-back text.
*/
-static void msg_puts_display(char_u *str, int maxlen, int attr, int recurse)
+static void msg_puts_display(const char_u *str, int maxlen, int attr,
+ int recurse)
{
- char_u *s = str;
- char_u *t_s = str; /* string from "t_s" to "s" is still todo */
- int t_col = 0; /* screen cells todo, 0 when "t_s" not used */
+ const char_u *s = str;
+ const char_u *t_s = str; // String from "t_s" to "s" is still todo.
+ int t_col = 0; // Screen cells todo, 0 when "t_s" not used.
int l;
int cw;
- char_u *sb_str = str;
+ const char_u *sb_str = str;
int sb_col = msg_col;
int wrap;
int did_last_char;
@@ -1665,26 +1668,27 @@ static void msg_puts_display(char_u *str, int maxlen, int attr, int recurse)
if (msg_col >= Columns) /* can happen after screen resize */
msg_col = Columns - 1;
- /* Display char in last column before showing more-prompt. */
- if (*s >= ' '
- && !cmdmsg_rl
- ) {
+ // Display char in last column before showing more-prompt.
+ if (*s >= ' ' && !cmdmsg_rl) {
if (has_mbyte) {
if (enc_utf8 && maxlen >= 0)
/* avoid including composing chars after the end */
l = utfc_ptr2len_len(s, (int)((str + maxlen) - s));
else
l = (*mb_ptr2len)(s);
- s = screen_puts_mbyte(s, l, attr);
- } else
+ s = screen_puts_mbyte((char_u *)s, l, attr);
+ } else {
msg_screen_putchar(*s++, attr);
- did_last_char = TRUE;
- } else
- did_last_char = FALSE;
+ }
+ did_last_char = true;
+ } else {
+ did_last_char = false;
+ }
- if (p_more)
- /* store text for scrolling back */
- store_sb_text(&sb_str, s, attr, &sb_col, TRUE);
+ if (p_more) {
+ // Store text for scrolling back.
+ store_sb_text((char_u **)&sb_str, (char_u *)s, attr, &sb_col, true);
+ }
inc_msg_scrolled();
need_wait_return = TRUE; /* may need wait_return in main() */
@@ -1720,13 +1724,15 @@ static void msg_puts_display(char_u *str, int maxlen, int attr, int recurse)
&& msg_col + t_col >= Columns - 1)
;
if (t_col > 0 && (wrap || *s == '\r' || *s == '\b'
- || *s == '\t' || *s == BELL))
- /* output any postponed text */
+ || *s == '\t' || *s == BELL)) {
+ // Output any postponed text.
t_puts(&t_col, t_s, s, attr);
+ }
- if (wrap && p_more && !recurse)
- /* store text for scrolling back */
- store_sb_text(&sb_str, s, attr, &sb_col, TRUE);
+ if (wrap && p_more && !recurse) {
+ // Store text for scrolling back.
+ store_sb_text((char_u **)&sb_str, (char_u *)s, attr, &sb_col, true);
+ }
if (*s == '\n') { /* go to next line */
msg_didout = FALSE; /* remember that line is empty */
@@ -1764,7 +1770,7 @@ static void msg_puts_display(char_u *str, int maxlen, int attr, int recurse)
// characters and draw them all at once later.
if (cmdmsg_rl || (cw > 1 && msg_col + t_col >= Columns - 1)) {
if (l > 1) {
- s = screen_puts_mbyte(s, l, attr) - 1;
+ s = screen_puts_mbyte((char_u *)s, l, attr) - 1;
} else {
msg_screen_putchar(*s, attr);
}
@@ -1779,11 +1785,13 @@ static void msg_puts_display(char_u *str, int maxlen, int attr, int recurse)
++s;
}
- /* output any postponed text */
- if (t_col > 0)
+ // Output any postponed text.
+ if (t_col > 0) {
t_puts(&t_col, t_s, s, attr);
- if (p_more && !recurse)
- store_sb_text(&sb_str, s, attr, &sb_col, FALSE);
+ }
+ if (p_more && !recurse) {
+ store_sb_text((char_u **)&sb_str, (char_u *)s, attr, &sb_col, false);
+ }
msg_check();
}
@@ -1959,11 +1967,11 @@ static msgchunk_T *disp_sb_line(int row, msgchunk_T *smp)
/*
* Output any postponed text for msg_puts_attr_len().
*/
-static void t_puts(int *t_col, char_u *t_s, char_u *s, int attr)
+static void t_puts(int *t_col, const char_u *t_s, const char_u *s, int attr)
{
- /* output postponed text */
- msg_didout = TRUE; /* remember that line is not empty */
- screen_puts_len(t_s, (int)(s - t_s), msg_row, msg_col, attr);
+ // Output postponed text.
+ msg_didout = true; // Remember that line is not empty.
+ screen_puts_len((char_u *)t_s, (int)(s - t_s), msg_row, msg_col, attr);
msg_col += *t_col;
*t_col = 0;
/* If the string starts with a composing character don't increment the
@@ -1984,13 +1992,13 @@ int msg_use_printf(void)
}
/// Print a message when there is no valid screen.
-static void msg_puts_printf(char *str, int maxlen)
+static void msg_puts_printf(const char *str, const ptrdiff_t maxlen)
{
- char *s = str;
+ const char *s = str;
char buf[4];
char *p;
- while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen)) {
+ while (*s != NUL && (maxlen < 0 || s - str < maxlen)) {
if (!(silent_mode && p_verbose == 0)) {
// NL --> CR NL translation (for Unix, not for "--version")
p = &buf[0];
@@ -2447,9 +2455,9 @@ void msg_check(void)
* May write a string to the redirection file.
* When "maxlen" is -1 write the whole string, otherwise up to "maxlen" bytes.
*/
-static void redir_write(char_u *str, int maxlen)
+static void redir_write(const char *const str, const ptrdiff_t maxlen)
{
- char_u *s = str;
+ const char_u *s = (char_u *)str;
static int cur_col = 0;
if (maxlen == 0) {
@@ -2493,23 +2501,28 @@ static void redir_write(char_u *str, int maxlen)
write_reg_contents(redir_reg, s, len, true);
}
if (redir_vname) {
- var_redir_str(s, maxlen);
+ var_redir_str((char_u *)s, maxlen);
}
- /* Write and adjust the current column. */
- while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen)) {
- if (!redir_reg && !redir_vname && !capture_ga)
- if (redir_fd != NULL)
+ // Write and adjust the current column.
+ while (*s != NUL
+ && (maxlen < 0 || (int)(s - (const char_u *)str) < maxlen)) {
+ if (!redir_reg && !redir_vname && !capture_ga) {
+ if (redir_fd != NULL) {
putc(*s, redir_fd);
- if (verbose_fd != NULL)
+ }
+ }
+ if (verbose_fd != NULL) {
putc(*s, verbose_fd);
- if (*s == '\r' || *s == '\n')
+ }
+ if (*s == '\r' || *s == '\n') {
cur_col = 0;
- else if (*s == '\t')
+ } else if (*s == '\t') {
cur_col += (8 - cur_col % 8);
- else
- ++cur_col;
- ++s;
+ } else {
+ cur_col++;
+ }
+ s++;
}
if (msg_silent != 0) /* should update msg_col */
@@ -2615,14 +2628,16 @@ void give_warning(char_u *message, bool hl) FUNC_ATTR_NONNULL_ARG(1)
set_vim_var_string(VV_WARNINGMSG, (char *) message, -1);
xfree(keep_msg);
keep_msg = NULL;
- if (hl)
+ if (hl) {
keep_msg_attr = hl_attr(HLF_W);
- else
+ } else {
keep_msg_attr = 0;
- if (msg_attr(message, keep_msg_attr) && msg_scrolled == 0)
+ }
+ if (msg_attr((const char *)message, keep_msg_attr) && msg_scrolled == 0) {
set_keep_msg(message, keep_msg_attr);
- msg_didout = FALSE; /* overwrite this message */
- msg_nowait = TRUE; /* don't wait for this message */
+ }
+ msg_didout = false; // Overwrite this message.
+ msg_nowait = true; // Don't wait for this message.
msg_col = 0;
--no_wait_return;
@@ -2958,11 +2973,12 @@ static void copy_hotkeys_and_msg(const char_u *message, char_u *buttons,
*/
void display_confirm_msg(void)
{
- /* avoid that 'q' at the more prompt truncates the message here */
- ++confirm_msg_used;
- if (confirm_msg != NULL)
- msg_puts_attr(confirm_msg, hl_attr(HLF_M));
- --confirm_msg_used;
+ // Avoid that 'q' at the more prompt truncates the message here.
+ confirm_msg_used++;
+ if (confirm_msg != NULL) {
+ msg_puts_attr((const char *)confirm_msg, hl_attr(HLF_M));
+ }
+ confirm_msg_used--;
}
int vim_dialog_yesno(int type, char_u *title, char_u *message, int dflt)
@@ -3001,834 +3017,3 @@ int vim_dialog_yesnoallcancel(int type, char_u *title, char_u *message, int dflt
}
return VIM_CANCEL;
}
-
-
-
-static char *e_printf = N_("E766: Insufficient arguments for printf()");
-
-/*
- * Get number argument from "idxp" entry in "tvs". First entry is 1.
- */
-static long tv_nr(typval_T *tvs, int *idxp)
-{
- int idx = *idxp - 1;
- long n = 0;
- int err = FALSE;
-
- if (tvs[idx].v_type == VAR_UNKNOWN)
- EMSG(_(e_printf));
- else {
- ++*idxp;
- n = get_tv_number_chk(&tvs[idx], &err);
- if (err)
- n = 0;
- }
- return n;
-}
-
-/*
- * Get string argument from "idxp" entry in "tvs". First entry is 1.
- * Returns NULL for an error.
- */
-static char *tv_str(typval_T *tvs, int *idxp)
-{
- int idx = *idxp - 1;
- char *s = NULL;
-
- if (tvs[idx].v_type == VAR_UNKNOWN)
- EMSG(_(e_printf));
- else {
- ++*idxp;
- s = (char *)get_tv_string_chk(&tvs[idx]);
- }
- return s;
-}
-
-/// Get pointer argument from the next entry in tvs
-///
-/// First entry is 1. Returns NULL for an error.
-///
-/// @param[in] tvs List of typval_T values.
-/// @param[in,out] idxp Pointer to the index of the current value.
-///
-/// @return Pointer stored in typval_T or NULL.
-static const void *tv_ptr(const typval_T *const tvs, int *const idxp)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
-{
-#define OFF(attr) offsetof(union typval_vval_union, attr)
- STATIC_ASSERT(
- OFF(v_string) == OFF(v_list)
- && OFF(v_string) == OFF(v_dict)
- && OFF(v_string) == OFF(v_partial)
- && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_list)
- && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_dict)
- && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_partial),
- "Strings, dictionaries, lists and partials are expected to be pointers, "
- "so that all three of them can be accessed via v_string");
-#undef OFF
- const int idx = *idxp - 1;
- if (tvs[idx].v_type == VAR_UNKNOWN) {
- EMSG(_(e_printf));
- return NULL;
- } else {
- (*idxp)++;
- return tvs[idx].vval.v_string;
- }
-}
-
-/*
- * Get float argument from "idxp" entry in "tvs". First entry is 1.
- */
-static double tv_float(typval_T *tvs, int *idxp)
-{
- int idx = *idxp - 1;
- double f = 0;
-
- if (tvs[idx].v_type == VAR_UNKNOWN)
- EMSG(_(e_printf));
- else {
- ++*idxp;
- if (tvs[idx].v_type == VAR_FLOAT)
- f = tvs[idx].vval.v_float;
- else if (tvs[idx].v_type == VAR_NUMBER)
- f = tvs[idx].vval.v_number;
- else
- EMSG(_("E807: Expected Float argument for printf()"));
- }
- return f;
-}
-
-/*
- * This code was included to provide a portable vsnprintf() and snprintf().
- * Some systems may provide their own, but we always use this one for
- * consistency.
- *
- * This code is based on snprintf.c - a portable implementation of snprintf
- * by Mark Martinec <mark.martinec@ijs.si>, Version 2.2, 2000-10-06.
- * Included with permission. It was heavily modified to fit in Vim.
- * The original code, including useful comments, can be found here:
- * http://www.ijs.si/software/snprintf/
- *
- * This snprintf() only supports the following conversion specifiers:
- * s, c, b, B, d, u, o, x, X, p (and synonyms: i, D, U, O - see below)
- * with flags: '-', '+', ' ', '0' and '#'.
- * An asterisk is supported for field width as well as precision.
- *
- * Limited support for floating point was added: 'f', 'e', 'E', 'g', 'G'.
- *
- * Length modifiers 'h' (short int) and 'l' (long int) are supported.
- * 'll' (long long int) is not supported.
- *
- * The locale is not used, the string is used as a byte string. This is only
- * relevant for double-byte encodings where the second byte may be '%'.
- *
- * It is permitted for "str_m" to be zero, and it is permitted to specify NULL
- * pointer for resulting string argument if "str_m" is zero (as per ISO C99).
- *
- * The return value is the number of characters which would be generated
- * for the given input, excluding the trailing NUL. If this value
- * is greater or equal to "str_m", not all characters from the result
- * have been stored in str, output bytes beyond the ("str_m"-1) -th character
- * are discarded. If "str_m" is greater than zero it is guaranteed
- * the resulting string will be NUL-terminated.
- */
-
-/*
- * When va_list is not supported we only define vim_snprintf().
- *
- * vim_vsnprintf() can be invoked with either "va_list" or a list of
- * "typval_T". When the latter is not used it must be NULL.
- */
-
-/* Like vim_vsnprintf() but append to the string. */
-int vim_snprintf_add(char *str, size_t str_m, char *fmt, ...)
-{
- va_list ap;
- int str_l;
- size_t len = STRLEN(str);
- size_t space;
-
- if (str_m <= len)
- space = 0;
- else
- space = str_m - len;
- va_start(ap, fmt);
- str_l = vim_vsnprintf(str + len, space, fmt, ap, NULL);
- va_end(ap);
- return str_l;
-}
-
-int vim_snprintf(char *str, size_t str_m, const char *fmt, ...)
-{
- va_list ap;
- int str_l;
-
- va_start(ap, fmt);
- str_l = vim_vsnprintf(str, str_m, fmt, ap, NULL);
- va_end(ap);
- return str_l;
-}
-
-int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap,
- typval_T *tvs)
-{
- size_t str_l = 0;
- bool str_avail = str_l < str_m;
- const char *p = fmt;
- int arg_idx = 1;
-
- if (!p) {
- p = "";
- }
- while (*p) {
- if (*p != '%') {
- // copy up to the next '%' or NUL without any changes
- size_t n = (size_t)(xstrchrnul(p + 1, '%') - p);
- if (str_avail) {
- size_t avail = str_m - str_l;
- memmove(str + str_l, p, MIN(n, avail));
- str_avail = n < avail;
- }
- p += n;
- assert(n <= SIZE_MAX - str_l);
- str_l += n;
- } else {
- size_t min_field_width = 0, precision = 0;
- int zero_padding = 0, precision_specified = 0, justify_left = 0;
- int alternate_form = 0, force_sign = 0;
-
- // if both ' ' and '+' flags appear, ' ' flag should be ignored
- int space_for_positive = 1;
-
- // allowed values: \0, h, l, 2 (for ll), z, L
- char length_modifier = '\0';
-
- // temporary buffer for simple numeric->string conversion
-# define TMP_LEN 350 // 1e308 seems reasonable as the maximum printable
- char tmp[TMP_LEN];
-
- // string address in case of string argument
- const char *str_arg;
-
- // natural field width of arg without padding and sign
- size_t str_arg_l;
-
- // unsigned char argument value (only defined for c conversion);
- // standard explicitly states the char argument for the c
- // conversion is unsigned
- unsigned char uchar_arg;
-
- // number of zeros to be inserted for numeric conversions as
- // required by the precision or minimal field width
- size_t number_of_zeros_to_pad = 0;
-
- // index into tmp where zero padding is to be inserted
- size_t zero_padding_insertion_ind = 0;
-
- // current conversion specifier character
- char fmt_spec = '\0';
-
- str_arg = NULL;
- p++; // skip '%'
-
- // parse flags
- while (*p == '0' || *p == '-' || *p == '+' || *p == ' '
- || *p == '#' || *p == '\'') {
- switch (*p) {
- case '0': zero_padding = 1; break;
- case '-': justify_left = 1; break;
- // if both '0' and '-' flags appear, '0' should be ignored
- case '+': force_sign = 1; space_for_positive = 0; break;
- case ' ': force_sign = 1; break;
- // if both ' ' and '+' flags appear, ' ' should be ignored
- case '#': alternate_form = 1; break;
- case '\'': break;
- }
- p++;
- }
-
- // parse field width
- if (*p == '*') {
- p++;
- int j = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int);
- if (j >= 0) {
- min_field_width = j;
- } else {
- min_field_width = -j;
- justify_left = 1;
- }
- } else if (ascii_isdigit((int)(*p))) {
- // size_t could be wider than unsigned int; make sure we treat
- // argument like common implementations do
- unsigned int uj = *p++ - '0';
-
- while (ascii_isdigit((int)(*p))) {
- uj = 10 * uj + (unsigned int)(*p++ - '0');
- }
- min_field_width = uj;
- }
-
- // parse precision
- if (*p == '.') {
- p++;
- precision_specified = 1;
- if (*p == '*') {
- int j = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int);
- p++;
- if (j >= 0) {
- precision = j;
- } else {
- precision_specified = 0;
- precision = 0;
- }
- } else if (ascii_isdigit((int)(*p))) {
- // size_t could be wider than unsigned int; make sure we
- // treat argument like common implementations do
- unsigned int uj = *p++ - '0';
-
- while (ascii_isdigit((int)(*p))) {
- uj = 10 * uj + (unsigned int)(*p++ - '0');
- }
- precision = uj;
- }
- }
-
- // parse 'h', 'l', 'll' and 'z' length modifiers
- if (*p == 'h' || *p == 'l' || *p == 'z') {
- length_modifier = *p;
- p++;
- if (length_modifier == 'l' && *p == 'l') { // ll, encoded as 2
- length_modifier = '2';
- p++;
- }
- }
-
- fmt_spec = *p;
-
- // common synonyms
- switch (fmt_spec) {
- case 'i': fmt_spec = 'd'; break;
- case 'D': fmt_spec = 'd'; length_modifier = 'l'; break;
- case 'U': fmt_spec = 'u'; length_modifier = 'l'; break;
- case 'O': fmt_spec = 'o'; length_modifier = 'l'; break;
- case 'F': fmt_spec = 'f'; break;
- default: break;
- }
-
- // get parameter value, do initial processing
- switch (fmt_spec) {
- // '%' and 'c' behave similar to 's' regarding flags and field widths
- case '%': case 'c': case 's': case 'S':
- str_arg_l = 1;
- switch (fmt_spec) {
- case '%':
- str_arg = p;
- break;
-
- case 'c': {
- int j = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int);
- // standard demands unsigned char
- uchar_arg = (unsigned char)j;
- str_arg = (char *)&uchar_arg;
- break;
- }
-
- case 's':
- case 'S':
- str_arg = tvs ? tv_str(tvs, &arg_idx) : va_arg(ap, char *);
- if (!str_arg) {
- str_arg = "[NULL]";
- str_arg_l = 6;
- } else if (!precision_specified) {
- // make sure not to address string beyond the specified precision
- str_arg_l = strlen(str_arg);
- } else if (precision == 0) {
- // truncate string if necessary as requested by precision
- str_arg_l = 0;
- } else {
- // memchr on HP does not like n > 2^31
- // TODO(elmart): check if this still holds / is relevant
- str_arg_l = (size_t)((char *)xmemscan(str_arg,
- NUL,
- MIN(precision, 0x7fffffff))
- - str_arg);
- }
- if (fmt_spec == 'S') {
- if (min_field_width != 0)
- min_field_width += strlen(str_arg)
- - mb_string2cells((char_u *) str_arg);
- if (precision) {
- char_u *p1 = (char_u *)str_arg;
- for (size_t i = 0; i < precision && *p1; i++) {
- p1 += mb_ptr2len(p1);
- }
- str_arg_l = precision = p1 - (char_u *)str_arg;
- }
- }
- break;
-
- default:
- break;
- }
- break;
-
- case 'd':
- case 'u':
- case 'b': case 'B':
- case 'o':
- case 'x': case 'X':
- case 'p': {
- // u, b, B, o, x, X and p conversion specifiers imply
- // the value is unsigned; d implies a signed value
-
- // 0 if numeric argument is zero (or if pointer is NULL for 'p'),
- // +1 if greater than zero (or non NULL for 'p'),
- // -1 if negative (unsigned argument is never negative)
- int arg_sign = 0;
-
- // only defined for length modifier h, or for no length modifiers
- int int_arg = 0;
- unsigned int uint_arg = 0;
-
- // only defined for length modifier l
- long int long_arg = 0;
- unsigned long int ulong_arg = 0;
-
- // only defined for length modifier ll
- long long int long_long_arg = 0;
- unsigned long long int ulong_long_arg = 0;
-
- // only defined for length modifier z
- size_t size_t_arg = 0;
-
- // only defined for p conversion
- const void *ptr_arg = NULL;
-
- if (fmt_spec == 'p') {
- length_modifier = '\0';
- ptr_arg = tvs ? tv_ptr(tvs, &arg_idx) : va_arg(ap, void *);
- if (ptr_arg) {
- arg_sign = 1;
- }
- } else if (fmt_spec == 'd') {
- // signed
- switch (length_modifier) {
- case '\0':
- case 'h':
- // char and short arguments are passed as int
- int_arg = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int);
- if (int_arg > 0) {
- arg_sign = 1;
- } else if (int_arg < 0) {
- arg_sign = -1;
- }
- break;
- case 'l':
- long_arg = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, long int);
- if (long_arg > 0) {
- arg_sign = 1;
- } else if (long_arg < 0) {
- arg_sign = -1;
- }
- break;
- case '2':
- long_long_arg = tvs ? tv_nr(tvs, &arg_idx)
- : va_arg(ap, long long int); // NOLINT (runtime/int)
- if (long_long_arg > 0) {
- arg_sign = 1;
- } else if (long_long_arg < 0) {
- arg_sign = -1;
- }
- break;
- }
- } else {
- // unsigned
- switch (length_modifier) {
- case '\0':
- case 'h':
- uint_arg = tvs ? (unsigned)tv_nr(tvs, &arg_idx)
- : va_arg(ap, unsigned int);
- if (uint_arg != 0) { arg_sign = 1; }
- break;
- case 'l':
- ulong_arg = tvs ? (unsigned long)tv_nr(tvs, &arg_idx)
- : va_arg(ap, unsigned long int);
- if (ulong_arg != 0) { arg_sign = 1; }
- break;
- case '2':
- ulong_long_arg = tvs
- ? (unsigned long long)tv_nr(tvs, &arg_idx) // NOLINT (runtime/int)
- : va_arg(ap, unsigned long long int); // NOLINT (runtime/int)
- if (ulong_long_arg) { arg_sign = 1; }
- break;
- case 'z':
- size_t_arg = tvs ? (size_t)tv_nr(tvs, &arg_idx)
- : va_arg(ap, size_t);
- if (size_t_arg) { arg_sign = 1; }
- break;
- }
- }
-
- str_arg = tmp;
- str_arg_l = 0;
-
- // For d, i, u, o, x, and X conversions, if precision is specified,
- // '0' flag should be ignored. This is so with Solaris 2.6, Digital UNIX
- // 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl.
- if (precision_specified) {
- zero_padding = 0;
- }
-
- if (fmt_spec == 'd') {
- if (force_sign && arg_sign >= 0) {
- tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
- }
- // leave negative numbers for sprintf to handle, to
- // avoid handling tricky cases like (short int)-32768
- } else if (alternate_form) {
- if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X'
- || fmt_spec == 'b' || fmt_spec == 'B')) {
- tmp[str_arg_l++] = '0';
- tmp[str_arg_l++] = fmt_spec;
- }
- // alternate form should have no effect for p * conversion, but ...
- }
-
- zero_padding_insertion_ind = str_arg_l;
- if (!precision_specified) {
- precision = 1; // default precision is 1
- }
- if (precision == 0 && arg_sign == 0) {
- // when zero value is formatted with an explicit precision 0,
- // resulting formatted string is empty (d, i, u, b, B, o, x, X, p)
- } else {
- char f[5];
- int f_l = 0;
-
- // construct a simple format string for sprintf
- f[f_l++] = '%';
- if (!length_modifier) {
- } else if (length_modifier == '2') {
- f[f_l++] = 'l';
- f[f_l++] = 'l';
- } else
- f[f_l++] = length_modifier;
- f[f_l++] = fmt_spec;
- f[f_l++] = '\0';
-
- if (fmt_spec == 'p')
- str_arg_l += sprintf(tmp + str_arg_l, f, ptr_arg);
- else if (fmt_spec == 'd') {
- // signed
- switch (length_modifier) {
- case '\0':
- case 'h': str_arg_l += sprintf(tmp + str_arg_l, f, int_arg);
- break;
- case 'l': str_arg_l += sprintf(tmp + str_arg_l, f, long_arg);
- break;
- case '2': str_arg_l += sprintf(tmp + str_arg_l, f, long_long_arg);
- break;
- }
- } else if (fmt_spec == 'b' || fmt_spec == 'B') {
- // binary
- size_t bits = 0;
- switch (length_modifier) {
- case '\0':
- case 'h': for (bits = sizeof(unsigned) * 8; bits > 0; bits--) {
- if ((uint_arg >> (bits - 1)) & 0x1) { break; } }
-
- while (bits > 0) {
- tmp[str_arg_l++] =
- ((uint_arg >> --bits) & 0x1) ? '1' : '0'; }
- break;
- case 'l': for (bits = sizeof(unsigned long) * 8; bits > 0; bits--) {
- if ((ulong_arg >> (bits - 1)) & 0x1) { break; } }
-
- while (bits > 0) {
- tmp[str_arg_l++] =
- ((ulong_arg >> --bits) & 0x1) ? '1' : '0'; }
- break;
- case '2': for (bits = sizeof(unsigned long long) * 8; // NOLINT (runtime/int)
- bits > 0; bits--) {
- if ((ulong_long_arg >> (bits - 1)) & 0x1) { break; } }
-
- while (bits > 0) {
- tmp[str_arg_l++] =
- ((ulong_long_arg >> --bits) & 0x1) ? '1' : '0'; }
- break;
- case 'z': for (bits = sizeof(size_t) * 8; bits > 0; bits--) {
- if ((size_t_arg >> (bits - 1)) & 0x1) { break; } }
-
- while (bits > 0) {
- tmp[str_arg_l++] =
- ((size_t_arg >> --bits) & 0x1) ? '1' : '0'; }
- break;
- }
- } else {
- // unsigned
- switch (length_modifier) {
- case '\0':
- case 'h': str_arg_l += sprintf(tmp + str_arg_l, f, uint_arg);
- break;
- case 'l': str_arg_l += sprintf(tmp + str_arg_l, f, ulong_arg);
- break;
- case '2': str_arg_l += sprintf(tmp + str_arg_l, f, ulong_long_arg);
- break;
- case 'z': str_arg_l += sprintf(tmp + str_arg_l, f, size_t_arg);
- break;
- }
- }
-
- // include the optional minus sign and possible "0x" in the region
- // before the zero padding insertion point
- if (zero_padding_insertion_ind < str_arg_l
- && tmp[zero_padding_insertion_ind] == '-')
- zero_padding_insertion_ind++;
- if (zero_padding_insertion_ind + 1 < str_arg_l
- && tmp[zero_padding_insertion_ind] == '0'
- && (tmp[zero_padding_insertion_ind + 1] == 'x'
- || tmp[zero_padding_insertion_ind + 1] == 'X'
- || tmp[zero_padding_insertion_ind + 1] == 'b'
- || tmp[zero_padding_insertion_ind + 1] == 'B'))
- zero_padding_insertion_ind += 2;
- }
-
- {
- size_t num_of_digits = str_arg_l - zero_padding_insertion_ind;
-
- if (alternate_form && fmt_spec == 'o'
- // unless zero is already the first character
- && !(zero_padding_insertion_ind < str_arg_l
- && tmp[zero_padding_insertion_ind] == '0')) {
- // assure leading zero for alternate-form octal numbers
- if (!precision_specified
- || precision < num_of_digits + 1) {
- // precision is increased to force the first character to be zero,
- // except if a zero value is formatted with an explicit precision
- // of zero
- precision = num_of_digits + 1;
- }
- }
- // zero padding to specified precision?
- if (num_of_digits < precision)
- number_of_zeros_to_pad = precision - num_of_digits;
- }
- // zero padding to specified minimal field width?
- if (!justify_left && zero_padding) {
- int n = (int)(min_field_width - (str_arg_l
- + number_of_zeros_to_pad));
- if (n > 0)
- number_of_zeros_to_pad += n;
- }
- break;
- }
-
- case 'f':
- case 'e':
- case 'E':
- case 'g':
- case 'G':
- {
- // floating point
- char format[40];
- int l;
- int remove_trailing_zeroes = false;
-
- double f = tvs ? tv_float(tvs, &arg_idx) : va_arg(ap, double);
- double abs_f = f < 0 ? -f : f;
-
- if (fmt_spec == 'g' || fmt_spec == 'G') {
- // can't use %g directly, cause it prints "1.0" as "1"
- if ((abs_f >= 0.001 && abs_f < 10000000.0) || abs_f == 0.0)
- fmt_spec = 'f';
- else
- fmt_spec = fmt_spec == 'g' ? 'e' : 'E';
- remove_trailing_zeroes = true;
- }
-
- if (fmt_spec == 'f' && abs_f > 1.0e307) {
- // avoid a buffer overflow
- strcpy(tmp, "inf");
- str_arg_l = 3;
- } else {
- format[0] = '%';
- l = 1;
- if (precision_specified) {
- size_t max_prec = TMP_LEN - 10;
-
- // make sure we don't get more digits than we have room for
- if (fmt_spec == 'f' && abs_f > 1.0)
- max_prec -= (size_t)log10(abs_f);
- if (precision > max_prec)
- precision = max_prec;
- l += sprintf(format + 1, ".%d", (int)precision);
- }
- format[l] = fmt_spec;
- format[l + 1] = NUL;
- str_arg_l = sprintf(tmp, format, f);
-
- if (remove_trailing_zeroes) {
- int i;
- char *tp;
-
- // using %g or %G: remove superfluous zeroes
- if (fmt_spec == 'f')
- tp = tmp + str_arg_l - 1;
- else {
- tp = (char *)vim_strchr((char_u *)tmp,
- fmt_spec == 'e' ? 'e' : 'E');
- if (tp) {
- // remove superfluous '+' and leading zeroes from exponent
- if (tp[1] == '+') {
- // change "1.0e+07" to "1.0e07"
- STRMOVE(tp + 1, tp + 2);
- --str_arg_l;
- }
- i = (tp[1] == '-') ? 2 : 1;
- while (tp[i] == '0') {
- // change "1.0e07" to "1.0e7"
- STRMOVE(tp + i, tp + i + 1);
- --str_arg_l;
- }
- --tp;
- }
- }
-
- if (tp != NULL && !precision_specified)
- // remove trailing zeroes, but keep the one just after a dot
- while (tp > tmp + 2 && *tp == '0' && tp[-1] != '.') {
- STRMOVE(tp, tp + 1);
- --tp;
- --str_arg_l;
- }
- } else {
- // be consistent: some printf("%e") use 1.0e+12 and some 1.0e+012;
- // remove one zero in the last case
- char *tp = (char *)vim_strchr((char_u *)tmp,
- fmt_spec == 'e' ? 'e' : 'E');
- if (tp && (tp[1] == '+' || tp[1] == '-') && tp[2] == '0'
- && ascii_isdigit(tp[3]) && ascii_isdigit(tp[4])) {
- STRMOVE(tp + 2, tp + 3);
- --str_arg_l;
- }
- }
- }
- str_arg = tmp;
- break;
- }
-
- default:
- // unrecognized conversion specifier, keep format string as-is
- zero_padding = 0; // turn zero padding off for non-numeric conversion
- justify_left = 1;
- min_field_width = 0; // reset flags
-
- // discard the unrecognized conversion, just keep
- // the unrecognized conversion character
- str_arg = p;
- str_arg_l = 0;
- if (*p)
- str_arg_l++; // include invalid conversion specifier
- // unchanged if not at end-of-string
- break;
- }
-
- if (*p)
- p++; // step over the just processed conversion specifier
-
- // insert padding to the left as requested by min_field_width;
- // this does not include the zero padding in case of numerical conversions
- if (!justify_left) {
- assert(str_arg_l <= SIZE_MAX - number_of_zeros_to_pad);
- if (min_field_width > str_arg_l + number_of_zeros_to_pad) {
- // left padding with blank or zero
- size_t pn = min_field_width - (str_arg_l + number_of_zeros_to_pad);
- if (str_avail) {
- size_t avail = str_m - str_l;
- memset(str + str_l, zero_padding ? '0' : ' ', MIN(pn, avail));
- str_avail = pn < avail;
- }
- assert(pn <= SIZE_MAX - str_l);
- str_l += pn;
- }
- }
-
- // zero padding as requested by the precision or by the minimal
- // field width for numeric conversions required?
- if (number_of_zeros_to_pad == 0) {
- // will not copy first part of numeric right now,
- // force it to be copied later in its entirety
- zero_padding_insertion_ind = 0;
- } else {
- // insert first part of numerics (sign or '0x') before zero padding
- if (zero_padding_insertion_ind > 0) {
- size_t zn = zero_padding_insertion_ind;
- if (str_avail) {
- size_t avail = str_m - str_l;
- memmove(str + str_l, str_arg, MIN(zn, avail));
- str_avail = zn < avail;
- }
- assert(zn <= SIZE_MAX - str_l);
- str_l += zn;
- }
-
- // insert zero padding as requested by precision or min field width
- if (number_of_zeros_to_pad > 0) {
- size_t zn = number_of_zeros_to_pad;
- if (str_avail) {
- size_t avail = str_m - str_l;
- memset(str + str_l, '0', MIN(zn, avail));
- str_avail = zn < avail;
- }
- assert(zn <= SIZE_MAX - str_l);
- str_l += zn;
- }
- }
-
- // insert formatted string
- // (or as-is conversion specifier for unknown conversions)
- if (str_arg_l > zero_padding_insertion_ind) {
- size_t sn = str_arg_l - zero_padding_insertion_ind;
- if (str_avail) {
- size_t avail = str_m - str_l;
- memmove(str + str_l,
- str_arg + zero_padding_insertion_ind,
- MIN(sn, avail));
- str_avail = sn < avail;
- }
- assert(sn <= SIZE_MAX - str_l);
- str_l += sn;
- }
-
- // insert right padding
- if (justify_left) {
- assert(str_arg_l <= SIZE_MAX - number_of_zeros_to_pad);
- if (min_field_width > str_arg_l + number_of_zeros_to_pad) {
- // right blank padding to the field width
- size_t pn = min_field_width - (str_arg_l + number_of_zeros_to_pad);
- if (str_avail) {
- size_t avail = str_m - str_l;
- memset(str + str_l, ' ', MIN(pn, avail));
- str_avail = pn < avail;
- }
- assert(pn <= SIZE_MAX - str_l);
- str_l += pn;
- }
- }
- }
- }
-
- if (str_m > 0) {
- // make sure the string is nul-terminated even at the expense of
- // overwriting the last character (shouldn't happen, but just in case)
- str[str_l <= str_m - 1 ? str_l : str_m - 1] = '\0';
- }
-
- if (tvs && tvs[arg_idx - 1].v_type != VAR_UNKNOWN)
- EMSG(_("E767: Too many arguments to printf()"));
-
- // return the number of characters formatted (excluding trailing nul
- // character); that is, the number of characters that would have been
- // written to the buffer if it were large enough.
- return (int)str_l;
-}
diff --git a/src/nvim/message.h b/src/nvim/message.h
index d3a16fff93..904a9d3ca1 100644
--- a/src/nvim/message.h
+++ b/src/nvim/message.h
@@ -3,8 +3,9 @@
#include <stdbool.h>
#include <stdarg.h>
-#include "nvim/eval_defs.h" // for typval_T
-#include "nvim/ex_cmds_defs.h" // for exarg_T
+#include <stddef.h>
+
+#include "nvim/types.h"
/*
* Types of dialogs passed to do_dialog().
@@ -29,7 +30,7 @@
#define MSG(s) msg((char_u *)(s))
/// Show message highlighted according to the attr
-#define MSG_ATTR(s, attr) msg_attr((char_u *)(s), (attr))
+#define MSG_ATTR(s, attr) msg_attr((const char *)(s), (attr))
/// Display error message
///
@@ -49,13 +50,13 @@
#define EMSGU(s, n) emsgf((const char *) (s), (uint64_t)(n))
/// Display message at the recorded position
-#define MSG_PUTS(s) msg_puts((char_u *)(s))
+#define MSG_PUTS(s) msg_puts((const char *)(s))
/// Display message at the recorded position, highlighted
-#define MSG_PUTS_ATTR(s, a) msg_puts_attr((char_u *)(s), (a))
+#define MSG_PUTS_ATTR(s, a) msg_puts_attr((const char *)(s), (a))
/// Like #MSG_PUTS, but highlight like title
-#define MSG_PUTS_TITLE(s) msg_puts_title((char_u *)(s))
+#define MSG_PUTS_TITLE(s) msg_puts_title((const char *)(s))
/// Like #MSG_PUTS, but if middle part of too long messages it will be replaced
#define MSG_PUTS_LONG(s) msg_puts_long_attr((char_u *)(s), 0)
diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c
index ba26381e23..db34159f24 100644
--- a/src/nvim/misc1.c
+++ b/src/nvim/misc1.c
@@ -2223,7 +2223,7 @@ change_warning (
*
* return the 'y' or 'n'
*/
-int ask_yesno(char_u *str, int direct)
+int ask_yesno(const char *str, bool direct)
{
int r = ' ';
int save_State = State;
@@ -2545,7 +2545,7 @@ void vim_beep(unsigned val)
* function give the user a hint where the beep comes from. */
if (vim_strchr(p_debug, 'e') != NULL) {
msg_source(hl_attr(HLF_W));
- msg_attr((char_u *)_("Beep!"), hl_attr(HLF_W));
+ msg_attr(_("Beep!"), hl_attr(HLF_W));
}
}
}
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index c2218d58be..756053dc73 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -617,7 +617,7 @@ static void normal_redraw_mode_message(NormalState *s)
update_screen(0);
// now reset it, otherwise it's put in the history again
keep_msg = kmsg;
- msg_attr(kmsg, keep_msg_attr);
+ msg_attr((const char *)kmsg, keep_msg_attr);
xfree(kmsg);
}
setcursor();
@@ -1276,7 +1276,7 @@ static void normal_redraw(NormalState *s)
// msg_attr_keep() will set keep_msg to NULL, must free the string here.
// Don't reset keep_msg, msg_attr_keep() uses it to check for duplicates.
char *p = (char *)keep_msg;
- msg_attr((uint8_t *)p, keep_msg_attr);
+ msg_attr(p, keep_msg_attr);
xfree(p);
}
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index d58c8700ca..8bfda3c193 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -1260,7 +1260,7 @@ int get_spec_reg(
/// Paste a yank register into the command line.
/// Only for non-special registers.
-/// Used by CTRL-R command in command-line mode
+/// Used by CTRL-R in command-line mode.
/// insert_reg() can't be used here, because special characters from the
/// register contents will be interpreted as commands.
///
@@ -1278,9 +1278,8 @@ bool cmdline_paste_reg(int regname, bool literally, bool remcr)
for (size_t i = 0; i < reg->y_size; i++) {
cmdline_paste_str(reg->y_array[i], literally);
- // Insert ^M between lines and after last line if type is kMTLineWise.
- // Don't do this when "remcr" is true.
- if ((reg->y_type == kMTLineWise || i < reg->y_size - 1) && !remcr) {
+ // Insert ^M between lines, unless `remcr` is true.
+ if (i < reg->y_size - 1 && !remcr) {
cmdline_paste_str((char_u *)"\r", literally);
}
diff --git a/src/nvim/option.c b/src/nvim/option.c
index a218323dac..e697ab3f51 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -2569,12 +2569,11 @@ did_set_string_option (
init_highlight(FALSE, FALSE);
- if (dark != (*p_bg == 'd')
- && get_var_value((char_u *)"g:colors_name") != NULL) {
- /* 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);
+ if (dark != (*p_bg == 'd') && get_var_value("g:colors_name") != NULL) {
+ // 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);
free_string_option(p_bg);
p_bg = vim_strsave((char_u *)(dark ? "dark" : "light"));
check_string_option(&p_bg);
@@ -3886,7 +3885,7 @@ set_bool_option (
"W17: Arabic requires UTF-8, do ':set encoding=utf-8'");
msg_source(hl_attr(HLF_W));
- MSG_ATTR(_(w_arabic), hl_attr(HLF_W));
+ msg_attr(_(w_arabic), hl_attr(HLF_W));
set_vim_var_string(VV_WARNINGMSG, _(w_arabic), -1);
}
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index 32021da922..602497461d 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -411,7 +411,6 @@ EXTERN char_u *p_efm; // 'errorformat'
EXTERN char_u *p_gefm; // 'grepformat'
EXTERN char_u *p_gp; // 'grepprg'
EXTERN char_u *p_ei; // 'eventignore'
-EXTERN int p_ek; // 'esckeys'
EXTERN int p_exrc; // 'exrc'
EXTERN char_u *p_fencs; // 'fileencodings'
EXTERN char_u *p_ffs; // 'fileformats'
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index fd68d1cde0..4130e69858 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -711,13 +711,6 @@ return {
defaults={if_true={vi=macros('DFLT_EFM')}}
},
{
- full_name='esckeys', abbreviation='ek',
- type='bool', scope={'global'},
- vim=true,
- varname='p_ek',
- defaults={if_true={vi=false, vim=true}}
- },
- {
full_name='eventignore', abbreviation='ei',
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
diff --git a/src/nvim/pos.h b/src/nvim/pos.h
index 864f3fe866..966255e6a4 100644
--- a/src/nvim/pos.h
+++ b/src/nvim/pos.h
@@ -2,6 +2,8 @@
#define NVIM_POS_H
typedef long linenr_T; // line number type
+/// Format used to print values which have linenr_T type
+#define PRIdLINENR "ld"
/// Column number type
typedef int colnr_T;
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index c40403e3f6..0da98713df 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -2068,21 +2068,20 @@ void qf_list(exarg_T *eap)
if (qfp->qf_lnum == 0) {
IObuff[0] = NUL;
} else if (qfp->qf_col == 0) {
- vim_snprintf((char *)IObuff, IOSIZE, ":%" PRId64,
- (int64_t)qfp->qf_lnum);
+ vim_snprintf((char *)IObuff, IOSIZE, ":%" PRIdLINENR, qfp->qf_lnum);
} else {
- vim_snprintf((char *)IObuff, IOSIZE, ":%" PRId64 " col %d",
- (int64_t)qfp->qf_lnum, qfp->qf_col);
+ vim_snprintf((char *)IObuff, IOSIZE, ":%" PRIdLINENR " col %d",
+ qfp->qf_lnum, qfp->qf_col);
}
vim_snprintf((char *)IObuff + STRLEN(IObuff), IOSIZE, "%s:",
(char *)qf_types(qfp->qf_type, qfp->qf_nr));
- msg_puts_attr(IObuff, hl_attr(HLF_N));
+ msg_puts_attr((const char *)IObuff, hl_attr(HLF_N));
if (qfp->qf_pattern != NULL) {
qf_fmt_text(qfp->qf_pattern, IObuff, IOSIZE);
- STRCAT(IObuff, ":");
- msg_puts(IObuff);
+ xstrlcat((char *)IObuff, ":", IOSIZE);
+ msg_puts((const char *)IObuff);
}
- msg_puts((char_u *)" ");
+ msg_puts(" ");
/* Remove newlines and leading whitespace from the text. For an
* unrecognized line keep the indent, the compiler may mark a word
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 3823fb2a23..6df443754b 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -6719,17 +6719,19 @@ int showmode(void)
if (edit_submode_pre != NULL)
length -= vim_strsize(edit_submode_pre);
if (length - vim_strsize(edit_submode) > 0) {
- if (edit_submode_pre != NULL)
- msg_puts_attr(edit_submode_pre, attr);
- msg_puts_attr(edit_submode, attr);
+ if (edit_submode_pre != NULL) {
+ msg_puts_attr((const char *)edit_submode_pre, attr);
+ }
+ msg_puts_attr((const char *)edit_submode, attr);
}
if (edit_submode_extra != NULL) {
- MSG_PUTS_ATTR(" ", attr); /* add a space in between */
- if ((int)edit_submode_highl < (int)HLF_COUNT)
+ MSG_PUTS_ATTR(" ", attr); // Add a space in between.
+ if ((int)edit_submode_highl < (int)HLF_COUNT) {
sub_attr = hl_attr(edit_submode_highl);
- else
+ } else {
sub_attr = attr;
- msg_puts_attr(edit_submode_extra, sub_attr);
+ }
+ msg_puts_attr((const char *)edit_submode_extra, sub_attr);
}
}
} else {
diff --git a/src/nvim/search.c b/src/nvim/search.c
index 2a087276e7..a9766a406e 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -4656,12 +4656,12 @@ static void show_pat_in_path(char_u *line, int type, int did_show, int action, F
*(p + 1) = NUL;
}
if (action == ACTION_SHOW_ALL) {
- sprintf((char *)IObuff, "%3ld: ", count); /* show match nr */
- msg_puts(IObuff);
- sprintf((char *)IObuff, "%4ld", *lnum); /* show line nr */
- /* Highlight line numbers */
- msg_puts_attr(IObuff, hl_attr(HLF_N));
- MSG_PUTS(" ");
+ snprintf((char *)IObuff, IOSIZE, "%3ld: ", count); // Show match nr.
+ msg_puts((const char *)IObuff);
+ snprintf((char *)IObuff, IOSIZE, "%4ld", *lnum); // Show line nr.
+ // Highlight line numbers.
+ msg_puts_attr((const char *)IObuff, hl_attr(HLF_N));
+ msg_puts(" ");
}
msg_prt_line(line, FALSE);
ui_flush(); /* show one line at a time */
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 1ace39344d..dea09cd633 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -3094,10 +3094,11 @@ count_common_word (
}
hash = hash_hash(p);
- hi = hash_lookup(&lp->sl_wordcount, p, hash);
+ const size_t p_len = STRLEN(p);
+ hi = hash_lookup(&lp->sl_wordcount, (const char *)p, p_len, hash);
if (HASHITEM_EMPTY(hi)) {
- wc = xmalloc(sizeof(wordcount_T) + STRLEN(p));
- STRCPY(wc->wc_word, p);
+ wc = xmalloc(sizeof(wordcount_T) + p_len);
+ memcpy(wc->wc_word, p, p_len + 1);
wc->wc_count = count;
hash_add_item(&lp->sl_wordcount, hi, wc->wc_word, hash);
} else {
@@ -5513,7 +5514,7 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
}
hash = hash_hash(dw);
- hi = hash_lookup(&ht, dw, hash);
+ hi = hash_lookup(&ht, (const char *)dw, STRLEN(dw), hash);
if (!HASHITEM_EMPTY(hi)) {
if (p_verbose > 0)
smsg(_("Duplicate word in %s line %d: %s"),
@@ -6343,7 +6344,7 @@ static int tree_add_word(spellinfo_T *spin, char_u *word, wordnode_T *root, int
if (spin->si_verbose) {
msg_start();
- msg_puts((char_u *)_(msg_compressing));
+ msg_puts(_(msg_compressing));
msg_clr_eos();
msg_didout = FALSE;
msg_col = 0;
@@ -6519,7 +6520,8 @@ node_compress (
// Try to find an identical child.
hash = hash_hash(child->wn_u1.hashkey);
- hi = hash_lookup(ht, child->wn_u1.hashkey, hash);
+ hi = hash_lookup(ht, (const char *)child->wn_u1.hashkey,
+ STRLEN(child->wn_u1.hashkey), hash);
if (!HASHITEM_EMPTY(hi)) {
// There are children we encountered before with a hash value
// identical to the current child. Now check if there is one
@@ -8515,7 +8517,7 @@ void spell_suggest(int count)
vim_snprintf((char *)IObuff, IOSIZE, ":ot \"%.*s\" egnahC",
sug.su_badlen, sug.su_badptr);
}
- msg_puts(IObuff);
+ msg_puts((const char *)IObuff);
msg_clr_eos();
msg_putchar('\n');
@@ -8531,18 +8533,19 @@ void spell_suggest(int count)
sug.su_badptr + stp->st_orglen,
sug.su_badlen - stp->st_orglen + 1);
vim_snprintf((char *)IObuff, IOSIZE, "%2d", i + 1);
- if (cmdmsg_rl)
+ if (cmdmsg_rl) {
rl_mirror(IObuff);
- msg_puts(IObuff);
+ }
+ msg_puts((const char *)IObuff);
vim_snprintf((char *)IObuff, IOSIZE, " \"%s\"", wcopy);
- msg_puts(IObuff);
+ msg_puts((const char *)IObuff);
// The word may replace more than "su_badlen".
if (sug.su_badlen < stp->st_orglen) {
vim_snprintf((char *)IObuff, IOSIZE, _(" < \"%.*s\""),
- stp->st_orglen, sug.su_badptr);
- msg_puts(IObuff);
+ stp->st_orglen, sug.su_badptr);
+ msg_puts((const char *)IObuff);
}
if (p_verbose > 0) {
@@ -8558,7 +8561,7 @@ void spell_suggest(int count)
// Mirror the numbers, but keep the leading space.
rl_mirror(IObuff + 1);
msg_advance(30);
- msg_puts(IObuff);
+ msg_puts((const char *)IObuff);
}
msg_putchar('\n');
}
@@ -11182,11 +11185,13 @@ add_sound_suggest (
// the words that have a better score than before. Use a hashtable to
// remember the words that have been done.
hash = hash_hash(goodword);
- hi = hash_lookup(&slang->sl_sounddone, goodword, hash);
+ const size_t goodword_len = STRLEN(goodword);
+ hi = hash_lookup(&slang->sl_sounddone, (const char *)goodword, goodword_len,
+ hash);
if (HASHITEM_EMPTY(hi)) {
- sft = xmalloc(sizeof(sftword_T) + STRLEN(goodword));
+ sft = xmalloc(sizeof(sftword_T) + goodword_len);
sft->sft_score = score;
- STRCPY(sft->sft_word, goodword);
+ memcpy(sft->sft_word, goodword, goodword_len + 1);
hash_add_item(&slang->sl_sounddone, hi, sft->sft_word, hash);
} else {
sft = HI2SFT(hi);
@@ -11453,10 +11458,10 @@ static void set_map_str(slang_T *lp, char_u *map)
mb_char2bytes(headc, b + cl + 1);
b[cl + 1 + headcl] = NUL;
hash = hash_hash(b);
- hi = hash_lookup(&lp->sl_map_hash, b, hash);
- if (HASHITEM_EMPTY(hi))
+ hi = hash_lookup(&lp->sl_map_hash, (const char *)b, STRLEN(b), hash);
+ if (HASHITEM_EMPTY(hi)) {
hash_add_item(&lp->sl_map_hash, hi, b, hash);
- else {
+ } else {
// This should have been checked when generating the .spl
// file.
EMSG(_("E783: duplicate char in MAP entry"));
@@ -11661,9 +11666,10 @@ static void add_banned(suginfo_T *su, char_u *word)
hashitem_T *hi;
hash = hash_hash(word);
- hi = hash_lookup(&su->su_banned, word, hash);
+ const size_t word_len = STRLEN(word);
+ hi = hash_lookup(&su->su_banned, (const char *)word, word_len, hash);
if (HASHITEM_EMPTY(hi)) {
- s = vim_strsave(word);
+ s = xmemdupz(word, word_len);
hash_add_item(&su->su_banned, hi, s, hash);
}
}
@@ -12995,19 +13001,17 @@ pop:
// ":spellinfo"
void ex_spellinfo(exarg_T *eap)
{
- langp_T *lp;
- char_u *p;
-
- if (no_spell_checking(curwin))
+ if (no_spell_checking(curwin)) {
return;
+ }
msg_start();
- for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len && !got_int; ++lpi) {
- lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
- msg_puts((char_u *)"file: ");
- msg_puts(lp->lp_slang->sl_fname);
+ for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len && !got_int; lpi++) {
+ langp_T *const lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
+ msg_puts("file: ");
+ msg_puts((const char *)lp->lp_slang->sl_fname);
msg_putchar('\n');
- p = lp->lp_slang->sl_info;
+ const char *const p = (const char *)lp->lp_slang->sl_info;
if (p != NULL) {
msg_puts(p);
msg_putchar('\n');
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index b38d4f8a58..f7218cc267 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -1,7 +1,11 @@
#include <inttypes.h>
+#include <stdarg.h>
#include <stdbool.h>
#include <string.h>
+#include <math.h>
+#include <assert.h>
+#include "nvim/assert.h"
#include "nvim/vim.h"
#include "nvim/ascii.h"
#include "nvim/strings.h"
@@ -541,3 +545,847 @@ char_u *concat_str(const char_u *restrict str1, const char_u *restrict str2)
return dest;
}
+
+static const char *const e_printf =
+ N_("E766: Insufficient arguments for printf()");
+
+/// Get number argument from idxp entry in tvs
+///
+/// Will give an error message for VimL entry with invalid type or for
+/// insufficient entries.
+///
+/// @param[in] tvs List of VimL values. List is terminated by VAR_UNKNOWN
+/// value.
+/// @param[in,out] idxp Index in a list. Will be incremented. Indexing starts
+/// at 1.
+///
+/// @return Number value or 0 in case of error.
+static varnumber_T tv_nr(typval_T *tvs, int *idxp)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ int idx = *idxp - 1;
+ varnumber_T n = 0;
+
+ if (tvs[idx].v_type == VAR_UNKNOWN) {
+ EMSG(_(e_printf));
+ } else {
+ (*idxp)++;
+ int err = false;
+ n = (varnumber_T)get_tv_number_chk(&tvs[idx], &err);
+ if (err) {
+ n = 0;
+ }
+ }
+ return n;
+}
+
+/// Get string argument from idxp entry in tvs
+///
+/// Will give an error message for VimL entry with invalid type or for
+/// insufficient entries.
+///
+/// @param[in] tvs List of VimL values. List is terminated by VAR_UNKNOWN
+/// value.
+/// @param[in,out] idxp Index in a list. Will be incremented.
+///
+/// @return String value or NULL in case of error.
+static char *tv_str(typval_T *tvs, int *idxp)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ int idx = *idxp - 1;
+ char *s = NULL;
+
+ if (tvs[idx].v_type == VAR_UNKNOWN) {
+ EMSG(_(e_printf));
+ } else {
+ (*idxp)++;
+ s = (char *)get_tv_string_chk(&tvs[idx]);
+ }
+ return s;
+}
+
+/// Get pointer argument from the next entry in tvs
+///
+/// Will give an error message for VimL entry with invalid type or for
+/// insufficient entries.
+///
+/// @param[in] tvs List of typval_T values.
+/// @param[in,out] idxp Pointer to the index of the current value.
+///
+/// @return Pointer stored in typval_T or NULL.
+static const void *tv_ptr(const typval_T *const tvs, int *const idxp)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+{
+#define OFF(attr) offsetof(union typval_vval_union, attr)
+ STATIC_ASSERT(
+ OFF(v_string) == OFF(v_list)
+ && OFF(v_string) == OFF(v_dict)
+ && OFF(v_string) == OFF(v_partial)
+ && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_list)
+ && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_dict)
+ && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_partial),
+ "Strings, dictionaries, lists and partials are expected to be pointers, "
+ "so that all three of them can be accessed via v_string");
+#undef OFF
+ const int idx = *idxp - 1;
+ if (tvs[idx].v_type == VAR_UNKNOWN) {
+ EMSG(_(e_printf));
+ return NULL;
+ } else {
+ (*idxp)++;
+ return tvs[idx].vval.v_string;
+ }
+}
+
+/// Get float argument from idxp entry in tvs
+///
+/// Will give an error message for VimL entry with invalid type or for
+/// insufficient entries.
+///
+/// @param[in] tvs List of VimL values. List is terminated by VAR_UNKNOWN
+/// value.
+/// @param[in,out] idxp Index in a list. Will be incremented.
+///
+/// @return Floating-point value or zero in case of error.
+static float_T tv_float(typval_T *const tvs, int *const idxp)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ int idx = *idxp - 1;
+ float_T f = 0;
+
+ if (tvs[idx].v_type == VAR_UNKNOWN) {
+ EMSG(_(e_printf));
+ } else {
+ (*idxp)++;
+ if (tvs[idx].v_type == VAR_FLOAT) {
+ f = tvs[idx].vval.v_float;
+ } else if (tvs[idx].v_type == VAR_NUMBER) {
+ f = tvs[idx].vval.v_number;
+ } else {
+ EMSG(_("E807: Expected Float argument for printf()"));
+ }
+ }
+ return f;
+}
+
+// This code was included to provide a portable vsnprintf() and snprintf().
+// Some systems may provide their own, but we always use this one for
+// consistency.
+//
+// This code is based on snprintf.c - a portable implementation of snprintf
+// by Mark Martinec <mark.martinec@ijs.si>, Version 2.2, 2000-10-06.
+// Included with permission. It was heavily modified to fit in Vim.
+// The original code, including useful comments, can be found here:
+//
+// http://www.ijs.si/software/snprintf/
+//
+// This snprintf() only supports the following conversion specifiers:
+// s, c, b, B, d, u, o, x, X, p (and synonyms: i, D, U, O - see below)
+// with flags: '-', '+', ' ', '0' and '#'.
+// An asterisk is supported for field width as well as precision.
+//
+// Limited support for floating point was added: 'f', 'e', 'E', 'g', 'G'.
+//
+// Length modifiers 'h' (short int), 'l' (long int) and "ll" (long long int) are
+// supported.
+//
+// The locale is not used, the string is used as a byte string. This is only
+// relevant for double-byte encodings where the second byte may be '%'.
+//
+// It is permitted for "str_m" to be zero, and it is permitted to specify NULL
+// pointer for resulting string argument if "str_m" is zero (as per ISO C99).
+//
+// The return value is the number of characters which would be generated
+// for the given input, excluding the trailing NUL. If this value
+// is greater or equal to "str_m", not all characters from the result
+// have been stored in str, output bytes beyond the ("str_m"-1) -th character
+// are discarded. If "str_m" is greater than zero it is guaranteed
+// the resulting string will be NUL-terminated.
+
+// vim_vsnprintf() can be invoked with either "va_list" or a list of
+// "typval_T". When the latter is not used it must be NULL.
+
+/// Append a formatted value to the string
+///
+/// @see vim_vsnprintf().
+int vim_snprintf_add(char *str, size_t str_m, char *fmt, ...)
+{
+ const size_t len = strlen(str);
+ size_t space;
+
+ if (str_m <= len) {
+ space = 0;
+ } else {
+ space = str_m - len;
+ }
+ va_list ap;
+ va_start(ap, fmt);
+ const int str_l = vim_vsnprintf(str + len, space, fmt, ap, NULL);
+ va_end(ap);
+ return str_l;
+}
+
+/// Write formatted value to the string
+///
+/// @param[out] str String to write to.
+/// @param[in] str_m String length.
+/// @param[in] fmt String format.
+///
+/// @return Number of bytes excluding NUL byte that would be written to the
+/// string if str_m was greater or equal to the return value.
+int vim_snprintf(char *str, size_t str_m, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ const int str_l = vim_vsnprintf(str, str_m, fmt, ap, NULL);
+ va_end(ap);
+ return str_l;
+}
+
+
+/// Write formatted value to the string
+///
+/// @param[out] str String to write to.
+/// @param[in] str_m String length.
+/// @param[in] fmt String format.
+/// @param[in] ap Values that should be formatted. Ignored if tvs is not NULL.
+/// @param[in] tvs Values that should be formatted, for printf() VimL
+/// function. Must be NULL in other cases.
+///
+/// @return Number of bytes excluding NUL byte that would be written to the
+/// string if str_m was greater or equal to the return value.
+int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap,
+ typval_T *const tvs)
+{
+ size_t str_l = 0;
+ bool str_avail = str_l < str_m;
+ const char *p = fmt;
+ int arg_idx = 1;
+
+ if (!p) {
+ p = "";
+ }
+ while (*p) {
+ if (*p != '%') {
+ // copy up to the next '%' or NUL without any changes
+ size_t n = (size_t)(xstrchrnul(p + 1, '%') - p);
+ if (str_avail) {
+ size_t avail = str_m - str_l;
+ memmove(str + str_l, p, MIN(n, avail));
+ str_avail = n < avail;
+ }
+ p += n;
+ assert(n <= SIZE_MAX - str_l);
+ str_l += n;
+ } else {
+ size_t min_field_width = 0, precision = 0;
+ int zero_padding = 0, precision_specified = 0, justify_left = 0;
+ int alternate_form = 0, force_sign = 0;
+
+ // if both ' ' and '+' flags appear, ' ' flag should be ignored
+ int space_for_positive = 1;
+
+ // allowed values: \0, h, l, 2 (for ll), z, L
+ char length_modifier = '\0';
+
+ // temporary buffer for simple numeric->string conversion
+# define TMP_LEN 350 // 1e308 seems reasonable as the maximum printable
+ char tmp[TMP_LEN];
+
+ // string address in case of string argument
+ const char *str_arg = NULL;
+
+ // natural field width of arg without padding and sign
+ size_t str_arg_l;
+
+ // unsigned char argument value (only defined for c conversion);
+ // standard explicitly states the char argument for the c
+ // conversion is unsigned
+ unsigned char uchar_arg;
+
+ // number of zeros to be inserted for numeric conversions as
+ // required by the precision or minimal field width
+ size_t number_of_zeros_to_pad = 0;
+
+ // index into tmp where zero padding is to be inserted
+ size_t zero_padding_insertion_ind = 0;
+
+ // current conversion specifier character
+ char fmt_spec = '\0';
+
+ p++; // skip '%'
+
+ // parse flags
+ while (true) {
+ switch (*p) {
+ case '0': zero_padding = 1; p++; continue;
+ case '-': justify_left = 1; p++; continue;
+ // if both '0' and '-' flags appear, '0' should be ignored
+ case '+': force_sign = 1; space_for_positive = 0; p++; continue;
+ case ' ': force_sign = 1; p++; continue;
+ // if both ' ' and '+' flags appear, ' ' should be ignored
+ case '#': alternate_form = 1; p++; continue;
+ case '\'': p++; continue;
+ default: break;
+ }
+ break;
+ }
+
+ // parse field width
+ if (*p == '*') {
+ p++;
+ const int j = tvs ? (int)tv_nr(tvs, &arg_idx) : va_arg(ap, int);
+ if (j >= 0) {
+ min_field_width = (size_t)j;
+ } else {
+ min_field_width = (size_t)-j;
+ justify_left = 1;
+ }
+ } else if (ascii_isdigit((int)(*p))) {
+ // size_t could be wider than unsigned int; make sure we treat
+ // argument like common implementations do
+ unsigned int uj = (unsigned)(*p++ - '0');
+
+ while (ascii_isdigit((int)(*p))) {
+ uj = 10 * uj + (unsigned int)(*p++ - '0');
+ }
+ min_field_width = uj;
+ }
+
+ // parse precision
+ if (*p == '.') {
+ p++;
+ precision_specified = 1;
+ if (*p == '*') {
+ const int j = tvs ? (int)tv_nr(tvs, &arg_idx) : va_arg(ap, int);
+ p++;
+ if (j >= 0) {
+ precision = (size_t)j;
+ } else {
+ precision_specified = 0;
+ precision = 0;
+ }
+ } else if (ascii_isdigit((int)(*p))) {
+ // size_t could be wider than unsigned int; make sure we
+ // treat argument like common implementations do
+ unsigned int uj = (unsigned)(*p++ - '0');
+
+ while (ascii_isdigit((int)(*p))) {
+ uj = 10 * uj + (unsigned int)(*p++ - '0');
+ }
+ precision = uj;
+ }
+ }
+
+ // parse 'h', 'l', 'll' and 'z' length modifiers
+ if (*p == 'h' || *p == 'l' || *p == 'z') {
+ length_modifier = *p;
+ p++;
+ if (length_modifier == 'l' && *p == 'l') { // ll, encoded as 2
+ length_modifier = '2';
+ p++;
+ }
+ }
+
+ fmt_spec = *p;
+
+ // common synonyms
+ switch (fmt_spec) {
+ case 'i': fmt_spec = 'd'; break;
+ case 'D': fmt_spec = 'd'; length_modifier = 'l'; break;
+ case 'U': fmt_spec = 'u'; length_modifier = 'l'; break;
+ case 'O': fmt_spec = 'o'; length_modifier = 'l'; break;
+ case 'F': fmt_spec = 'f'; break;
+ default: break;
+ }
+
+ // get parameter value, do initial processing
+ switch (fmt_spec) {
+ // '%' and 'c' behave similar to 's' regarding flags and field widths
+ case '%': case 'c': case 's': case 'S':
+ str_arg_l = 1;
+ switch (fmt_spec) {
+ case '%':
+ str_arg = p;
+ break;
+
+ case 'c': {
+ const int j = tvs ? (int)tv_nr(tvs, &arg_idx) : va_arg(ap, int);
+ // standard demands unsigned char
+ uchar_arg = (unsigned char)j;
+ str_arg = (char *)&uchar_arg;
+ break;
+ }
+
+ case 's':
+ case 'S':
+ str_arg = tvs ? tv_str(tvs, &arg_idx) : va_arg(ap, char *);
+ if (!str_arg) {
+ str_arg = "[NULL]";
+ str_arg_l = 6;
+ } else if (!precision_specified) {
+ // make sure not to address string beyond the specified
+ // precision
+ str_arg_l = strlen(str_arg);
+ } else if (precision == 0) {
+ // truncate string if necessary as requested by precision
+ str_arg_l = 0;
+ } else {
+ // memchr on HP does not like n > 2^31
+ // TODO(elmart): check if this still holds / is relevant
+ str_arg_l = (size_t)((char *)xmemscan(str_arg,
+ NUL,
+ MIN(precision,
+ 0x7fffffff))
+ - str_arg);
+ }
+ if (fmt_spec == 'S') {
+ if (min_field_width != 0) {
+ min_field_width += (strlen(str_arg)
+ - mb_string2cells((char_u *)str_arg));
+ }
+ if (precision) {
+ const char *p1 = str_arg;
+ for (size_t i = 0; i < precision && *p1; i++) {
+ p1 += mb_ptr2len((const char_u *)p1);
+ }
+ str_arg_l = precision = (size_t)(p1 - str_arg);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case 'd':
+ case 'u':
+ case 'b': case 'B':
+ case 'o':
+ case 'x': case 'X':
+ case 'p': {
+ // u, b, B, o, x, X and p conversion specifiers imply
+ // the value is unsigned; d implies a signed value
+
+ // 0 if numeric argument is zero (or if pointer is NULL for 'p'),
+ // +1 if greater than zero (or non NULL for 'p'),
+ // -1 if negative (unsigned argument is never negative)
+ int arg_sign = 0;
+
+ intmax_t arg = 0;
+ uintmax_t uarg = 0;
+
+ // only defined for p conversion
+ const void *ptr_arg = NULL;
+
+ if (fmt_spec == 'p') {
+ length_modifier = '\0';
+ ptr_arg = tvs ? tv_ptr(tvs, &arg_idx) : va_arg(ap, void *);
+ if (ptr_arg) {
+ arg_sign = 1;
+ }
+ } else if (fmt_spec == 'd') {
+ // signed
+ switch (length_modifier) {
+ case '\0':
+ case 'h': {
+ // char and short arguments are passed as int
+ arg = (tvs ? (int)tv_nr(tvs, &arg_idx) : va_arg(ap, int));
+ break;
+ }
+ case 'l': {
+ arg = (tvs ? (long)tv_nr(tvs, &arg_idx) : va_arg(ap, long));
+ break;
+ }
+ case '2': {
+ arg = (
+ tvs
+ ? (long long)tv_nr(tvs, &arg_idx) // NOLINT (runtime/int)
+ : va_arg(ap, long long)); // NOLINT (runtime/int)
+ break;
+ }
+ case 'z': {
+ arg = (tvs
+ ? (ptrdiff_t)tv_nr(tvs, &arg_idx)
+ : va_arg(ap, ptrdiff_t));
+ break;
+ }
+ }
+ if (arg > 0) {
+ arg_sign = 1;
+ } else if (arg < 0) {
+ arg_sign = -1;
+ }
+ } else {
+ // unsigned
+ switch (length_modifier) {
+ case '\0':
+ case 'h': {
+ uarg = (tvs
+ ? (unsigned)tv_nr(tvs, &arg_idx)
+ : va_arg(ap, unsigned));
+ break;
+ }
+ case 'l': {
+ uarg = (tvs
+ ? (unsigned long)tv_nr(tvs, &arg_idx)
+ : va_arg(ap, unsigned long));
+ break;
+ }
+ case '2': {
+ uarg = (uintmax_t)(unsigned long long)( // NOLINT (runtime/int)
+ tvs
+ ? ((unsigned long long) // NOLINT (runtime/int)
+ tv_nr(tvs, &arg_idx))
+ : va_arg(ap, unsigned long long)); // NOLINT (runtime/int)
+ break;
+ }
+ case 'z': {
+ uarg = (tvs
+ ? (size_t)tv_nr(tvs, &arg_idx)
+ : va_arg(ap, size_t));
+ break;
+ }
+ }
+ arg_sign = (uarg != 0);
+ }
+
+ str_arg = tmp;
+ str_arg_l = 0;
+
+ // For d, i, u, o, x, and X conversions, if precision is specified,
+ // '0' flag should be ignored. This is so with Solaris 2.6, Digital
+ // UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl.
+ if (precision_specified) {
+ zero_padding = 0;
+ }
+
+ if (fmt_spec == 'd') {
+ if (force_sign && arg_sign >= 0) {
+ tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
+ }
+ // leave negative numbers for snprintf to handle, to
+ // avoid handling tricky cases like (short int)-32768
+ } else if (alternate_form) {
+ if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X'
+ || fmt_spec == 'b' || fmt_spec == 'B')) {
+ tmp[str_arg_l++] = '0';
+ tmp[str_arg_l++] = fmt_spec;
+ }
+ // alternate form should have no effect for p * conversion, but ...
+ }
+
+ zero_padding_insertion_ind = str_arg_l;
+ if (!precision_specified) {
+ precision = 1; // default precision is 1
+ }
+ if (precision == 0 && arg_sign == 0) {
+ // when zero value is formatted with an explicit precision 0,
+ // resulting formatted string is empty (d, i, u, b, B, o, x, X, p)
+ } else {
+ switch (fmt_spec) {
+ case 'p': { // pointer
+ str_arg_l += (size_t)snprintf(tmp + str_arg_l,
+ sizeof(tmp) - str_arg_l,
+ "%p", ptr_arg);
+ break;
+ }
+ case 'd': { // signed
+ str_arg_l += (size_t)snprintf(tmp + str_arg_l,
+ sizeof(tmp) - str_arg_l,
+ "%" PRIdMAX, arg);
+ break;
+ }
+ case 'b': case 'B': { // binary
+ size_t bits = 0;
+ for (bits = sizeof(uintmax_t) * 8; bits > 0; bits--) {
+ if ((uarg >> (bits - 1)) & 0x1) {
+ break;
+ }
+ }
+
+ while (bits > 0) {
+ tmp[str_arg_l++] = ((uarg >> --bits) & 0x1) ? '1' : '0';
+ }
+ break;
+ }
+ default: { // unsigned
+ // construct a simple format string for snprintf
+ char f[] = "%" PRIuMAX;
+ f[sizeof("%" PRIuMAX) - 1 - 1] = fmt_spec;
+ assert(PRIuMAX[sizeof(PRIuMAX) - 1 - 1] == 'u');
+ str_arg_l += (size_t)snprintf(tmp + str_arg_l,
+ sizeof(tmp) - str_arg_l,
+ f, uarg);
+ break;
+ }
+ assert(str_arg_l < sizeof(tmp));
+ }
+
+ // include the optional minus sign and possible "0x" in the region
+ // before the zero padding insertion point
+ if (zero_padding_insertion_ind < str_arg_l
+ && tmp[zero_padding_insertion_ind] == '-') {
+ zero_padding_insertion_ind++;
+ }
+ if (zero_padding_insertion_ind + 1 < str_arg_l
+ && tmp[zero_padding_insertion_ind] == '0'
+ && (tmp[zero_padding_insertion_ind + 1] == 'x'
+ || tmp[zero_padding_insertion_ind + 1] == 'X'
+ || tmp[zero_padding_insertion_ind + 1] == 'b'
+ || tmp[zero_padding_insertion_ind + 1] == 'B')) {
+ zero_padding_insertion_ind += 2;
+ }
+ }
+
+ {
+ size_t num_of_digits = str_arg_l - zero_padding_insertion_ind;
+
+ if (alternate_form && fmt_spec == 'o'
+ // unless zero is already the first character
+ && !(zero_padding_insertion_ind < str_arg_l
+ && tmp[zero_padding_insertion_ind] == '0')) {
+ // assure leading zero for alternate-form octal numbers
+ if (!precision_specified
+ || precision < num_of_digits + 1) {
+ // precision is increased to force the first character to be
+ // zero, except if a zero value is formatted with an explicit
+ // precision of zero
+ precision = num_of_digits + 1;
+ }
+ }
+ // zero padding to specified precision?
+ if (num_of_digits < precision) {
+ number_of_zeros_to_pad = precision - num_of_digits;
+ }
+ }
+ // zero padding to specified minimal field width?
+ if (!justify_left && zero_padding) {
+ const int n = (int)(min_field_width - (str_arg_l
+ + number_of_zeros_to_pad));
+ if (n > 0) {
+ number_of_zeros_to_pad += (size_t)n;
+ }
+ }
+ break;
+ }
+
+ case 'f':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ {
+ // floating point
+ char format[40];
+ int remove_trailing_zeroes = false;
+
+ double f = tvs ? tv_float(tvs, &arg_idx) : va_arg(ap, double);
+ double abs_f = f < 0 ? -f : f;
+
+ if (fmt_spec == 'g' || fmt_spec == 'G') {
+ // can't use %g directly, cause it prints "1.0" as "1"
+ if ((abs_f >= 0.001 && abs_f < 10000000.0) || abs_f == 0.0) {
+ fmt_spec = 'f';
+ } else {
+ fmt_spec = fmt_spec == 'g' ? 'e' : 'E';
+ }
+ remove_trailing_zeroes = true;
+ }
+
+ if (fmt_spec == 'f' && abs_f > 1.0e307) {
+ // avoid a buffer overflow
+ memmove(tmp, "inf", sizeof("inf"));
+ str_arg_l = sizeof("inf") - 1;
+ } else {
+ format[0] = '%';
+ int l = 1;
+ if (precision_specified) {
+ size_t max_prec = TMP_LEN - 10;
+
+ // make sure we don't get more digits than we have room for
+ if (fmt_spec == 'f' && abs_f > 1.0) {
+ max_prec -= (size_t)log10(abs_f);
+ }
+ if (precision > max_prec) {
+ precision = max_prec;
+ }
+ l += snprintf(format + 1, sizeof(format) - 1, ".%d",
+ (int)precision);
+ }
+ format[l] = fmt_spec;
+ format[l + 1] = NUL;
+ assert(l + 1 < (int)sizeof(format));
+ str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f);
+ assert(str_arg_l < sizeof(tmp));
+
+ if (remove_trailing_zeroes) {
+ int i;
+ char *tp;
+
+ // using %g or %G: remove superfluous zeroes
+ if (fmt_spec == 'f') {
+ tp = tmp + str_arg_l - 1;
+ } else {
+ tp = (char *)vim_strchr((char_u *)tmp,
+ fmt_spec == 'e' ? 'e' : 'E');
+ if (tp) {
+ // remove superfluous '+' and leading zeroes from exponent
+ if (tp[1] == '+') {
+ // change "1.0e+07" to "1.0e07"
+ STRMOVE(tp + 1, tp + 2);
+ str_arg_l--;
+ }
+ i = (tp[1] == '-') ? 2 : 1;
+ while (tp[i] == '0') {
+ // change "1.0e07" to "1.0e7"
+ STRMOVE(tp + i, tp + i + 1);
+ str_arg_l--;
+ }
+ tp--;
+ }
+ }
+
+ if (tp != NULL && !precision_specified) {
+ // remove trailing zeroes, but keep the one just after a dot
+ while (tp > tmp + 2 && *tp == '0' && tp[-1] != '.') {
+ STRMOVE(tp, tp + 1);
+ tp--;
+ str_arg_l--;
+ }
+ }
+ } else {
+ // Be consistent: some printf("%e") use 1.0e+12 and some
+ // 1.0e+012; remove one zero in the last case.
+ char *tp = (char *)vim_strchr((char_u *)tmp,
+ fmt_spec == 'e' ? 'e' : 'E');
+ if (tp && (tp[1] == '+' || tp[1] == '-') && tp[2] == '0'
+ && ascii_isdigit(tp[3]) && ascii_isdigit(tp[4])) {
+ STRMOVE(tp + 2, tp + 3);
+ str_arg_l--;
+ }
+ }
+ }
+ str_arg = tmp;
+ break;
+ }
+
+ default:
+ // unrecognized conversion specifier, keep format string as-is
+ zero_padding = 0; // turn zero padding off for non-numeric conversion
+ justify_left = 1;
+ min_field_width = 0; // reset flags
+
+ // discard the unrecognized conversion, just keep
+ // the unrecognized conversion character
+ str_arg = p;
+ str_arg_l = 0;
+ if (*p) {
+ str_arg_l++; // include invalid conversion specifier
+ }
+ // unchanged if not at end-of-string
+ break;
+ }
+
+ if (*p) {
+ p++; // step over the just processed conversion specifier
+ }
+
+ // insert padding to the left as requested by min_field_width;
+ // this does not include the zero padding in case of numerical conversions
+ if (!justify_left) {
+ assert(str_arg_l <= SIZE_MAX - number_of_zeros_to_pad);
+ if (min_field_width > str_arg_l + number_of_zeros_to_pad) {
+ // left padding with blank or zero
+ size_t pn = min_field_width - (str_arg_l + number_of_zeros_to_pad);
+ if (str_avail) {
+ size_t avail = str_m - str_l;
+ memset(str + str_l, zero_padding ? '0' : ' ', MIN(pn, avail));
+ str_avail = pn < avail;
+ }
+ assert(pn <= SIZE_MAX - str_l);
+ str_l += pn;
+ }
+ }
+
+ // zero padding as requested by the precision or by the minimal
+ // field width for numeric conversions required?
+ if (number_of_zeros_to_pad == 0) {
+ // will not copy first part of numeric right now,
+ // force it to be copied later in its entirety
+ zero_padding_insertion_ind = 0;
+ } else {
+ // insert first part of numerics (sign or '0x') before zero padding
+ if (zero_padding_insertion_ind > 0) {
+ size_t zn = zero_padding_insertion_ind;
+ if (str_avail) {
+ size_t avail = str_m - str_l;
+ memmove(str + str_l, str_arg, MIN(zn, avail));
+ str_avail = zn < avail;
+ }
+ assert(zn <= SIZE_MAX - str_l);
+ str_l += zn;
+ }
+
+ // insert zero padding as requested by precision or min field width
+ if (number_of_zeros_to_pad > 0) {
+ size_t zn = number_of_zeros_to_pad;
+ if (str_avail) {
+ size_t avail = str_m - str_l;
+ memset(str + str_l, '0', MIN(zn, avail));
+ str_avail = zn < avail;
+ }
+ assert(zn <= SIZE_MAX - str_l);
+ str_l += zn;
+ }
+ }
+
+ // insert formatted string
+ // (or as-is conversion specifier for unknown conversions)
+ if (str_arg_l > zero_padding_insertion_ind) {
+ size_t sn = str_arg_l - zero_padding_insertion_ind;
+ if (str_avail) {
+ size_t avail = str_m - str_l;
+ memmove(str + str_l,
+ str_arg + zero_padding_insertion_ind,
+ MIN(sn, avail));
+ str_avail = sn < avail;
+ }
+ assert(sn <= SIZE_MAX - str_l);
+ str_l += sn;
+ }
+
+ // insert right padding
+ if (justify_left) {
+ assert(str_arg_l <= SIZE_MAX - number_of_zeros_to_pad);
+ if (min_field_width > str_arg_l + number_of_zeros_to_pad) {
+ // right blank padding to the field width
+ size_t pn = min_field_width - (str_arg_l + number_of_zeros_to_pad);
+ if (str_avail) {
+ size_t avail = str_m - str_l;
+ memset(str + str_l, ' ', MIN(pn, avail));
+ str_avail = pn < avail;
+ }
+ assert(pn <= SIZE_MAX - str_l);
+ str_l += pn;
+ }
+ }
+ }
+ }
+
+ if (str_m > 0) {
+ // make sure the string is nul-terminated even at the expense of
+ // overwriting the last character (shouldn't happen, but just in case)
+ str[str_l <= str_m - 1 ? str_l : str_m - 1] = '\0';
+ }
+
+ if (tvs && tvs[arg_idx - 1].v_type != VAR_UNKNOWN) {
+ EMSG(_("E767: Too many arguments to printf()"));
+ }
+
+ // return the number of characters formatted (excluding trailing nul
+ // character); that is, the number of characters that would have been
+ // written to the buffer if it were large enough.
+ return (int)str_l;
+}
diff --git a/src/nvim/strings.h b/src/nvim/strings.h
index 3f0f0c8d6a..eb8b83c7d0 100644
--- a/src/nvim/strings.h
+++ b/src/nvim/strings.h
@@ -1,7 +1,12 @@
#ifndef NVIM_STRINGS_H
#define NVIM_STRINGS_H
+#include <stdarg.h>
#include <stdbool.h>
+#include <stddef.h>
+
+#include "nvim/types.h"
+#include "nvim/eval_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "strings.h.generated.h"
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 37e5542dad..0a27d9dd92 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -3576,22 +3576,24 @@ syn_list_one (
}
syn_list_flags(namelist1, spp->sp_flags, attr);
- if (spp->sp_cont_list != NULL)
- put_id_list((char_u *)"contains", spp->sp_cont_list, attr);
+ if (spp->sp_cont_list != NULL) {
+ put_id_list("contains", spp->sp_cont_list, attr);
+ }
- if (spp->sp_syn.cont_in_list != NULL)
- put_id_list((char_u *)"containedin",
- spp->sp_syn.cont_in_list, attr);
+ if (spp->sp_syn.cont_in_list != NULL) {
+ put_id_list("containedin", spp->sp_syn.cont_in_list, attr);
+ }
if (spp->sp_next_list != NULL) {
- put_id_list((char_u *)"nextgroup", spp->sp_next_list, attr);
+ put_id_list("nextgroup", spp->sp_next_list, attr);
syn_list_flags(namelist2, spp->sp_flags, attr);
}
if (spp->sp_flags & (HL_SYNC_HERE|HL_SYNC_THERE)) {
- if (spp->sp_flags & HL_SYNC_HERE)
- msg_puts_attr((char_u *)"grouphere", attr);
- else
- msg_puts_attr((char_u *)"groupthere", attr);
+ if (spp->sp_flags & HL_SYNC_HERE) {
+ msg_puts_attr("grouphere", attr);
+ } else {
+ msg_puts_attr("groupthere", attr);
+ }
msg_putchar(' ');
if (spp->sp_sync_idx >= 0)
msg_outtrans(HL_TABLE()[SYN_ITEMS(curwin->w_s)
@@ -3605,7 +3607,7 @@ syn_list_one (
/* list the link, if there is one */
if (HL_TABLE()[id - 1].sg_link && (did_header || link_only) && !got_int) {
(void)syn_list_header(did_header, 999, id);
- msg_puts_attr((char_u *)"links to", attr);
+ msg_puts_attr("links to", attr);
msg_putchar(' ');
msg_outtrans(HL_TABLE()[HL_TABLE()[id - 1].sg_link - 1].sg_name);
}
@@ -3617,7 +3619,7 @@ static void syn_list_flags(struct name_list *nlist, int flags, int attr)
for (i = 0; nlist[i].flag != 0; ++i)
if (flags & nlist[i].flag) {
- msg_puts_attr((char_u *)nlist[i].name, attr);
+ msg_puts_attr(nlist[i].name, attr);
msg_putchar(' ');
}
}
@@ -3640,15 +3642,16 @@ static void syn_list_cluster(int id)
msg_advance(endcol);
if (SYN_CLSTR(curwin->w_s)[id].scl_list != NULL) {
- put_id_list((char_u *)"cluster", SYN_CLSTR(curwin->w_s)[id].scl_list,
- hl_attr(HLF_D));
+ put_id_list("cluster", SYN_CLSTR(curwin->w_s)[id].scl_list, hl_attr(HLF_D));
} else {
- msg_puts_attr((char_u *)"cluster", hl_attr(HLF_D));
- msg_puts((char_u *)"=NONE");
+ msg_puts_attr("cluster", hl_attr(HLF_D));
+ msg_puts("=NONE");
}
}
-static void put_id_list(char_u *name, short *list, int attr)
+static void put_id_list(const char *name,
+ short *list, // NOLINT(runtime/int)
+ int attr)
{
short *p;
@@ -3656,14 +3659,15 @@ static void put_id_list(char_u *name, short *list, int attr)
msg_putchar('=');
for (p = list; *p; ++p) {
if (*p >= SYNID_ALLBUT && *p < SYNID_TOP) {
- if (p[1])
- MSG_PUTS("ALLBUT");
- else
- MSG_PUTS("ALL");
+ if (p[1]) {
+ msg_puts("ALLBUT");
+ } else {
+ msg_puts("ALL");
+ }
} else if (*p >= SYNID_TOP && *p < SYNID_CONTAINED) {
- MSG_PUTS("TOP");
+ msg_puts("TOP");
} else if (*p >= SYNID_CONTAINED && *p < SYNID_CLUSTER) {
- MSG_PUTS("CONTAINED");
+ msg_puts("CONTAINED");
} else if (*p >= SYNID_CLUSTER) {
short scl_id = *p - SYNID_CLUSTER;
@@ -3688,7 +3692,7 @@ static void put_pattern(char *s, int c, synpat_T *spp, int attr)
/* May have to write "matchgroup=group" */
if (last_matchgroup != spp->sp_syn_match_id) {
last_matchgroup = spp->sp_syn_match_id;
- msg_puts_attr((char_u *)"matchgroup", attr);
+ msg_puts_attr("matchgroup", attr);
msg_putchar('=');
if (last_matchgroup == 0)
msg_outtrans((char_u *)"NONE");
@@ -3697,8 +3701,8 @@ static void put_pattern(char *s, int c, synpat_T *spp, int attr)
msg_putchar(' ');
}
- /* output the name of the pattern and an '=' or ' ' */
- msg_puts_attr((char_u *)s, attr);
+ // Output the name of the pattern and an '=' or ' '.
+ msg_puts_attr(s, attr);
msg_putchar(c);
/* output the pattern, in between a char that is not in the pattern */
@@ -3718,9 +3722,10 @@ static void put_pattern(char *s, int c, synpat_T *spp, int attr)
if (!(spp->sp_off_flags & (mask + (mask << SPO_COUNT)))) {
continue;
}
- if (!first)
- msg_putchar(','); /* separate with commas */
- msg_puts((char_u *)spo_name_tab[i]);
+ if (!first) {
+ msg_putchar(','); // Separate with commas.
+ }
+ msg_puts(spo_name_tab[i]);
n = spp->sp_offsets[i];
if (i != SPO_LC_OFF) {
if (spp->sp_off_flags & mask)
@@ -3792,32 +3797,31 @@ syn_list_keywords (
}
did_header = TRUE;
if (prev_contained != (kp->flags & HL_CONTAINED)) {
- msg_puts_attr((char_u *)"contained", attr);
+ msg_puts_attr("contained", attr);
msg_putchar(' ');
prev_contained = (kp->flags & HL_CONTAINED);
}
if (kp->k_syn.cont_in_list != prev_cont_in_list) {
- put_id_list((char_u *)"containedin",
- kp->k_syn.cont_in_list, attr);
+ put_id_list("containedin", kp->k_syn.cont_in_list, attr);
msg_putchar(' ');
prev_cont_in_list = kp->k_syn.cont_in_list;
}
if (kp->next_list != prev_next_list) {
- put_id_list((char_u *)"nextgroup", kp->next_list, attr);
+ put_id_list("nextgroup", kp->next_list, attr);
msg_putchar(' ');
prev_next_list = kp->next_list;
if (kp->flags & HL_SKIPNL) {
- msg_puts_attr((char_u *)"skipnl", attr);
+ msg_puts_attr("skipnl", attr);
msg_putchar(' ');
prev_skipnl = (kp->flags & HL_SKIPNL);
}
if (kp->flags & HL_SKIPWHITE) {
- msg_puts_attr((char_u *)"skipwhite", attr);
+ msg_puts_attr("skipwhite", attr);
msg_putchar(' ');
prev_skipwhite = (kp->flags & HL_SKIPWHITE);
}
if (kp->flags & HL_SKIPEMPTY) {
- msg_puts_attr((char_u *)"skipempty", attr);
+ msg_puts_attr("skipempty", attr);
msg_putchar(' ');
prev_skipempty = (kp->flags & HL_SKIPEMPTY);
}
@@ -3929,7 +3933,8 @@ static void add_keyword(char_u *name,
hash_T hash = hash_hash(kp->keyword);
hashtab_T *ht = (curwin->w_s->b_syn_ic) ? &curwin->w_s->b_keywtab_ic
: &curwin->w_s->b_keywtab;
- hashitem_T *hi = hash_lookup(ht, kp->keyword, hash);
+ hashitem_T *hi = hash_lookup(ht, (const char *)kp->keyword,
+ STRLEN(kp->keyword), hash);
// even though it looks like only the kp->keyword member is
// being used here, vim uses some pointer trickery to get the orignal
@@ -5516,19 +5521,21 @@ void ex_ownsyntax(exarg_T *eap)
clear_string_option(&curwin->w_s->b_syn_isk);
}
- /* save value of b:current_syntax */
- old_value = get_var_value((char_u *)"b:current_syntax");
- if (old_value != NULL)
+ // Save value of b:current_syntax.
+ old_value = get_var_value("b:current_syntax");
+ if (old_value != NULL) {
old_value = vim_strsave(old_value);
+ }
/* Apply the "syntax" autocommand event, this finds and loads the syntax
* file. */
apply_autocmds(EVENT_SYNTAX, eap->arg, curbuf->b_fname, TRUE, curbuf);
- /* move value of b:current_syntax to w:current_syntax */
- new_value = get_var_value((char_u *)"b:current_syntax");
- if (new_value != NULL)
+ // Move value of b:current_syntax to w:current_syntax.
+ new_value = get_var_value("b:current_syntax");
+ if (new_value != NULL) {
set_internal_string_var((char_u *)"w:current_syntax", new_value);
+ }
/* restore value of b:current_syntax */
if (old_value == NULL)
@@ -5988,7 +5995,7 @@ init_highlight (
* Try finding the color scheme file. Used when a color file was loaded
* and 'background' or 't_Co' is changed.
*/
- char_u *p = get_var_value((char_u *)"g:colors_name");
+ char_u *p = get_var_value("g:colors_name");
if (p != NULL) {
// Value of g:colors_name could be freed in load_colors() and make
// p invalid, so copy it.
@@ -6042,7 +6049,7 @@ init_highlight (
/*
* If syntax highlighting is enabled load the highlighting for it.
*/
- if (get_var_value((char_u *)"g:syntax_on") != NULL) {
+ if (get_var_value("g:syntax_on") != NULL) {
static int recursive = 0;
if (recursive >= 5) {
@@ -6871,8 +6878,8 @@ static void highlight_list_one(int id)
if (sgp->sg_link && !got_int) {
(void)syn_list_header(didh, 9999, id);
- didh = TRUE;
- msg_puts_attr((char_u *)"links to", hl_attr(HLF_D));
+ didh = true;
+ msg_puts_attr("links to", hl_attr(HLF_D));
msg_putchar(' ');
msg_outtrans(HL_TABLE()[HL_TABLE()[id - 1].sg_link - 1].sg_name);
}
@@ -7057,7 +7064,7 @@ syn_list_header (
/* Show "xxx" with the attributes. */
if (!did_header) {
- msg_puts_attr((char_u *)"xxx", syn_id2attr(id));
+ msg_puts_attr("xxx", syn_id2attr(id));
msg_putchar(' ');
}
@@ -7517,7 +7524,7 @@ static void highlight_list(void)
static void highlight_list_two(int cnt, int attr)
{
- msg_puts_attr((char_u *)&("N \bI \b! \b"[cnt / 11]), attr);
+ msg_puts_attr(&("N \bI \b! \b"[cnt / 11]), attr);
msg_clr_eos();
ui_flush();
os_delay(cnt == 99 ? 40L : (long)cnt * 50L, false);
@@ -7528,22 +7535,25 @@ static void highlight_list_two(int cnt, int attr)
* Function given to ExpandGeneric() to obtain the list of group names.
* Also used for synIDattr() function.
*/
-char_u *get_highlight_name(expand_T *xp, int idx)
-{
- //TODO: 'xp' is unused
- if (idx == highlight_ga.ga_len && include_none != 0)
- return (char_u *)"none";
- if (idx == highlight_ga.ga_len + include_none && include_default != 0)
- return (char_u *)"default";
- if (idx == highlight_ga.ga_len + include_none + include_default
- && include_link != 0)
- return (char_u *)"link";
- if (idx == highlight_ga.ga_len + include_none + include_default + 1
- && include_link != 0)
- return (char_u *)"clear";
- if (idx < 0 || idx >= highlight_ga.ga_len)
+const char *get_highlight_name(expand_T *const xp, const int idx)
+ FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ // TODO(justinmk): 'xp' is unused
+ if (idx == highlight_ga.ga_len && include_none != 0) {
+ return "none";
+ } else if (idx == highlight_ga.ga_len + include_none
+ && include_default != 0) {
+ return "default";
+ } else if (idx == highlight_ga.ga_len + include_none + include_default
+ && include_link != 0) {
+ return "link";
+ } else if (idx == highlight_ga.ga_len + include_none + include_default + 1
+ && include_link != 0) {
+ return "clear";
+ } else if (idx < 0 || idx >= highlight_ga.ga_len) {
return NULL;
- return HL_TABLE()[idx].sg_name;
+ }
+ return (const char *)HL_TABLE()[idx].sg_name;
}
color_name_table_T color_name_table[] = {
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index 0b76e36a6b..e723ea20c9 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -540,10 +540,11 @@ do_tag (
}
vim_snprintf((char *)IObuff + 1, IOSIZE - 1, "%2d %s ", i + 1,
mt_names[matches[i][0] & MT_MASK]);
- msg_puts(IObuff);
- if (tagp.tagkind != NULL)
+ msg_puts((const char *)IObuff);
+ if (tagp.tagkind != NULL) {
msg_outtrans_len(tagp.tagkind,
- (int)(tagp.tagkind_end - tagp.tagkind));
+ (int)(tagp.tagkind_end - tagp.tagkind));
+ }
msg_advance(13);
msg_outtrans_len_attr(tagp.tagname,
(int)(tagp.tagname_end - tagp.tagname),
@@ -595,7 +596,7 @@ do_tag (
}
p = msg_outtrans_one(p, attr);
if (*p == TAB) {
- msg_puts_attr((char_u *)" ", attr);
+ msg_puts_attr(" ", attr);
break;
}
if (*p == ':')
@@ -858,13 +859,15 @@ do_tag (
STRCAT(IObuff, _(" Using tag with different case!"));
if ((num_matches > prev_num_matches || new_tag)
&& num_matches > 1) {
- if (ic)
- msg_attr(IObuff, hl_attr(HLF_W));
- else
+ if (ic) {
+ msg_attr((const char *)IObuff, hl_attr(HLF_W));
+ } else {
msg(IObuff);
- msg_scroll = TRUE; /* don't overwrite this message */
- } else
+ }
+ msg_scroll = true; // Don't overwrite this message.
+ } else {
give_warning(IObuff, ic);
+ }
if (ic && !msg_scrolled && msg_silent == 0) {
ui_flush();
os_delay(1000L, true);
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index ed82e23be2..9fbbe8be92 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -1014,7 +1014,7 @@ static const char *tui_tk_ti_getstr(const char *name, const char *value,
} else if (strcmp(name, "key_dc") == 0) {
ILOG("libtermkey:kdch1=%s", value);
// Vim: "If <BS> and <DEL> are now the same, redefine <DEL>."
- if (stty_erase != NULL && strcmp(stty_erase, value) == 0) {
+ if (stty_erase != NULL && value != NULL && strcmp(stty_erase, value) == 0) {
return stty_erase[0] == DEL ? (char *)CTRL_H_STR : (char *)DEL_STR;
}
}
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 4b267a1627..8cedfcb905 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -2512,13 +2512,14 @@ void ex_undolist(exarg_T *eap)
sort_strings((char_u **)ga.ga_data, ga.ga_len);
msg_start();
- msg_puts_attr((char_u *)_("number changes when saved"),
- hl_attr(HLF_T));
- for (int i = 0; i < ga.ga_len && !got_int; ++i) {
+ msg_puts_attr(_("number changes when saved"),
+ hl_attr(HLF_T));
+ for (int i = 0; i < ga.ga_len && !got_int; i++) {
msg_putchar('\n');
- if (got_int)
+ if (got_int) {
break;
- msg_puts(((char_u **)ga.ga_data)[i]);
+ }
+ msg_puts(((const char **)ga.ga_data)[i]);
}
msg_end();
diff --git a/src/nvim/version.c b/src/nvim/version.c
index e4890b9568..3787ba6908 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -2572,7 +2572,7 @@ static void list_features(void)
int idx = (i / ncol) + (i % ncol) * nrow;
if (idx < nfeat) {
int last_col = (i + 1) % ncol == 0;
- msg_puts((char_u *)features[idx]);
+ msg_puts(features[idx]);
if (last_col) {
if (msg_col > 0) {
msg_putchar('\n');