eval: Move remaining get_tv_string* functions to eval/typval.c

This commit is contained in:
ZyX
2016-09-04 02:25:24 +03:00
parent 50ebd1dff5
commit c8e63a8db8
26 changed files with 1244 additions and 1055 deletions

View File

@@ -20,15 +20,13 @@
#define BS '\010'
#define TAB '\011'
#define NL '\012'
#define NL_STR (char_u *)"\012"
#define NL_STR "\012"
#define FF '\014'
#define CAR '\015' /* CR is used by Mac OS X */
#define ESC '\033'
#define ESC_STR (char_u *)"\033"
#define ESC_STR_nc "\033"
#define ESC_STR "\033"
#define DEL 0x7f
#define DEL_STR (char_u *)"\177"
#define CSI 0x9b /* Control Sequence Introducer */
#define CSI 0x9b // Control Sequence Introducer
#define CSI_STR "\233"
#define DCS 0x90 /* Device Control String */
#define STERM 0x9c /* String Terminator */

View File

@@ -90,7 +90,6 @@ int buf_init_chartab(buf_T *buf, int global)
{
int c;
int c2;
char_u *p;
int i;
bool tilde;
bool do_isalpha;
@@ -144,7 +143,8 @@ int buf_init_chartab(buf_T *buf, int global)
// Walk through the 'isident', 'iskeyword', 'isfname' and 'isprint'
// options Each option is a list of characters, character numbers or
// ranges, separated by commas, e.g.: "200-210,x,#-178,-"
for (i = global ? 0 : 3; i <= 3; ++i) {
for (i = global ? 0 : 3; i <= 3; i++) {
const char_u *p;
if (i == 0) {
// first round: 'isident'
p = p_isi;
@@ -169,7 +169,7 @@ int buf_init_chartab(buf_T *buf, int global)
}
if (ascii_isdigit(*p)) {
c = getdigits_int(&p);
c = getdigits_int((char_u **)&p);
} else {
c = mb_ptr2char_adv(&p);
}
@@ -179,7 +179,7 @@ int buf_init_chartab(buf_T *buf, int global)
++p;
if (ascii_isdigit(*p)) {
c2 = getdigits_int(&p);
c2 = getdigits_int((char_u **)&p);
} else {
c2 = mb_ptr2char_adv(&p);
}

View File

@@ -1423,7 +1423,7 @@ static void ins_ctrl_v(void)
edit_putchar('^', TRUE);
did_putchar = TRUE;
}
AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */
AppendToRedobuff(CTRL_V_STR);
add_to_showcmd_c(Ctrl_V);
@@ -1977,7 +1977,6 @@ static bool ins_compl_accept_char(int c)
*/
int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int dir, int flags)
{
char_u *p;
int i, c;
int actual_len; /* Take multi-byte characters */
int actual_compl_length; /* into account. */
@@ -1987,11 +1986,11 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int
int was_letter = FALSE;
if (p_ic && curbuf->b_p_inf && len > 0) {
/* Infer case of completed part. */
// Infer case of completed part.
/* Find actual length of completion. */
// Find actual length of completion.
if (has_mbyte) {
p = str;
const char_u *p = str;
actual_len = 0;
while (*p != NUL) {
mb_ptr_adv(p);
@@ -2002,7 +2001,7 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int
/* Find actual length of original text. */
if (has_mbyte) {
p = compl_orig_text;
const char_u *p = compl_orig_text;
actual_compl_length = 0;
while (*p != NUL) {
mb_ptr_adv(p);
@@ -2018,27 +2017,35 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int
/* Allocate wide character array for the completion and fill it. */
wca = xmalloc(actual_len * sizeof(*wca));
p = str;
for (i = 0; i < actual_len; ++i)
if (has_mbyte)
wca[i] = mb_ptr2char_adv(&p);
else
wca[i] = *(p++);
{
const char_u *p = str;
for (i = 0; i < actual_len; i++) {
if (has_mbyte) {
wca[i] = mb_ptr2char_adv(&p);
} else {
wca[i] = *(p++);
}
}
}
/* Rule 1: Were any chars converted to lower? */
p = compl_orig_text;
for (i = 0; i < min_len; ++i) {
if (has_mbyte)
c = mb_ptr2char_adv(&p);
else
c = *(p++);
if (vim_islower(c)) {
has_lower = TRUE;
if (vim_isupper(wca[i])) {
/* Rule 1 is satisfied. */
for (i = actual_compl_length; i < actual_len; ++i)
wca[i] = vim_tolower(wca[i]);
break;
// Rule 1: Were any chars converted to lower?
{
const char_u *p = compl_orig_text;
for (i = 0; i < min_len; i++) {
if (has_mbyte) {
c = mb_ptr2char_adv(&p);
} else {
c = *(p++);
}
if (vim_islower(c)) {
has_lower = true;
if (vim_isupper(wca[i])) {
// Rule 1 is satisfied.
for (i = actual_compl_length; i < actual_len; i++) {
wca[i] = vim_tolower(wca[i]);
}
break;
}
}
}
}
@@ -2048,49 +2055,57 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int
* upper case.
*/
if (!has_lower) {
p = compl_orig_text;
for (i = 0; i < min_len; ++i) {
if (has_mbyte)
const char_u *p = compl_orig_text;
for (i = 0; i < min_len; i++) {
if (has_mbyte) {
c = mb_ptr2char_adv(&p);
else
} else {
c = *(p++);
}
if (was_letter && vim_isupper(c) && vim_islower(wca[i])) {
/* Rule 2 is satisfied. */
for (i = actual_compl_length; i < actual_len; ++i)
// Rule 2 is satisfied.
for (i = actual_compl_length; i < actual_len; i++) {
wca[i] = vim_toupper(wca[i]);
}
break;
}
was_letter = vim_islower(c) || vim_isupper(c);
}
}
/* Copy the original case of the part we typed. */
p = compl_orig_text;
for (i = 0; i < min_len; ++i) {
if (has_mbyte)
c = mb_ptr2char_adv(&p);
else
c = *(p++);
if (vim_islower(c))
wca[i] = vim_tolower(wca[i]);
else if (vim_isupper(c))
wca[i] = vim_toupper(wca[i]);
// Copy the original case of the part we typed.
{
const char_u *p = compl_orig_text;
for (i = 0; i < min_len; i++) {
if (has_mbyte) {
c = mb_ptr2char_adv(&p);
} else {
c = *(p++);
}
if (vim_islower(c)) {
wca[i] = vim_tolower(wca[i]);
} else if (vim_isupper(c)) {
wca[i] = vim_toupper(wca[i]);
}
}
}
/*
* Generate encoding specific output from wide character array.
* Multi-byte characters can occupy up to five bytes more than
* ASCII characters, and we also need one byte for NUL, so stay
* six bytes away from the edge of IObuff.
*/
p = IObuff;
i = 0;
while (i < actual_len && (p - IObuff + 6) < IOSIZE)
if (has_mbyte)
p += (*mb_char2bytes)(wca[i++], p);
else
*(p++) = wca[i++];
*p = NUL;
// Generate encoding specific output from wide character array.
// Multi-byte characters can occupy up to five bytes more than
// ASCII characters, and we also need one byte for NUL, so stay
// six bytes away from the edge of IObuff.
{
char_u *p = IObuff;
i = 0;
while (i < actual_len && (p - IObuff + 6) < IOSIZE) {
if (has_mbyte) {
p += (*mb_char2bytes)(wca[i++], p);
} else {
*(p++) = wca[i++];
}
}
*p = NUL;
}
xfree(wca);
@@ -3594,7 +3609,7 @@ int ins_compl_add_tv(typval_T *const tv, const Direction dir)
adup = (bool)tv_dict_get_number(tv->vval.v_dict, "dup");
aempty = (bool)tv_dict_get_number(tv->vval.v_dict, "empty");
} else {
word = (const char *)get_tv_string_chk(tv);
word = (const char *)tv_get_string_chk(tv);
memset(cptext, 0, sizeof(cptext));
}
if (word == NULL || (!aempty && *word == NUL)) {
@@ -5785,15 +5800,16 @@ comp_textwidth (
*/
static void redo_literal(int c)
{
char_u buf[10];
char buf[10];
/* Only digits need special treatment. Translate them into a string of
* three digits. */
// Only digits need special treatment. Translate them into a string of
// three digits.
if (ascii_isdigit(c)) {
vim_snprintf((char *)buf, sizeof(buf), "%03d", c);
vim_snprintf(buf, sizeof(buf), "%03d", c);
AppendToRedobuff(buf);
} else
} else {
AppendCharToRedobuff(c);
}
}
// start_arrow() is called when an arrow key is used in insert mode.
@@ -5822,8 +5838,8 @@ static void start_arrow_common(pos_T *end_insert_pos, bool end_change)
{
if (!arrow_used && end_change) { // something has been inserted
AppendToRedobuff(ESC_STR);
stop_insert(end_insert_pos, FALSE, FALSE);
arrow_used = TRUE; /* this means we stopped the current insert */
stop_insert(end_insert_pos, false, false);
arrow_used = true; // This means we stopped the current insert.
}
check_spell_redraw();
}
@@ -5880,7 +5896,7 @@ int stop_arrow(void)
vr_lines_changed = 1;
}
ResetRedobuff();
AppendToRedobuff((char_u *)"1i"); /* pretend we start an insertion */
AppendToRedobuff("1i"); // Pretend we start an insertion.
new_insert_skip = 2;
} else if (ins_need_undo) {
if (u_save_cursor() == OK)
@@ -6345,12 +6361,13 @@ stuff_inserted (
}
do {
stuffReadbuff(ptr);
/* a trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^" */
if (last)
stuffReadbuff((char_u *)(last == '0'
? "\026\060\064\070"
: "\026^"));
stuffReadbuff((const char *)ptr);
// A trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^".
if (last) {
stuffReadbuff((last == '0'
? "\026\060\064\070"
: "\026^"));
}
} while (--count > 0);
if (last)
@@ -7143,13 +7160,12 @@ static bool ins_esc(long *count, int cmdchar, bool nomove)
disabled_redraw = false;
}
if (!arrow_used) {
/*
* Don't append the ESC for "r<CR>" and "grx".
* When 'insertmode' is set only CTRL-L stops Insert mode. Needed for
* when "count" is non-zero.
*/
if (cmdchar != 'r' && cmdchar != 'v')
AppendToRedobuff(p_im ? (char_u *)"\014" : ESC_STR);
// Don't append the ESC for "r<CR>" and "grx".
// When 'insertmode' is set only CTRL-L stops Insert mode. Needed for
// when "count" is non-zero.
if (cmdchar != 'r' && cmdchar != 'v') {
AppendToRedobuff(p_im ? "\014" : ESC_STR);
}
/*
* Repeating insert may take a long time. Check for
@@ -7303,7 +7319,8 @@ static bool ins_start_select(int c)
// Execute the key in (insert) Select mode.
stuffcharReadbuff(Ctrl_O);
if (mod_mask) {
char_u buf[4] = { K_SPECIAL, KS_MODIFIER, mod_mask, NUL };
const char buf[] = { (char)K_SPECIAL, (char)KS_MODIFIER,
(char)(uint8_t)mod_mask, NUL };
stuffReadbuff(buf);
}
stuffcharReadbuff(c);
@@ -8111,11 +8128,11 @@ static bool ins_tab(void)
return true;
}
did_ai = FALSE;
did_si = FALSE;
can_si = FALSE;
can_si_back = FALSE;
AppendToRedobuff((char_u *)"\t");
did_ai = false;
did_si = false;
can_si = false;
can_si_back = false;
AppendToRedobuff("\t");
if (p_sta && ind) { // insert tab in indent, use "shiftwidth"
temp = get_sw_value(curbuf);
@@ -8380,8 +8397,8 @@ static int ins_digraph(void)
edit_unputchar();
}
if (cc != ESC) {
AppendToRedobuff((char_u *)CTRL_V_STR);
c = getdigraph(c, cc, TRUE);
AppendToRedobuff(CTRL_V_STR);
c = getdigraph(c, cc, true);
clear_showcmd();
return c;
}
@@ -8443,12 +8460,13 @@ static int ins_ctrl_ey(int tc)
if (c != NUL) {
long tw_save;
/* The character must be taken literally, insert like it
* was typed after a CTRL-V, and pretend 'textwidth'
* wasn't set. Digits, 'o' and 'x' are special after a
* CTRL-V, don't use it for these. */
if (c < 256 && !isalnum(c))
AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */
// The character must be taken literally, insert like it
// was typed after a CTRL-V, and pretend 'textwidth'
// wasn't set. Digits, 'o' and 'x' are special after a
// CTRL-V, don't use it for these.
if (c < 256 && !isalnum(c)) {
AppendToRedobuff(CTRL_V_STR);
}
tw_save = curbuf->b_p_tw;
curbuf->b_p_tw = -1;
insert_special(c, TRUE, FALSE);

File diff suppressed because it is too large Load Diff

View File

@@ -796,7 +796,7 @@ static bool tv_dict_watcher_matches(DictWatcher *watcher, const char *const key)
// of the string means it should match everything up to the '*' instead of the
// whole string.
const size_t len = strlen(watcher->key_pattern);
if (watcher->key_pattern[len - 1] == '*') {
if (len && watcher->key_pattern[len - 1] == '*') {
return strncmp(key, watcher->key_pattern, len - 1) == 0;
} else {
return strcmp(key, watcher->key_pattern) == 0;
@@ -2020,7 +2020,7 @@ bool tv_equal(typval_T *const tv1, typval_T *const tv2, const bool ic,
///
/// @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
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
switch (tv->v_type) {
case VAR_NUMBER:
@@ -2072,7 +2072,7 @@ static const char *const num_errors[] = {
/// Check that given value is a number or can be converted to it
///
/// Error messages are compatible with tv_get_number() previously used for
/// Error messages are compatible with tv_get_number_chk() previously used for
/// the same purpose.
///
/// @param[in] tv Value to check.
@@ -2101,6 +2101,50 @@ bool tv_check_num(const typval_T *const tv)
return false;
}
#define FUNC_ERROR "E729: using Funcref as a String"
static const char *const str_errors[] = {
[VAR_PARTIAL]=N_(FUNC_ERROR),
[VAR_FUNC]=N_(FUNC_ERROR),
[VAR_LIST]=N_("E730: using List as a String"),
[VAR_DICT]=N_("E731: using Dictionary as a String"),
[VAR_FLOAT]=((const char *)e_float_as_string),
[VAR_UNKNOWN]=N_("E908: using an invalid value as a String"),
};
#undef FUNC_ERROR
/// Check that given value is a string or can be converted to it
///
/// Error messages are compatible with tv_get_string_chk() previously used for
/// the same purpose.
///
/// @param[in] tv Value to check.
///
/// @return true if everything is OK, false otherwise.
bool tv_check_str(const typval_T *const tv)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
switch (tv->v_type) {
case VAR_NUMBER:
case VAR_SPECIAL:
case VAR_STRING: {
return true;
}
case VAR_PARTIAL:
case VAR_FUNC:
case VAR_LIST:
case VAR_DICT:
case VAR_FLOAT:
case VAR_UNKNOWN: {
EMSG(_(str_errors[tv->v_type]));
return false;
}
}
assert(false);
return false;
}
//{{{2 Get
/// Get the number value of a VimL object
@@ -2245,6 +2289,48 @@ float_T tv_get_float(const typval_T *const tv)
return 0;
}
/// Get the string value of a VimL object
///
/// @param[in] tv Object to get value of.
/// @param buf Buffer used to hold numbers and special variables converted to
/// string. When function encounters one of these stringified value
/// will be written to buf and buf will be returned.
///
/// Buffer must have NUMBUFLEN size.
///
/// @return Object value if it is VAR_STRING object, number converted to
/// a string for VAR_NUMBER, v: variable name for VAR_SPECIAL or NULL.
const char *tv_get_string_buf_chk(const typval_T *const tv, char *const buf)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
switch (tv->v_type) {
case VAR_NUMBER: {
snprintf(buf, NUMBUFLEN, "%" PRIdVARNUMBER, tv->vval.v_number);
return buf;
}
case VAR_STRING: {
if (tv->vval.v_string != NULL) {
return (const char *)tv->vval.v_string;
}
return "";
}
case VAR_SPECIAL: {
STRCPY(buf, encode_special_var_names[tv->vval.v_special]);
return buf;
}
case VAR_PARTIAL:
case VAR_FUNC:
case VAR_LIST:
case VAR_DICT:
case VAR_FLOAT:
case VAR_UNKNOWN: {
EMSG(_(str_errors[tv->v_type]));
return false;
}
}
return NULL;
}
/// Get the string value of a VimL object
///
/// @warning For number and special values it uses a single, static buffer. It
@@ -2252,7 +2338,26 @@ float_T tv_get_float(const typval_T *const tv)
/// tv_get_string_buf() if you need to use tv_get_string() output after
/// calling it again.
///
/// @note get_tv_string_chk() and get_tv_string_buf_chk() are similar, but
/// @param[in] tv Object to get value of.
///
/// @return Object value if it is VAR_STRING object, number converted to
/// a string for VAR_NUMBER, v: variable name for VAR_SPECIAL or NULL.
const char *tv_get_string_chk(const typval_T *const tv)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
static char mybuf[NUMBUFLEN];
return tv_get_string_buf_chk(tv, mybuf);
}
/// Get the string value of a VimL object
///
/// @warning For number and special values it uses a single, static buffer. It
/// may be used only once, next call to get_tv_string may reuse it. Use
/// tv_get_string_buf() if you need to use tv_get_string() output after
/// calling it again.
///
/// @note tv_get_string_chk() and tv_get_string_buf_chk() are similar, but
/// return NULL on error.
///
/// @param[in] tv Object to get value of.
@@ -2269,7 +2374,7 @@ const char *tv_get_string(const typval_T *const tv)
/// Get the string value of a VimL object
///
/// @note get_tv_string_chk() and get_tv_string_buf_chk() are similar, but
/// @note tv_get_string_chk() and tv_get_string_buf_chk() are similar, but
/// return NULL on error.
///
/// @param[in] tv Object to get value of.
@@ -2285,8 +2390,7 @@ const char *tv_get_string(const typval_T *const tv)
const char *tv_get_string_buf(const typval_T *const tv, char *const buf)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT
{
const char *const res = (const char *)get_tv_string_buf_chk(
(typval_T *)tv, (char_u *)buf);
const char *const res = (const char *)tv_get_string_buf_chk(tv, buf);
return res != NULL ? res : "";
}

View File

@@ -27,6 +27,7 @@ typedef double float_T;
/// Mimimal possible value of varnumber_T variable
#define VARNUMBER_MIN INT_MIN
#define PRIdVARNUMBER "d"
/// %d printf format specifier for varnumber_T
#define PRIdVARNUMBER "d"

View File

@@ -1008,8 +1008,8 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out)
AppendToRedobuffLit(cmd, -1);
xfree(cmd);
AppendToRedobuff((char_u *)"\n");
bangredo = FALSE;
AppendToRedobuff("\n");
bangredo = false;
}
/*
* Add quotes around the command, for shells that need them.

View File

@@ -6794,7 +6794,7 @@ do_exedit (
int ms = msg_scroll;
if (eap->nextcmd != NULL) {
stuffReadbuff(eap->nextcmd);
stuffReadbuff((const char *)eap->nextcmd);
eap->nextcmd = NULL;
}

View File

@@ -2554,19 +2554,22 @@ void cmdline_paste_str(char_u *s, int literally)
else
while (*s != NUL) {
cv = *s;
if (cv == Ctrl_V && s[1])
++s;
if (has_mbyte)
c = mb_cptr2char_adv(&s);
else
if (cv == Ctrl_V && s[1]) {
s++;
}
if (has_mbyte) {
c = mb_cptr2char_adv((const char_u **)&s);
} else {
c = *s++;
}
if (cv == Ctrl_V || c == ESC || c == Ctrl_C
|| c == CAR || c == NL || c == Ctrl_L
#ifdef UNIX
|| c == intr_char
#endif
|| (c == Ctrl_BSL && *s == Ctrl_N))
|| (c == Ctrl_BSL && *s == Ctrl_N)) {
stuffcharReadbuff(Ctrl_V);
}
stuffcharReadbuff(c);
}
}
@@ -4636,7 +4639,7 @@ in_history (
///
/// @return Any value from HistoryType enum, including HIST_INVALID. May not
/// return HIST_DEFAULT unless return_default is true.
HistoryType get_histtype(const char_u *const name, const size_t len,
HistoryType get_histtype(const char *const name, const size_t len,
const bool return_default)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
@@ -5029,7 +5032,7 @@ void ex_history(exarg_T *eap)
while (ASCII_ISALPHA(*end)
|| vim_strchr((char_u *)":=@>/?", *end) != NULL)
end++;
histype1 = get_histtype(arg, end - arg, false);
histype1 = get_histtype((const char *)arg, end - arg, false);
if (histype1 == HIST_INVALID) {
if (STRNICMP(arg, "all", end - arg) == 0) {
histype1 = 0;
@@ -5288,18 +5291,18 @@ static int ex_window(void)
cmdwin_result = Ctrl_C;
/* Set the new command line from the cmdline buffer. */
xfree(ccline.cmdbuff);
if (cmdwin_result == K_XF1 || cmdwin_result == K_XF2) { /* :qa[!] typed */
char *p = (cmdwin_result == K_XF2) ? "qa" : "qa!";
if (cmdwin_result == K_XF1 || cmdwin_result == K_XF2) { // :qa[!] typed
const char *p = (cmdwin_result == K_XF2) ? "qa" : "qa!";
if (histtype == HIST_CMD) {
/* Execute the command directly. */
ccline.cmdbuff = vim_strsave((char_u *)p);
// Execute the command directly.
ccline.cmdbuff = (char_u *)xstrdup(p);
cmdwin_result = CAR;
} else {
/* First need to cancel what we were doing. */
// First need to cancel what we were doing.
ccline.cmdbuff = NULL;
stuffcharReadbuff(':');
stuffReadbuff((char_u *)p);
stuffReadbuff(p);
stuffcharReadbuff(CAR);
}
} else if (cmdwin_result == K_XF2) { /* :qa typed */

View File

@@ -614,10 +614,12 @@ readfile (
return FAIL;
}
#ifdef UNIX
/* Set swap file protection bits after creating it. */
// Set swap file protection bits after creating it.
if (swap_mode > 0 && curbuf->b_ml.ml_mfp != NULL
&& curbuf->b_ml.ml_mfp->mf_fname != NULL)
(void)os_setperm(curbuf->b_ml.ml_mfp->mf_fname, (long)swap_mode);
&& curbuf->b_ml.ml_mfp->mf_fname != NULL) {
(void)os_setperm((const char *)curbuf->b_ml.ml_mfp->mf_fname,
(long)swap_mode);
}
#endif
}
@@ -2870,9 +2872,9 @@ buf_write (
xfree(backup);
backup = NULL;
} else {
/* set file protection same as original file, but
* strip s-bit */
(void)os_setperm(backup, perm & 0777);
// set file protection same as original file, but
// strip s-bit.
(void)os_setperm((const char *)backup, perm & 0777);
#ifdef UNIX
/*
@@ -2883,7 +2885,8 @@ buf_write (
*/
if (file_info_new.stat.st_gid != file_info_old.stat.st_gid
&& os_fchown(bfd, -1, file_info_old.stat.st_gid) != 0) {
os_setperm(backup, (perm & 0707) | ((perm & 07) << 3));
os_setperm((const char *)backup,
(perm & 0707) | ((perm & 07) << 3));
}
# ifdef HAVE_SELINUX
mch_copy_sec(fname, backup);
@@ -3037,8 +3040,8 @@ nobackup:
&& file_info_old.stat.st_uid == getuid()
&& vim_strchr(p_cpo, CPO_FWRITE) == NULL) {
perm |= 0200;
(void)os_setperm(fname, perm);
made_writable = TRUE;
(void)os_setperm((const char *)fname, perm);
made_writable = true;
}
#endif
@@ -3402,8 +3405,9 @@ restore_backup:
|| file_info.stat.st_uid != file_info_old.stat.st_uid
|| file_info.stat.st_gid != file_info_old.stat.st_gid) {
os_fchown(fd, file_info_old.stat.st_uid, file_info_old.stat.st_gid);
if (perm >= 0) /* set permission again, may have changed */
(void)os_setperm(wfname, perm);
if (perm >= 0) { // Set permission again, may have changed.
(void)os_setperm((const char *)wfname, perm);
}
}
buf_set_file_id(buf);
} else if (!buf->file_id_valid) {
@@ -3421,8 +3425,9 @@ restore_backup:
if (made_writable)
perm &= ~0200; /* reset 'w' bit for security reasons */
#endif
if (perm >= 0) /* set perm. of new file same as old file */
(void)os_setperm(wfname, perm);
if (perm >= 0) { // Set perm. of new file same as old file.
(void)os_setperm((const char *)wfname, perm);
}
#ifdef HAVE_ACL
/* Probably need to set the ACL before changing the user (can't set the
* ACL on a file the user doesn't own). */
@@ -3628,7 +3633,7 @@ restore_backup:
close(empty_fd);
}
if (org != NULL) {
os_setperm((char_u *)org, os_getperm((const char *)fname) & 0777);
os_setperm(org, os_getperm((const char *)fname) & 0777);
xfree(org);
}
}
@@ -4690,8 +4695,8 @@ int vim_rename(const char_u *from, const char_u *to)
errmsg = _("E210: Error reading \"%s\"");
to = from;
}
#ifndef UNIX /* for Unix os_open() already set the permission */
os_setperm(to, perm);
#ifndef UNIX // For Unix os_open() already set the permission.
os_setperm((const char *)to, perm);
#endif
#ifdef HAVE_ACL
mch_set_acl(to, acl);

View File

@@ -235,19 +235,18 @@ char_u *get_inserted(void)
return get_buffcont(&redobuff, FALSE);
}
/*
* Add string "s" after the current block of buffer "buf".
* K_SPECIAL and CSI should have been escaped already.
*/
static void
add_buff (
buffheader_T *buf,
char_u *s,
ssize_t slen // length of "s" or -1
)
/// Add string after the current block of the given buffer
///
/// K_SPECIAL and CSI should have been escaped already.
///
/// @param[out] buf Buffer to add to.
/// @param[in] s String to add.
/// @param[in] slen String length or -1 for NUL-terminated string.
static void add_buff(buffheader_T *const buf, const char *const s,
ptrdiff_t slen)
{
if (slen < 0) {
slen = (ssize_t)STRLEN(s);
slen = (ptrdiff_t)strlen(s);
}
if (slen == 0) { // don't add empty strings
return;
@@ -292,9 +291,8 @@ add_buff (
*/
static void add_num_buff(buffheader_T *buf, long n)
{
char_u number[32];
sprintf((char *)number, "%" PRId64, (int64_t)n);
char number[32];
snprintf(number, sizeof(number), "%ld", n);
add_buff(buf, number, -1L);
}
@@ -304,27 +302,29 @@ static void add_num_buff(buffheader_T *buf, long n)
*/
static void add_char_buff(buffheader_T *buf, int c)
{
char_u bytes[MB_MAXBYTES + 1];
char bytes[MB_MAXBYTES + 1];
int len;
int i;
char_u temp[4];
if (IS_SPECIAL(c))
if (IS_SPECIAL(c)) {
len = 1;
else
len = (*mb_char2bytes)(c, bytes);
for (i = 0; i < len; ++i) {
if (!IS_SPECIAL(c))
c = bytes[i];
} else {
len = (*mb_char2bytes)(c, (char_u *)bytes);
}
for (int i = 0; i < len; i++) {
if (!IS_SPECIAL(c)) {
c = bytes[i];
}
char temp[4];
if (IS_SPECIAL(c) || c == K_SPECIAL || c == NUL) {
/* translate special key code into three byte sequence */
temp[0] = K_SPECIAL;
temp[1] = (char_u)K_SECOND(c);
temp[2] = (char_u)K_THIRD(c);
// Translate special key code into three byte sequence.
temp[0] = (char)K_SPECIAL;
temp[1] = (char)K_SECOND(c);
temp[2] = (char)K_THIRD(c);
temp[3] = NUL;
} else {
temp[0] = (char_u)c;
temp[0] = (char)c;
temp[1] = NUL;
}
add_buff(buf, temp, -1L);
@@ -479,16 +479,14 @@ static int save_level = 0;
void saveRedobuff(void)
{
char_u *s;
if (save_level++ == 0) {
save_redobuff = redobuff;
redobuff.bh_first.b_next = NULL;
save_old_redobuff = old_redobuff;
old_redobuff.bh_first.b_next = NULL;
/* Make a copy, so that ":normal ." in a function works. */
s = get_buffcont(&save_redobuff, FALSE);
// Make a copy, so that ":normal ." in a function works.
char *const s = (char *)get_buffcont(&save_redobuff, false);
if (s != NULL) {
add_buff(&redobuff, s, -1L);
xfree(s);
@@ -514,10 +512,11 @@ void restoreRedobuff(void)
* Append "s" to the redo buffer.
* K_SPECIAL and CSI should already have been escaped.
*/
void AppendToRedobuff(char_u *s)
void AppendToRedobuff(const char *s)
{
if (!block_redo)
add_buff(&redobuff, s, -1L);
if (!block_redo) {
add_buff(&redobuff, (const char *)s, -1L);
}
}
/*
@@ -530,44 +529,47 @@ AppendToRedobuffLit (
int len /* length of "str" or -1 for up to the NUL */
)
{
char_u *s = str;
int c;
char_u *start;
if (block_redo)
if (block_redo) {
return;
}
while (len < 0 ? *s != NUL : s - str < len) {
/* Put a string of normal characters in the redo buffer (that's
* faster). */
start = s;
while (*s >= ' ' && *s < DEL && (len < 0 || s - str < len))
++s;
const char *s = (const char *)str;
while (len < 0 ? *s != NUL : s - (const char *)str < len) {
// Put a string of normal characters in the redo buffer (that's
// faster).
const char *start = s;
while (*s >= ' ' && *s < DEL && (len < 0 || s - (const char *)str < len)) {
s++;
}
/* Don't put '0' or '^' as last character, just in case a CTRL-D is
* typed next. */
if (*s == NUL && (s[-1] == '0' || s[-1] == '^'))
--s;
if (s > start)
// Don't put '0' or '^' as last character, just in case a CTRL-D is
// typed next.
if (*s == NUL && (s[-1] == '0' || s[-1] == '^')) {
s--;
}
if (s > start) {
add_buff(&redobuff, start, (long)(s - start));
}
if (*s == NUL || (len >= 0 && s - str >= len))
if (*s == NUL || (len >= 0 && s - (const char *)str >= len)) {
break;
}
/* Handle a special or multibyte character. */
if (has_mbyte)
/* Handle composing chars separately. */
c = mb_cptr2char_adv(&s);
else
c = *s++;
if (c < ' ' || c == DEL || (*s == NUL && (c == '0' || c == '^')))
// Handle a special or multibyte character.
// Composing chars separately are handled separately.
const int c = (has_mbyte
? mb_cptr2char_adv((const char_u **)&s)
: (uint8_t)(*s++));
if (c < ' ' || c == DEL || (*s == NUL && (c == '0' || c == '^'))) {
add_char_buff(&redobuff, Ctrl_V);
}
/* CTRL-V '0' must be inserted as CTRL-V 048 */
if (*s == NUL && c == '0')
add_buff(&redobuff, (char_u *)"048", 3L);
else
// CTRL-V '0' must be inserted as CTRL-V 048.
if (*s == NUL && c == '0') {
add_buff(&redobuff, "048", 3L);
} else {
add_char_buff(&redobuff, c);
}
}
}
@@ -594,19 +596,19 @@ void AppendNumberToRedobuff(long n)
* Append string "s" to the stuff buffer.
* CSI and K_SPECIAL must already have been escaped.
*/
void stuffReadbuff(char_u *s)
void stuffReadbuff(const char *s)
{
add_buff(&readbuf1, s, -1L);
}
/// Append string "s" to the redo stuff buffer.
/// @remark CSI and K_SPECIAL must already have been escaped.
void stuffRedoReadbuff(char_u *s)
void stuffRedoReadbuff(const char *s)
{
add_buff(&readbuf2, s, -1L);
}
void stuffReadbuffLen(char_u *s, long len)
void stuffReadbuffLen(const char *s, long len)
{
add_buff(&readbuf1, s, len);
}
@@ -616,19 +618,18 @@ void stuffReadbuffLen(char_u *s, long len)
* escaping other K_SPECIAL and CSI bytes.
* Change CR, LF and ESC into a space.
*/
void stuffReadbuffSpec(char_u *s)
void stuffReadbuffSpec(const char *s)
{
int c;
while (*s != NUL) {
if (*s == K_SPECIAL && s[1] != NUL && s[2] != NUL) {
/* Insert special key literally. */
stuffReadbuffLen(s, 3L);
if ((uint8_t)(*s) == K_SPECIAL && s[1] != NUL && s[2] != NUL) {
// Insert special key literally.
stuffReadbuffLen(s, 3);
s += 3;
} else {
c = mb_ptr2char_adv(&s);
if (c == CAR || c == NL || c == ESC)
int c = mb_ptr2char_adv((const char_u **)&s);
if (c == CAR || c == NL || c == ESC) {
c = ' ';
}
stuffcharReadbuff(c);
}
}
@@ -747,8 +748,8 @@ int start_redo(long count, int old_redo)
/* copy the buffer name, if present */
if (c == '"') {
add_buff(&readbuf2, (char_u *)"\"", 1L);
c = read_redo(FALSE, old_redo);
add_buff(&readbuf2, "\"", 1L);
c = read_redo(false, old_redo);
/* if a numbered buffer is used, increment the number */
if (c >= '1' && c < '9')
@@ -1091,21 +1092,19 @@ static void gotchars(char_u *chars, size_t len)
{
char_u *s = chars;
int c;
char_u buf[2];
// remember how many chars were last recorded
if (Recording) {
last_recorded_len += len;
}
buf[1] = NUL;
while (len--) {
// Handle one byte at a time; no translation to be done.
c = *s++;
updatescript(c);
if (Recording) {
buf[0] = (char_u)c;
char buf[2] = { (char)c, NUL };
add_buff(&recordbuff, buf, 1L);
}
}

View File

@@ -1199,6 +1199,7 @@ EXTERN char_u e_dirnotf[] INIT(= N_(
"E919: Directory not found in '%s': \"%s\""));
EXTERN char_u e_unsupportedoption[] INIT(= N_("E519: Option not supported"));
EXTERN char_u e_fnametoolong[] INIT(= N_("E856: Filename too long"));
EXTERN char_u e_float_as_string[] INIT(= N_("E806: using Float as a String"));
EXTERN char top_bot_msg[] INIT(= N_("search hit TOP, continuing at BOTTOM"));

View File

@@ -625,7 +625,7 @@ static int utf_safe_read_char_adv(const char_u **s, size_t *n)
* Get character at **pp and advance *pp to the next character.
* Note: composing characters are skipped!
*/
int mb_ptr2char_adv(char_u **pp)
int mb_ptr2char_adv(const char_u **const pp)
{
int c;
@@ -638,7 +638,7 @@ int mb_ptr2char_adv(char_u **pp)
* Get character at **pp and advance *pp to the next character.
* Note: composing characters are returned as separate characters.
*/
int mb_cptr2char_adv(char_u **pp)
int mb_cptr2char_adv(const char_u **pp)
{
int c;

View File

@@ -1155,7 +1155,7 @@ static void normal_check_stuff_buffer(NormalState *s)
if (need_start_insertmode && goto_im() && !VIsual_active) {
need_start_insertmode = false;
stuffReadbuff((uint8_t *)"i"); // start insert mode next
stuffReadbuff("i"); // start insert mode next
// skip the fileinfo message now, because it would be shown
// after insert mode finishes!
need_fileinfo = false;
@@ -1469,8 +1469,9 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
* If 'cpoptions' does not contain 'r', insert the search
* pattern to really repeat the same command.
*/
if (vim_strchr(p_cpo, CPO_REDO) == NULL)
if (vim_strchr(p_cpo, CPO_REDO) == NULL) {
AppendToRedobuffLit(cap->searchbuf, -1);
}
AppendToRedobuff(NL_STR);
} else if (cap->cmdchar == ':') {
/* do_cmdline() has stored the first typed line in
@@ -1853,10 +1854,11 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
break;
case OP_FILTER:
if (vim_strchr(p_cpo, CPO_FILTER) != NULL)
AppendToRedobuff((char_u *)"!\r"); /* use any last used !cmd */
else
bangredo = true; /* do_bang() will put cmd in redo buffer */
if (vim_strchr(p_cpo, CPO_FILTER) != NULL) {
AppendToRedobuff("!\r"); // Use any last used !cmd.
} else {
bangredo = true; // do_bang() will put cmd in redo buffer.
}
case OP_INDENT:
case OP_COLON:
@@ -2026,43 +2028,44 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
static void op_colon(oparg_T *oap)
{
stuffcharReadbuff(':');
if (oap->is_VIsual)
stuffReadbuff((char_u *)"'<,'>");
else {
/*
* Make the range look nice, so it can be repeated.
*/
if (oap->start.lnum == curwin->w_cursor.lnum)
if (oap->is_VIsual) {
stuffReadbuff("'<,'>");
} else {
// Make the range look nice, so it can be repeated.
if (oap->start.lnum == curwin->w_cursor.lnum) {
stuffcharReadbuff('.');
else
} else {
stuffnumReadbuff((long)oap->start.lnum);
}
if (oap->end.lnum != oap->start.lnum) {
stuffcharReadbuff(',');
if (oap->end.lnum == curwin->w_cursor.lnum)
if (oap->end.lnum == curwin->w_cursor.lnum) {
stuffcharReadbuff('.');
else if (oap->end.lnum == curbuf->b_ml.ml_line_count)
} else if (oap->end.lnum == curbuf->b_ml.ml_line_count) {
stuffcharReadbuff('$');
else if (oap->start.lnum == curwin->w_cursor.lnum) {
stuffReadbuff((char_u *)".+");
} else if (oap->start.lnum == curwin->w_cursor.lnum) {
stuffReadbuff(".+");
stuffnumReadbuff(oap->line_count - 1);
} else
} else {
stuffnumReadbuff((long)oap->end.lnum);
}
}
}
if (oap->op_type != OP_COLON)
stuffReadbuff((char_u *)"!");
if (oap->op_type != OP_COLON) {
stuffReadbuff("!");
}
if (oap->op_type == OP_INDENT) {
stuffReadbuff(get_equalprg());
stuffReadbuff((char_u *)"\n");
stuffReadbuff((const char *)get_equalprg());
stuffReadbuff("\n");
} else if (oap->op_type == OP_FORMAT) {
if (*curbuf->b_p_fp != NUL) {
stuffReadbuff(curbuf->b_p_fp);
stuffReadbuff((const char *)curbuf->b_p_fp);
} else if (*p_fp != NUL) {
stuffReadbuff(p_fp);
stuffReadbuff((const char *)p_fp);
} else {
stuffReadbuff((char_u *)"fmt");
stuffReadbuff("fmt");
}
stuffReadbuff((char_u *)"\n']");
stuffReadbuff("\n']");
}
/*
@@ -2304,7 +2307,7 @@ do_mouse (
if (VIsual_active) {
if (VIsual_select) {
stuffcharReadbuff(Ctrl_G);
stuffReadbuff((char_u *)"\"+p");
stuffReadbuff("\"+p");
} else {
stuffcharReadbuff('y');
stuffcharReadbuff(K_MIDDLEMOUSE);
@@ -4476,7 +4479,7 @@ static void nv_colon(cmdarg_T *cap)
/* translate "count:" into ":.,.+(count - 1)" */
stuffcharReadbuff('.');
if (cap->count0 > 1) {
stuffReadbuff((char_u *)",.+");
stuffReadbuff(",.+");
stuffnumReadbuff(cap->count0 - 1L);
}
}
@@ -6156,17 +6159,15 @@ static void nv_abbrev(cmdarg_T *cap)
*/
static void nv_optrans(cmdarg_T *cap)
{
static char_u *(ar[8]) = {(char_u *)"dl", (char_u *)"dh",
(char_u *)"d$", (char_u *)"c$",
(char_u *)"cl", (char_u *)"cc",
(char_u *)"yy", (char_u *)":s\r"};
static char_u *str = (char_u *)"xXDCsSY&";
static const char *(ar[]) = { "dl", "dh", "d$", "c$", "cl", "cc", "yy",
":s\r" };
static const char *str = "xXDCsSY&";
if (!checkclearopq(cap->oap)) {
if (cap->count0) {
stuffnumReadbuff(cap->count0);
}
stuffReadbuff(ar[(int)(vim_strchr(str, cap->cmdchar) - str)]);
stuffReadbuff(ar[strchr(str, (char)cap->cmdchar) - str]);
}
cap->opcount = 0;
}

View File

@@ -1109,7 +1109,6 @@ int insert_reg(
)
{
int retval = OK;
char_u *arg;
int allocated;
/*
@@ -1125,21 +1124,24 @@ int insert_reg(
if (regname != NUL && !valid_yank_reg(regname, false))
return FAIL;
if (regname == '.') /* insert last inserted text */
retval = stuff_inserted(NUL, 1L, TRUE);
else if (get_spec_reg(regname, &arg, &allocated, TRUE)) {
if (arg == NULL)
char_u *arg;
if (regname == '.') { // Insert last inserted text.
retval = stuff_inserted(NUL, 1L, true);
} else if (get_spec_reg(regname, &arg, &allocated, true)) {
if (arg == NULL) {
return FAIL;
stuffescaped(arg, literally);
if (allocated)
}
stuffescaped((const char *)arg, literally);
if (allocated) {
xfree(arg);
} else { /* name or number register */
}
} else { // Name or number register.
yankreg_T *reg = get_yank_register(regname, YREG_PASTE);
if (reg->y_array == NULL) {
retval = FAIL;
} else {
for (size_t i = 0; i < reg->y_size; i++) {
stuffescaped(reg->y_array[i], literally);
stuffescaped((const char *)reg->y_array[i], literally);
// Insert a newline between lines and after last line if
// y_type is kMTLineWise.
if (reg->y_type == kMTLineWise || i < reg->y_size - 1) {
@@ -1156,29 +1158,29 @@ int insert_reg(
* Stuff a string into the typeahead buffer, such that edit() will insert it
* literally ("literally" TRUE) or interpret is as typed characters.
*/
static void stuffescaped(char_u *arg, int literally)
static void stuffescaped(const char *arg, int literally)
{
int c;
char_u *start;
while (*arg != NUL) {
/* Stuff a sequence of normal ASCII characters, that's fast. Also
* stuff K_SPECIAL to get the effect of a special key when "literally"
* is TRUE. */
start = arg;
while ((*arg >= ' ' && *arg < DEL) || (*arg == K_SPECIAL && !literally))
++arg;
if (arg > start)
// Stuff a sequence of normal ASCII characters, that's fast. Also
// stuff K_SPECIAL to get the effect of a special key when "literally"
// is TRUE.
const char *const start = arg;
while ((*arg >= ' ' && *arg < DEL) || ((uint8_t)(*arg) == K_SPECIAL
&& !literally)) {
arg++;
}
if (arg > start) {
stuffReadbuffLen(start, (long)(arg - start));
}
/* stuff a single special character */
if (*arg != NUL) {
if (has_mbyte)
c = mb_cptr2char_adv(&arg);
else
c = *arg++;
if (literally && ((c < ' ' && c != TAB) || c == DEL))
const int c = (has_mbyte
? mb_cptr2char_adv((const char_u **)&arg)
: (uint8_t)(*arg++));
if (literally && ((c < ' ' && c != TAB) || c == DEL)) {
stuffcharReadbuff(Ctrl_V);
}
stuffcharReadbuff(c);
}
}
@@ -2663,7 +2665,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
// back to the previous line in the case of 'noautoindent' and
// 'backspace' includes "eol". So we insert a dummy space for Ctrl_U
// to consume.
stuffReadbuff((char_u *)"\n ");
stuffReadbuff("\n ");
stuffcharReadbuff(Ctrl_U);
}
}
@@ -2675,7 +2677,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
// character. Simulate it with motion commands after the insert.
if (flags & PUT_CURSEND) {
if (flags & PUT_LINE) {
stuffReadbuff((char_u *)"j0");
stuffReadbuff("j0");
} else {
// Avoid ringing the bell from attempting to move into the space after
// the current line. We can stuff the readbuffer with "l" if:
@@ -2705,7 +2707,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
}
}
} else if (flags & PUT_LINE) {
stuffReadbuff((char_u *)"g'[");
stuffReadbuff("g'[");
}
// So the 'u' command restores cursor position after ".p, save the cursor
@@ -4981,7 +4983,7 @@ void write_reg_contents(int name, const char_u *str, ssize_t len,
write_reg_contents_ex(name, str, len, must_append, kMTUnknown, 0L);
}
void write_reg_contents_lst(int name, char_u **strings, int maxlen,
void write_reg_contents_lst(int name, char_u **strings,
bool must_append, MotionType yank_type,
colnr_T block_len)
{

View File

@@ -3419,15 +3419,18 @@ static char_u *set_chars_option(char_u **varp)
&& p[len] == ':'
&& p[len + 1] != NUL) {
s = p + len + 1;
c1 = mb_ptr2char_adv(&s);
if (mb_char2cells(c1) > 1)
c1 = mb_ptr2char_adv((const char_u **)&s);
if (mb_char2cells(c1) > 1) {
continue;
}
if (tab[i].cp == &lcs_tab2) {
if (*s == NUL)
if (*s == NUL) {
continue;
c2 = mb_ptr2char_adv(&s);
if (mb_char2cells(c2) > 1)
}
c2 = mb_ptr2char_adv((const char_u **)&s);
if (mb_char2cells(c2) > 1) {
continue;
}
}
if (*s == ',' || *s == NUL) {
if (round) {
@@ -6887,8 +6890,8 @@ void set_fileformat(int eol_style, int opt_flags)
need_maketitle = true; // Set window title later.
}
/// Skip to next part of an option argument: Skip space and comma.
char_u *skip_to_option_part(char_u *p)
/// Skip to next part of an option argument: skip space and comma
char_u *skip_to_option_part(const char_u *p)
{
if (*p == ',') {
p++;
@@ -6896,7 +6899,7 @@ char_u *skip_to_option_part(char_u *p)
while (*p == ' ') {
p++;
}
return p;
return (char_u *)p;
}
/// Isolate one part of a string option separated by `sep_chars`.

View File

@@ -622,11 +622,11 @@ int32_t os_getperm(const char *name)
/// Set the permission of a file.
///
/// @return `OK` for success, `FAIL` for failure.
int os_setperm(const char_u *name, int perm)
int os_setperm(const char *const name, int perm)
FUNC_ATTR_NONNULL_ALL
{
int r;
RUN_UV_FS_FUNC(r, uv_fs_chmod, (const char *)name, perm, NULL);
RUN_UV_FS_FUNC(r, uv_fs_chmod, name, perm, NULL);
return (r == kLibuvSuccess ? OK : FAIL);
}

View File

@@ -2221,10 +2221,11 @@ collection:
if (*regparse == '[')
endc = get_coll_element(&regparse);
if (endc == 0) {
if (has_mbyte)
endc = mb_ptr2char_adv(&regparse);
else
if (has_mbyte) {
endc = mb_ptr2char_adv((const char_u **)&regparse);
} else {
endc = *regparse++;
}
}
/* Handle \o40, \x20 and \u20AC style sequences */
@@ -6271,8 +6272,8 @@ static int cstrncmp(char_u *s1, char_u *s2, int *n)
str2 = s2;
c1 = c2 = 0;
while ((int)(str1 - s1) < *n) {
c1 = mb_ptr2char_adv(&str1);
c2 = mb_ptr2char_adv(&str2);
c1 = mb_ptr2char_adv((const char_u **)&str1);
c2 = mb_ptr2char_adv((const char_u **)&str2);
/* decompose the character if necessary, into 'base' characters
* because I don't care about Arabic, I will hard-code the Hebrew
@@ -6586,7 +6587,6 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest,
if (expr != NULL) {
typval_T argv[2];
int dummy;
char_u buf[NUMBUFLEN];
typval_T rettv;
staticList10_T matchList;
@@ -6616,7 +6616,8 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest,
clear_submatch_list(&matchList);
}
}
eval_result = get_tv_string_buf_chk(&rettv, buf);
char buf[NUMBUFLEN];
eval_result = (char_u *)tv_get_string_buf_chk(&rettv, buf);
if (eval_result != NULL) {
eval_result = vim_strsave(eval_result);
}

View File

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

View File

@@ -2309,10 +2309,11 @@ int captype(char_u *word, char_u *end)
for (p = word; !spell_iswordp_nmw(p, curwin); mb_ptr_adv(p))
if (end == NULL ? *p == NUL : p >= end)
return 0; // only non-word characters, illegal word
if (has_mbyte)
c = mb_ptr2char_adv(&p);
else
if (has_mbyte) {
c = mb_ptr2char_adv((const char_u **)&p);
} else {
c = *p++;
}
firstcap = allcap = SPELL_ISUPPER(c);
// Need to check all letters to find a word with mixed upper/lower.
@@ -2607,14 +2608,15 @@ static bool spell_iswordp(char_u *p, win_T *wp)
// Returns true if "p" points to a word character.
// Unlike spell_iswordp() this doesn't check for "midword" characters.
bool spell_iswordp_nmw(char_u *p, win_T *wp)
bool spell_iswordp_nmw(const char_u *p, win_T *wp)
{
int c;
if (has_mbyte) {
c = mb_ptr2char(p);
if (c > 255)
if (c > 255) {
return spell_mb_isword_class(mb_get_class(p), wp);
}
return spelltab.st_isw[c];
}
return spelltab.st_isw[*p];
@@ -2675,7 +2677,7 @@ int spell_casefold(char_u *str, int len, char_u *buf, int buflen)
buf[outi] = NUL;
return FAIL;
}
c = mb_cptr2char_adv(&p);
c = mb_cptr2char_adv((const char_u **)&p);
outi += mb_char2bytes(SPELL_TOFOLD(c), buf + outi);
}
buf[outi] = NUL;
@@ -2937,7 +2939,7 @@ void spell_suggest(int count)
// For redo we use a change-word command.
ResetRedobuff();
AppendToRedobuff((char_u *)"ciw");
AppendToRedobuff("ciw");
AppendToRedobuffLit(p + c,
stp->st_wordlen + sug.su_badlen - stp->st_orglen);
AppendCharToRedobuff(ESC);
@@ -3406,17 +3408,19 @@ void onecap_copy(char_u *word, char_u *wcopy, bool upper)
int l;
p = word;
if (has_mbyte)
c = mb_cptr2char_adv(&p);
else
if (has_mbyte) {
c = mb_cptr2char_adv((const char_u **)&p);
} else {
c = *p++;
if (upper)
}
if (upper) {
c = SPELL_TOUPPER(c);
else
} else {
c = SPELL_TOFOLD(c);
if (has_mbyte)
}
if (has_mbyte) {
l = mb_char2bytes(c, wcopy);
else {
} else {
l = 1;
wcopy[0] = c;
}
@@ -3433,10 +3437,11 @@ static void allcap_copy(char_u *word, char_u *wcopy)
d = wcopy;
for (s = word; *s != NUL; ) {
if (has_mbyte)
c = mb_cptr2char_adv(&s);
else
if (has_mbyte) {
c = mb_cptr2char_adv((const char_u **)&s);
} else {
c = *s++;
}
if (c == 0xdf) {
c = 'S';
@@ -5938,12 +5943,12 @@ static void spell_soundfold_sofo(slang_T *slang, char_u *inword, char_u *res)
// The sl_sal_first[] table contains the translation for chars up to
// 255, sl_sal the rest.
for (s = inword; *s != NUL; ) {
c = mb_cptr2char_adv(&s);
if (enc_utf8 ? utf_class(c) == 0 : ascii_iswhite(c))
c = mb_cptr2char_adv((const char_u **)&s);
if (enc_utf8 ? utf_class(c) == 0 : ascii_iswhite(c)) {
c = ' ';
else if (c < 256)
} else if (c < 256) {
c = slang->sl_sal_first[c];
else {
} else {
ip = ((int **)slang->sl_sal.ga_data)[c & 0xff];
if (ip == NULL) // empty list, can't match
c = NUL;
@@ -6228,9 +6233,7 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
int word[MAXWLEN];
int wres[MAXWLEN];
int l;
char_u *s;
int *ws;
char_u *t;
int *pf;
int i, j, z;
int reslen;
@@ -6250,9 +6253,9 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
// Remove accents, if wanted. We actually remove all non-word characters.
// But keep white space.
wordlen = 0;
for (s = inword; *s != NUL; ) {
t = s;
c = mb_cptr2char_adv(&s);
for (const char_u *s = inword; *s != NUL; ) {
const char_u *t = s;
c = mb_cptr2char_adv((const char_u **)&s);
if (slang->sl_rem_accents) {
if (enc_utf8 ? utf_class(c) == 0 : ascii_iswhite(c)) {
if (did_white)
@@ -6261,8 +6264,9 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
did_white = true;
} else {
did_white = false;
if (!spell_iswordp_nmw(t, curwin))
if (!spell_iswordp_nmw(t, curwin)) {
continue;
}
}
}
word[wordlen++] = c;
@@ -6309,7 +6313,7 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
continue;
++k;
}
s = smp[n].sm_rules;
char_u *s = smp[n].sm_rules;
pri = 5; // default priority
p0 = *s;
@@ -6708,25 +6712,30 @@ soundalike_score (
// support multi-byte characters.
static int spell_edit_score(slang_T *slang, char_u *badword, char_u *goodword)
{
int *cnt;
int badlen, goodlen; // lengths including NUL
int *cnt;
int j, i;
int t;
int bc, gc;
int pbc, pgc;
char_u *p;
int wbadword[MAXWLEN];
int wgoodword[MAXWLEN];
const bool l_has_mbyte = has_mbyte;
// Lengths with NUL.
int badlen;
int goodlen;
if (l_has_mbyte) {
// Get the characters from the multi-byte strings and put them in an
// int array for easy access.
for (p = badword, badlen = 0; *p != NUL; )
badlen = 0;
for (const char_u *p = badword; *p != NUL; ) {
wbadword[badlen++] = mb_cptr2char_adv(&p);
}
wbadword[badlen++] = 0;
for (p = goodword, goodlen = 0; *p != NUL; )
goodlen = 0;
for (const char_u *p = goodword; *p != NUL; ) {
wgoodword[goodlen++] = mb_cptr2char_adv(&p);
}
wgoodword[goodlen++] = 0;
} else {
badlen = (int)STRLEN(badword) + 1;
@@ -6960,19 +6969,20 @@ static int spell_edit_score_limit_w(slang_T *slang, char_u *badword, char_u *goo
int score_off;
int minscore;
int round;
char_u *p;
int wbadword[MAXWLEN];
int wgoodword[MAXWLEN];
// Get the characters from the multi-byte strings and put them in an
// int array for easy access.
bi = 0;
for (p = badword; *p != NUL; )
for (const char_u *p = badword; *p != NUL; ) {
wbadword[bi++] = mb_cptr2char_adv(&p);
}
wbadword[bi++] = 0;
gi = 0;
for (p = goodword; *p != NUL; )
for (const char_u *p = goodword; *p != NUL; ) {
wgoodword[gi++] = mb_cptr2char_adv(&p);
}
wgoodword[gi++] = 0;
// The idea is to go from start to end over the words. So long as

View File

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

View File

@@ -598,22 +598,21 @@ static varnumber_T tv_nr(typval_T *tvs, int *idxp)
/// free "*tofree".
///
/// @return String value or NULL in case of error.
static char *tv_str(typval_T *tvs, int *idxp, char ** const tofree)
static const char *tv_str(typval_T *tvs, int *idxp, char **const tofree)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
int idx = *idxp - 1;
char *s = NULL;
const char *s = NULL;
if (tvs[idx].v_type == VAR_UNKNOWN) {
EMSG(_(e_printf));
} else {
(*idxp)++;
if (tvs[idx].v_type == VAR_STRING || tvs[idx].v_type == VAR_NUMBER) {
s = (char *)get_tv_string_chk(&tvs[idx]);
s = tv_get_string_chk(&tvs[idx]);
*tofree = NULL;
} else {
s = encode_tv2echo(&tvs[idx], NULL);
*tofree = s;
s = *tofree = encode_tv2echo(&tvs[idx], NULL);
}
}
return s;
@@ -953,7 +952,7 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap,
case 's':
case 'S':
str_arg = tvs ? tv_str(tvs, &arg_idx, &tofree)
: va_arg(ap, char *);
: va_arg(ap, const char *);
if (!str_arg) {
str_arg = "[NULL]";
str_arg_l = 6;

View File

@@ -1140,7 +1140,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
EMSG2(_(e_not_open), file_name);
goto theend;
}
(void)os_setperm((char_u *)file_name, perm);
(void)os_setperm(file_name, perm);
if (p_verbose > 0) {
verbose_enter();
smsg(_("Writing undo file: %s"), file_name);
@@ -1165,7 +1165,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
&& os_fileinfo(file_name, &file_info_new)
&& file_info_old.stat.st_gid != file_info_new.stat.st_gid
&& os_fchown(fd, (uv_uid_t)-1, (uv_gid_t)file_info_old.stat.st_gid)) {
os_setperm((char_u *)file_name, (perm & 0707) | ((perm & 07) << 3));
os_setperm(file_name, (perm & 0707) | ((perm & 07) << 3));
}
# ifdef HAVE_SELINUX
if (buf->b_ffname != NULL)

View File

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

View File

@@ -44,3 +44,18 @@ describe('setmatches()', function()
eq({}, funcs.getmatches())
end)
end)
describe('matchadd()', function()
it('correctly works when first two arguments and conceal are numbers at once',
function()
command('hi def link 1 PreProc')
eq(4, funcs.matchadd(1, 2, 3, 4, {conceal=5}))
eq({{
group='1',
pattern='2',
priority=3,
id=4,
conceal='5',
}}, funcs.getmatches())
end)
end)

View File

@@ -9,7 +9,7 @@ local eval = helpers.eval
describe('dictionary change notifications', function()
local channel
setup(function()
before_each(function()
clear()
channel = nvim('get_api_info')[1]
nvim('set_var', 'channel', channel)
@@ -18,19 +18,15 @@ describe('dictionary change notifications', function()
-- the same set of tests are applied to top-level dictionaries(g:, b:, w: and
-- t:) and a dictionary variable, so we generate them in the following
-- function.
local function gentests(dict_expr, dict_expr_suffix, dict_init)
if not dict_expr_suffix then
dict_expr_suffix = ''
end
local function gentests(dict_expr, dict_init)
local function update(opval, key)
if not key then
key = 'watched'
end
if opval == '' then
nvim('command', "unlet "..dict_expr..dict_expr_suffix..key)
command(('unlet %s[\'%s\']'):format(dict_expr, key))
else
nvim('command', "let "..dict_expr..dict_expr_suffix..key.." "..opval)
command(('let %s[\'%s\'] %s'):format(dict_expr, key, opval))
end
end
@@ -50,7 +46,7 @@ describe('dictionary change notifications', function()
describe(dict_expr .. ' watcher', function()
if dict_init then
setup(function()
before_each(function()
source(dict_init)
end)
end
@@ -143,6 +139,32 @@ describe('dictionary change notifications', function()
]])
end)
it('is triggered for empty keys', function()
command([[
call dictwatcheradd(]]..dict_expr..[[, "", "g:Changed")
]])
update('= 1', '')
verify_value({new = 1}, '')
update('= 2', '')
verify_value({old = 1, new = 2}, '')
command([[
call dictwatcherdel(]]..dict_expr..[[, "", "g:Changed")
]])
end)
it('is triggered for empty keys when using catch-all *', function()
command([[
call dictwatcheradd(]]..dict_expr..[[, "*", "g:Changed")
]])
update('= 1', '')
verify_value({new = 1}, '')
update('= 2', '')
verify_value({old = 1, new = 2}, '')
command([[
call dictwatcherdel(]]..dict_expr..[[, "*", "g:Changed")
]])
end)
-- test a sequence of updates of different types to ensure proper memory
-- management(with ASAN)
local function test_updates(tests)
@@ -190,10 +212,10 @@ describe('dictionary change notifications', function()
gentests('b:')
gentests('w:')
gentests('t:')
gentests('g:dict_var', '.', 'let g:dict_var = {}')
gentests('g:dict_var', 'let g:dict_var = {}')
describe('multiple watchers on the same dict/key', function()
setup(function()
before_each(function()
source([[
function! g:Watcher1(dict, key, value)
call rpcnotify(g:channel, '1', a:key, a:value)
@@ -213,6 +235,9 @@ describe('dictionary change notifications', function()
end)
it('only removes watchers that fully match dict, key and callback', function()
nvim('command', 'let g:key = "value"')
eq({'notification', '1', {'key', {new = 'value'}}}, next_msg())
eq({'notification', '2', {'key', {new = 'value'}}}, next_msg())
nvim('command', 'call dictwatcherdel(g:, "key", "g:Watcher1")')
nvim('command', 'let g:key = "v2"')
eq({'notification', '2', {'key', {old = 'value', new = 'v2'}}}, next_msg())
@@ -220,6 +245,17 @@ describe('dictionary change notifications', function()
end)
describe('errors', function()
before_each(function()
source([[
function! g:Watcher1(dict, key, value)
call rpcnotify(g:channel, '1', a:key, a:value)
endfunction
function! g:Watcher2(dict, key, value)
call rpcnotify(g:channel, '2', a:key, a:value)
endfunction
]])
end)
-- WARNING: This suite depends on the above tests
it('fails to remove if no watcher with matching callback is found', function()
eq("Vim(call):Couldn't find a watcher matching key and callback",
@@ -236,15 +272,10 @@ describe('dictionary change notifications', function()
command('call dictwatcherdel(g:, "key", "g:InvalidCb")')
end)
it('fails with empty keys', function()
eq("Vim(call):E713: Cannot use empty key for Dictionary",
exc_exec('call dictwatcheradd(g:, "", "g:Watcher1")'))
eq("Vim(call):E713: Cannot use empty key for Dictionary",
exc_exec('call dictwatcherdel(g:, "", "g:Watcher1")'))
end)
it('does not fail to replace a watcher function', function()
source([[
let g:key = 'v2'
call dictwatcheradd(g:, "key", "g:Watcher2")
function! g:ReplaceWatcher2()
function! g:Watcher2(dict, key, value)
call rpcnotify(g:channel, '2b', a:key, a:value)