mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
patch 8.2.5003: cannot do bitwise shifts
Problem: Cannot do bitwise shifts. Solution: Add the >> and << operators. (Yegappan Lakshmanan, closes #8457)
This commit is contained in:
committed by
Bram Moolenaar
parent
9b2edfd3bf
commit
a061f34191
163
src/eval.c
163
src/eval.c
@@ -49,10 +49,11 @@ static int eval2(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
||||
static int eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
||||
static int eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
||||
static int eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
||||
static int eval6(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string);
|
||||
static int eval7t(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string);
|
||||
static int eval6(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
||||
static int eval7(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string);
|
||||
static int eval7_leader(typval_T *rettv, int numeric_only, char_u *start_leader, char_u **end_leaderp);
|
||||
static int eval8(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string);
|
||||
static int eval9(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string);
|
||||
static int eval9_leader(typval_T *rettv, int numeric_only, char_u *start_leader, char_u **end_leaderp);
|
||||
|
||||
static int free_unref_items(int copyID);
|
||||
static char_u *make_expanded_name(char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end);
|
||||
@@ -638,7 +639,7 @@ deref_function_name(
|
||||
char_u *name = *arg;
|
||||
|
||||
ref.v_type = VAR_UNKNOWN;
|
||||
if (eval7(arg, &ref, evalarg, FALSE) == FAIL)
|
||||
if (eval9(arg, &ref, evalarg, FALSE) == FAIL)
|
||||
{
|
||||
dictitem_T *v;
|
||||
|
||||
@@ -2591,7 +2592,7 @@ eval2(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
||||
int getnext;
|
||||
|
||||
/*
|
||||
* Get the first variable.
|
||||
* Get the first expression.
|
||||
*/
|
||||
if (eval3(arg, rettv, evalarg) == FAIL)
|
||||
return FAIL;
|
||||
@@ -2717,7 +2718,7 @@ eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
||||
int getnext;
|
||||
|
||||
/*
|
||||
* Get the first variable.
|
||||
* Get the first expression.
|
||||
*/
|
||||
if (eval4(arg, rettv, evalarg) == FAIL)
|
||||
return FAIL;
|
||||
@@ -2856,12 +2857,13 @@ eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
||||
int type_is = FALSE;
|
||||
|
||||
/*
|
||||
* Get the first variable.
|
||||
* Get the first expression.
|
||||
*/
|
||||
if (eval5(arg, rettv, evalarg) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
p = eval_next_non_blank(*arg, evalarg, &getnext);
|
||||
|
||||
type = get_compare_type(p, &len, &type_is);
|
||||
|
||||
/*
|
||||
@@ -2991,7 +2993,120 @@ eval_addlist(typval_T *tv1, typval_T *tv2)
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle fourth level expression:
|
||||
* Handle the bitwise left/right shift operator expression:
|
||||
* var1 << var2
|
||||
* var1 >> var2
|
||||
*
|
||||
* "arg" must point to the first non-white of the expression.
|
||||
* "arg" is advanced to just after the recognized expression.
|
||||
*
|
||||
* Return OK or FAIL.
|
||||
*/
|
||||
static int
|
||||
eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
||||
{
|
||||
/*
|
||||
* Get the first expression.
|
||||
*/
|
||||
if (eval6(arg, rettv, evalarg) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
/*
|
||||
* Repeat computing, until no '<<' or '>>' is following.
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
char_u *p;
|
||||
int getnext;
|
||||
exprtype_T type;
|
||||
int evaluate;
|
||||
typval_T var2;
|
||||
int vim9script;
|
||||
|
||||
p = eval_next_non_blank(*arg, evalarg, &getnext);
|
||||
if (p[0] == '<' && p[1] == '<')
|
||||
type = EXPR_LSHIFT;
|
||||
else if (p[0] == '>' && p[1] == '>')
|
||||
type = EXPR_RSHIFT;
|
||||
else
|
||||
return OK;
|
||||
|
||||
// Handle a bitwise left or right shift operator
|
||||
if (rettv->v_type != VAR_NUMBER)
|
||||
{
|
||||
// left operand should be a number
|
||||
emsg(_(e_bitshift_ops_must_be_number));
|
||||
clear_tv(rettv);
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
|
||||
vim9script = in_vim9script();
|
||||
if (getnext)
|
||||
{
|
||||
*arg = eval_next_line(*arg, evalarg);
|
||||
p = *arg;
|
||||
}
|
||||
else if (evaluate && vim9script && !VIM_ISWHITE(**arg))
|
||||
{
|
||||
error_white_both(*arg, 2);
|
||||
clear_tv(rettv);
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the second variable.
|
||||
*/
|
||||
if (evaluate && vim9script && !IS_WHITE_OR_NUL(p[2]))
|
||||
{
|
||||
error_white_both(p, 2);
|
||||
clear_tv(rettv);
|
||||
return FAIL;
|
||||
}
|
||||
*arg = skipwhite_and_linebreak(p + 2, evalarg);
|
||||
if (eval6(arg, &var2, evalarg) == FAIL)
|
||||
{
|
||||
clear_tv(rettv);
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
if (var2.v_type != VAR_NUMBER || var2.vval.v_number < 0)
|
||||
{
|
||||
// right operand should be a positive number
|
||||
if (var2.v_type != VAR_NUMBER)
|
||||
emsg(_(e_bitshift_ops_must_be_number));
|
||||
else
|
||||
emsg(_(e_bitshift_ops_must_be_postive));
|
||||
clear_tv(rettv);
|
||||
clear_tv(&var2);
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
if (evaluate)
|
||||
{
|
||||
if (var2.vval.v_number > MAX_LSHIFT_BITS)
|
||||
// shifting more bits than we have always results in zero
|
||||
rettv->vval.v_number = 0;
|
||||
else if (type == EXPR_LSHIFT)
|
||||
rettv->vval.v_number =
|
||||
rettv->vval.v_number << var2.vval.v_number;
|
||||
else
|
||||
{
|
||||
rettv->vval.v_number =
|
||||
rettv->vval.v_number >> var2.vval.v_number;
|
||||
// clear the topmost sign bit
|
||||
rettv->vval.v_number &= ~((uvarnumber_T)1 << MAX_LSHIFT_BITS);
|
||||
}
|
||||
}
|
||||
|
||||
clear_tv(&var2);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle fifth level expression:
|
||||
* + number addition, concatenation of list or blob
|
||||
* - number subtraction
|
||||
* . string concatenation (if script version is 1)
|
||||
@@ -3003,12 +3118,12 @@ eval_addlist(typval_T *tv1, typval_T *tv2)
|
||||
* Return OK or FAIL.
|
||||
*/
|
||||
static int
|
||||
eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
||||
eval6(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
||||
{
|
||||
/*
|
||||
* Get the first variable.
|
||||
* Get the first expression.
|
||||
*/
|
||||
if (eval6(arg, rettv, evalarg, FALSE) == FAIL)
|
||||
if (eval7(arg, rettv, evalarg, FALSE) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
/*
|
||||
@@ -3086,7 +3201,7 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
||||
return FAIL;
|
||||
}
|
||||
*arg = skipwhite_and_linebreak(*arg + oplen, evalarg);
|
||||
if (eval6(arg, &var2, evalarg, !vim9script && op == '.') == FAIL)
|
||||
if (eval7(arg, &var2, evalarg, !vim9script && op == '.') == FAIL)
|
||||
{
|
||||
clear_tv(rettv);
|
||||
return FAIL;
|
||||
@@ -3221,7 +3336,7 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle fifth level expression:
|
||||
* Handle sixth level expression:
|
||||
* * number multiplication
|
||||
* / number division
|
||||
* % number modulo
|
||||
@@ -3232,7 +3347,7 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
||||
* Return OK or FAIL.
|
||||
*/
|
||||
static int
|
||||
eval6(
|
||||
eval7(
|
||||
char_u **arg,
|
||||
typval_T *rettv,
|
||||
evalarg_T *evalarg,
|
||||
@@ -3243,9 +3358,9 @@ eval6(
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Get the first variable.
|
||||
* Get the first expression.
|
||||
*/
|
||||
if (eval7t(arg, rettv, evalarg, want_string) == FAIL)
|
||||
if (eval8(arg, rettv, evalarg, want_string) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
/*
|
||||
@@ -3318,7 +3433,7 @@ eval6(
|
||||
return FAIL;
|
||||
}
|
||||
*arg = skipwhite_and_linebreak(*arg + 1, evalarg);
|
||||
if (eval7t(arg, &var2, evalarg, FALSE) == FAIL)
|
||||
if (eval8(arg, &var2, evalarg, FALSE) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
if (evaluate)
|
||||
@@ -3415,7 +3530,7 @@ eval6(
|
||||
* Return OK or FAIL.
|
||||
*/
|
||||
static int
|
||||
eval7t(
|
||||
eval8(
|
||||
char_u **arg,
|
||||
typval_T *rettv,
|
||||
evalarg_T *evalarg,
|
||||
@@ -3453,7 +3568,7 @@ eval7t(
|
||||
*arg = skipwhite_and_linebreak(*arg, evalarg);
|
||||
}
|
||||
|
||||
res = eval7(arg, rettv, evalarg, want_string);
|
||||
res = eval9(arg, rettv, evalarg, want_string);
|
||||
|
||||
if (want_type != NULL && evaluate)
|
||||
{
|
||||
@@ -3642,7 +3757,7 @@ handle_predefined(char_u *s, int len, typval_T *rettv)
|
||||
* Return OK or FAIL.
|
||||
*/
|
||||
static int
|
||||
eval7(
|
||||
eval9(
|
||||
char_u **arg,
|
||||
typval_T *rettv,
|
||||
evalarg_T *evalarg,
|
||||
@@ -3720,7 +3835,7 @@ eval7(
|
||||
// "->" follows.
|
||||
if (ret == OK && evaluate && end_leader > start_leader
|
||||
&& rettv->v_type != VAR_BLOB)
|
||||
ret = eval7_leader(rettv, TRUE, start_leader, &end_leader);
|
||||
ret = eval9_leader(rettv, TRUE, start_leader, &end_leader);
|
||||
break;
|
||||
|
||||
/*
|
||||
@@ -3920,19 +4035,19 @@ eval7(
|
||||
* Apply logical NOT and unary '-', from right to left, ignore '+'.
|
||||
*/
|
||||
if (ret == OK && evaluate && end_leader > start_leader)
|
||||
ret = eval7_leader(rettv, FALSE, start_leader, &end_leader);
|
||||
ret = eval9_leader(rettv, FALSE, start_leader, &end_leader);
|
||||
|
||||
--recurse;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply the leading "!" and "-" before an eval7 expression to "rettv".
|
||||
* Apply the leading "!" and "-" before an eval9 expression to "rettv".
|
||||
* When "numeric_only" is TRUE only handle "+" and "-".
|
||||
* Adjusts "end_leaderp" until it is at "start_leader".
|
||||
*/
|
||||
static int
|
||||
eval7_leader(
|
||||
eval9_leader(
|
||||
typval_T *rettv,
|
||||
int numeric_only,
|
||||
char_u *start_leader,
|
||||
|
Reference in New Issue
Block a user