mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
patch 8.2.0149: maintaining a Vim9 branch separately is more work
Problem: Maintaining a Vim9 branch separately is more work. Solution: Merge the Vim9 script changes.
This commit is contained in:
498
src/eval.c
498
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)
|
||||
@@ -3412,11 +3355,121 @@ get_option_tv(
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
Reference in New Issue
Block a user