To: vim_dev@googlegroups.com Subject: Patch 8.0.1511 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.0.1511 (after 8.0.1505) Problem: Some code for the debugger watch expression is clumsy. Solution: Clean up the code. Files: src/ex_cmds2.c, src/eval.c, src/proto/eval.pro *** ../vim-8.0.1510/src/ex_cmds2.c 2018-02-12 22:07:45.593058158 +0100 --- src/ex_cmds2.c 2018-02-13 12:44:35.560861213 +0100 *************** *** 988,1010 **** } else { ! typval_T val3; ! ! if (typval_copy(bp->dbg_val, &val3) == OK) { ! 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; ! } } free_tv(tv); } --- 988,1007 ---- } else { ! if (typval_compare(tv, bp->dbg_val, TYPE_EQUAL, ! TRUE, FALSE) == OK ! && tv->vval.v_number == FALSE) { ! 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); } *** ../vim-8.0.1510/src/eval.c 2018-02-13 12:26:08.904247750 +0100 --- src/eval.c 2018-02-13 12:44:47.396760236 +0100 *************** *** 3596,3602 **** clear_tv(rettv); return FAIL; } ! return typval_compare(rettv, &var2, type, type_is, ic, evaluate); } return OK; --- 3596,3608 ---- clear_tv(rettv); return FAIL; } ! if (evaluate) ! { ! int ret = typval_compare(rettv, &var2, type, type_is, ic); ! ! clear_tv(&var2); ! return ret; ! } } return OK; *************** *** 9091,9317 **** } } ! 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 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) { ! /* 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) ! { ! 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; ! } 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; ! } } ! ! else if (typ1->v_type == VAR_DICT || typ2->v_type == VAR_DICT) { ! 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; ! } } ! 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); ! 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); 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) { ! 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 */ ! } } ! #endif ! /* ! * 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; ! ! case TYPE_UNKNOWN: break; /* avoid gcc warning */ ! } ! } ! clear_tv(typ1); ! clear_tv(typ2); ! typ1->v_type = VAR_NUMBER; ! typ1->vval.v_number = n1; } - return OK; - } ! int ! typval_copy(typ1, typ2) ! typval_T *typ1; ! typval_T *typ2; ! { ! if (typ2 == NULL) ! rettv_list_alloc(typ2); ! if (typ1 != NULL && typ2 != NULL) ! return item_copy(typ1, typ2, TRUE, 0); ! return FAIL; } char_u * --- 9097,9304 ---- } } ! /* ! * 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 i; varnumber_T n1, n2; char_u *s1, *s2; char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; ! 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) { ! 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); ! return FAIL; } ! 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; } + } ! else if (typ1->v_type == VAR_DICT || typ2->v_type == VAR_DICT) ! { ! 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); ! 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; ! } ! } ! 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; } ! 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); ! 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) ! { ! 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 */ ! } ! } ! #endif ! /* ! * 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; ! ! case TYPE_UNKNOWN: break; /* avoid gcc warning */ ! } ! } ! clear_tv(typ1); ! typ1->v_type = VAR_NUMBER; ! typ1->vval.v_number = n1; ! ! return OK; } char_u * *** ../vim-8.0.1510/src/proto/eval.pro 2018-02-13 12:26:08.904247750 +0100 --- src/proto/eval.pro 2018-02-13 12:45:37.008343019 +0100 *************** *** 130,137 **** 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); 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); --- 130,136 ---- 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); 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); *** ../vim-8.0.1510/src/version.c 2018-02-13 12:26:08.908247730 +0100 --- src/version.c 2018-02-13 12:45:48.416248398 +0100 *************** *** 773,774 **** --- 773,776 ---- { /* Add new patch number below this line */ + /**/ + 1511, /**/ -- ARTHUR: A scratch? Your arm's off! BLACK KNIGHT: No, it isn't. ARTHUR: Well, what's that then? BLACK KNIGHT: I've had worse. The Quest for the Holy Grail (Monty Python) /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///