summaryrefslogtreecommitdiffstats
path: root/src/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c498
1 files changed, 283 insertions, 215 deletions
diff --git a/src/eval.c b/src/eval.c
index fe6dee1f1b..72f932498b 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -20,12 +20,10 @@
# include <float.h>
#endif
-static char *e_missbrac = N_("E111: Missing ']'");
static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary");
#ifdef FEAT_FLOAT
static char *e_float_as_string = N_("E806: using Float as a String");
#endif
-static char *e_nowhitespace = N_("E274: No white space allowed before parenthesis");
#define NAMESPACE_CHAR (char_u *)"abglstvw"
@@ -60,10 +58,7 @@ static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string);
static int eval7(char_u **arg, typval_T *rettv, int evaluate, int want_string);
static int eval7_leader(typval_T *rettv, char_u *start_leader, char_u **end_leaderp);
-static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate);
-static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate);
static int free_unref_items(int copyID);
-static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate);
static char_u *make_expanded_name(char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end);
static int tv_check_lock(typval_T *tv, char_u *name, int use_gettext);
@@ -222,6 +217,11 @@ eval1_emsg(char_u **arg, typval_T *rettv, int evaluate)
return ret;
}
+/*
+ * Evaluate an expression, which can be a function, partial or string.
+ * Pass arguments "argv[argc]".
+ * Return the result in "rettv" and OK or FAIL.
+ */
int
eval_expr_typval(typval_T *expr, typval_T *argv, int argc, typval_T *rettv)
{
@@ -243,14 +243,22 @@ eval_expr_typval(typval_T *expr, typval_T *argv, int argc, typval_T *rettv)
{
partial_T *partial = expr->vval.v_partial;
- s = partial_name(partial);
- if (s == NULL || *s == NUL)
- return FAIL;
- vim_memset(&funcexe, 0, sizeof(funcexe));
- funcexe.evaluate = TRUE;
- funcexe.partial = partial;
- if (call_func(s, -1, rettv, argc, argv, &funcexe) == FAIL)
- return FAIL;
+ if (partial->pt_func != NULL && partial->pt_func->uf_dfunc_idx >= 0)
+ {
+ if (call_def_function(partial->pt_func, argc, argv, rettv) == FAIL)
+ return FAIL;
+ }
+ else
+ {
+ s = partial_name(partial);
+ if (s == NULL || *s == NUL)
+ return FAIL;
+ vim_memset(&funcexe, 0, sizeof(funcexe));
+ funcexe.evaluate = TRUE;
+ funcexe.partial = partial;
+ if (call_func(s, -1, rettv, argc, argv, &funcexe) == FAIL)
+ return FAIL;
+ }
}
else
{
@@ -652,6 +660,7 @@ get_lval(
// Find the end of the name.
p = find_name_end(name, &expr_start, &expr_end, fne_flags);
+ lp->ll_name_end = p;
if (expr_start != NULL)
{
// Don't expand the name when we already know there is an error.
@@ -678,8 +687,20 @@ get_lval(
lp->ll_name = lp->ll_exp_name;
}
else
+ {
lp->ll_name = name;
+ if (current_sctx.sc_version == SCRIPT_VERSION_VIM9 && *p == ':')
+ {
+ scriptitem_T *si = &SCRIPT_ITEM(current_sctx.sc_sid);
+ char_u *tp = skipwhite(p + 1);
+
+ // parse the type after the name
+ lp->ll_type = parse_type(&tp, &si->sn_type_list);
+ lp->ll_name_end = tp;
+ }
+ }
+
// Without [idx] or .key we are done.
if ((*p != '[' && *p != '.') || lp->ll_name == NULL)
return p;
@@ -1002,6 +1023,7 @@ get_lval(
}
clear_tv(&var1);
+ lp->ll_name_end = p;
return p;
}
@@ -1027,7 +1049,7 @@ set_var_lval(
char_u *endp,
typval_T *rettv,
int copy,
- int is_const, // Disallow to modify existing variable for :const
+ int flags, // LET_IS_CONST and/or LET_NO_COMMAND
char_u *op)
{
int cc;
@@ -1093,7 +1115,7 @@ set_var_lval(
{
typval_T tv;
- if (is_const)
+ if (flags & LET_IS_CONST)
{
emsg(_(e_cannot_mod));
*endp = cc;
@@ -1114,7 +1136,7 @@ set_var_lval(
}
}
else
- set_var_const(lp->ll_name, rettv, copy, is_const);
+ set_var_const(lp->ll_name, lp->ll_type, rettv, copy, flags);
*endp = cc;
}
else if (var_check_lock(lp->ll_newkey == NULL
@@ -1126,7 +1148,7 @@ set_var_lval(
listitem_T *ll_li = lp->ll_li;
int ll_n1 = lp->ll_n1;
- if (is_const)
+ if (flags & LET_IS_CONST)
{
emsg(_("E996: Cannot lock a range"));
return;
@@ -1185,7 +1207,7 @@ set_var_lval(
/*
* Assign to a List or Dictionary item.
*/
- if (is_const)
+ if (flags & LET_IS_CONST)
{
emsg(_("E996: Cannot lock a list or dict"));
return;
@@ -1250,6 +1272,7 @@ tv_op(typval_T *tv1, typval_T *tv2, char_u *op)
switch (tv1->v_type)
{
case VAR_UNKNOWN:
+ case VAR_VOID:
case VAR_DICT:
case VAR_FUNC:
case VAR_PARTIAL:
@@ -1392,14 +1415,14 @@ eval_for_line(
if (fi == NULL)
return NULL;
- expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon);
+ expr = skip_var_list(arg, TRUE, &fi->fi_varcount, &fi->fi_semicolon);
if (expr == NULL)
return fi;
expr = skipwhite(expr);
if (expr[0] != 'i' || expr[1] != 'n' || !VIM_ISWHITE(expr[2]))
{
- emsg(_("E690: Missing \"in\" after :for"));
+ emsg(_(e_missing_in));
return fi;
}
@@ -1420,6 +1443,9 @@ eval_for_line(
}
else
{
+ // Need a real list here.
+ range_list_materialize(l);
+
// No need to increment the refcount, it's already set for
// the list being used in "tv".
fi->fi_list = l;
@@ -1436,7 +1462,7 @@ eval_for_line(
// Make a copy, so that the iteration still works when the
// blob is changed.
- blob_copy(&tv, &btv);
+ blob_copy(tv.vval.v_blob, &btv);
fi->fi_blob = btv.vval.v_blob;
}
clear_tv(&tv);
@@ -1478,7 +1504,7 @@ next_for_item(void *fi_void, char_u *arg)
tv.vval.v_number = blob_get(fi->fi_blob, fi->fi_bi);
++fi->fi_bi;
return ex_let_vars(arg, &tv, TRUE, fi->fi_semicolon,
- fi->fi_varcount, FALSE, NULL) == OK;
+ fi->fi_varcount, 0, NULL) == OK;
}
item = fi->fi_lw.lw_item;
@@ -1488,7 +1514,7 @@ next_for_item(void *fi_void, char_u *arg)
{
fi->fi_lw.lw_item = item->li_next;
result = (ex_let_vars(arg, &item->li_tv, TRUE, fi->fi_semicolon,
- fi->fi_varcount, FALSE, NULL) == OK);
+ fi->fi_varcount, 0, NULL) == OK);
}
return result;
}
@@ -1814,7 +1840,7 @@ eval1(char_u **arg, typval_T *rettv, int evaluate)
*/
if ((*arg)[0] != ':')
{
- emsg(_("E109: Missing ':' after '?'"));
+ emsg(_(e_missing_colon));
if (evaluate && result)
clear_tv(rettv);
return FAIL;
@@ -2089,6 +2115,43 @@ eval4(char_u **arg, typval_T *rettv, int evaluate)
return OK;
}
+ void
+eval_addblob(typval_T *tv1, typval_T *tv2)
+{
+ blob_T *b1 = tv1->vval.v_blob;
+ blob_T *b2 = tv2->vval.v_blob;
+ blob_T *b = blob_alloc();
+ int i;
+
+ if (b != NULL)
+ {
+ for (i = 0; i < blob_len(b1); i++)
+ ga_append(&b->bv_ga, blob_get(b1, i));
+ for (i = 0; i < blob_len(b2); i++)
+ ga_append(&b->bv_ga, blob_get(b2, i));
+
+ clear_tv(tv1);
+ rettv_blob_set(tv1, b);
+ }
+}
+
+ int
+eval_addlist(typval_T *tv1, typval_T *tv2)
+{
+ typval_T var3;
+
+ // concatenate Lists
+ if (list_concat(tv1->vval.v_list, tv2->vval.v_list, &var3) == FAIL)
+ {
+ clear_tv(tv1);
+ clear_tv(tv2);
+ return FAIL;
+ }
+ clear_tv(tv1);
+ *tv1 = var3;
+ return OK;
+}
+
/*
* Handle fourth level expression:
* + number addition
@@ -2105,7 +2168,6 @@ eval4(char_u **arg, typval_T *rettv, int evaluate)
eval5(char_u **arg, typval_T *rettv, int evaluate)
{
typval_T var2;
- typval_T var3;
int op;
varnumber_T n1, n2;
#ifdef FEAT_FLOAT
@@ -2189,36 +2251,12 @@ eval5(char_u **arg, typval_T *rettv, int evaluate)
}
else if (op == '+' && rettv->v_type == VAR_BLOB
&& var2.v_type == VAR_BLOB)
- {
- blob_T *b1 = rettv->vval.v_blob;
- blob_T *b2 = var2.vval.v_blob;
- blob_T *b = blob_alloc();
- int i;
-
- if (b != NULL)
- {
- for (i = 0; i < blob_len(b1); i++)
- ga_append(&b->bv_ga, blob_get(b1, i));
- for (i = 0; i < blob_len(b2); i++)
- ga_append(&b->bv_ga, blob_get(b2, i));
-
- clear_tv(rettv);
- rettv_blob_set(rettv, b);
- }
- }
+ eval_addblob(rettv, &var2);
else if (op == '+' && rettv->v_type == VAR_LIST
&& var2.v_type == VAR_LIST)
{
- // concatenate Lists
- if (list_concat(rettv->vval.v_list, var2.vval.v_list,
- &var3) == FAIL)
- {
- clear_tv(rettv);
- clear_tv(&var2);
+ if (eval_addlist(rettv, &var2) == FAIL)
return FAIL;
- }
- clear_tv(rettv);
- *rettv = var3;
}
else
{
@@ -2424,7 +2462,7 @@ eval6(
}
else
{
- emsg(_("E804: Cannot use '%' with Float"));
+ emsg(_(e_modulus));
return FAIL;
}
rettv->v_type = VAR_FLOAT;
@@ -2462,6 +2500,7 @@ eval6(
* $VAR environment variable
* (expression) nested expression
* [expr, expr] List
+ * {arg, arg -> expr} Lambda
* {key: val, key: val} Dictionary
* #{key: val, key: val} Dictionary with literal keys
*
@@ -2483,9 +2522,8 @@ eval7(
char_u **arg,
typval_T *rettv,
int evaluate,
- int want_string UNUSED) // after "." operator
+ int want_string) // after "." operator
{
- varnumber_T n;
int len;
char_u *s;
char_u *start_leader, *end_leader;
@@ -2532,105 +2570,8 @@ eval7(
case '7':
case '8':
case '9':
- case '.':
- {
-#ifdef FEAT_FLOAT
- char_u *p;
- int get_float = FALSE;
-
- // We accept a float when the format matches
- // "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very
- // strict to avoid backwards compatibility problems.
- // With script version 2 and later the leading digit can be
- // omitted.
- // Don't look for a float after the "." operator, so that
- // ":let vers = 1.2.3" doesn't fail.
- if (**arg == '.')
- p = *arg;
- else
- p = skipdigits(*arg + 1);
- if (!want_string && p[0] == '.' && vim_isdigit(p[1]))
- {
- get_float = TRUE;
- p = skipdigits(p + 2);
- if (*p == 'e' || *p == 'E')
- {
- ++p;
- if (*p == '-' || *p == '+')
- ++p;
- if (!vim_isdigit(*p))
- get_float = FALSE;
- else
- p = skipdigits(p + 1);
- }
- if (ASCII_ISALPHA(*p) || *p == '.')
- get_float = FALSE;
- }
- if (get_float)
- {
- float_T f;
-
- *arg += string2float(*arg, &f);
- if (evaluate)
- {
- rettv->v_type = VAR_FLOAT;
- rettv->vval.v_float = f;
- }
- }
- else
-#endif
- if (**arg == '0' && ((*arg)[1] == 'z' || (*arg)[1] == 'Z'))
- {
- char_u *bp;
- blob_T *blob = NULL; // init for gcc
-
- // Blob constant: 0z0123456789abcdef
- if (evaluate)
- blob = blob_alloc();
- for (bp = *arg + 2; vim_isxdigit(bp[0]); bp += 2)
- {
- if (!vim_isxdigit(bp[1]))
- {
- if (blob != NULL)
- {
- emsg(_("E973: Blob literal should have an even number of hex characters"));
- ga_clear(&blob->bv_ga);
- VIM_CLEAR(blob);
- }
- ret = FAIL;
- break;
- }
- if (blob != NULL)
- ga_append(&blob->bv_ga,
- (hex2nr(*bp) << 4) + hex2nr(*(bp+1)));
- if (bp[2] == '.' && vim_isxdigit(bp[3]))
- ++bp;
- }
- if (blob != NULL)
- rettv_blob_set(rettv, blob);
- *arg = bp;
- }
- else
- {
- // decimal, hex or octal number
- vim_str2nr(*arg, NULL, &len, current_sctx.sc_version >= 4
- ? STR2NR_NO_OCT + STR2NR_QUOTE
- : STR2NR_ALL, &n, NULL, 0, TRUE);
- if (len == 0)
- {
- semsg(_(e_invexpr2), *arg);
- ret = FAIL;
- break;
- }
- *arg += len;
- if (evaluate)
- {
- rettv->v_type = VAR_NUMBER;
- rettv->vval.v_number = n;
- }
- }
+ case '.': ret = get_number_tv(arg, rettv, evaluate, want_string);
break;
- }
/*
* String constant: "string".
@@ -2647,7 +2588,7 @@ eval7(
/*
* List: [expr, expr]
*/
- case '[': ret = get_list_tv(arg, rettv, evaluate);
+ case '[': ret = get_list_tv(arg, rettv, evaluate, TRUE);
break;
/*
@@ -2706,7 +2647,7 @@ eval7(
++*arg;
else if (ret == OK)
{
- emsg(_("E110: Missing ')'"));
+ emsg(_(e_missing_close));
clear_tv(rettv);
ret = FAIL;
}
@@ -2907,7 +2848,7 @@ eval_lambda(
if (*skipwhite(*arg) == '(')
semsg(_(e_nowhitespace));
else
- semsg(_(e_missingparen), "lambda");
+ semsg(_(e_missing_paren), "lambda");
}
clear_tv(rettv);
ret = FAIL;
@@ -2961,7 +2902,7 @@ eval_method(
if (**arg != '(')
{
if (verbose)
- semsg(_(e_missingparen), name);
+ semsg(_(e_missing_paren), name);
ret = FAIL;
}
else if (VIM_ISWHITE((*arg)[-1]))
@@ -3024,6 +2965,7 @@ eval_index(
emsg(_("E909: Cannot index a special variable"));
return FAIL;
case VAR_UNKNOWN:
+ case VAR_VOID:
if (evaluate)
return FAIL;
// FALLTHROUGH
@@ -3129,6 +3071,7 @@ eval_index(
switch (rettv->v_type)
{
case VAR_UNKNOWN:
+ case VAR_VOID:
case VAR_FUNC:
case VAR_PARTIAL:
case VAR_FLOAT:
@@ -3377,7 +3320,7 @@ get_option_tv(
if (opt_type == -3) // invalid name
{
if (rettv != NULL)
- semsg(_("E113: Unknown option: %s"), *arg);
+ semsg(_(e_unknown_option), *arg);
ret = FAIL;
}
else if (rettv != NULL)
@@ -3413,10 +3356,120 @@ get_option_tv(
}
/*
+ * Allocate a variable for a number constant. Also deals with "0z" for blob.
+ * Return OK or FAIL.
+ */
+ int
+get_number_tv(
+ char_u **arg,
+ typval_T *rettv,
+ int evaluate,
+ int want_string UNUSED)
+{
+ int len;
+#ifdef FEAT_FLOAT
+ char_u *p;
+ int get_float = FALSE;
+
+ // We accept a float when the format matches
+ // "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very
+ // strict to avoid backwards compatibility problems.
+ // With script version 2 and later the leading digit can be
+ // omitted.
+ // Don't look for a float after the "." operator, so that
+ // ":let vers = 1.2.3" doesn't fail.
+ if (**arg == '.')
+ p = *arg;
+ else
+ p = skipdigits(*arg + 1);
+ if (!want_string && p[0] == '.' && vim_isdigit(p[1]))
+ {
+ get_float = TRUE;
+ p = skipdigits(p + 2);
+ if (*p == 'e' || *p == 'E')
+ {
+ ++p;
+ if (*p == '-' || *p == '+')
+ ++p;
+ if (!vim_isdigit(*p))
+ get_float = FALSE;
+ else
+ p = skipdigits(p + 1);
+ }
+ if (ASCII_ISALPHA(*p) || *p == '.')
+ get_float = FALSE;
+ }
+ if (get_float)
+ {
+ float_T f;
+
+ *arg += string2float(*arg, &f);
+ if (evaluate)
+ {
+ rettv->v_type = VAR_FLOAT;
+ rettv->vval.v_float = f;
+ }
+ }
+ else
+#endif
+ if (**arg == '0' && ((*arg)[1] == 'z' || (*arg)[1] == 'Z'))
+ {
+ char_u *bp;
+ blob_T *blob = NULL; // init for gcc
+
+ // Blob constant: 0z0123456789abcdef
+ if (evaluate)
+ blob = blob_alloc();
+ for (bp = *arg + 2; vim_isxdigit(bp[0]); bp += 2)
+ {
+ if (!vim_isxdigit(bp[1]))
+ {
+ if (blob != NULL)
+ {
+ emsg(_("E973: Blob literal should have an even number of hex characters"));
+ ga_clear(&blob->bv_ga);
+ VIM_CLEAR(blob);
+ }
+ return FAIL;
+ }
+ if (blob != NULL)
+ ga_append(&blob->bv_ga,
+ (hex2nr(*bp) << 4) + hex2nr(*(bp+1)));
+ if (bp[2] == '.' && vim_isxdigit(bp[3]))
+ ++bp;
+ }
+ if (blob != NULL)
+ rettv_blob_set(rettv, blob);
+ *arg = bp;
+ }
+ else
+ {
+ varnumber_T n;
+
+ // decimal, hex or octal number
+ vim_str2nr(*arg, NULL, &len, current_sctx.sc_version >= 4
+ ? STR2NR_NO_OCT + STR2NR_QUOTE
+ : STR2NR_ALL, &n, NULL, 0, TRUE);
+ if (len == 0)
+ {
+ semsg(_(e_invexpr2), *arg);
+ return FAIL;
+ }
+ *arg += len;
+ if (evaluate)
+ {
+ rettv->v_type = VAR_NUMBER;
+ rettv->vval.v_number = n;
+ }
+ }
+ return OK;
+}
+
+/*
* Allocate a variable for a string constant.
* Return OK or FAIL.
*/
- static int
+ int
get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
{
char_u *p;
@@ -3553,7 +3606,7 @@ get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
* Allocate a variable for a 'str''ing' constant.
* Return OK or FAIL.
*/
- static int
+ int
get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate)
{
char_u *p;
@@ -3772,6 +3825,8 @@ tv_equal(
return blob_equal(tv1->vval.v_blob, tv2->vval.v_blob);
case VAR_NUMBER:
+ case VAR_BOOL:
+ case VAR_SPECIAL:
return tv1->vval.v_number == tv2->vval.v_number;
case VAR_STRING:
@@ -3779,10 +3834,6 @@ tv_equal(
s2 = tv_get_string_buf(tv2, buf2);
return ((ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2)) == 0);
- case VAR_BOOL:
- case VAR_SPECIAL:
- return tv1->vval.v_number == tv2->vval.v_number;
-
case VAR_FLOAT:
#ifdef FEAT_FLOAT
return tv1->vval.v_float == tv2->vval.v_float;
@@ -3795,9 +3846,11 @@ tv_equal(
#ifdef FEAT_JOB_CHANNEL
return tv1->vval.v_channel == tv2->vval.v_channel;
#endif
+
case VAR_FUNC:
case VAR_PARTIAL:
case VAR_UNKNOWN:
+ case VAR_VOID:
break;
}
@@ -4511,6 +4564,7 @@ echo_string_core(
case VAR_NUMBER:
case VAR_UNKNOWN:
+ case VAR_VOID:
*tofree = NULL;
r = tv_get_string_buf(tv, numbuf);
break;
@@ -4668,7 +4722,7 @@ string2float(
* If the environment variable was not set, silently assume it is empty.
* Return FAIL if the name is invalid.
*/
- static int
+ int
get_env_tv(char_u **arg, typval_T *rettv, int evaluate)
{
char_u *string = NULL;
@@ -5363,6 +5417,7 @@ free_tv(typval_T *varp)
case VAR_NUMBER:
case VAR_FLOAT:
case VAR_UNKNOWN:
+ case VAR_VOID:
case VAR_BOOL:
case VAR_SPECIAL:
break;
@@ -5425,6 +5480,7 @@ clear_tv(typval_T *varp)
varp->vval.v_channel = NULL;
#endif
case VAR_UNKNOWN:
+ case VAR_VOID:
break;
}
varp->v_lock = 0;
@@ -5503,6 +5559,7 @@ tv_get_number_chk(typval_T *varp, int *denote)
emsg(_("E974: Using a Blob as a Number"));
break;
case VAR_UNKNOWN:
+ case VAR_VOID:
internal_error("tv_get_number(UNKNOWN)");
break;
}
@@ -5556,6 +5613,7 @@ tv_get_float(typval_T *varp)
emsg(_("E975: Using a Blob as a Float"));
break;
case VAR_UNKNOWN:
+ case VAR_VOID:
internal_error("tv_get_float(UNKNOWN)");
break;
}
@@ -5678,6 +5736,7 @@ tv_get_string_buf_chk(typval_T *varp, char_u *buf)
#endif
break;
case VAR_UNKNOWN:
+ case VAR_VOID:
emsg(_(e_inval_string));
break;
}
@@ -5826,6 +5885,7 @@ copy_tv(typval_T *from, typval_T *to)
}
break;
case VAR_UNKNOWN:
+ case VAR_VOID:
internal_error("copy_tv(UNKNOWN)");
break;
}
@@ -5885,7 +5945,7 @@ item_copy(
ret = FAIL;
break;
case VAR_BLOB:
- ret = blob_copy(from, to);
+ ret = blob_copy(from->vval.v_blob, to);
break;
case VAR_DICT:
to->v_type = VAR_DICT;
@@ -5904,6 +5964,7 @@ item_copy(
ret = FAIL;
break;
case VAR_UNKNOWN:
+ case VAR_VOID:
internal_error("item_copy(UNKNOWN)");
ret = FAIL;
}
@@ -5911,6 +5972,59 @@ item_copy(
return ret;
}
+ void
+echo_one(typval_T *rettv, int with_space, int *atstart, int *needclr)
+{
+ char_u *tofree;
+ char_u numbuf[NUMBUFLEN];
+ char_u *p = echo_string(rettv, &tofree, numbuf, get_copyID());
+
+ if (*atstart)
+ {
+ *atstart = FALSE;
+ // Call msg_start() after eval1(), evaluating the expression
+ // may cause a message to appear.
+ if (with_space)
+ {
+ // Mark the saved text as finishing the line, so that what
+ // follows is displayed on a new line when scrolling back
+ // at the more prompt.
+ msg_sb_eol();
+ msg_start();
+ }
+ }
+ else if (with_space)
+ msg_puts_attr(" ", echo_attr);
+
+ if (p != NULL)
+ for ( ; *p != NUL && !got_int; ++p)
+ {
+ if (*p == '\n' || *p == '\r' || *p == TAB)
+ {
+ if (*p != TAB && *needclr)
+ {
+ // remove any text still there from the command
+ msg_clr_eos();
+ *needclr = FALSE;
+ }
+ msg_putchar_attr(*p, echo_attr);
+ }
+ else
+ {
+ if (has_mbyte)
+ {
+ int i = (*mb_ptr2len)(p);
+
+ (void)msg_outtrans_len_attr(p, i, echo_attr);
+ p += i - 1;
+ }
+ else
+ (void)msg_outtrans_len_attr(p, 1, echo_attr);
+ }
+ }
+ vim_free(tofree);
+}
+
/*
* ":echo expr1 ..." print each argument separated with a space, add a
* newline at the end.
@@ -5921,11 +6035,9 @@ ex_echo(exarg_T *eap)
{
char_u *arg = eap->arg;
typval_T rettv;
- char_u *tofree;
char_u *p;
int needclr = TRUE;
int atstart = TRUE;
- char_u numbuf[NUMBUFLEN];
int did_emsg_before = did_emsg;
int called_emsg_before = called_emsg;
@@ -5954,52 +6066,8 @@ ex_echo(exarg_T *eap)
need_clr_eos = FALSE;
if (!eap->skip)
- {
- if (atstart)
- {
- atstart = FALSE;
- // Call msg_start() after eval1(), evaluating the expression
- // may cause a message to appear.
- if (eap->cmdidx == CMD_echo)
- {
- // Mark the saved text as finishing the line, so that what
- // follows is displayed on a new line when scrolling back
- // at the more prompt.
- msg_sb_eol();
- msg_start();
- }
- }
- else if (eap->cmdidx == CMD_echo)
- msg_puts_attr(" ", echo_attr);
- p = echo_string(&rettv, &tofree, numbuf, get_copyID());
- if (p != NULL)
- for ( ; *p != NUL && !got_int; ++p)
- {
- if (*p == '\n' || *p == '\r' || *p == TAB)
- {
- if (*p != TAB && needclr)
- {
- // remove any text still there from the command
- msg_clr_eos();
- needclr = FALSE;
- }
- msg_putchar_attr(*p, echo_attr);
- }
- else
- {
- if (has_mbyte)
- {
- int i = (*mb_ptr2len)(p);
+ echo_one(&rettv, eap->cmdidx == CMD_echo, &atstart, &needclr);
- (void)msg_outtrans_len_attr(p, i, echo_attr);
- p += i - 1;
- }
- else
- (void)msg_outtrans_len_attr(p, 1, echo_attr);
- }
- }
- vim_free(tofree);
- }
clear_tv(&rettv);
arg = skipwhite(arg);
}
@@ -6369,7 +6437,7 @@ typval_compare(
case EXPR_SEQUAL: n1 = (f1 <= f2); break;
case EXPR_UNKNOWN:
case EXPR_MATCH:
- case EXPR_NOMATCH: break; // avoid gcc warning
+ default: break; // avoid gcc warning
}
}
#endif
@@ -6395,7 +6463,7 @@ typval_compare(
case EXPR_SEQUAL: n1 = (n1 <= n2); break;
case EXPR_UNKNOWN:
case EXPR_MATCH:
- case EXPR_NOMATCH: break; // avoid gcc warning
+ default: break; // avoid gcc warning
}
}
else
@@ -6425,7 +6493,7 @@ typval_compare(
n1 = !n1;
break;
- case EXPR_UNKNOWN: break; // avoid gcc warning
+ default: break; // avoid gcc warning
}
}
clear_tv(typ1);