Mercurial > vim
comparison src/eval.c @ 156:c5b05f6de1ad v7.0047
updated for version 7.0047
author | vimboss |
---|---|
date | Wed, 02 Feb 2005 23:11:38 +0000 |
parents | 40a0699b6c62 |
children | 389c8abd5925 |
comparison
equal
deleted
inserted
replaced
155:e91a302ad53a | 156:c5b05f6de1ad |
---|---|
328 static int dict_equal __ARGS((dict_T *d1, dict_T *d2, int ic)); | 328 static int dict_equal __ARGS((dict_T *d1, dict_T *d2, int ic)); |
329 static int tv_equal __ARGS((typval_T *tv1, typval_T *tv2, int ic)); | 329 static int tv_equal __ARGS((typval_T *tv1, typval_T *tv2, int ic)); |
330 static int string_isa_number __ARGS((char_u *s)); | 330 static int string_isa_number __ARGS((char_u *s)); |
331 static listitem_T *list_find __ARGS((list_T *l, long n)); | 331 static listitem_T *list_find __ARGS((list_T *l, long n)); |
332 static long list_idx_of_item __ARGS((list_T *l, listitem_T *item)); | 332 static long list_idx_of_item __ARGS((list_T *l, listitem_T *item)); |
333 static listitem_T *list_find_ext __ARGS((list_T *l, long *ip)); | |
334 static void list_append __ARGS((list_T *l, listitem_T *item)); | 333 static void list_append __ARGS((list_T *l, listitem_T *item)); |
335 static int list_append_tv __ARGS((list_T *l, typval_T *tv)); | 334 static int list_append_tv __ARGS((list_T *l, typval_T *tv)); |
336 static int list_insert_tv __ARGS((list_T *l, typval_T *tv, listitem_T *item)); | 335 static int list_insert_tv __ARGS((list_T *l, typval_T *tv, listitem_T *item)); |
337 static int list_extend __ARGS((list_T *l1, list_T *l2, listitem_T *bef)); | 336 static int list_extend __ARGS((list_T *l1, list_T *l2, listitem_T *bef)); |
338 static int list_concat __ARGS((list_T *l1, list_T *l2, typval_T *tv)); | 337 static int list_concat __ARGS((list_T *l1, list_T *l2, typval_T *tv)); |
1056 else | 1055 else |
1057 { | 1056 { |
1058 /* If the result is a number, just return the number. */ | 1057 /* If the result is a number, just return the number. */ |
1059 if (tv.v_type == VAR_NUMBER) | 1058 if (tv.v_type == VAR_NUMBER) |
1060 retval = tv.vval.v_number; | 1059 retval = tv.vval.v_number; |
1061 else if (tv.v_type == VAR_UNKNOWN | 1060 else if (tv.v_type != VAR_STRING || tv.vval.v_string == NULL) |
1062 || tv.vval.v_string == NULL) | |
1063 retval = 0; | 1061 retval = 0; |
1064 else | 1062 else |
1065 { | 1063 { |
1066 /* If the result is a string, check if there is a non-digit before | 1064 /* If the result is a string, check if there is a non-digit before |
1067 * the number. */ | 1065 * the number. */ |
1255 } | 1253 } |
1256 | 1254 |
1257 /* | 1255 /* |
1258 * ":let [v1, v2] = list" or ":for [v1, v2] in listlist" | 1256 * ":let [v1, v2] = list" or ":for [v1, v2] in listlist" |
1259 */ | 1257 */ |
1260 l = tv->vval.v_list; | 1258 if (tv->v_type != VAR_LIST || (l = tv->vval.v_list) == NULL) |
1261 if (tv->v_type != VAR_LIST || l == NULL) | |
1262 { | 1259 { |
1263 EMSG(_(e_listreq)); | 1260 EMSG(_(e_listreq)); |
1264 return FAIL; | 1261 return FAIL; |
1265 } | 1262 } |
1266 | 1263 |
2209 if (copy) | 2206 if (copy) |
2210 copy_tv(rettv, lp->ll_tv); | 2207 copy_tv(rettv, lp->ll_tv); |
2211 else | 2208 else |
2212 { | 2209 { |
2213 *lp->ll_tv = *rettv; | 2210 *lp->ll_tv = *rettv; |
2211 lp->ll_tv->v_lock = 0; | |
2214 init_tv(rettv); | 2212 init_tv(rettv); |
2215 } | 2213 } |
2216 } | 2214 } |
2217 } | 2215 } |
2218 | 2216 |
2291 lw->lw_next = l->lv_watch; | 2289 lw->lw_next = l->lv_watch; |
2292 l->lv_watch = lw; | 2290 l->lv_watch = lw; |
2293 } | 2291 } |
2294 | 2292 |
2295 /* | 2293 /* |
2296 * Remove a watches from a list. | 2294 * Remove a watcher from a list. |
2297 * No warning when it isn't found... | 2295 * No warning when it isn't found... |
2298 */ | 2296 */ |
2299 static void | 2297 static void |
2300 list_rem_watch(l, lwrem) | 2298 list_rem_watch(l, lwrem) |
2301 list_T *l; | 2299 list_T *l; |
4732 */ | 4730 */ |
4733 static long | 4731 static long |
4734 list_len(l) | 4732 list_len(l) |
4735 list_T *l; | 4733 list_T *l; |
4736 { | 4734 { |
4737 listitem_T *item; | |
4738 long len = 0; | |
4739 | |
4740 if (l == NULL) | 4735 if (l == NULL) |
4741 return 0L; | 4736 return 0L; |
4742 for (item = l->lv_first; item != NULL; item = item->li_next) | 4737 return l->lv_len; |
4743 ++len; | |
4744 return len; | |
4745 } | 4738 } |
4746 | 4739 |
4747 /* | 4740 /* |
4748 * Return TRUE when two lists have exactly the same values. | 4741 * Return TRUE when two lists have exactly the same values. |
4749 */ | 4742 */ |
4879 listitem_T *item; | 4872 listitem_T *item; |
4880 long idx; | 4873 long idx; |
4881 | 4874 |
4882 if (l == NULL) | 4875 if (l == NULL) |
4883 return NULL; | 4876 return NULL; |
4877 | |
4878 /* Negative index is relative to the end. */ | |
4884 if (n < 0) | 4879 if (n < 0) |
4885 { | 4880 n = l->lv_len + n; |
4886 idx = -1; /* search from the end */ | 4881 |
4887 for (item = l->lv_last; item != NULL && idx > n; item = item->li_prev) | 4882 /* Check for index out of range. */ |
4888 --idx; | 4883 if (n < 0 || n >= l->lv_len) |
4884 return NULL; | |
4885 | |
4886 /* When there is a cached index may start search from there. */ | |
4887 if (l->lv_idx_item != NULL) | |
4888 { | |
4889 if (n < l->lv_idx / 2) | |
4890 { | |
4891 /* closest to the start of the list */ | |
4892 item = l->lv_first; | |
4893 idx = 0; | |
4894 } | |
4895 else if (n > (l->lv_idx + l->lv_len) / 2) | |
4896 { | |
4897 /* closest to the end of the list */ | |
4898 item = l->lv_last; | |
4899 idx = l->lv_len - 1; | |
4900 } | |
4901 else | |
4902 { | |
4903 /* closest to the cached index */ | |
4904 item = l->lv_idx_item; | |
4905 idx = l->lv_idx; | |
4906 } | |
4889 } | 4907 } |
4890 else | 4908 else |
4891 { | 4909 { |
4892 idx = 0; /* search from the start */ | 4910 if (n < l->lv_len / 2) |
4893 for (item = l->lv_first; item != NULL && idx < n; item = item->li_next) | 4911 { |
4894 ++idx; | 4912 /* closest to the start of the list */ |
4895 } | 4913 item = l->lv_first; |
4896 if (idx != n) | 4914 idx = 0; |
4897 return NULL; | 4915 } |
4916 else | |
4917 { | |
4918 /* closest to the end of the list */ | |
4919 item = l->lv_last; | |
4920 idx = l->lv_len - 1; | |
4921 } | |
4922 } | |
4923 | |
4924 while (n > idx) | |
4925 { | |
4926 /* search forward */ | |
4927 item = item->li_next; | |
4928 ++idx; | |
4929 } | |
4930 while (n < idx) | |
4931 { | |
4932 /* search backward */ | |
4933 item = item->li_prev; | |
4934 --idx; | |
4935 } | |
4936 | |
4937 /* cache the used index */ | |
4938 l->lv_idx = idx; | |
4939 l->lv_idx_item = item; | |
4940 | |
4898 return item; | 4941 return item; |
4899 } | 4942 } |
4900 | 4943 |
4901 /* | 4944 /* |
4902 * Locate "item" list "l" and return its index. | 4945 * Locate "item" list "l" and return its index. |
4919 return -1; | 4962 return -1; |
4920 return idx;; | 4963 return idx;; |
4921 } | 4964 } |
4922 | 4965 |
4923 /* | 4966 /* |
4924 * Like list_find(), but also find an item just past the end. | |
4925 * "*ip" is the item to find. | |
4926 * When found "*ip" is set to zero, when not found "*ip" is non-zero. | |
4927 * Returns NULL when item not found or item is just past the end. | |
4928 */ | |
4929 static listitem_T * | |
4930 list_find_ext(l, ip) | |
4931 list_T *l; | |
4932 long *ip; | |
4933 { | |
4934 long n; | |
4935 listitem_T *item; | |
4936 | |
4937 if (*ip < 0) | |
4938 { | |
4939 /* Count from the end: -1 is before last item. */ | |
4940 item = l->lv_last; | |
4941 for (n = *ip + 1; n < 0 && item != NULL; ++n) | |
4942 item = item->li_prev; | |
4943 if (item == NULL) | |
4944 n = 1; /* error! */ | |
4945 } | |
4946 else | |
4947 { | |
4948 item = l->lv_first; | |
4949 for (n = *ip; n > 0 && item != NULL; --n) | |
4950 item = item->li_next; | |
4951 } | |
4952 *ip = n; | |
4953 return item; | |
4954 } | |
4955 | |
4956 /* | |
4957 * Append item "item" to the end of list "l". | 4967 * Append item "item" to the end of list "l". |
4958 */ | 4968 */ |
4959 static void | 4969 static void |
4960 list_append(l, item) | 4970 list_append(l, item) |
4961 list_T *l; | 4971 list_T *l; |
4972 { | 4982 { |
4973 l->lv_last->li_next = item; | 4983 l->lv_last->li_next = item; |
4974 item->li_prev = l->lv_last; | 4984 item->li_prev = l->lv_last; |
4975 l->lv_last = item; | 4985 l->lv_last = item; |
4976 } | 4986 } |
4987 ++l->lv_len; | |
4977 item->li_next = NULL; | 4988 item->li_next = NULL; |
4978 } | 4989 } |
4979 | 4990 |
4980 /* | 4991 /* |
4981 * Append typval_T "tv" to the end of list "l". | 4992 * Append typval_T "tv" to the end of list "l". |
5018 { | 5029 { |
5019 /* Insert new item before existing item. */ | 5030 /* Insert new item before existing item. */ |
5020 ni->li_prev = item->li_prev; | 5031 ni->li_prev = item->li_prev; |
5021 ni->li_next = item; | 5032 ni->li_next = item; |
5022 if (item->li_prev == NULL) | 5033 if (item->li_prev == NULL) |
5034 { | |
5023 l->lv_first = ni; | 5035 l->lv_first = ni; |
5036 ++l->lv_idx; | |
5037 } | |
5024 else | 5038 else |
5039 { | |
5025 item->li_prev->li_next = ni; | 5040 item->li_prev->li_next = ni; |
5041 l->lv_idx_item = NULL; | |
5042 } | |
5026 item->li_prev = ni; | 5043 item->li_prev = ni; |
5044 ++l->lv_len; | |
5027 } | 5045 } |
5028 return OK; | 5046 return OK; |
5029 } | 5047 } |
5030 | 5048 |
5031 /* | 5049 /* |
5120 listitem_T *ip; | 5138 listitem_T *ip; |
5121 | 5139 |
5122 /* notify watchers */ | 5140 /* notify watchers */ |
5123 for (ip = item; ip != NULL; ip = ip->li_next) | 5141 for (ip = item; ip != NULL; ip = ip->li_next) |
5124 { | 5142 { |
5143 --l->lv_len; | |
5125 list_fix_watch(l, ip); | 5144 list_fix_watch(l, ip); |
5126 if (ip == item2) | 5145 if (ip == item2) |
5127 break; | 5146 break; |
5128 } | 5147 } |
5129 | 5148 |
5133 item2->li_next->li_prev = item->li_prev; | 5152 item2->li_next->li_prev = item->li_prev; |
5134 if (item->li_prev == NULL) | 5153 if (item->li_prev == NULL) |
5135 l->lv_first = item2->li_next; | 5154 l->lv_first = item2->li_next; |
5136 else | 5155 else |
5137 item->li_prev->li_next = item2->li_next; | 5156 item->li_prev->li_next = item2->li_next; |
5157 l->lv_idx_item = NULL; | |
5138 } | 5158 } |
5139 | 5159 |
5140 /* | 5160 /* |
5141 * Return an allocated string with the string representation of a list. | 5161 * Return an allocated string with the string representation of a list. |
5142 * May return NULL. | 5162 * May return NULL. |
6545 { | 6565 { |
6546 buf_T *buf = NULL; | 6566 buf_T *buf = NULL; |
6547 | 6567 |
6548 if (avar->v_type == VAR_NUMBER) | 6568 if (avar->v_type == VAR_NUMBER) |
6549 buf = buflist_findnr((int)avar->vval.v_number); | 6569 buf = buflist_findnr((int)avar->vval.v_number); |
6550 else if (avar->vval.v_string != NULL) | 6570 else if (avar->v_type == VAR_STRING && avar->vval.v_string != NULL) |
6551 { | 6571 { |
6552 buf = buflist_findname_exp(avar->vval.v_string); | 6572 buf = buflist_findname_exp(avar->vval.v_string); |
6553 if (buf == NULL) | 6573 if (buf == NULL) |
6554 { | 6574 { |
6555 /* No full path name match, try a match with a URL or a "nofile" | 6575 /* No full path name match, try a match with a URL or a "nofile" |
6621 char_u *save_cpo; | 6641 char_u *save_cpo; |
6622 buf_T *buf; | 6642 buf_T *buf; |
6623 | 6643 |
6624 if (tv->v_type == VAR_NUMBER) | 6644 if (tv->v_type == VAR_NUMBER) |
6625 return buflist_findnr((int)tv->vval.v_number); | 6645 return buflist_findnr((int)tv->vval.v_number); |
6646 if (tv->v_type != VAR_STRING) | |
6647 return NULL; | |
6626 if (name == NULL || *name == NUL) | 6648 if (name == NULL || *name == NUL) |
6627 return curbuf; | 6649 return curbuf; |
6628 if (name[0] == '$' && name[1] == NUL) | 6650 if (name[0] == '$' && name[1] == NUL) |
6629 return lastbuf; | 6651 return lastbuf; |
6630 | 6652 |
7287 typval_T *argvars; | 7309 typval_T *argvars; |
7288 typval_T *rettv; | 7310 typval_T *rettv; |
7289 { | 7311 { |
7290 char_u buf[NUMBUFLEN]; | 7312 char_u buf[NUMBUFLEN]; |
7291 | 7313 |
7292 rettv->vval.v_string = | 7314 rettv->vval.v_string = vim_strsave_escaped(get_tv_string(&argvars[0]), |
7293 vim_strsave_escaped(get_tv_string(&argvars[0]), | 7315 get_tv_string_buf(&argvars[1], buf)); |
7294 get_tv_string_buf(&argvars[1], buf)); | |
7295 rettv->v_type = VAR_STRING; | 7316 rettv->v_type = VAR_STRING; |
7296 } | 7317 } |
7297 | 7318 |
7298 /* | 7319 /* |
7299 * "eval()" function | 7320 * "eval()" function |
7465 if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST) | 7486 if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST) |
7466 { | 7487 { |
7467 list_T *l1, *l2; | 7488 list_T *l1, *l2; |
7468 listitem_T *item; | 7489 listitem_T *item; |
7469 long before; | 7490 long before; |
7470 long n; | |
7471 | 7491 |
7472 l1 = argvars[0].vval.v_list; | 7492 l1 = argvars[0].vval.v_list; |
7473 l2 = argvars[1].vval.v_list; | 7493 l2 = argvars[1].vval.v_list; |
7474 if (l1 != NULL && !tv_check_lock(l1->lv_lock, (char_u *)"extend()") | 7494 if (l1 != NULL && !tv_check_lock(l1->lv_lock, (char_u *)"extend()") |
7475 && l2 != NULL) | 7495 && l2 != NULL) |
7476 { | 7496 { |
7477 if (argvars[2].v_type != VAR_UNKNOWN) | 7497 if (argvars[2].v_type != VAR_UNKNOWN) |
7478 { | 7498 { |
7479 n = before = get_tv_number(&argvars[2]); | 7499 before = get_tv_number(&argvars[2]); |
7480 item = list_find_ext(l1, &n); | 7500 if (before == l1->lv_len) |
7481 if (n != 0) | 7501 item = NULL; |
7502 else | |
7482 { | 7503 { |
7483 EMSGN(_(e_listidx), before); | 7504 item = list_find(l1, before); |
7484 return; | 7505 if (item == NULL) |
7506 { | |
7507 EMSGN(_(e_listidx), before); | |
7508 return; | |
7509 } | |
7485 } | 7510 } |
7486 } | 7511 } |
7487 else | 7512 else |
7488 item = NULL; | 7513 item = NULL; |
7489 list_extend(l1, l2, item); | 7514 list_extend(l1, l2, item); |
9485 typval_T *rettv; | 9510 typval_T *rettv; |
9486 { | 9511 { |
9487 list_T *l; | 9512 list_T *l; |
9488 listitem_T *item; | 9513 listitem_T *item; |
9489 long idx = 0; | 9514 long idx = 0; |
9490 long min_idx = 0; | |
9491 int ic = FALSE; | 9515 int ic = FALSE; |
9492 | 9516 |
9493 rettv->vval.v_number = -1; | 9517 rettv->vval.v_number = -1; |
9494 if (argvars[0].v_type != VAR_LIST) | 9518 if (argvars[0].v_type != VAR_LIST) |
9495 { | 9519 { |
9497 return; | 9521 return; |
9498 } | 9522 } |
9499 l = argvars[0].vval.v_list; | 9523 l = argvars[0].vval.v_list; |
9500 if (l != NULL) | 9524 if (l != NULL) |
9501 { | 9525 { |
9526 item = l->lv_first; | |
9502 if (argvars[2].v_type != VAR_UNKNOWN) | 9527 if (argvars[2].v_type != VAR_UNKNOWN) |
9503 { | 9528 { |
9504 min_idx = get_tv_number(&argvars[2]); | 9529 /* Start at specified item. Use the cached index that list_find() |
9530 * sets, so that a negative number also works. */ | |
9531 item = list_find(l, get_tv_number(&argvars[2])); | |
9532 idx = l->lv_idx; | |
9505 if (argvars[3].v_type != VAR_UNKNOWN) | 9533 if (argvars[3].v_type != VAR_UNKNOWN) |
9506 ic = get_tv_number(&argvars[3]); | 9534 ic = get_tv_number(&argvars[3]); |
9507 } | 9535 } |
9508 | 9536 |
9509 for (item = l->lv_first; item != NULL; item = item->li_next, ++idx) | 9537 for ( ; item != NULL; item = item->li_next, ++idx) |
9510 if (idx >= min_idx && tv_equal(&item->li_tv, &argvars[1], ic)) | 9538 if (tv_equal(&item->li_tv, &argvars[1], ic)) |
9511 { | 9539 { |
9512 rettv->vval.v_number = idx; | 9540 rettv->vval.v_number = idx; |
9513 break; | 9541 break; |
9514 } | 9542 } |
9515 } | 9543 } |
9688 f_insert(argvars, rettv) | 9716 f_insert(argvars, rettv) |
9689 typval_T *argvars; | 9717 typval_T *argvars; |
9690 typval_T *rettv; | 9718 typval_T *rettv; |
9691 { | 9719 { |
9692 long before = 0; | 9720 long before = 0; |
9693 long n; | |
9694 listitem_T *item; | 9721 listitem_T *item; |
9695 list_T *l; | 9722 list_T *l; |
9696 | 9723 |
9697 rettv->vval.v_number = 0; | 9724 rettv->vval.v_number = 0; |
9698 if (argvars[0].v_type != VAR_LIST) | 9725 if (argvars[0].v_type != VAR_LIST) |
9701 && !tv_check_lock(l->lv_lock, (char_u *)"insert()")) | 9728 && !tv_check_lock(l->lv_lock, (char_u *)"insert()")) |
9702 { | 9729 { |
9703 if (argvars[2].v_type != VAR_UNKNOWN) | 9730 if (argvars[2].v_type != VAR_UNKNOWN) |
9704 before = get_tv_number(&argvars[2]); | 9731 before = get_tv_number(&argvars[2]); |
9705 | 9732 |
9706 n = before; | 9733 if (before == l->lv_len) |
9707 item = list_find_ext(l, &n); | 9734 item = NULL; |
9708 if (n > 0) | |
9709 EMSGN(_(e_listidx), before); | |
9710 else | 9735 else |
9736 { | |
9737 item = list_find(l, before); | |
9738 if (item == NULL) | |
9739 { | |
9740 EMSGN(_(e_listidx), before); | |
9741 l = NULL; | |
9742 } | |
9743 } | |
9744 if (l != NULL) | |
9711 { | 9745 { |
9712 list_insert_tv(l, &argvars[1], item); | 9746 list_insert_tv(l, &argvars[1], item); |
9713 ++l->lv_refcount; | 9747 ++l->lv_refcount; |
9714 copy_tv(&argvars[0], rettv); | 9748 copy_tv(&argvars[0], rettv); |
9715 } | 9749 } |
10019 | 10053 |
10020 #ifdef FEAT_LIBCALL | 10054 #ifdef FEAT_LIBCALL |
10021 /* The first two args must be strings, otherwise its meaningless */ | 10055 /* The first two args must be strings, otherwise its meaningless */ |
10022 if (argvars[0].v_type == VAR_STRING && argvars[1].v_type == VAR_STRING) | 10056 if (argvars[0].v_type == VAR_STRING && argvars[1].v_type == VAR_STRING) |
10023 { | 10057 { |
10024 if (argvars[2].v_type == VAR_NUMBER) | 10058 string_in = NULL; |
10025 string_in = NULL; | 10059 if (argvars[2].v_type == VAR_STRING) |
10026 else | |
10027 string_in = argvars[2].vval.v_string; | 10060 string_in = argvars[2].vval.v_string; |
10028 if (type == VAR_NUMBER) | 10061 if (type == VAR_NUMBER) |
10029 string_result = NULL; | 10062 string_result = NULL; |
10030 else | 10063 else |
10031 string_result = &rettv->vval.v_string; | 10064 string_result = &rettv->vval.v_string; |
10273 if (l != NULL) | 10306 if (l != NULL) |
10274 { | 10307 { |
10275 li = list_find(l, start); | 10308 li = list_find(l, start); |
10276 if (li == NULL) | 10309 if (li == NULL) |
10277 goto theend; | 10310 goto theend; |
10278 if (start < 0) | 10311 idx = l->lv_idx; /* use the cached index */ |
10279 { | |
10280 listitem_T *ni; | |
10281 | |
10282 /* Need to compute the index. */ | |
10283 for (ni = li; ni->li_prev != NULL; ni = ni->li_prev) | |
10284 ++idx; | |
10285 } | |
10286 else | |
10287 idx = start; | |
10288 } | 10312 } |
10289 else | 10313 else |
10290 { | 10314 { |
10291 if (start < 0) | 10315 if (start < 0) |
10292 start = 0; | 10316 start = 0; |
10466 } | 10490 } |
10467 } | 10491 } |
10468 } | 10492 } |
10469 } | 10493 } |
10470 else | 10494 else |
10471 EMSG(_(e_listreq)); | 10495 EMSG(_(e_listdictarg)); |
10472 rettv->vval.v_number = n; | 10496 rettv->vval.v_number = n; |
10473 } | 10497 } |
10474 | 10498 |
10475 /* | 10499 /* |
10476 * "max()" function | 10500 * "max()" function |
10902 if (argvars[0].v_type == VAR_DICT) | 10926 if (argvars[0].v_type == VAR_DICT) |
10903 { | 10927 { |
10904 if (argvars[2].v_type != VAR_UNKNOWN) | 10928 if (argvars[2].v_type != VAR_UNKNOWN) |
10905 EMSG2(_(e_toomanyarg), "remove()"); | 10929 EMSG2(_(e_toomanyarg), "remove()"); |
10906 else if ((d = argvars[0].vval.v_dict) != NULL | 10930 else if ((d = argvars[0].vval.v_dict) != NULL |
10907 && !tv_check_lock(d->dv_lock, (char_u *)"remove()")) | 10931 && !tv_check_lock(d->dv_lock, (char_u *)"remove()")) |
10908 { | 10932 { |
10909 key = get_tv_string(&argvars[1]); | 10933 key = get_tv_string(&argvars[1]); |
10910 di = dict_find(d, key, -1); | 10934 di = dict_find(d, key, -1); |
10911 if (di == NULL) | 10935 if (di == NULL) |
10912 EMSG2(_(e_dictkey), key); | 10936 EMSG2(_(e_dictkey), key); |
10943 item2 = list_find(l, end); | 10967 item2 = list_find(l, end); |
10944 if (item2 == NULL) | 10968 if (item2 == NULL) |
10945 EMSGN(_(e_listidx), end); | 10969 EMSGN(_(e_listidx), end); |
10946 else | 10970 else |
10947 { | 10971 { |
10948 for (li = item; li != item2 && li != NULL; li = li->li_next) | 10972 int cnt = 0; |
10949 ; | 10973 |
10974 for (li = item; li != NULL; li = li->li_next) | |
10975 { | |
10976 ++cnt; | |
10977 if (li == item2) | |
10978 break; | |
10979 } | |
10950 if (li == NULL) /* didn't find "item2" after "item" */ | 10980 if (li == NULL) /* didn't find "item2" after "item" */ |
10951 EMSG(_(e_invrange)); | 10981 EMSG(_(e_invrange)); |
10952 else | 10982 else |
10953 { | 10983 { |
10954 list_remove(l, item, item2); | 10984 list_remove(l, item, item2); |
10960 l->lv_first = item; | 10990 l->lv_first = item; |
10961 l->lv_last = item2; | 10991 l->lv_last = item2; |
10962 l->lv_refcount = 1; | 10992 l->lv_refcount = 1; |
10963 item->li_prev = NULL; | 10993 item->li_prev = NULL; |
10964 item2->li_next = NULL; | 10994 item2->li_next = NULL; |
10995 l->lv_len = cnt; | |
10965 } | 10996 } |
10966 } | 10997 } |
10967 } | 10998 } |
10968 } | 10999 } |
10969 } | 11000 } |
11258 else if ((l = argvars[0].vval.v_list) != NULL | 11289 else if ((l = argvars[0].vval.v_list) != NULL |
11259 && !tv_check_lock(l->lv_lock, (char_u *)"reverse()")) | 11290 && !tv_check_lock(l->lv_lock, (char_u *)"reverse()")) |
11260 { | 11291 { |
11261 li = l->lv_last; | 11292 li = l->lv_last; |
11262 l->lv_first = l->lv_last = li; | 11293 l->lv_first = l->lv_last = li; |
11294 l->lv_len = 0; | |
11263 while (li != NULL) | 11295 while (li != NULL) |
11264 { | 11296 { |
11265 ni = li->li_prev; | 11297 ni = li->li_prev; |
11266 list_append(l, li); | 11298 list_append(l, li); |
11267 li = ni; | 11299 li = ni; |
11943 qsort((void *)ptrs, (size_t)len, sizeof(listitem_T *), | 11975 qsort((void *)ptrs, (size_t)len, sizeof(listitem_T *), |
11944 item_compare_func == NULL ? item_compare : item_compare2); | 11976 item_compare_func == NULL ? item_compare : item_compare2); |
11945 | 11977 |
11946 /* Clear the List and append the items in the sorted order. */ | 11978 /* Clear the List and append the items in the sorted order. */ |
11947 l->lv_first = l->lv_last = NULL; | 11979 l->lv_first = l->lv_last = NULL; |
11980 l->lv_len = 0; | |
11948 for (i = 0; i < len; ++i) | 11981 for (i = 0; i < len; ++i) |
11949 list_append(l, ptrs[i]); | 11982 list_append(l, ptrs[i]); |
11950 } | 11983 } |
11951 | 11984 |
11952 vim_free(ptrs); | 11985 vim_free(ptrs); |
12771 { | 12804 { |
12772 case VAR_NUMBER: n = 0; break; | 12805 case VAR_NUMBER: n = 0; break; |
12773 case VAR_STRING: n = 1; break; | 12806 case VAR_STRING: n = 1; break; |
12774 case VAR_FUNC: n = 2; break; | 12807 case VAR_FUNC: n = 2; break; |
12775 case VAR_LIST: n = 3; break; | 12808 case VAR_LIST: n = 3; break; |
12809 case VAR_DICT: n = 4; break; | |
12776 default: EMSG2(_(e_intern2), "f_type()"); n = 0; break; | 12810 default: EMSG2(_(e_intern2), "f_type()"); n = 0; break; |
12777 } | 12811 } |
12778 rettv->vval.v_number = n; | 12812 rettv->vval.v_number = n; |
12779 } | 12813 } |
12780 | 12814 |
13518 list_unref(varp->vval.v_list); | 13552 list_unref(varp->vval.v_list); |
13519 break; | 13553 break; |
13520 case VAR_DICT: | 13554 case VAR_DICT: |
13521 dict_unref(varp->vval.v_dict); | 13555 dict_unref(varp->vval.v_dict); |
13522 break; | 13556 break; |
13557 case VAR_NUMBER: | |
13558 case VAR_UNKNOWN: | |
13559 break; | |
13523 default: | 13560 default: |
13561 EMSG2(_(e_intern2), "free_tv()"); | |
13524 break; | 13562 break; |
13525 } | 13563 } |
13526 vim_free(varp); | 13564 vim_free(varp); |
13527 } | 13565 } |
13528 } | 13566 } |
13598 if (varp->vval.v_string != NULL) | 13636 if (varp->vval.v_string != NULL) |
13599 vim_str2nr(varp->vval.v_string, NULL, NULL, | 13637 vim_str2nr(varp->vval.v_string, NULL, NULL, |
13600 TRUE, TRUE, &n, NULL); | 13638 TRUE, TRUE, &n, NULL); |
13601 break; | 13639 break; |
13602 case VAR_LIST: | 13640 case VAR_LIST: |
13603 EMSG(_("E703: Using a List as a number")); | 13641 EMSG(_("E745: Using a List as a number")); |
13604 break; | 13642 break; |
13605 case VAR_DICT: | 13643 case VAR_DICT: |
13606 EMSG(_("E728: Using a Dictionary as a number")); | 13644 EMSG(_("E728: Using a Dictionary as a number")); |
13607 break; | 13645 break; |
13608 default: | 13646 default: |
14018 EMSG2(_("E706: Variable type mismatch for: %s"), name); | 14056 EMSG2(_("E706: Variable type mismatch for: %s"), name); |
14019 return; | 14057 return; |
14020 } | 14058 } |
14021 | 14059 |
14022 /* | 14060 /* |
14023 * Handle setting internal v: variables separately: we keep the type. | 14061 * Handle setting internal v: variables separately: we don't change |
14062 * the type. | |
14024 */ | 14063 */ |
14025 if (ht == &vimvarht) | 14064 if (ht == &vimvarht) |
14026 { | 14065 { |
14027 if (v->di_tv.v_type == VAR_STRING) | 14066 if (v->di_tv.v_type == VAR_STRING) |
14028 { | 14067 { |
14830 if (fudi.fd_newkey == NULL && !eap->forceit) | 14869 if (fudi.fd_newkey == NULL && !eap->forceit) |
14831 { | 14870 { |
14832 EMSG(_(e_funcdict)); | 14871 EMSG(_(e_funcdict)); |
14833 goto erret; | 14872 goto erret; |
14834 } | 14873 } |
14874 if (fudi.fd_di == NULL) | |
14875 { | |
14876 /* Can't add a function to a locked dictionary */ | |
14877 if (tv_check_lock(fudi.fd_dict->dv_lock, eap->arg)) | |
14878 goto erret; | |
14879 } | |
14880 /* Can't change an existing function if it is locked */ | |
14881 else if (tv_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg)) | |
14882 goto erret; | |
14835 | 14883 |
14836 /* Give the function a sequential number. Can only be used with a | 14884 /* Give the function a sequential number. Can only be used with a |
14837 * Funcref! */ | 14885 * Funcref! */ |
14838 vim_free(name); | 14886 vim_free(name); |
14839 sprintf(numbuf, "%d", ++func_nr); | 14887 sprintf(numbuf, "%d", ++func_nr); |
15508 msg_scroll = TRUE; /* always scroll up, don't overwrite */ | 15556 msg_scroll = TRUE; /* always scroll up, don't overwrite */ |
15509 msg_str((char_u *)_("calling %s"), sourcing_name); | 15557 msg_str((char_u *)_("calling %s"), sourcing_name); |
15510 if (p_verbose >= 14) | 15558 if (p_verbose >= 14) |
15511 { | 15559 { |
15512 char_u buf[MSG_BUF_LEN]; | 15560 char_u buf[MSG_BUF_LEN]; |
15561 char_u numbuf[NUMBUFLEN]; | |
15562 char_u *tofree; | |
15513 | 15563 |
15514 msg_puts((char_u *)"("); | 15564 msg_puts((char_u *)"("); |
15515 for (i = 0; i < argcount; ++i) | 15565 for (i = 0; i < argcount; ++i) |
15516 { | 15566 { |
15517 if (i > 0) | 15567 if (i > 0) |
15518 msg_puts((char_u *)", "); | 15568 msg_puts((char_u *)", "); |
15519 if (argvars[i].v_type == VAR_NUMBER) | 15569 if (argvars[i].v_type == VAR_NUMBER) |
15520 msg_outnum((long)argvars[i].vval.v_number); | 15570 msg_outnum((long)argvars[i].vval.v_number); |
15521 else | 15571 else |
15522 { | 15572 { |
15523 trunc_string(get_tv_string(&argvars[i]), | 15573 trunc_string(tv2string(&argvars[i], &tofree, numbuf), |
15524 buf, MSG_BUF_LEN); | 15574 buf, MSG_BUF_LEN); |
15525 msg_puts((char_u *)"\""); | |
15526 msg_puts(buf); | 15575 msg_puts(buf); |
15527 msg_puts((char_u *)"\""); | 15576 vim_free(tofree); |
15528 } | 15577 } |
15529 } | 15578 } |
15530 msg_puts((char_u *)")"); | 15579 msg_puts((char_u *)")"); |
15531 } | 15580 } |
15532 msg_puts((char_u *)"\n"); /* don't overwrite this either */ | 15581 msg_puts((char_u *)"\n"); /* don't overwrite this either */ |
15554 } | 15603 } |
15555 | 15604 |
15556 /* when being verbose, mention the return value */ | 15605 /* when being verbose, mention the return value */ |
15557 if (p_verbose >= 12) | 15606 if (p_verbose >= 12) |
15558 { | 15607 { |
15559 char_u *sn, *val; | 15608 char_u *sn; |
15560 | 15609 |
15561 ++no_wait_return; | 15610 ++no_wait_return; |
15562 msg_scroll = TRUE; /* always scroll up, don't overwrite */ | 15611 msg_scroll = TRUE; /* always scroll up, don't overwrite */ |
15563 | 15612 |
15564 /* Make sure the output fits in IObuff. */ | 15613 /* Make sure the output fits in IObuff. */ |
15569 if (aborting()) | 15618 if (aborting()) |
15570 smsg((char_u *)_("%s aborted"), sn); | 15619 smsg((char_u *)_("%s aborted"), sn); |
15571 else if (fc.rettv->v_type == VAR_NUMBER) | 15620 else if (fc.rettv->v_type == VAR_NUMBER) |
15572 smsg((char_u *)_("%s returning #%ld"), sn, | 15621 smsg((char_u *)_("%s returning #%ld"), sn, |
15573 (long)fc.rettv->vval.v_number); | 15622 (long)fc.rettv->vval.v_number); |
15574 else if (fc.rettv->v_type == VAR_STRING) | 15623 else |
15575 { | 15624 { |
15576 val = get_tv_string(fc.rettv); | 15625 char_u buf[MSG_BUF_LEN]; |
15577 if (STRLEN(val) > IOSIZE / 2 - 50) | 15626 char_u numbuf[NUMBUFLEN]; |
15578 val = val + STRLEN(val) - (IOSIZE / 2 - 50); | 15627 char_u *tofree; |
15579 smsg((char_u *)_("%s returning \"%s\""), sn, val); | 15628 |
15629 trunc_string(tv2string(fc.rettv, &tofree, numbuf), | |
15630 buf, MSG_BUF_LEN); | |
15631 smsg((char_u *)_("%s returning %s"), sn, buf); | |
15632 vim_free(tofree); | |
15580 } | 15633 } |
15581 msg_puts((char_u *)"\n"); /* don't overwrite this either */ | 15634 msg_puts((char_u *)"\n"); /* don't overwrite this either */ |
15582 cmdline_row = msg_row; | 15635 cmdline_row = msg_row; |
15583 --no_wait_return; | 15636 --no_wait_return; |
15584 } | 15637 } |