vim-patch:9.2.0031: Inefficient use of ga_concat()

Problem:  Inefficient use of ga_concat()
Solution: Use ga_concat_len() when the length is already known to avoid
          use of strlen() (John Marriott).

closes: vim/vim#19422

ed202035b1

Co-authored-by: John Marriott <basilisk@internode.on.net>
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
This commit is contained in:
zeertzjq
2026-02-21 06:32:20 +08:00
parent 9aa936d892
commit b3a3028fd9
8 changed files with 118 additions and 104 deletions

View File

@@ -74,7 +74,7 @@ EXTERN const char e_noroom[] INIT(= N_("E36: Not enough room"));
EXTERN const char e_notmp[] INIT(= N_("E483: Can't get temp file name"));
EXTERN const char e_notopen[] INIT(= N_("E484: Can't open file %s"));
EXTERN const char e_notopen_2[] INIT(= N_("E484: Can't open file %s: %s"));
EXTERN const char e_notread[] INIT(= N_("E485: Can't read file %s"));
EXTERN const char e_cant_read_file_str[] INIT(= N_("E485: Can't read file %s"));
EXTERN const char e_null[] INIT(= N_("E38: Null argument"));
EXTERN const char e_number_exp[] INIT(= N_("E39: Number expected"));
EXTERN const char e_openerrf[] INIT(= N_("E40: Can't open errorfile %s"));

View File

@@ -124,7 +124,7 @@ static int conv_error(const char *const msg, const MPConvStack *const mpstack,
const char *const partial_self_msg = _("partial self dictionary");
for (size_t i = 0; i < kv_size(*mpstack); i++) {
if (i != 0) {
ga_concat_len(&msg_ga, S_LEN(", "));
GA_CONCAT_LITERAL(&msg_ga, ", ");
}
MPConvStackVal v = kv_A(*mpstack, i);
switch (v.type) {
@@ -296,7 +296,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
do { \
const char *const buf_ = (buf); \
if (buf_ == NULL) { \
ga_concat_len(gap, S_LEN("''")); \
GA_CONCAT_LITERAL(gap, "''"); \
} else { \
const size_t len_ = (len); \
ga_grow(gap, (int)(2 + len_ + memcnt(buf_, '\'', len_))); \
@@ -321,13 +321,13 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
const blob_T *const blob_ = (blob); \
const int len_ = (len); \
if (len_ == 0) { \
ga_concat_len(gap, S_LEN("0z")); \
GA_CONCAT_LITERAL(gap, "0z"); \
} else { \
/* Allocate space for "0z", the two hex chars per byte, and a */ \
/* "." separator after every eight hex chars. */ \
/* Example: "0z00112233.44556677.8899" */ \
ga_grow(gap, 2 + 2 * len_ + (len_ - 1) / 4); \
ga_concat_len(gap, S_LEN("0z")); \
GA_CONCAT_LITERAL(gap, "0z"); \
char numbuf[NUMBUFLEN]; \
for (int i_ = 0; i_ < len_; i_++) { \
if (i_ > 0 && (i_ & 3) == 0) { \
@@ -343,8 +343,9 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
#define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \
do { \
char numbuf[NUMBUFLEN]; \
vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%" PRId64, (int64_t)(num)); \
ga_concat(gap, numbuf); \
size_t numbuflen = vim_snprintf_safelen(numbuf, ARRAY_SIZE(numbuf), \
"%" PRId64, (int64_t)(num)); \
ga_concat_len(gap, numbuf, numbuflen); \
} while (0)
#define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \
@@ -352,20 +353,21 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
const float_T flt_ = (flt); \
switch (xfpclassify(flt_)) { \
case FP_NAN: { \
ga_concat_len(gap, S_LEN("str2float('nan')")); \
GA_CONCAT_LITERAL(gap, "str2float('nan')"); \
break; \
} \
case FP_INFINITE: { \
if (flt_ < 0) { \
ga_append(gap, '-'); \
} \
ga_concat_len(gap, S_LEN("str2float('inf')")); \
GA_CONCAT_LITERAL(gap, "str2float('inf')"); \
break; \
} \
default: { \
char numbuf[NUMBUFLEN]; \
vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%g", flt_); \
ga_concat(gap, numbuf); \
size_t numbuflen = vim_snprintf_safelen(numbuf, ARRAY_SIZE(numbuf), \
"%g", flt_); \
ga_concat_len(gap, numbuf, numbuflen); \
} \
} \
} while (0)
@@ -375,10 +377,10 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
const char *const fun_ = (fun); \
if (fun_ == NULL) { \
internal_error("string(): NULL function name"); \
ga_concat_len(gap, S_LEN("function(NULL")); \
GA_CONCAT_LITERAL(gap, "function(NULL"); \
} else { \
const char *const prefix_ = (prefix); \
ga_concat_len(gap, S_LEN("function(")); \
GA_CONCAT_LITERAL(gap, "function("); \
const int name_off = gap->ga_len; \
ga_concat(gap, prefix_); \
TYPVAL_ENCODE_CONV_STRING(tv, fun_, strlen(fun_)); \
@@ -391,14 +393,14 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len) \
do { \
if ((len) != 0) { \
ga_concat_len(gap, S_LEN(", ")); \
GA_CONCAT_LITERAL(gap, ", "); \
} \
} while (0)
#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, len) \
do { \
if ((ptrdiff_t)(len) != -1) { \
ga_concat_len(gap, S_LEN(", ")); \
GA_CONCAT_LITERAL(gap, ", "); \
} \
} while (0)
@@ -406,7 +408,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
ga_append(gap, ')')
#define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \
ga_concat_len(gap, S_LEN("[]"))
GA_CONCAT_LITERAL(gap, "[]")
#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \
ga_append(gap, '[')
@@ -414,19 +416,19 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
#define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv)
#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \
ga_concat_len(gap, S_LEN("{}"))
GA_CONCAT_LITERAL(gap, "{}")
#define TYPVAL_ENCODE_CHECK_BEFORE
#define TYPVAL_ENCODE_CONV_NIL(tv) \
ga_concat_len(gap, S_LEN("v:null"))
GA_CONCAT_LITERAL(gap, "v:null")
#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \
do { \
if (num) { \
ga_concat_len(gap, S_LEN("v:true")); \
GA_CONCAT_LITERAL(gap, "v:true"); \
} else { \
ga_concat_len(gap, S_LEN("v:false")); \
GA_CONCAT_LITERAL(gap, "v:false"); \
} \
} while (0)
@@ -441,10 +443,10 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
ga_append(gap, '}')
#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict) \
ga_concat_len(gap, S_LEN(": "))
GA_CONCAT_LITERAL(gap, ": ")
#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) \
ga_concat_len(gap, S_LEN(", "))
GA_CONCAT_LITERAL(gap, ", ")
#define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(label, key)
@@ -552,15 +554,15 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
#undef TYPVAL_ENCODE_CONV_NIL
#define TYPVAL_ENCODE_CONV_NIL(tv) \
ga_concat_len(gap, S_LEN("null"))
GA_CONCAT_LITERAL(gap, "null")
#undef TYPVAL_ENCODE_CONV_BOOL
#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \
do { \
if (num) { \
ga_concat_len(gap, S_LEN("true")); \
GA_CONCAT_LITERAL(gap, "true"); \
} else { \
ga_concat_len(gap, S_LEN("false")); \
GA_CONCAT_LITERAL(gap, "false"); \
} \
} while (0)
@@ -568,8 +570,9 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, num) \
do { \
char numbuf[NUMBUFLEN]; \
vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%" PRIu64, (num)); \
ga_concat(gap, numbuf); \
size_t numbuflen = vim_snprintf_safelen(numbuf, ARRAY_SIZE(numbuf), \
"%" PRIu64, (num)); \
ga_concat_len(gap, numbuf, numbuflen); \
} while (0)
#undef TYPVAL_ENCODE_CONV_FLOAT
@@ -587,8 +590,9 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
} \
default: { \
char numbuf[NUMBUFLEN]; \
vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%g", flt_); \
ga_concat(gap, numbuf); \
size_t numbuflen = vim_snprintf_safelen(numbuf, ARRAY_SIZE(numbuf), \
"%g", flt_); \
ga_concat_len(gap, numbuf, numbuflen); \
break; \
} \
} \
@@ -620,7 +624,7 @@ static inline int convert_to_json_string(garray_T *const gap, const char *const
{
const char *utf_buf = buf;
if (utf_buf == NULL) {
ga_concat_len(gap, S_LEN("\"\""));
GA_CONCAT_LITERAL(gap, "\"\"");
} else {
size_t utf_len = len;
char *tofree = NULL;
@@ -749,17 +753,17 @@ static inline int convert_to_json_string(garray_T *const gap, const char *const
const blob_T *const blob_ = (blob); \
const int len_ = (len); \
if (len_ == 0) { \
ga_concat_len(gap, S_LEN("[]")); \
GA_CONCAT_LITERAL(gap, "[]"); \
} else { \
ga_append(gap, '['); \
char numbuf[NUMBUFLEN]; \
for (int i_ = 0; i_ < len_; i_++) { \
if (i_ > 0) { \
ga_concat_len(gap, S_LEN(", ")); \
GA_CONCAT_LITERAL(gap, ", "); \
} \
vim_snprintf((char *)numbuf, ARRAY_SIZE(numbuf), "%d", \
(int)tv_blob_get(blob_, i_)); \
ga_concat(gap, numbuf); \
size_t numbuflen = vim_snprintf_safelen(numbuf, ARRAY_SIZE(numbuf), \
"%d", (int)tv_blob_get(blob_, i_)); \
ga_concat_len(gap, numbuf, numbuflen); \
} \
ga_append(gap, ']'); \
} \

View File

@@ -1307,7 +1307,7 @@ static void read_file_or_blob(typval_T *argvars, typval_T *rettv, bool always_bl
if (blob) {
if (read_blob(fd, rettv, offset, size) == FAIL) {
semsg(_(e_notread), fname);
semsg(_(e_cant_read_file_str), fname);
}
fclose(fd);
return;

View File

@@ -971,7 +971,7 @@ int tv_list_slice_or_index(list_T *list, bool range, varnumber_T n1_arg, varnumb
}
typedef struct {
char *s;
String s;
char *tofree;
} Join;
@@ -995,25 +995,26 @@ static int list_join_inner(garray_T *const gap, list_T *const l, const char *con
if (got_int) {
break;
}
char *s;
size_t len;
s = encode_tv2echo(TV_LIST_ITEM_TV(item), &len);
if (s == NULL) {
String s;
s.data = encode_tv2echo(TV_LIST_ITEM_TV(item), &s.size);
if (s.data == NULL) {
return FAIL;
}
sumlen += len;
sumlen += s.size;
Join *const p = GA_APPEND_VIA_PTR(Join, join_gap);
p->tofree = p->s = s;
p->s = s;
p->tofree = s.data;
line_breakcheck();
});
// Allocate result buffer with its total size, avoid re-allocation and
// multiple copy operations. Add 2 for a tailing ']' and NUL.
size_t seplen = strlen(sep);
if (join_gap->ga_len >= 2) {
sumlen += strlen(sep) * (size_t)(join_gap->ga_len - 1);
sumlen += seplen * (size_t)(join_gap->ga_len - 1);
}
ga_grow(gap, (int)sumlen + 2);
@@ -1021,12 +1022,12 @@ static int list_join_inner(garray_T *const gap, list_T *const l, const char *con
if (first) {
first = false;
} else {
ga_concat(gap, sep);
ga_concat_len(gap, sep, seplen);
}
const Join *const p = ((const Join *)join_gap->ga_data) + i;
if (p->s != NULL) {
ga_concat(gap, p->s);
if (p->s.data != NULL) {
ga_concat_len(gap, p->s.data, p->s.size);
}
line_breakcheck();
}
@@ -1106,8 +1107,10 @@ void f_list2str(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
char buf[MB_MAXBYTES + 1];
TV_LIST_ITER_CONST(l, li, {
buf[utf_char2bytes((int)tv_get_number(TV_LIST_ITEM_TV(li)), buf)] = NUL;
ga_concat(&ga, buf);
const varnumber_T n = tv_get_number(TV_LIST_ITEM_TV(li));
const size_t buflen = (size_t)utf_char2bytes((int)n, buf);
buf[buflen] = NUL;
ga_concat_len(&ga, buf, buflen);
});
ga_append(&ga, NUL);

View File

@@ -1373,7 +1373,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
READ_FILTER, false) != OK) {
if (!aborting()) {
msg_putchar('\n');
semsg(_(e_notread), otmp);
semsg(_(e_cant_read_file_str), otmp);
}
goto error;
}

View File

@@ -4,6 +4,7 @@
#include <stddef.h>
#include "nvim/garray_defs.h" // IWYU pragma: keep
#include "nvim/macros_defs.h" // IWYU pragma: keep
#include "nvim/memory.h"
#define GA_EMPTY(ga_ptr) ((ga_ptr)->ga_len <= 0)
@@ -45,3 +46,5 @@
///
/// @param gap the garray to be freed
#define GA_DEEP_CLEAR_PTR(gap) GA_DEEP_CLEAR(gap, void *, FREE_PTR_PTR)
#define GA_CONCAT_LITERAL(gap, s) ga_concat_len((gap), S_LEN(s))

View File

@@ -415,7 +415,7 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
os_remove(tempname);
if (readlen != len) {
// unexpected read error
semsg(_(e_notread), tempname);
semsg(_(e_cant_read_file_str), tempname);
xfree(tempname);
xfree(buffer);
return FAIL;
@@ -809,7 +809,7 @@ char *get_cmd_output(char *cmd, char *infile, int flags, size_t *ret_len)
fclose(fd);
os_remove(tempname);
if (i != len) {
semsg(_(e_notread), tempname);
semsg(_(e_cant_read_file_str), tempname);
XFREE_CLEAR(buffer);
} else if (ret_len == NULL) {
// Change NUL into SOH, otherwise the string is truncated.

View File

@@ -57,7 +57,6 @@ static const char e_calling_test_garbagecollect_now_while_v_testing_is_not_set[]
/// Prepare "gap" for an assert error and add the sourcing position.
static void prepare_assert_error(garray_T *gap)
{
char buf[NUMBUFLEN];
char *sname = estack_sfile(ESTACK_NONE);
ga_init(gap, 1, 100);
@@ -68,11 +67,13 @@ static void prepare_assert_error(garray_T *gap)
}
}
if (SOURCING_LNUM > 0) {
vim_snprintf(buf, ARRAY_SIZE(buf), "line %" PRId64, (int64_t)SOURCING_LNUM);
ga_concat(gap, buf);
char buf[NUMBUFLEN];
size_t buflen = vim_snprintf_safelen(buf, ARRAY_SIZE(buf),
"line %" PRId64, (int64_t)SOURCING_LNUM);
ga_concat_len(gap, buf, buflen);
}
if (sname != NULL || SOURCING_LNUM > 0) {
ga_concat(gap, ": ");
GA_CONCAT_LITERAL(gap, ": ");
}
xfree(sname);
}
@@ -87,29 +88,29 @@ static void ga_concat_esc(garray_T *gap, const char *p, int clen)
if (clen > 1) {
memmove(buf, p, (size_t)clen);
buf[clen] = NUL;
ga_concat(gap, buf);
ga_concat_len(gap, buf, (size_t)clen);
return;
}
switch (*p) {
case BS:
ga_concat(gap, "\\b"); break;
GA_CONCAT_LITERAL(gap, "\\b"); break;
case ESC:
ga_concat(gap, "\\e"); break;
GA_CONCAT_LITERAL(gap, "\\e"); break;
case FF:
ga_concat(gap, "\\f"); break;
GA_CONCAT_LITERAL(gap, "\\f"); break;
case NL:
ga_concat(gap, "\\n"); break;
GA_CONCAT_LITERAL(gap, "\\n"); break;
case TAB:
ga_concat(gap, "\\t"); break;
GA_CONCAT_LITERAL(gap, "\\t"); break;
case CAR:
ga_concat(gap, "\\r"); break;
GA_CONCAT_LITERAL(gap, "\\r"); break;
case '\\':
ga_concat(gap, "\\\\"); break;
GA_CONCAT_LITERAL(gap, "\\\\"); break;
default:
if ((uint8_t)(*p) < ' ' || *p == 0x7f) {
vim_snprintf(buf, NUMBUFLEN, "\\x%02x", *p);
ga_concat(gap, buf);
size_t buflen = vim_snprintf_safelen(buf, NUMBUFLEN, "\\x%02x", *p);
ga_concat_len(gap, buf, buflen);
} else {
ga_append(gap, (uint8_t)(*p));
}
@@ -125,7 +126,7 @@ static void ga_concat_shorten_esc(garray_T *gap, const char *str)
char buf[NUMBUFLEN];
if (str == NULL) {
ga_concat(gap, "NULL");
GA_CONCAT_LITERAL(gap, "NULL");
return;
}
@@ -139,12 +140,12 @@ static void ga_concat_shorten_esc(garray_T *gap, const char *str)
s += clen;
}
if (same_len > 20) {
ga_concat(gap, "\\[");
GA_CONCAT_LITERAL(gap, "\\[");
ga_concat_esc(gap, p, clen);
ga_concat(gap, " occurs ");
vim_snprintf(buf, NUMBUFLEN, "%d", same_len);
ga_concat(gap, buf);
ga_concat(gap, " times]");
GA_CONCAT_LITERAL(gap, " occurs ");
size_t buflen = vim_snprintf_safelen(buf, NUMBUFLEN, "%d", same_len);
ga_concat_len(gap, buf, buflen);
GA_CONCAT_LITERAL(gap, " times]");
p = s;
} else {
ga_concat_esc(gap, p, clen);
@@ -169,15 +170,15 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, const char *e
char *tofree = encode_tv2echo(opt_msg_tv, NULL);
ga_concat(gap, tofree);
xfree(tofree);
ga_concat(gap, ": ");
GA_CONCAT_LITERAL(gap, ": ");
}
if (atype == ASSERT_MATCH || atype == ASSERT_NOTMATCH) {
ga_concat(gap, "Pattern ");
GA_CONCAT_LITERAL(gap, "Pattern ");
} else if (atype == ASSERT_NOTEQUAL) {
ga_concat(gap, "Expected not equal to ");
GA_CONCAT_LITERAL(gap, "Expected not equal to ");
} else {
ga_concat(gap, "Expected ");
GA_CONCAT_LITERAL(gap, "Expected ");
}
if (exp_str == NULL) {
@@ -232,21 +233,21 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, const char *e
xfree(tofree);
} else {
if (atype == ASSERT_FAILS) {
ga_concat(gap, "'");
GA_CONCAT_LITERAL(gap, "'");
}
ga_concat_shorten_esc(gap, exp_str);
if (atype == ASSERT_FAILS) {
ga_concat(gap, "'");
GA_CONCAT_LITERAL(gap, "'");
}
}
if (atype != ASSERT_NOTEQUAL) {
if (atype == ASSERT_MATCH) {
ga_concat(gap, " does not match ");
GA_CONCAT_LITERAL(gap, " does not match ");
} else if (atype == ASSERT_NOTMATCH) {
ga_concat(gap, " does match ");
GA_CONCAT_LITERAL(gap, " does match ");
} else {
ga_concat(gap, " but got ");
GA_CONCAT_LITERAL(gap, " but got ");
}
char *tofree = encode_tv2string(got_tv, NULL);
ga_concat_shorten_esc(gap, tofree);
@@ -254,9 +255,10 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, const char *e
if (omitted != 0) {
char buf[100];
vim_snprintf(buf, sizeof(buf), " - %d equal item%s omitted", omitted,
omitted == 1 ? "" : "s");
ga_concat(gap, buf);
size_t buflen = vim_snprintf_safelen(buf, sizeof(buf),
" - %d equal item%s omitted",
omitted, omitted == 1 ? "" : "s");
ga_concat_len(gap, buf, buflen);
}
}
@@ -354,9 +356,9 @@ static int assert_beeps(typval_T *argvars, bool no_beep)
garray_T ga;
prepare_assert_error(&ga);
if (no_beep) {
ga_concat(&ga, "command did beep: ");
GA_CONCAT_LITERAL(&ga, "command did beep: ");
} else {
ga_concat(&ga, "command did not beep: ");
GA_CONCAT_LITERAL(&ga, "command did not beep: ");
}
ga_concat(&ga, cmd);
assert_error(&ga);
@@ -400,17 +402,18 @@ static int assert_equalfile(typval_T *argvars)
}
IObuff[0] = NUL;
size_t IObufflen = 0;
FILE *const fd1 = os_fopen(fname1, READBIN);
char line1[200];
char line2[200];
ptrdiff_t lineidx = 0;
if (fd1 == NULL) {
snprintf(IObuff, IOSIZE, e_notread, fname1);
IObufflen = vim_snprintf_safelen(IObuff, IOSIZE, e_cant_read_file_str, fname1);
} else {
FILE *const fd2 = os_fopen(fname2, READBIN);
if (fd2 == NULL) {
fclose(fd1);
snprintf(IObuff, IOSIZE, e_notread, fname2);
IObufflen = vim_snprintf_safelen(IObuff, IOSIZE, e_cant_read_file_str, fname2);
} else {
int64_t linecount = 1;
for (int64_t count = 0;; count++) {
@@ -418,20 +421,21 @@ static int assert_equalfile(typval_T *argvars)
const int c2 = fgetc(fd2);
if (c1 == EOF) {
if (c2 != EOF) {
xstrlcpy(IObuff, "first file is shorter", IOSIZE);
IObufflen = xstrlcpy(IObuff, "first file is shorter", IOSIZE);
}
break;
} else if (c2 == EOF) {
xstrlcpy(IObuff, "second file is shorter", IOSIZE);
IObufflen = xstrlcpy(IObuff, "second file is shorter", IOSIZE);
break;
} else {
line1[lineidx] = (char)c1;
line2[lineidx] = (char)c2;
lineidx++;
if (c1 != c2) {
snprintf(IObuff, IOSIZE,
"difference at byte %" PRId64 ", line %" PRId64,
count, linecount);
IObufflen
= vim_snprintf_safelen(IObuff, IOSIZE,
"difference at byte %" PRId64 ", line %" PRId64,
count, linecount);
break;
}
}
@@ -449,26 +453,26 @@ static int assert_equalfile(typval_T *argvars)
}
}
if (IObuff[0] != NUL) {
if (IObufflen > 0) {
garray_T ga;
prepare_assert_error(&ga);
if (argvars[2].v_type != VAR_UNKNOWN) {
char *const tofree = encode_tv2echo(&argvars[2], NULL);
ga_concat(&ga, tofree);
xfree(tofree);
ga_concat(&ga, ": ");
GA_CONCAT_LITERAL(&ga, ": ");
}
ga_concat(&ga, IObuff);
ga_concat_len(&ga, IObuff, IObufflen);
if (lineidx > 0) {
line1[lineidx] = NUL;
line2[lineidx] = NUL;
ga_concat(&ga, " after \"");
ga_concat(&ga, line1);
GA_CONCAT_LITERAL(&ga, " after \"");
ga_concat_len(&ga, line1, (size_t)lineidx);
if (strcmp(line1, line2) != 0) {
ga_concat(&ga, "\" vs \"");
ga_concat(&ga, line2);
GA_CONCAT_LITERAL(&ga, "\" vs \"");
ga_concat_len(&ga, line2, (size_t)lineidx);
}
ga_concat(&ga, "\"");
GA_CONCAT_LITERAL(&ga, "\"");
}
assert_error(&ga);
ga_clear(&ga);
@@ -498,7 +502,7 @@ void f_assert_exception(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
const char *const error = tv_get_string_chk(&argvars[0]);
if (*get_vim_var_str(VV_EXCEPTION) == NUL) {
prepare_assert_error(&ga);
ga_concat(&ga, "v:exception is not set");
GA_CONCAT_LITERAL(&ga, "v:exception is not set");
assert_error(&ga);
ga_clear(&ga);
rettv->vval.v_number = 1;
@@ -547,7 +551,7 @@ void f_assert_fails(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (called_emsg == called_emsg_before) {
prepare_assert_error(&ga);
ga_concat(&ga, "command did not fail: ");
GA_CONCAT_LITERAL(&ga, "command did not fail: ");
assert_append_cmd_or_arg(&ga, argvars, cmd);
assert_error(&ga);
ga_clear(&ga);
@@ -633,7 +637,7 @@ void f_assert_fails(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
fill_assert_error(&ga, &argvars[2], expected_str,
&argvars[error_found_index], &actual_tv, ASSERT_FAILS);
ga_concat(&ga, ": ");
GA_CONCAT_LITERAL(&ga, ": ");
assert_append_cmd_or_arg(&ga, argvars, cmd);
assert_error(&ga);
ga_clear(&ga);