diff options
-rw-r--r-- | src/eval.c | 355 | ||||
-rw-r--r-- | src/ex_cmds2.c | 29 | ||||
-rw-r--r-- | src/proto/eval.pro | 3 | ||||
-rw-r--r-- | src/version.c | 2 |
4 files changed, 187 insertions, 202 deletions
diff --git a/src/eval.c b/src/eval.c index b1f7a8606..e5c1dbf88 100644 --- a/src/eval.c +++ b/src/eval.c @@ -3596,7 +3596,13 @@ eval4(char_u **arg, typval_T *rettv, int evaluate) clear_tv(rettv); return FAIL; } - return typval_compare(rettv, &var2, type, type_is, ic, evaluate); + if (evaluate) + { + int ret = typval_compare(rettv, &var2, type, type_is, ic); + + clear_tv(&var2); + return ret; + } } return OK; @@ -9091,227 +9097,208 @@ fill_assert_error( } } - +/* + * Compare "typ1" and "typ2". Put the result in "typ1". + */ int typval_compare( typval_T *typ1, /* first operand */ typval_T *typ2, /* second operand */ exptype_T type, /* operator */ int type_is, /* TRUE for "is" and "isnot" */ - int ic, /* ignore case */ - int evaluate) + int ic) /* ignore case */ { int i; varnumber_T n1, n2; char_u *s1, *s2; char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; - if (evaluate) + if (type_is && typ1->v_type != typ2->v_type) { - if (type_is && typ1->v_type != typ2->v_type) + /* For "is" a different type always means FALSE, for "notis" + * it means TRUE. */ + n1 = (type == TYPE_NEQUAL); + } + else if (typ1->v_type == VAR_LIST || typ2->v_type == VAR_LIST) + { + if (type_is) { - /* For "is" a different type always means FALSE, for "notis" - * it means TRUE. */ - n1 = (type == TYPE_NEQUAL); + n1 = (typ1->v_type == typ2->v_type + && typ1->vval.v_list == typ2->vval.v_list); + if (type == TYPE_NEQUAL) + n1 = !n1; } - else if (typ1->v_type == VAR_LIST || typ2->v_type == VAR_LIST) + else if (typ1->v_type != typ2->v_type + || (type != TYPE_EQUAL && type != TYPE_NEQUAL)) { - if (type_is) - { - n1 = (typ1->v_type == typ2->v_type - && typ1->vval.v_list == typ2->vval.v_list); - if (type == TYPE_NEQUAL) - n1 = !n1; - } - else if (typ1->v_type != typ2->v_type - || (type != TYPE_EQUAL && type != TYPE_NEQUAL)) - { - if (typ1->v_type != typ2->v_type) - EMSG(_("E691: Can only compare List with List")); - else - EMSG(_("E692: Invalid operation for List")); - clear_tv(typ1); - clear_tv(typ2); - return FAIL; - } + if (typ1->v_type != typ2->v_type) + EMSG(_("E691: Can only compare List with List")); else - { - /* Compare two Lists for being equal or unequal. */ - n1 = list_equal(typ1->vval.v_list, typ2->vval.v_list, - ic, FALSE); - if (type == TYPE_NEQUAL) - n1 = !n1; - } + EMSG(_("E692: Invalid operation for List")); + clear_tv(typ1); + return FAIL; } - - else if (typ1->v_type == VAR_DICT || typ2->v_type == VAR_DICT) + else { - if (type_is) - { - n1 = (typ1->v_type == typ2->v_type - && typ1->vval.v_dict == typ2->vval.v_dict); - if (type == TYPE_NEQUAL) - n1 = !n1; - } - else if (typ1->v_type != typ2->v_type - || (type != TYPE_EQUAL && type != TYPE_NEQUAL)) - { - if (typ1->v_type != typ2->v_type) - EMSG(_("E735: Can only compare Dictionary with Dictionary")); - else - EMSG(_("E736: Invalid operation for Dictionary")); - clear_tv(typ1); - clear_tv(typ2); - return FAIL; - } - else - { - /* Compare two Dictionaries for being equal or unequal. */ - n1 = dict_equal(typ1->vval.v_dict, typ2->vval.v_dict, - ic, FALSE); - if (type == TYPE_NEQUAL) - n1 = !n1; - } + /* Compare two Lists for being equal or unequal. */ + n1 = list_equal(typ1->vval.v_list, typ2->vval.v_list, + ic, FALSE); + if (type == TYPE_NEQUAL) + n1 = !n1; } + } - else if (typ1->v_type == VAR_FUNC || typ2->v_type == VAR_FUNC - || typ1->v_type == VAR_PARTIAL || typ2->v_type == VAR_PARTIAL) + else if (typ1->v_type == VAR_DICT || typ2->v_type == VAR_DICT) + { + if (type_is) { - if (type != TYPE_EQUAL && type != TYPE_NEQUAL) - { - EMSG(_("E694: Invalid operation for Funcrefs")); - clear_tv(typ1); - clear_tv(typ2); - return FAIL; - } - if ((typ1->v_type == VAR_PARTIAL - && typ1->vval.v_partial == NULL) - || (typ2->v_type == VAR_PARTIAL - && typ2->vval.v_partial == NULL)) - /* when a partial is NULL assume not equal */ - n1 = FALSE; - else if (type_is) - { - if (typ1->v_type == VAR_FUNC && typ2->v_type == VAR_FUNC) - /* strings are considered the same if their value is - * the same */ - n1 = tv_equal(typ1, typ2, ic, FALSE); - else if (typ1->v_type == VAR_PARTIAL - && typ2->v_type == VAR_PARTIAL) - n1 = (typ1->vval.v_partial == typ2->vval.v_partial); - else - n1 = FALSE; - } - else - n1 = tv_equal(typ1, typ2, ic, FALSE); + n1 = (typ1->v_type == typ2->v_type + && typ1->vval.v_dict == typ2->vval.v_dict); if (type == TYPE_NEQUAL) n1 = !n1; } - -#ifdef FEAT_FLOAT - /* - * If one of the two variables is a float, compare as a float. - * When using "=~" or "!~", always compare as string. - */ - else if ((typ1->v_type == VAR_FLOAT || typ2->v_type == VAR_FLOAT) - && type != TYPE_MATCH && type != TYPE_NOMATCH) + else if (typ1->v_type != typ2->v_type + || (type != TYPE_EQUAL && type != TYPE_NEQUAL)) { - float_T f1, f2; - - if (typ1->v_type == VAR_FLOAT) - f1 = typ1->vval.v_float; - else - f1 = get_tv_number(typ1); - if (typ2->v_type == VAR_FLOAT) - f2 = typ2->vval.v_float; + if (typ1->v_type != typ2->v_type) + EMSG(_("E735: Can only compare Dictionary with Dictionary")); else - f2 = get_tv_number(typ2); - n1 = FALSE; - switch (type) - { - case TYPE_EQUAL: n1 = (f1 == f2); break; - case TYPE_NEQUAL: n1 = (f1 != f2); break; - case TYPE_GREATER: n1 = (f1 > f2); break; - case TYPE_GEQUAL: n1 = (f1 >= f2); break; - case TYPE_SMALLER: n1 = (f1 < f2); break; - case TYPE_SEQUAL: n1 = (f1 <= f2); break; - case TYPE_UNKNOWN: - case TYPE_MATCH: - case TYPE_NOMATCH: break; /* avoid gcc warning */ - } + EMSG(_("E736: Invalid operation for Dictionary")); + clear_tv(typ1); + return FAIL; } -#endif + else + { + /* Compare two Dictionaries for being equal or unequal. */ + n1 = dict_equal(typ1->vval.v_dict, typ2->vval.v_dict, + ic, FALSE); + if (type == TYPE_NEQUAL) + n1 = !n1; + } + } - /* - * If one of the two variables is a number, compare as a number. - * When using "=~" or "!~", always compare as string. - */ - else if ((typ1->v_type == VAR_NUMBER || typ2->v_type == VAR_NUMBER) - && type != TYPE_MATCH && type != TYPE_NOMATCH) - { - n1 = get_tv_number(typ1); - n2 = get_tv_number(typ2); - switch (type) - { - case TYPE_EQUAL: n1 = (n1 == n2); break; - case TYPE_NEQUAL: n1 = (n1 != n2); break; - case TYPE_GREATER: n1 = (n1 > n2); break; - case TYPE_GEQUAL: n1 = (n1 >= n2); break; - case TYPE_SMALLER: n1 = (n1 < n2); break; - case TYPE_SEQUAL: n1 = (n1 <= n2); break; - case TYPE_UNKNOWN: - case TYPE_MATCH: - case TYPE_NOMATCH: break; /* avoid gcc warning */ - } + else if (typ1->v_type == VAR_FUNC || typ2->v_type == VAR_FUNC + || typ1->v_type == VAR_PARTIAL || typ2->v_type == VAR_PARTIAL) + { + if (type != TYPE_EQUAL && type != TYPE_NEQUAL) + { + EMSG(_("E694: Invalid operation for Funcrefs")); + clear_tv(typ1); + return FAIL; } - else + if ((typ1->v_type == VAR_PARTIAL + && typ1->vval.v_partial == NULL) + || (typ2->v_type == VAR_PARTIAL + && typ2->vval.v_partial == NULL)) + /* when a partial is NULL assume not equal */ + n1 = FALSE; + else if (type_is) { - s1 = get_tv_string_buf(typ1, buf1); - s2 = get_tv_string_buf(typ2, buf2); - if (type != TYPE_MATCH && type != TYPE_NOMATCH) - i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2); + if (typ1->v_type == VAR_FUNC && typ2->v_type == VAR_FUNC) + /* strings are considered the same if their value is + * the same */ + n1 = tv_equal(typ1, typ2, ic, FALSE); + else if (typ1->v_type == VAR_PARTIAL + && typ2->v_type == VAR_PARTIAL) + n1 = (typ1->vval.v_partial == typ2->vval.v_partial); else - i = 0; - n1 = FALSE; - switch (type) - { - case TYPE_EQUAL: n1 = (i == 0); break; - case TYPE_NEQUAL: n1 = (i != 0); break; - case TYPE_GREATER: n1 = (i > 0); break; - case TYPE_GEQUAL: n1 = (i >= 0); break; - case TYPE_SMALLER: n1 = (i < 0); break; - case TYPE_SEQUAL: n1 = (i <= 0); break; - - case TYPE_MATCH: - case TYPE_NOMATCH: - n1 = pattern_match(s2, s1, ic); - if (type == TYPE_NOMATCH) - n1 = !n1; - break; + n1 = FALSE; + } + else + n1 = tv_equal(typ1, typ2, ic, FALSE); + if (type == TYPE_NEQUAL) + n1 = !n1; + } - case TYPE_UNKNOWN: break; /* avoid gcc warning */ - } +#ifdef FEAT_FLOAT + /* + * If one of the two variables is a float, compare as a float. + * When using "=~" or "!~", always compare as string. + */ + else if ((typ1->v_type == VAR_FLOAT || typ2->v_type == VAR_FLOAT) + && type != TYPE_MATCH && type != TYPE_NOMATCH) + { + float_T f1, f2; + + if (typ1->v_type == VAR_FLOAT) + f1 = typ1->vval.v_float; + else + f1 = get_tv_number(typ1); + if (typ2->v_type == VAR_FLOAT) + f2 = typ2->vval.v_float; + else + f2 = get_tv_number(typ2); + n1 = FALSE; + switch (type) + { + case TYPE_EQUAL: n1 = (f1 == f2); break; + case TYPE_NEQUAL: n1 = (f1 != f2); break; + case TYPE_GREATER: n1 = (f1 > f2); break; + case TYPE_GEQUAL: n1 = (f1 >= f2); break; + case TYPE_SMALLER: n1 = (f1 < f2); break; + case TYPE_SEQUAL: n1 = (f1 <= f2); break; + case TYPE_UNKNOWN: + case TYPE_MATCH: + case TYPE_NOMATCH: break; /* avoid gcc warning */ } - clear_tv(typ1); - clear_tv(typ2); - typ1->v_type = VAR_NUMBER; - typ1->vval.v_number = n1; } - return OK; -} +#endif - int -typval_copy(typ1, typ2) - typval_T *typ1; - typval_T *typ2; -{ - if (typ2 == NULL) - rettv_list_alloc(typ2); + /* + * If one of the two variables is a number, compare as a number. + * When using "=~" or "!~", always compare as string. + */ + else if ((typ1->v_type == VAR_NUMBER || typ2->v_type == VAR_NUMBER) + && type != TYPE_MATCH && type != TYPE_NOMATCH) + { + n1 = get_tv_number(typ1); + n2 = get_tv_number(typ2); + switch (type) + { + case TYPE_EQUAL: n1 = (n1 == n2); break; + case TYPE_NEQUAL: n1 = (n1 != n2); break; + case TYPE_GREATER: n1 = (n1 > n2); break; + case TYPE_GEQUAL: n1 = (n1 >= n2); break; + case TYPE_SMALLER: n1 = (n1 < n2); break; + case TYPE_SEQUAL: n1 = (n1 <= n2); break; + case TYPE_UNKNOWN: + case TYPE_MATCH: + case TYPE_NOMATCH: break; /* avoid gcc warning */ + } + } + else + { + s1 = get_tv_string_buf(typ1, buf1); + s2 = get_tv_string_buf(typ2, buf2); + if (type != TYPE_MATCH && type != TYPE_NOMATCH) + i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2); + else + i = 0; + n1 = FALSE; + switch (type) + { + case TYPE_EQUAL: n1 = (i == 0); break; + case TYPE_NEQUAL: n1 = (i != 0); break; + case TYPE_GREATER: n1 = (i > 0); break; + case TYPE_GEQUAL: n1 = (i >= 0); break; + case TYPE_SMALLER: n1 = (i < 0); break; + case TYPE_SEQUAL: n1 = (i <= 0); break; + + case TYPE_MATCH: + case TYPE_NOMATCH: + n1 = pattern_match(s2, s1, ic); + if (type == TYPE_NOMATCH) + n1 = !n1; + break; - if (typ1 != NULL && typ2 != NULL) - return item_copy(typ1, typ2, TRUE, 0); + case TYPE_UNKNOWN: break; /* avoid gcc warning */ + } + } + clear_tv(typ1); + typ1->v_type = VAR_NUMBER; + typ1->vval.v_number = n1; - return FAIL; + return OK; } char_u * diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c index c36435cc1..6476d5516 100644 --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -988,23 +988,20 @@ debuggy_find( } else { - typval_T val3; - - if (typval_copy(bp->dbg_val, &val3) == OK) + if (typval_compare(tv, bp->dbg_val, TYPE_EQUAL, + TRUE, FALSE) == OK + && tv->vval.v_number == FALSE) { - if (typval_compare(tv, &val3, TYPE_EQUAL, - TRUE, FALSE, TRUE) == OK - && tv->vval.v_number == FALSE) - { - typval_T *v; - - line = TRUE; - debug_oldval = typval_tostring(bp->dbg_val); - v = eval_expr(bp->dbg_name, NULL); - debug_newval = typval_tostring(v); - free_tv(bp->dbg_val); - bp->dbg_val = v; - } + typval_T *v; + + line = TRUE; + debug_oldval = typval_tostring(bp->dbg_val); + /* Need to evaluate again, typval_compare() overwrites + * "tv". */ + v = eval_expr(bp->dbg_name, NULL); + debug_newval = typval_tostring(v); + free_tv(bp->dbg_val); + bp->dbg_val = v; } free_tv(tv); } diff --git a/src/proto/eval.pro b/src/proto/eval.pro index e3e4a532b..ba7dcec59 100644 --- a/src/proto/eval.pro +++ b/src/proto/eval.pro @@ -130,8 +130,7 @@ void assert_exception(typval_T *argvars); void assert_beeps(typval_T *argvars); void assert_fails(typval_T *argvars); void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_str, typval_T *exp_tv, typval_T *got_tv, assert_type_T atype); -int typval_compare(typval_T *typ1, typval_T *typ2, exptype_T type, int type_is, int ic, int evaluate); -int typval_copy(typval_T *typ1, typval_T *typ2); +int typval_compare(typval_T *typ1, typval_T *typ2, exptype_T type, int type_is, int ic); char_u *typval_tostring(typval_T *arg); int var_exists(char_u *var); int modify_fname(char_u *src, int *usedlen, char_u **fnamep, char_u **bufp, int *fnamelen); diff --git a/src/version.c b/src/version.c index 7028ad39c..a9643caea 100644 --- a/src/version.c +++ b/src/version.c @@ -772,6 +772,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1511, +/**/ 1510, /**/ 1509, |