Mercurial > vim
comparison src/eval.c @ 121:86d71ae0c85a v7.0042
updated for version 7.0042
author | vimboss |
---|---|
date | Wed, 19 Jan 2005 22:24:34 +0000 |
parents | d4ea645c7748 |
children | f455396f3c3f |
comparison
equal
deleted
inserted
replaced
120:34423a71d203 | 121:86d71ae0c85a |
---|---|
107 | 107 |
108 #define VAR_MAXNEST 100 /* maximum nesting of lists and dicts */ | 108 #define VAR_MAXNEST 100 /* maximum nesting of lists and dicts */ |
109 | 109 |
110 /* | 110 /* |
111 * Structure to hold an item of a Dictionary. | 111 * Structure to hold an item of a Dictionary. |
112 * The key is copied into "di_key" to avoid an extra alloc/free for it. | |
112 */ | 113 */ |
113 struct dictitem_S | 114 struct dictitem_S |
114 { | 115 { |
115 struct dictitem_S *di_next; /* next item in list */ | |
116 char_u *di_key; /* key (never NULL!) */ | |
117 typeval di_tv; /* type and value of the variable */ | 116 typeval di_tv; /* type and value of the variable */ |
117 char_u di_key[1]; /* key (actually longer!) */ | |
118 }; | 118 }; |
119 | 119 |
120 typedef struct dictitem_S dictitem; | 120 typedef struct dictitem_S dictitem; |
121 | 121 |
122 /* | 122 /* |
123 * In a hashtable item "hi_key" points to "di_key" in a dictitem. | |
124 * This avoids adding a pointer to the hashtable item. | |
125 * DI2HIKEY() converts a dictitem pointer to a hashitem key pointer. | |
126 * HIKEY2DI() converts a hashitem key pointer to a dictitem pointer. | |
127 * HI2DI() converts a hashitem pointer to a dictitem pointer. | |
128 */ | |
129 static dictitem dumdi; | |
130 #define DI2HIKEY(p) ((p)->di_key) | |
131 #define HIKEY2DI(p) ((dictitem *)(p - (dumdi.di_key - (char_u *)&dumdi.di_tv))) | |
132 #define HI2DI(p) HIKEY2DI((p)->hi_key) | |
133 | |
134 /* | |
123 * Structure to hold info about a Dictionary. | 135 * Structure to hold info about a Dictionary. |
124 */ | 136 */ |
125 struct dictvar_S | 137 struct dictvar_S |
126 { | 138 { |
127 int dv_refcount; /* reference count */ | 139 int dv_refcount; /* reference count */ |
128 dictitem *dv_first; /* first item, NULL if none */ | 140 hashtable dv_hashtable; /* hashtable that refers to the items */ |
129 }; | 141 }; |
130 | 142 |
131 typedef struct dictvar_S dictvar; | 143 typedef struct dictvar_S dictvar; |
132 | 144 |
133 /* | 145 /* |
171 long ll_n2; /* Second index for list range */ | 183 long ll_n2; /* Second index for list range */ |
172 int ll_empty2; /* Second index is empty: [i:] */ | 184 int ll_empty2; /* Second index is empty: [i:] */ |
173 dictvar *ll_dict; /* The Dictionary or NULL */ | 185 dictvar *ll_dict; /* The Dictionary or NULL */ |
174 dictitem *ll_di; /* The dictitem or NULL */ | 186 dictitem *ll_di; /* The dictitem or NULL */ |
175 char_u *ll_newkey; /* New key for Dict in alloc. mem or NULL. */ | 187 char_u *ll_newkey; /* New key for Dict in alloc. mem or NULL. */ |
176 dictitem **ll_pdi; /* di_next field pointing to found dictitem */ | |
177 } lval; | 188 } lval; |
178 | 189 |
179 | 190 |
180 static char *e_letunexp = N_("E18: Unexpected characters in :let"); | 191 static char *e_letunexp = N_("E18: Unexpected characters in :let"); |
181 static char *e_listidx = N_("E684: list index out of range: %ld"); | 192 static char *e_listidx = N_("E684: list index out of range: %ld"); |
182 static char *e_undefvar = N_("E121: Undefined variable: %s"); | 193 static char *e_undefvar = N_("E121: Undefined variable: %s"); |
183 static char *e_missbrac = N_("E111: Missing ']'"); | 194 static char *e_missbrac = N_("E111: Missing ']'"); |
184 static char *e_intern2 = N_("E685: Internal error: %s"); | |
185 static char *e_listarg = N_("E686: Argument of %s must be a List"); | 195 static char *e_listarg = N_("E686: Argument of %s must be a List"); |
186 static char *e_listdictarg = N_("E712: Argument of %s must be a List or Dictionaary"); | 196 static char *e_listdictarg = N_("E712: Argument of %s must be a List or Dictionaary"); |
187 static char *e_emptykey = N_("E713: Empty key in Dictionary"); | 197 static char *e_emptykey = N_("E713: Cannot use empty key for Dictionary"); |
188 static char *e_listreq = N_("E714: List required"); | 198 static char *e_listreq = N_("E714: List required"); |
189 static char *e_dictreq = N_("E715: Dictionary required"); | 199 static char *e_dictreq = N_("E715: Dictionary required"); |
190 static char *e_toomanyarg = N_("E118: Too many arguments for function: %s"); | 200 static char *e_toomanyarg = N_("E118: Too many arguments for function: %s"); |
191 static char *e_dictkey = N_("E716: Key not present in Dictionary: %s"); | 201 static char *e_dictkey = N_("E716: Key not present in Dictionary: %s"); |
192 static char *e_funcexts = N_("E122: Function %s already exists, add ! to replace it"); | 202 static char *e_funcexts = N_("E122: Function %s already exists, add ! to replace it"); |
287 typedef struct | 297 typedef struct |
288 { | 298 { |
289 dictvar *fd_dict; /* Dictionary used */ | 299 dictvar *fd_dict; /* Dictionary used */ |
290 char_u *fd_newkey; /* new key in "dict" */ | 300 char_u *fd_newkey; /* new key in "dict" */ |
291 dictitem *fd_di; /* Dictionary item used */ | 301 dictitem *fd_di; /* Dictionary item used */ |
292 dictitem **fd_pdi; /* field that points to "fd_di" */ | |
293 } funcdict; | 302 } funcdict; |
294 | 303 |
295 /* | 304 /* |
296 * Return the name of the executed function. | 305 * Return the name of the executed function. |
297 */ | 306 */ |
449 static void list_join __ARGS((garray_T *gap, listvar *l, char_u *sep, int echo)); | 458 static void list_join __ARGS((garray_T *gap, listvar *l, char_u *sep, int echo)); |
450 | 459 |
451 static dictvar *dict_alloc __ARGS((void)); | 460 static dictvar *dict_alloc __ARGS((void)); |
452 static void dict_unref __ARGS((dictvar *d)); | 461 static void dict_unref __ARGS((dictvar *d)); |
453 static void dict_free __ARGS((dictvar *d)); | 462 static void dict_free __ARGS((dictvar *d)); |
454 static dictitem *dictitem_alloc __ARGS((void)); | 463 static dictitem *dictitem_alloc __ARGS((char_u *key)); |
455 static dictitem *dictitem_copy __ARGS((dictitem *org)); | 464 static dictitem *dictitem_copy __ARGS((dictitem *org)); |
465 static void dictitem_remove __ARGS((dictvar *dict, dictitem *item)); | |
456 static void dictitem_free __ARGS((dictitem *item)); | 466 static void dictitem_free __ARGS((dictitem *item)); |
457 static void dict_add __ARGS((dictvar *d, dictitem *item)); | 467 static int dict_add __ARGS((dictvar *d, dictitem *item)); |
458 static long dict_len __ARGS((dictvar *d)); | 468 static long dict_len __ARGS((dictvar *d)); |
459 static dictitem *dict_find __ARGS((dictvar *d, char_u *key, int len, dictitem ***pdi)); | 469 static dictitem *dict_find __ARGS((dictvar *d, char_u *key, int len)); |
460 static char_u *dict2string __ARGS((typeval *tv)); | 470 static char_u *dict2string __ARGS((typeval *tv)); |
461 static int get_dict_tv __ARGS((char_u **arg, typeval *rettv, int evaluate)); | 471 static int get_dict_tv __ARGS((char_u **arg, typeval *rettv, int evaluate)); |
462 | 472 |
463 static char_u *echo_string __ARGS((typeval *tv, char_u **tofree, char_u *numbuf)); | 473 static char_u *echo_string __ARGS((typeval *tv, char_u **tofree, char_u *numbuf)); |
464 static char_u *tv2string __ARGS((typeval *tv, char_u **tofree, char_u *numbuf)); | 474 static char_u *tv2string __ARGS((typeval *tv, char_u **tofree, char_u *numbuf)); |
1827 /* Report an invalid expression in braces, unless the | 1837 /* Report an invalid expression in braces, unless the |
1828 * expression evaluation has been cancelled due to an | 1838 * expression evaluation has been cancelled due to an |
1829 * aborting error, an interrupt, or an exception. */ | 1839 * aborting error, an interrupt, or an exception. */ |
1830 if (!aborting() && !quiet) | 1840 if (!aborting() && !quiet) |
1831 { | 1841 { |
1832 if (unlet) | 1842 emsg_severe = TRUE; |
1833 emsg_severe = TRUE; | |
1834 EMSG2(_(e_invarg2), name); | 1843 EMSG2(_(e_invarg2), name); |
1835 return NULL; | 1844 return NULL; |
1836 } | 1845 } |
1837 } | 1846 } |
1838 lp->ll_name = lp->ll_exp_name; | 1847 lp->ll_name = lp->ll_exp_name; |
1968 return NULL; | 1977 return NULL; |
1969 } | 1978 } |
1970 } | 1979 } |
1971 lp->ll_list = NULL; | 1980 lp->ll_list = NULL; |
1972 lp->ll_dict = lp->ll_tv->vval.v_dict; | 1981 lp->ll_dict = lp->ll_tv->vval.v_dict; |
1973 lp->ll_di = dict_find(lp->ll_dict, key, len, &lp->ll_pdi); | 1982 lp->ll_di = dict_find(lp->ll_dict, key, len); |
1974 if (lp->ll_di == NULL) | 1983 if (lp->ll_di == NULL) |
1975 { | 1984 { |
1976 /* Key does not exist in dict: may need toadd it. */ | 1985 /* Key does not exist in dict: may need to add it. */ |
1977 if (*p == '[' || *p == '.' || unlet) | 1986 if (*p == '[' || *p == '.' || unlet) |
1978 { | 1987 { |
1979 if (!quiet) | 1988 if (!quiet) |
1980 EMSG2(_(e_dictkey), key); | 1989 EMSG2(_(e_dictkey), key); |
1981 if (len == -1) | 1990 if (len == -1) |
2163 EMSG2(_(e_letwrong), op); | 2172 EMSG2(_(e_letwrong), op); |
2164 return; | 2173 return; |
2165 } | 2174 } |
2166 | 2175 |
2167 /* Need to add an item to the Dictionary. */ | 2176 /* Need to add an item to the Dictionary. */ |
2168 di = dictitem_alloc(); | 2177 di = dictitem_alloc(lp->ll_newkey); |
2169 if (di == NULL) | 2178 if (di == NULL) |
2170 return; | 2179 return; |
2171 di->di_key = lp->ll_newkey; | 2180 if (dict_add(lp->ll_tv->vval.v_dict, di) == FAIL) |
2172 lp->ll_newkey = NULL; | 2181 { |
2173 dict_add(lp->ll_tv->vval.v_dict, di); | 2182 vim_free(di); |
2183 return; | |
2184 } | |
2174 lp->ll_tv = &di->di_tv; | 2185 lp->ll_tv = &di->di_tv; |
2175 } | 2186 } |
2176 else if (op != NULL && *op != '=') | 2187 else if (op != NULL && *op != '=') |
2177 { | 2188 { |
2178 tv_op(lp->ll_tv, rettv, op); | 2189 tv_op(lp->ll_tv, rettv, op); |
2530 int len; | 2541 int len; |
2531 typeval rettv; | 2542 typeval rettv; |
2532 linenr_T lnum; | 2543 linenr_T lnum; |
2533 int doesrange; | 2544 int doesrange; |
2534 int failed = FALSE; | 2545 int failed = FALSE; |
2535 | 2546 funcdict fudi; |
2536 tofree = trans_function_name(&arg, eap->skip, TFN_INT, NULL); | 2547 |
2548 tofree = trans_function_name(&arg, eap->skip, TFN_INT, &fudi); | |
2549 vim_free(fudi.fd_newkey); | |
2537 if (tofree == NULL) | 2550 if (tofree == NULL) |
2538 return; | 2551 return; |
2552 | |
2553 /* Increase refcount on dictionary, it could get deleted when evaluating | |
2554 * the arguments. */ | |
2555 if (fudi.fd_dict != NULL) | |
2556 ++fudi.fd_dict->dv_refcount; | |
2539 | 2557 |
2540 /* If it is the name of a variable of type VAR_FUNC use its contents. */ | 2558 /* If it is the name of a variable of type VAR_FUNC use its contents. */ |
2541 len = STRLEN(tofree); | 2559 len = STRLEN(tofree); |
2542 name = deref_func_name(tofree, &len); | 2560 name = deref_func_name(tofree, &len); |
2543 | 2561 |
2570 curwin->w_cursor.lnum = lnum; | 2588 curwin->w_cursor.lnum = lnum; |
2571 curwin->w_cursor.col = 0; | 2589 curwin->w_cursor.col = 0; |
2572 } | 2590 } |
2573 arg = startarg; | 2591 arg = startarg; |
2574 if (get_func_tv(name, STRLEN(name), &rettv, &arg, | 2592 if (get_func_tv(name, STRLEN(name), &rettv, &arg, |
2575 eap->line1, eap->line2, &doesrange, !eap->skip, NULL) == FAIL) | 2593 eap->line1, eap->line2, &doesrange, |
2594 !eap->skip, fudi.fd_dict) == FAIL) | |
2576 { | 2595 { |
2577 failed = TRUE; | 2596 failed = TRUE; |
2578 break; | 2597 break; |
2579 } | 2598 } |
2580 clear_tv(&rettv); | 2599 clear_tv(&rettv); |
2601 else | 2620 else |
2602 eap->nextcmd = check_nextcmd(arg); | 2621 eap->nextcmd = check_nextcmd(arg); |
2603 } | 2622 } |
2604 | 2623 |
2605 end: | 2624 end: |
2625 dict_unref(fudi.fd_dict); | |
2606 vim_free(tofree); | 2626 vim_free(tofree); |
2607 } | 2627 } |
2608 | 2628 |
2609 /* | 2629 /* |
2610 * ":unlet[!] var1 ... " command. | 2630 * ":unlet[!] var1 ... " command. |
2689 ++lp->ll_n1; | 2709 ++lp->ll_n1; |
2690 } | 2710 } |
2691 } | 2711 } |
2692 else | 2712 else |
2693 { | 2713 { |
2694 clear_tv(lp->ll_tv); | |
2695 if (lp->ll_list != NULL) | 2714 if (lp->ll_list != NULL) |
2696 { | |
2697 /* unlet a List item. */ | 2715 /* unlet a List item. */ |
2698 listitem_remove(lp->ll_list, lp->ll_li); | 2716 listitem_remove(lp->ll_list, lp->ll_li); |
2699 } | |
2700 else | 2717 else |
2701 { | |
2702 /* unlet a Dictionary item. */ | 2718 /* unlet a Dictionary item. */ |
2703 *lp->ll_pdi = lp->ll_di->di_next; | 2719 dictitem_remove(lp->ll_dict, lp->ll_di); |
2704 dictitem_free(lp->ll_di); | |
2705 } | |
2706 } | 2720 } |
2707 | 2721 |
2708 return ret; | 2722 return ret; |
2709 } | 2723 } |
2710 | 2724 |
3759 *arg = skipwhite(*arg); | 3773 *arg = skipwhite(*arg); |
3760 | 3774 |
3761 /* | 3775 /* |
3762 * Handle expr[expr], expr[expr:expr] subscript and .name lookup. | 3776 * Handle expr[expr], expr[expr:expr] subscript and .name lookup. |
3763 * Also handle function call with Funcref variable: func(expr) | 3777 * Also handle function call with Funcref variable: func(expr) |
3764 * Can all be combined: dict.func(expr)[idx].func(expr) | 3778 * Can all be combined: dict.func(expr)[idx]['func'](expr) |
3765 */ | 3779 */ |
3766 selfdict = NULL; | 3780 selfdict = NULL; |
3767 while (ret == OK | 3781 while (ret == OK |
3768 && (**arg == '[' | 3782 && (**arg == '[' |
3769 || (**arg == '.' && rettv->v_type == VAR_DICT) | 3783 || (**arg == '.' && rettv->v_type == VAR_DICT) |
3777 /* Invoke the function. Recursive! */ | 3791 /* Invoke the function. Recursive! */ |
3778 ret = get_func_tv(s, STRLEN(s), rettv, arg, | 3792 ret = get_func_tv(s, STRLEN(s), rettv, arg, |
3779 curwin->w_cursor.lnum, curwin->w_cursor.lnum, | 3793 curwin->w_cursor.lnum, curwin->w_cursor.lnum, |
3780 &len, evaluate, selfdict); | 3794 &len, evaluate, selfdict); |
3781 | 3795 |
3782 /* Stop the expression evaluation when immediately | 3796 /* Stop the expression evaluation when immediately aborting on |
3783 * aborting on error, or when an interrupt occurred or | 3797 * error, or when an interrupt occurred or an exception was thrown |
3784 * an exception was thrown but not caught. */ | 3798 * but not caught. */ |
3785 if (aborting()) | 3799 if (aborting()) |
3786 { | 3800 { |
3787 if (ret == OK) | 3801 if (ret == OK) |
3788 clear_tv(rettv); | 3802 clear_tv(rettv); |
3789 ret = FAIL; | 3803 ret = FAIL; |
3790 } | 3804 } |
3805 dict_unref(selfdict); | |
3791 selfdict = NULL; | 3806 selfdict = NULL; |
3792 } | 3807 } |
3793 else | 3808 else /* **arg == '[' || **arg == '.' */ |
3794 { | 3809 { |
3810 dict_unref(selfdict); | |
3795 if (rettv->v_type == VAR_DICT) | 3811 if (rettv->v_type == VAR_DICT) |
3812 { | |
3796 selfdict = rettv->vval.v_dict; | 3813 selfdict = rettv->vval.v_dict; |
3814 if (selfdict != NULL) | |
3815 ++selfdict->dv_refcount; | |
3816 } | |
3797 else | 3817 else |
3798 selfdict = NULL; | 3818 selfdict = NULL; |
3799 if (eval_index(arg, rettv, evaluate) == FAIL) | 3819 if (eval_index(arg, rettv, evaluate) == FAIL) |
3800 { | 3820 { |
3801 clear_tv(rettv); | 3821 clear_tv(rettv); |
3802 ret = FAIL; | 3822 ret = FAIL; |
3803 } | 3823 } |
3804 } | 3824 } |
3805 } | 3825 } |
3826 dict_unref(selfdict); | |
3806 | 3827 |
3807 /* | 3828 /* |
3808 * Apply logical NOT and unary '-', from right to left, ignore '+'. | 3829 * Apply logical NOT and unary '-', from right to left, ignore '+'. |
3809 */ | 3830 */ |
3810 if (ret == OK && evaluate && end_leader > start_leader) | 3831 if (ret == OK && evaluate && end_leader > start_leader) |
4031 clear_tv(&var1); | 4052 clear_tv(&var1); |
4032 return FAIL; | 4053 return FAIL; |
4033 } | 4054 } |
4034 } | 4055 } |
4035 | 4056 |
4036 item = dict_find(rettv->vval.v_dict, key, (int)len, NULL); | 4057 item = dict_find(rettv->vval.v_dict, key, (int)len); |
4037 | 4058 |
4038 if (item == NULL) | 4059 if (item == NULL) |
4039 EMSG2(_(e_dictkey), key); | 4060 EMSG2(_(e_dictkey), key); |
4040 if (len == -1) | 4061 if (len == -1) |
4041 clear_tv(&var1); | 4062 clear_tv(&var1); |
4369 if (item != NULL) | 4390 if (item != NULL) |
4370 { | 4391 { |
4371 item->li_tv = tv; | 4392 item->li_tv = tv; |
4372 list_append(l, item); | 4393 list_append(l, item); |
4373 } | 4394 } |
4395 else | |
4396 clear_tv(&tv); | |
4374 } | 4397 } |
4375 | 4398 |
4376 if (**arg == ']') | 4399 if (**arg == ']') |
4377 break; | 4400 break; |
4378 if (**arg != ',') | 4401 if (**arg != ',') |
4521 dict_equal(d1, d2, ic) | 4544 dict_equal(d1, d2, ic) |
4522 dictvar *d1; | 4545 dictvar *d1; |
4523 dictvar *d2; | 4546 dictvar *d2; |
4524 int ic; /* ignore case for strings */ | 4547 int ic; /* ignore case for strings */ |
4525 { | 4548 { |
4526 dictitem *item1, *item2; | 4549 hashitem *hi; |
4550 dictitem *item2; | |
4551 int todo; | |
4527 | 4552 |
4528 if (dict_len(d1) != dict_len(d2)) | 4553 if (dict_len(d1) != dict_len(d2)) |
4529 return FALSE; | 4554 return FALSE; |
4530 | 4555 |
4531 for (item1 = d1->dv_first; item1 != NULL; item1 = item1->di_next) | 4556 todo = d1->dv_hashtable.ht_used; |
4532 { | 4557 for (hi = d1->dv_hashtable.ht_array; todo > 0; ++hi) |
4533 item2 = dict_find(d2, item1->di_key, -1, NULL); | 4558 { |
4534 if (item2 == NULL) | 4559 if (!HASHITEM_EMPTY(hi)) |
4535 return FALSE; | 4560 { |
4536 if (!tv_equal(&item1->di_tv, &item2->di_tv, ic)) | 4561 item2 = dict_find(d2, hi->hi_key, -1); |
4537 return FALSE; | 4562 if (item2 == NULL) |
4563 return FALSE; | |
4564 if (!tv_equal(&HI2DI(hi)->di_tv, &item2->di_tv, ic)) | |
4565 return FALSE; | |
4566 --todo; | |
4567 } | |
4538 } | 4568 } |
4539 return TRUE; | 4569 return TRUE; |
4540 } | 4570 } |
4541 | 4571 |
4542 /* | 4572 /* |
4554 if (tv1->v_type == VAR_LIST || tv2->v_type == VAR_LIST) | 4584 if (tv1->v_type == VAR_LIST || tv2->v_type == VAR_LIST) |
4555 { | 4585 { |
4556 /* recursive! */ | 4586 /* recursive! */ |
4557 if (tv1->v_type != tv2->v_type | 4587 if (tv1->v_type != tv2->v_type |
4558 || !list_equal(tv1->vval.v_list, tv2->vval.v_list, ic)) | 4588 || !list_equal(tv1->vval.v_list, tv2->vval.v_list, ic)) |
4589 return FALSE; | |
4590 } | |
4591 else if (tv1->v_type == VAR_DICT || tv2->v_type == VAR_DICT) | |
4592 { | |
4593 /* recursive! */ | |
4594 if (tv1->v_type != tv2->v_type | |
4595 || !dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic)) | |
4559 return FALSE; | 4596 return FALSE; |
4560 } | 4597 } |
4561 else if (tv1->v_type == VAR_FUNC || tv2->v_type == VAR_FUNC) | 4598 else if (tv1->v_type == VAR_FUNC || tv2->v_type == VAR_FUNC) |
4562 { | 4599 { |
4563 if (tv1->v_type != tv2->v_type | 4600 if (tv1->v_type != tv2->v_type |
4929 * Allocate an empty header for a dictionary. | 4966 * Allocate an empty header for a dictionary. |
4930 */ | 4967 */ |
4931 static dictvar * | 4968 static dictvar * |
4932 dict_alloc() | 4969 dict_alloc() |
4933 { | 4970 { |
4934 return (dictvar *)alloc_clear(sizeof(dictvar)); | 4971 dictvar *d; |
4972 | |
4973 d = (dictvar *)alloc(sizeof(dictvar)); | |
4974 if (d != NULL) | |
4975 hash_init(&d->dv_hashtable); | |
4976 return d; | |
4935 } | 4977 } |
4936 | 4978 |
4937 /* | 4979 /* |
4938 * Unreference a Dictionary: decrement the reference count and free it when it | 4980 * Unreference a Dictionary: decrement the reference count and free it when it |
4939 * becomes zero. | 4981 * becomes zero. |
4952 */ | 4994 */ |
4953 static void | 4995 static void |
4954 dict_free(d) | 4996 dict_free(d) |
4955 dictvar *d; | 4997 dictvar *d; |
4956 { | 4998 { |
4957 dictitem *item; | 4999 int todo; |
4958 dictitem *next; | 5000 hashitem *hi; |
4959 | 5001 |
4960 for (item = d->dv_first; item != NULL; item = next) | 5002 /* Careful: we free the dictitems while they still appear in the |
4961 { | 5003 * hashtable. Must not try to resize the hashtable! */ |
4962 next = item->di_next; | 5004 todo = d->dv_hashtable.ht_used; |
4963 dictitem_free(item); | 5005 for (hi = d->dv_hashtable.ht_array; todo > 0; ++hi) |
5006 { | |
5007 if (!HASHITEM_EMPTY(hi)) | |
5008 { | |
5009 dictitem_free(HI2DI(hi)); | |
5010 --todo; | |
5011 } | |
4964 } | 5012 } |
4965 vim_free(d); | 5013 vim_free(d); |
4966 } | 5014 } |
4967 | 5015 |
4968 /* | 5016 /* |
4969 * Allocate a Dictionary item. | 5017 * Allocate a Dictionary item. |
5018 * The "key" is copied to the new item. | |
5019 * Note that the value of the item "di_tv" still needs to be initialized! | |
5020 * Returns NULL when out of memory. | |
4970 */ | 5021 */ |
4971 static dictitem * | 5022 static dictitem * |
4972 dictitem_alloc() | 5023 dictitem_alloc(key) |
4973 { | 5024 char_u *key; |
4974 return (dictitem *)alloc(sizeof(dictitem)); | 5025 { |
5026 dictitem *di; | |
5027 | |
5028 di = (dictitem *)alloc(sizeof(dictitem) + STRLEN(key)); | |
5029 if (di != NULL) | |
5030 STRCPY(di->di_key, key); | |
5031 return di; | |
4975 } | 5032 } |
4976 | 5033 |
4977 /* | 5034 /* |
4978 * Make a copy of a Dictionary item. | 5035 * Make a copy of a Dictionary item. |
4979 */ | 5036 */ |
4981 dictitem_copy(org) | 5038 dictitem_copy(org) |
4982 dictitem *org; | 5039 dictitem *org; |
4983 { | 5040 { |
4984 dictitem *di; | 5041 dictitem *di; |
4985 | 5042 |
4986 di = (dictitem *)alloc(sizeof(dictitem)); | 5043 di = (dictitem *)alloc(sizeof(dictitem) + STRLEN(org->di_key)); |
4987 if (di != NULL) | 5044 if (di != NULL) |
4988 { | 5045 { |
4989 di->di_key = vim_strsave(org->di_key); | 5046 STRCPY(di->di_key, org->di_key); |
4990 if (di->di_key == NULL) | |
4991 { | |
4992 vim_free(di); | |
4993 return NULL; | |
4994 } | |
4995 copy_tv(&org->di_tv, &di->di_tv); | 5047 copy_tv(&org->di_tv, &di->di_tv); |
4996 } | 5048 } |
4997 return di; | 5049 return di; |
5050 } | |
5051 | |
5052 /* | |
5053 * Remove item "item" from Dictionary "dict" and free it. | |
5054 */ | |
5055 static void | |
5056 dictitem_remove(dict, item) | |
5057 dictvar *dict; | |
5058 dictitem *item; | |
5059 { | |
5060 hashitem *hi; | |
5061 | |
5062 hi = hash_find(&dict->dv_hashtable, item->di_key); | |
5063 if (HASHITEM_EMPTY(hi)) | |
5064 EMSG2(_(e_intern2), "dictitem_remove()"); | |
5065 else | |
5066 hash_remove(&dict->dv_hashtable, hi); | |
5067 dictitem_free(item); | |
4998 } | 5068 } |
4999 | 5069 |
5000 /* | 5070 /* |
5001 * Free a dict item. Also clears the value. | 5071 * Free a dict item. Also clears the value. |
5002 */ | 5072 */ |
5003 static void | 5073 static void |
5004 dictitem_free(item) | 5074 dictitem_free(item) |
5005 dictitem *item; | 5075 dictitem *item; |
5006 { | 5076 { |
5007 vim_free(item->di_key); | |
5008 clear_tv(&item->di_tv); | 5077 clear_tv(&item->di_tv); |
5009 vim_free(item); | 5078 vim_free(item); |
5010 } | 5079 } |
5011 | 5080 |
5012 /* | 5081 /* |
5018 dict_copy(orig, deep) | 5087 dict_copy(orig, deep) |
5019 dictvar *orig; | 5088 dictvar *orig; |
5020 int deep; | 5089 int deep; |
5021 { | 5090 { |
5022 dictvar *copy; | 5091 dictvar *copy; |
5023 dictitem *item; | |
5024 dictitem *di; | 5092 dictitem *di; |
5093 int todo; | |
5094 hashitem *hi; | |
5025 | 5095 |
5026 if (orig == NULL) | 5096 if (orig == NULL) |
5027 return NULL; | 5097 return NULL; |
5028 | 5098 |
5029 copy = dict_alloc(); | 5099 copy = dict_alloc(); |
5030 if (copy != NULL) | 5100 if (copy != NULL) |
5031 { | 5101 { |
5032 for (item = orig->dv_first; item != NULL; item = item->di_next) | 5102 todo = orig->dv_hashtable.ht_used; |
5033 { | 5103 for (hi = orig->dv_hashtable.ht_array; todo > 0; ++hi) |
5034 di = dictitem_alloc(); | 5104 { |
5035 if (di == NULL) | 5105 if (!HASHITEM_EMPTY(hi)) |
5036 break; | |
5037 di->di_key = vim_strsave(item->di_key); | |
5038 if (di->di_key == NULL) | |
5039 { | 5106 { |
5040 vim_free(di); | 5107 --todo; |
5041 break; | 5108 |
5109 di = dictitem_alloc(hi->hi_key); | |
5110 if (di == NULL) | |
5111 break; | |
5112 if (deep) | |
5113 item_copy(&HI2DI(hi)->di_tv, &di->di_tv, deep); | |
5114 else | |
5115 copy_tv(&HI2DI(hi)->di_tv, &di->di_tv); | |
5116 if (dict_add(copy, di) == FAIL) | |
5117 { | |
5118 dictitem_free(di); | |
5119 break; | |
5120 } | |
5042 } | 5121 } |
5043 if (deep) | 5122 } |
5044 item_copy(&item->di_tv, &di->di_tv, deep); | 5123 |
5045 else | |
5046 copy_tv(&item->di_tv, &di->di_tv); | |
5047 dict_add(copy, di); | |
5048 } | |
5049 ++copy->dv_refcount; | 5124 ++copy->dv_refcount; |
5050 } | 5125 } |
5051 | 5126 |
5052 return copy; | 5127 return copy; |
5053 } | 5128 } |
5054 | 5129 |
5055 /* | 5130 /* |
5056 * Add item "item" to Dictionary "d". | 5131 * Add item "item" to Dictionary "d". |
5057 */ | 5132 * Returns FAIL when out of memory and when key already existed. |
5058 static void | 5133 */ |
5134 static int | |
5059 dict_add(d, item) | 5135 dict_add(d, item) |
5060 dictvar *d; | 5136 dictvar *d; |
5061 dictitem *item; | 5137 dictitem *item; |
5062 { | 5138 { |
5063 item->di_next = d->dv_first; | 5139 return hash_add(&d->dv_hashtable, item->di_key); |
5064 d->dv_first = item; | 5140 } |
5065 } | |
5066 | |
5067 #if 0 /* not currently used */ | |
5068 static void dict_set_item __ARGS((dictvar *d, int type, char *key, void *val)); | |
5069 | |
5070 /* | |
5071 * Add an item to Dictionary "d" with type "type", key "key" and value "val". | |
5072 * If it already exists it is overwritten. | |
5073 * The key and value are copied to allocated memory. | |
5074 */ | |
5075 static void | |
5076 dict_set_item(d, type, key, val) | |
5077 dictvar *d; | |
5078 int type; | |
5079 char *key; | |
5080 void *val; | |
5081 { | |
5082 dictitem *di; | |
5083 char_u *dkey; | |
5084 | |
5085 di = dict_find(d, (char_u *)key, -1, NULL); | |
5086 if (di == NULL) | |
5087 { | |
5088 dkey = vim_strsave((char_u *)key); | |
5089 if (dkey != NULL) | |
5090 { | |
5091 di = dictitem_alloc(); | |
5092 if (di == NULL) | |
5093 vim_free(dkey); | |
5094 else | |
5095 di->di_key = dkey; | |
5096 } | |
5097 } | |
5098 else | |
5099 clear_tv(&di->di_tv); | |
5100 | |
5101 if (di != NULL) | |
5102 { | |
5103 di->di_tv.v_type = type; | |
5104 switch (type) | |
5105 { | |
5106 case VAR_NUMBER: | |
5107 di->di_tv.vval.v_number = (varnumber_T)val; | |
5108 break; | |
5109 case VAR_FUNC: | |
5110 case VAR_STRING: | |
5111 di->di_tv.vval.v_string = vim_strsave((char_u *)val); | |
5112 break; | |
5113 default: | |
5114 EMSG2(_(e_intern2), "dict_set_item()"); | |
5115 } | |
5116 dict_add(d, di); | |
5117 } | |
5118 } | |
5119 #endif | |
5120 | 5141 |
5121 /* | 5142 /* |
5122 * Get the number of items in a Dictionary. | 5143 * Get the number of items in a Dictionary. |
5123 */ | 5144 */ |
5124 static long | 5145 static long |
5125 dict_len(d) | 5146 dict_len(d) |
5126 dictvar *d; | 5147 dictvar *d; |
5127 { | 5148 { |
5128 dictitem *item; | |
5129 long len = 0; | |
5130 | |
5131 if (d == NULL) | 5149 if (d == NULL) |
5132 return 0L; | 5150 return 0L; |
5133 for (item = d->dv_first; item != NULL; item = item->di_next) | 5151 return d->dv_hashtable.ht_used; |
5134 ++len; | |
5135 return len; | |
5136 } | 5152 } |
5137 | 5153 |
5138 /* | 5154 /* |
5139 * Find item "key[len]" in Dictionary "d". | 5155 * Find item "key[len]" in Dictionary "d". |
5140 * If "len" is negative use strlen(key). | 5156 * If "len" is negative use strlen(key). |
5141 * Sets "*pdi" to pointer to found item, unless "pdi" is NULL. | |
5142 * Returns NULL when not found. | 5157 * Returns NULL when not found. |
5143 */ | 5158 */ |
5144 static dictitem * | 5159 static dictitem * |
5145 dict_find(d, key, len, pdi) | 5160 dict_find(d, key, len) |
5146 dictvar *d; | 5161 dictvar *d; |
5147 char_u *key; | 5162 char_u *key; |
5148 int len; | 5163 int len; |
5149 dictitem ***pdi; | 5164 { |
5150 { | 5165 #define AKEYLEN 200 |
5151 static dictitem *di; | 5166 char_u buf[AKEYLEN]; |
5152 | 5167 char_u *akey; |
5153 if (pdi != NULL) | 5168 char_u *tofree = NULL; |
5154 *pdi = &d->dv_first; | 5169 hashitem *hi; |
5155 for (di = d->dv_first; di != NULL; di = di->di_next) | 5170 |
5156 { | 5171 if (len < 0) |
5157 if (len < 0 | 5172 akey = key; |
5158 ? STRCMP(di->di_key, key) == 0 | 5173 else if (len >= AKEYLEN) |
5159 : STRNCMP(di->di_key, key, len) == 0 && di->di_key[len] == NUL) | 5174 { |
5160 return di; | 5175 tofree = akey = vim_strnsave(key, len); |
5161 if (pdi != NULL) | 5176 if (akey == NULL) |
5162 *pdi = &di->di_next; | 5177 return NULL; |
5163 } | 5178 } |
5164 return NULL; | 5179 else |
5180 { | |
5181 /* Avoid a malloc/free by using buf[]. */ | |
5182 STRNCPY(buf, key, len); | |
5183 buf[len] = NUL; | |
5184 akey = buf; | |
5185 } | |
5186 | |
5187 hi = hash_find(&d->dv_hashtable, akey); | |
5188 vim_free(tofree); | |
5189 if (HASHITEM_EMPTY(hi)) | |
5190 return NULL; | |
5191 return HI2DI(hi); | |
5165 } | 5192 } |
5166 | 5193 |
5167 /* | 5194 /* |
5168 * Return an allocated string with the string representation of a Dictionary. | 5195 * Return an allocated string with the string representation of a Dictionary. |
5169 * May return NULL. | 5196 * May return NULL. |
5174 { | 5201 { |
5175 garray_T ga; | 5202 garray_T ga; |
5176 int first = TRUE; | 5203 int first = TRUE; |
5177 char_u *tofree; | 5204 char_u *tofree; |
5178 char_u numbuf[NUMBUFLEN]; | 5205 char_u numbuf[NUMBUFLEN]; |
5179 dictitem *item; | 5206 hashitem *hi; |
5180 char_u *s; | 5207 char_u *s; |
5181 | 5208 dictvar *d; |
5182 if (tv->vval.v_dict == NULL) | 5209 int todo; |
5210 | |
5211 if ((d = tv->vval.v_dict) == NULL) | |
5183 return NULL; | 5212 return NULL; |
5184 ga_init2(&ga, (int)sizeof(char), 80); | 5213 ga_init2(&ga, (int)sizeof(char), 80); |
5185 ga_append(&ga, '{'); | 5214 ga_append(&ga, '{'); |
5186 | 5215 |
5187 for (item = tv->vval.v_dict->dv_first; item != NULL; item = item->di_next) | 5216 todo = d->dv_hashtable.ht_used; |
5188 { | 5217 for (hi = d->dv_hashtable.ht_array; todo > 0; ++hi) |
5189 if (first) | 5218 { |
5190 first = FALSE; | 5219 if (!HASHITEM_EMPTY(hi)) |
5191 else | 5220 { |
5192 ga_concat(&ga, (char_u *)", "); | 5221 --todo; |
5193 | 5222 |
5194 tofree = string_quote(item->di_key, FALSE); | 5223 if (first) |
5195 if (tofree != NULL) | 5224 first = FALSE; |
5196 { | 5225 else |
5197 ga_concat(&ga, tofree); | 5226 ga_concat(&ga, (char_u *)", "); |
5227 | |
5228 tofree = string_quote(hi->hi_key, FALSE); | |
5229 if (tofree != NULL) | |
5230 { | |
5231 ga_concat(&ga, tofree); | |
5232 vim_free(tofree); | |
5233 } | |
5234 ga_concat(&ga, (char_u *)": "); | |
5235 s = tv2string(&HI2DI(hi)->di_tv, &tofree, numbuf); | |
5236 if (s != NULL) | |
5237 ga_concat(&ga, s); | |
5198 vim_free(tofree); | 5238 vim_free(tofree); |
5199 } | 5239 } |
5200 ga_concat(&ga, (char_u *)": "); | |
5201 s = tv2string(&item->di_tv, &tofree, numbuf); | |
5202 if (s != NULL) | |
5203 ga_concat(&ga, s); | |
5204 vim_free(tofree); | |
5205 } | 5240 } |
5206 | 5241 |
5207 ga_append(&ga, '}'); | 5242 ga_append(&ga, '}'); |
5208 ga_append(&ga, NUL); | 5243 ga_append(&ga, NUL); |
5209 return (char_u *)ga.ga_data; | 5244 return (char_u *)ga.ga_data; |
5218 char_u **arg; | 5253 char_u **arg; |
5219 typeval *rettv; | 5254 typeval *rettv; |
5220 int evaluate; | 5255 int evaluate; |
5221 { | 5256 { |
5222 dictvar *d = NULL; | 5257 dictvar *d = NULL; |
5258 typeval tvkey; | |
5223 typeval tv; | 5259 typeval tv; |
5224 char_u *key; | 5260 char_u *key; |
5225 dictitem *item; | 5261 dictitem *item; |
5226 char_u *start = skipwhite(*arg + 1); | 5262 char_u *start = skipwhite(*arg + 1); |
5263 char_u buf[NUMBUFLEN]; | |
5227 | 5264 |
5228 /* | 5265 /* |
5229 * First check if it's not a curly-braces thing: {expr}. | 5266 * First check if it's not a curly-braces thing: {expr}. |
5230 * Must do this without evaluating, otherwise a function may be called | 5267 * Must do this without evaluating, otherwise a function may be called |
5231 * twice. Unfortunately this means we need to call eval1() twice for the | 5268 * twice. Unfortunately this means we need to call eval1() twice for the |
5244 { | 5281 { |
5245 d = dict_alloc(); | 5282 d = dict_alloc(); |
5246 if (d == NULL) | 5283 if (d == NULL) |
5247 return FAIL; | 5284 return FAIL; |
5248 } | 5285 } |
5286 tvkey.v_type = VAR_UNKNOWN; | |
5287 tv.v_type = VAR_UNKNOWN; | |
5249 | 5288 |
5250 *arg = skipwhite(*arg + 1); | 5289 *arg = skipwhite(*arg + 1); |
5251 while (**arg != '}' && **arg != NUL) | 5290 while (**arg != '}' && **arg != NUL) |
5252 { | 5291 { |
5253 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */ | 5292 if (eval1(arg, &tvkey, evaluate) == FAIL) /* recursive! */ |
5254 goto failret; | 5293 goto failret; |
5255 if (**arg != ':') | 5294 if (**arg != ':') |
5256 { | 5295 { |
5257 EMSG2(_("E720: Missing colon in Dictionary: %s"), *arg); | 5296 EMSG2(_("E720: Missing colon in Dictionary: %s"), *arg); |
5258 clear_tv(&tv); | 5297 clear_tv(&tvkey); |
5259 goto failret; | 5298 goto failret; |
5260 } | 5299 } |
5261 key = get_tv_string(&tv); | 5300 key = get_tv_string_buf(&tvkey, buf); |
5262 if (*key == NUL) | 5301 if (*key == NUL) |
5263 { | 5302 { |
5264 EMSG(_(e_emptykey)); | 5303 EMSG(_(e_emptykey)); |
5265 clear_tv(&tv); | 5304 clear_tv(&tvkey); |
5266 goto failret; | 5305 goto failret; |
5267 } | 5306 } |
5268 key = vim_strsave(key); | |
5269 clear_tv(&tv); | |
5270 if (key == NULL) | |
5271 goto failret; | |
5272 | 5307 |
5273 *arg = skipwhite(*arg + 1); | 5308 *arg = skipwhite(*arg + 1); |
5274 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */ | 5309 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */ |
5275 { | 5310 { |
5276 vim_free(key); | 5311 clear_tv(&tvkey); |
5277 goto failret; | 5312 goto failret; |
5278 } | 5313 } |
5279 if (evaluate) | 5314 if (evaluate) |
5280 { | 5315 { |
5281 item = dict_find(d, key, -1, NULL); | 5316 item = dict_find(d, key, -1); |
5282 if (item != NULL) | 5317 if (item != NULL) |
5283 { | 5318 { |
5284 EMSG(_("E721: Duplicate key in Dictionary")); | 5319 EMSG(_("E721: Duplicate key in Dictionary")); |
5285 vim_free(key); | 5320 clear_tv(&tvkey); |
5286 clear_tv(&tv); | 5321 clear_tv(&tv); |
5287 goto failret; | 5322 goto failret; |
5288 } | 5323 } |
5289 item = dictitem_alloc(); | 5324 item = dictitem_alloc(key); |
5290 if (item == NULL) | 5325 clear_tv(&tvkey); |
5291 vim_free(key); | 5326 if (item != NULL) |
5292 else | |
5293 { | 5327 { |
5294 item->di_key = key; | |
5295 item->di_tv = tv; | 5328 item->di_tv = tv; |
5296 dict_add(d, item); | 5329 if (dict_add(d, item) == FAIL) |
5330 dictitem_free(item); | |
5297 } | 5331 } |
5298 } | 5332 } |
5299 | 5333 |
5300 if (**arg == '}') | 5334 if (**arg == '}') |
5301 break; | 5335 break; |
5992 saveRedobuff(); | 6026 saveRedobuff(); |
5993 ++fp->calls; | 6027 ++fp->calls; |
5994 call_user_func(fp, argcount, argvars, rettv, | 6028 call_user_func(fp, argcount, argvars, rettv, |
5995 firstline, lastline, | 6029 firstline, lastline, |
5996 (fp->flags & FC_DICT) ? selfdict : NULL); | 6030 (fp->flags & FC_DICT) ? selfdict : NULL); |
5997 if (--fp->calls <= 0 && isdigit(*fp->name)) | 6031 if (--fp->calls <= 0 && isdigit(*fp->name) |
6032 && fp->refcount <= 0) | |
5998 /* Function was unreferenced while being used, free it | 6033 /* Function was unreferenced while being used, free it |
5999 * now. */ | 6034 * now. */ |
6000 func_free(fp); | 6035 func_free(fp); |
6001 restoreRedobuff(); | 6036 restoreRedobuff(); |
6002 restore_search_patterns(); | 6037 restore_search_patterns(); |
6742 ++n; | 6777 ++n; |
6743 } | 6778 } |
6744 } | 6779 } |
6745 else if (argvars[0].v_type == VAR_DICT) | 6780 else if (argvars[0].v_type == VAR_DICT) |
6746 { | 6781 { |
6747 if (argvars[0].vval.v_dict != NULL) | 6782 int todo; |
6748 { | 6783 dictvar *d; |
6749 dictitem *di; | 6784 hashitem *hi; |
6750 | 6785 |
6751 di = argvars[0].vval.v_dict->dv_first; | 6786 if ((d = argvars[0].vval.v_dict) != NULL) |
6787 { | |
6752 if (argvars[2].v_type != VAR_UNKNOWN) | 6788 if (argvars[2].v_type != VAR_UNKNOWN) |
6753 { | 6789 { |
6754 ic = get_tv_number(&argvars[2]); | 6790 ic = get_tv_number(&argvars[2]); |
6755 if (argvars[3].v_type != VAR_UNKNOWN) | 6791 if (argvars[3].v_type != VAR_UNKNOWN) |
6756 EMSG(_(e_invarg)); | 6792 EMSG(_(e_invarg)); |
6757 } | 6793 } |
6758 | 6794 |
6759 for ( ; di != NULL; di = di->di_next) | 6795 todo = d->dv_hashtable.ht_used; |
6760 if (tv_equal(&di->di_tv, &argvars[1], ic)) | 6796 for (hi = d->dv_hashtable.ht_array; todo > 0; ++hi) |
6761 ++n; | 6797 { |
6798 if (!HASHITEM_EMPTY(hi)) | |
6799 { | |
6800 --todo; | |
6801 if (tv_equal(&HI2DI(hi)->di_tv, &argvars[1], ic)) | |
6802 ++n; | |
6803 } | |
6804 } | |
6762 } | 6805 } |
6763 } | 6806 } |
6764 else | 6807 else |
6765 EMSG2(_(e_listdictarg), "count()"); | 6808 EMSG2(_(e_listdictarg), "count()"); |
6766 rettv->vval.v_number = n; | 6809 rettv->vval.v_number = n; |
6970 n = argvars[0].vval.v_list == NULL | 7013 n = argvars[0].vval.v_list == NULL |
6971 || argvars[0].vval.v_list->lv_first == NULL; | 7014 || argvars[0].vval.v_list->lv_first == NULL; |
6972 break; | 7015 break; |
6973 case VAR_DICT: | 7016 case VAR_DICT: |
6974 n = argvars[0].vval.v_dict == NULL | 7017 n = argvars[0].vval.v_dict == NULL |
6975 || argvars[0].vval.v_dict->dv_first == NULL; | 7018 || argvars[0].vval.v_dict->dv_hashtable.ht_used == 0; |
6976 break; | 7019 break; |
6977 default: | 7020 default: |
6978 EMSG2(_(e_intern2), "f_empty()"); | 7021 EMSG2(_(e_intern2), "f_empty()"); |
6979 n = 0; | 7022 n = 0; |
6980 } | 7023 } |
7195 } | 7238 } |
7196 } | 7239 } |
7197 else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT) | 7240 else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT) |
7198 { | 7241 { |
7199 dictvar *d1, *d2; | 7242 dictvar *d1, *d2; |
7200 dictitem *d1i, *d2i; | 7243 dictitem *di1; |
7201 char_u *action; | 7244 char_u *action; |
7202 int i; | 7245 int i; |
7246 hashitem *hi2; | |
7247 int todo; | |
7203 | 7248 |
7204 d1 = argvars[0].vval.v_dict; | 7249 d1 = argvars[0].vval.v_dict; |
7205 d2 = argvars[1].vval.v_dict; | 7250 d2 = argvars[1].vval.v_dict; |
7206 if (d1 != NULL && d2 != NULL) | 7251 if (d1 != NULL && d2 != NULL) |
7207 { | 7252 { |
7223 else | 7268 else |
7224 action = (char_u *)"force"; | 7269 action = (char_u *)"force"; |
7225 | 7270 |
7226 /* Go over all entries in the second dict and add them to the | 7271 /* Go over all entries in the second dict and add them to the |
7227 * first dict. */ | 7272 * first dict. */ |
7228 for (d2i = d2->dv_first; d2i != NULL; d2i = d2i->di_next) | 7273 todo = d2->dv_hashtable.ht_used; |
7274 for (hi2 = d2->dv_hashtable.ht_array; todo > 0; ++hi2) | |
7229 { | 7275 { |
7230 d1i = dict_find(d1, d2i->di_key, -1, NULL); | 7276 if (!HASHITEM_EMPTY(hi2)) |
7231 if (d1i == NULL) | |
7232 { | 7277 { |
7233 d1i = dictitem_copy(d2i); | 7278 --todo; |
7234 if (d1i != NULL) | 7279 di1 = dict_find(d1, hi2->hi_key, -1); |
7235 dict_add(d1, d1i); | 7280 if (di1 == NULL) |
7236 } | 7281 { |
7237 else if (*action == 'e') | 7282 di1 = dictitem_copy(HI2DI(hi2)); |
7238 { | 7283 if (di1 != NULL && dict_add(d1, di1) == FAIL) |
7239 EMSG2(_("Key already exists: %s"), d2i->di_key); | 7284 dictitem_free(di1); |
7240 break; | 7285 } |
7241 } | 7286 else if (*action == 'e') |
7242 else if (*action == 'f') | 7287 { |
7243 { | 7288 EMSG2(_("E737: Key already exists: %s"), hi2->hi_key); |
7244 clear_tv(&d1i->di_tv); | 7289 break; |
7245 copy_tv(&d2i->di_tv, &d1i->di_tv); | 7290 } |
7291 else if (*action == 'f') | |
7292 { | |
7293 clear_tv(&di1->di_tv); | |
7294 copy_tv(&HI2DI(hi2)->di_tv, &di1->di_tv); | |
7295 } | |
7246 } | 7296 } |
7247 } | 7297 } |
7248 | 7298 |
7249 ++d1->dv_refcount; | 7299 ++d1->dv_refcount; |
7250 copy_tv(&argvars[0], rettv); | 7300 copy_tv(&argvars[0], rettv); |
7376 { | 7426 { |
7377 char_u buf[NUMBUFLEN]; | 7427 char_u buf[NUMBUFLEN]; |
7378 char_u *expr; | 7428 char_u *expr; |
7379 listitem *li, *nli; | 7429 listitem *li, *nli; |
7380 listvar *l = NULL; | 7430 listvar *l = NULL; |
7381 dictitem *di, **pdi; | 7431 dictitem *di; |
7432 hashitem *hi; | |
7382 dictvar *d = NULL; | 7433 dictvar *d = NULL; |
7383 typeval save_val; | 7434 typeval save_val; |
7384 typeval save_key; | 7435 typeval save_key; |
7385 int rem; | 7436 int rem; |
7437 int todo; | |
7386 | 7438 |
7387 rettv->vval.v_number = 0; | 7439 rettv->vval.v_number = 0; |
7388 if (argvars[0].v_type == VAR_LIST) | 7440 if (argvars[0].v_type == VAR_LIST) |
7389 { | 7441 { |
7390 if ((l = argvars[0].vval.v_list) == NULL) | 7442 if ((l = argvars[0].vval.v_list) == NULL) |
7406 | 7458 |
7407 if (argvars[0].v_type == VAR_DICT) | 7459 if (argvars[0].v_type == VAR_DICT) |
7408 { | 7460 { |
7409 save_key = vimvars[VV_KEY].tv; | 7461 save_key = vimvars[VV_KEY].tv; |
7410 vimvars[VV_KEY].tv.v_type = VAR_STRING; | 7462 vimvars[VV_KEY].tv.v_type = VAR_STRING; |
7411 pdi = &d->dv_first; | 7463 |
7412 for (di = d->dv_first; di != NULL; di = *pdi) | 7464 todo = d->dv_hashtable.ht_used; |
7413 { | 7465 for (hi = d->dv_hashtable.ht_array; todo > 0; ++hi) |
7414 vimvars[VV_KEY].tv.vval.v_string = vim_strsave(di->di_key); | 7466 { |
7415 if (filter_map_one(&di->di_tv, expr, map, &rem) == FAIL) | 7467 if (!HASHITEM_EMPTY(hi)) |
7416 break; | |
7417 if (!map && rem) | |
7418 { | 7468 { |
7419 *pdi = di->di_next; | 7469 --todo; |
7420 dictitem_free(di); | 7470 di = HI2DI(hi); |
7471 vimvars[VV_KEY].tv.vval.v_string = vim_strsave(di->di_key); | |
7472 if (filter_map_one(&di->di_tv, expr, map, &rem) == FAIL) | |
7473 break; | |
7474 if (!map && rem) | |
7475 dictitem_remove(d, di); | |
7476 clear_tv(&vimvars[VV_KEY].tv); | |
7421 } | 7477 } |
7422 else | 7478 } |
7423 pdi = &di->di_next; | 7479 |
7424 clear_tv(&vimvars[VV_KEY].tv); | |
7425 } | |
7426 clear_tv(&vimvars[VV_KEY].tv); | 7480 clear_tv(&vimvars[VV_KEY].tv); |
7427 vimvars[VV_KEY].tv = save_key; | 7481 vimvars[VV_KEY].tv = save_key; |
7428 } | 7482 } |
7429 else | 7483 else |
7430 { | 7484 { |
7782 } | 7836 } |
7783 else if (argvars[0].v_type == VAR_DICT) | 7837 else if (argvars[0].v_type == VAR_DICT) |
7784 { | 7838 { |
7785 if ((d = argvars[0].vval.v_dict) != NULL) | 7839 if ((d = argvars[0].vval.v_dict) != NULL) |
7786 { | 7840 { |
7787 di = dict_find(d, get_tv_string(&argvars[1]), -1, NULL); | 7841 di = dict_find(d, get_tv_string(&argvars[1]), -1); |
7788 if (di != NULL) | 7842 if (di != NULL) |
7789 tv = &di->di_tv; | 7843 tv = &di->di_tv; |
7790 } | 7844 } |
7791 } | 7845 } |
7792 else | 7846 else |
8915 } | 8969 } |
8916 if (argvars[0].vval.v_dict == NULL) | 8970 if (argvars[0].vval.v_dict == NULL) |
8917 return; | 8971 return; |
8918 | 8972 |
8919 rettv->vval.v_number = dict_find(argvars[0].vval.v_dict, | 8973 rettv->vval.v_number = dict_find(argvars[0].vval.v_dict, |
8920 get_tv_string(&argvars[1]), -1, NULL) != NULL; | 8974 get_tv_string(&argvars[1]), -1) != NULL; |
8921 } | 8975 } |
8922 | 8976 |
8923 /* | 8977 /* |
8924 * "hasmapto()" function | 8978 * "hasmapto()" function |
8925 */ | 8979 */ |
9410 int what; | 9464 int what; |
9411 { | 9465 { |
9412 listvar *l; | 9466 listvar *l; |
9413 listvar *l2; | 9467 listvar *l2; |
9414 dictitem *di; | 9468 dictitem *di; |
9469 hashitem *hi; | |
9415 listitem *li; | 9470 listitem *li; |
9416 listitem *li2; | 9471 listitem *li2; |
9472 dictvar *d; | |
9473 int todo; | |
9417 | 9474 |
9418 rettv->vval.v_number = 0; | 9475 rettv->vval.v_number = 0; |
9419 if (argvars[0].v_type != VAR_DICT) | 9476 if (argvars[0].v_type != VAR_DICT) |
9420 { | 9477 { |
9421 EMSG(_(e_dictreq)); | 9478 EMSG(_(e_dictreq)); |
9422 return; | 9479 return; |
9423 } | 9480 } |
9424 if (argvars[0].vval.v_dict == NULL) | 9481 if ((d = argvars[0].vval.v_dict) == NULL) |
9425 return; | 9482 return; |
9426 | 9483 |
9427 l = list_alloc(); | 9484 l = list_alloc(); |
9428 if (l == NULL) | 9485 if (l == NULL) |
9429 return; | 9486 return; |
9430 rettv->v_type = VAR_LIST; | 9487 rettv->v_type = VAR_LIST; |
9431 rettv->vval.v_list = l; | 9488 rettv->vval.v_list = l; |
9432 ++l->lv_refcount; | 9489 ++l->lv_refcount; |
9433 | 9490 |
9434 for (di = argvars[0].vval.v_dict->dv_first; di != NULL; di = di->di_next) | 9491 todo = d->dv_hashtable.ht_used; |
9435 { | 9492 for (hi = d->dv_hashtable.ht_array; todo > 0; ++hi) |
9436 li = listitem_alloc(); | 9493 { |
9437 if (li == NULL) | 9494 if (!HASHITEM_EMPTY(hi)) |
9438 break; | 9495 { |
9439 list_append(l, li); | 9496 --todo; |
9440 | 9497 di = HI2DI(hi); |
9441 if (what == 0) | 9498 |
9442 { | 9499 li = listitem_alloc(); |
9443 /* keys() */ | 9500 if (li == NULL) |
9444 li->li_tv.v_type = VAR_STRING; | |
9445 li->li_tv.vval.v_string = vim_strsave(di->di_key); | |
9446 } | |
9447 else if (what == 1) | |
9448 { | |
9449 /* values() */ | |
9450 copy_tv(&di->di_tv, &li->li_tv); | |
9451 } | |
9452 else | |
9453 { | |
9454 /* items() */ | |
9455 l2 = list_alloc(); | |
9456 li->li_tv.v_type = VAR_LIST; | |
9457 li->li_tv.vval.v_list = l2; | |
9458 if (l2 == NULL) | |
9459 break; | 9501 break; |
9460 ++l2->lv_refcount; | 9502 list_append(l, li); |
9461 | 9503 |
9462 li2 = listitem_alloc(); | 9504 if (what == 0) |
9463 if (li2 == NULL) | 9505 { |
9464 break; | 9506 /* keys() */ |
9465 list_append(l2, li2); | 9507 li->li_tv.v_type = VAR_STRING; |
9466 li2->li_tv.v_type = VAR_STRING; | 9508 li->li_tv.vval.v_string = vim_strsave(di->di_key); |
9467 li2->li_tv.vval.v_string = vim_strsave(di->di_key); | 9509 } |
9468 | 9510 else if (what == 1) |
9469 li2 = listitem_alloc(); | 9511 { |
9470 if (li2 == NULL) | 9512 /* values() */ |
9471 break; | 9513 copy_tv(&di->di_tv, &li->li_tv); |
9472 list_append(l2, li2); | 9514 } |
9473 copy_tv(&di->di_tv, &li2->li_tv); | 9515 else |
9516 { | |
9517 /* items() */ | |
9518 l2 = list_alloc(); | |
9519 li->li_tv.v_type = VAR_LIST; | |
9520 li->li_tv.vval.v_list = l2; | |
9521 if (l2 == NULL) | |
9522 break; | |
9523 ++l2->lv_refcount; | |
9524 | |
9525 li2 = listitem_alloc(); | |
9526 if (li2 == NULL) | |
9527 break; | |
9528 list_append(l2, li2); | |
9529 li2->li_tv.v_type = VAR_STRING; | |
9530 li2->li_tv.vval.v_string = vim_strsave(di->di_key); | |
9531 | |
9532 li2 = listitem_alloc(); | |
9533 if (li2 == NULL) | |
9534 break; | |
9535 list_append(l2, li2); | |
9536 copy_tv(&di->di_tv, &li2->li_tv); | |
9537 } | |
9474 } | 9538 } |
9475 } | 9539 } |
9476 } | 9540 } |
9477 | 9541 |
9478 /* | 9542 /* |
10021 } | 10085 } |
10022 } | 10086 } |
10023 else if (argvars[0].v_type == VAR_DICT) | 10087 else if (argvars[0].v_type == VAR_DICT) |
10024 { | 10088 { |
10025 dictvar *d; | 10089 dictvar *d; |
10026 dictitem *di; | 10090 int first = TRUE; |
10091 hashitem *hi; | |
10092 int todo; | |
10027 | 10093 |
10028 d = argvars[0].vval.v_dict; | 10094 d = argvars[0].vval.v_dict; |
10029 if (d != NULL) | 10095 if (d != NULL) |
10030 { | 10096 { |
10031 di = d->dv_first; | 10097 todo = d->dv_hashtable.ht_used; |
10032 if (di != NULL) | 10098 for (hi = d->dv_hashtable.ht_array; todo > 0; ++hi) |
10033 { | 10099 { |
10034 n = get_tv_number(&di->di_tv); | 10100 if (!HASHITEM_EMPTY(hi)) |
10035 while (1) | |
10036 { | 10101 { |
10037 di = di->di_next; | 10102 --todo; |
10038 if (di == NULL) | 10103 i = get_tv_number(&HI2DI(hi)->di_tv); |
10039 break; | 10104 if (first) |
10040 i = get_tv_number(&di->di_tv); | 10105 { |
10041 if (domax ? i > n : i < n) | 10106 n = i; |
10107 first = FALSE; | |
10108 } | |
10109 else if (domax ? i > n : i < n) | |
10042 n = i; | 10110 n = i; |
10043 } | 10111 } |
10044 } | 10112 } |
10045 } | 10113 } |
10046 } | 10114 } |
10470 listitem *li; | 10538 listitem *li; |
10471 long idx; | 10539 long idx; |
10472 long end; | 10540 long end; |
10473 char_u *key; | 10541 char_u *key; |
10474 dictvar *d; | 10542 dictvar *d; |
10475 dictitem *di, **pdi; | 10543 dictitem *di; |
10476 | 10544 |
10477 rettv->vval.v_number = 0; | 10545 rettv->vval.v_number = 0; |
10478 if (argvars[0].v_type == VAR_DICT) | 10546 if (argvars[0].v_type == VAR_DICT) |
10479 { | 10547 { |
10480 if (argvars[2].v_type != VAR_UNKNOWN) | 10548 if (argvars[2].v_type != VAR_UNKNOWN) |
10481 EMSG2(_(e_toomanyarg), "remove()"); | 10549 EMSG2(_(e_toomanyarg), "remove()"); |
10482 else if ((d = argvars[0].vval.v_dict) != NULL) | 10550 else if ((d = argvars[0].vval.v_dict) != NULL) |
10483 { | 10551 { |
10484 key = get_tv_string(&argvars[1]); | 10552 key = get_tv_string(&argvars[1]); |
10485 pdi = &d->dv_first; | 10553 di = dict_find(d, key, -1); |
10486 for (di = d->dv_first; di != NULL; pdi = &di->di_next, di = *pdi) | |
10487 if (STRCMP(di->di_key, key) == 0) | |
10488 { | |
10489 *pdi = di->di_next; | |
10490 *rettv = di->di_tv; | |
10491 init_tv(&di->di_tv); | |
10492 dictitem_free(di); | |
10493 break; | |
10494 } | |
10495 if (di == NULL) | 10554 if (di == NULL) |
10496 EMSG2(_(e_dictkey), key); | 10555 EMSG2(_(e_dictkey), key); |
10556 else | |
10557 { | |
10558 *rettv = di->di_tv; | |
10559 init_tv(&di->di_tv); | |
10560 dictitem_remove(d, di); | |
10561 } | |
10497 } | 10562 } |
10498 } | 10563 } |
10499 else if (argvars[0].v_type != VAR_LIST) | 10564 else if (argvars[0].v_type != VAR_LIST) |
10500 EMSG2(_(e_listdictarg), "remove()"); | 10565 EMSG2(_(e_listdictarg), "remove()"); |
10501 else if ((l = argvars[0].vval.v_list) != NULL) | 10566 else if ((l = argvars[0].vval.v_list) != NULL) |
13132 vim_free(varp->vval.v_string); | 13197 vim_free(varp->vval.v_string); |
13133 varp->vval.v_string = NULL; | 13198 varp->vval.v_string = NULL; |
13134 break; | 13199 break; |
13135 case VAR_LIST: | 13200 case VAR_LIST: |
13136 list_unref(varp->vval.v_list); | 13201 list_unref(varp->vval.v_list); |
13202 varp->vval.v_list = NULL; | |
13137 break; | 13203 break; |
13138 case VAR_DICT: | 13204 case VAR_DICT: |
13139 dict_unref(varp->vval.v_dict); | 13205 dict_unref(varp->vval.v_dict); |
13206 varp->vval.v_dict = NULL; | |
13140 break; | 13207 break; |
13141 case VAR_NUMBER: | 13208 case VAR_NUMBER: |
13142 varp->vval.v_number = 0; | 13209 varp->vval.v_number = 0; |
13143 break; | 13210 break; |
13144 case VAR_UNKNOWN: | 13211 case VAR_UNKNOWN: |
14001 * evaluation has been cancelled due to an aborting error, an | 14068 * evaluation has been cancelled due to an aborting error, an |
14002 * interrupt, or an exception. | 14069 * interrupt, or an exception. |
14003 */ | 14070 */ |
14004 if (!aborting()) | 14071 if (!aborting()) |
14005 { | 14072 { |
14073 if (!eap->skip && fudi.fd_newkey != NULL) | |
14074 EMSG2(_(e_dictkey), fudi.fd_newkey); | |
14006 vim_free(fudi.fd_newkey); | 14075 vim_free(fudi.fd_newkey); |
14007 return; | 14076 return; |
14008 } | 14077 } |
14009 else | 14078 else |
14010 eap->skip = TRUE; | 14079 eap->skip = TRUE; |
14346 if (fudi.fd_dict != NULL) | 14415 if (fudi.fd_dict != NULL) |
14347 { | 14416 { |
14348 if (fudi.fd_di == NULL) | 14417 if (fudi.fd_di == NULL) |
14349 { | 14418 { |
14350 /* add new dict entry */ | 14419 /* add new dict entry */ |
14351 fudi.fd_di = dictitem_alloc(); | 14420 fudi.fd_di = dictitem_alloc(fudi.fd_newkey); |
14352 if (fudi.fd_di == NULL) | 14421 if (fudi.fd_di == NULL) |
14353 { | 14422 { |
14354 vim_free(fp); | 14423 vim_free(fp); |
14355 goto erret; | 14424 goto erret; |
14356 } | 14425 } |
14357 fudi.fd_di->di_key = fudi.fd_newkey; | 14426 if (dict_add(fudi.fd_dict, fudi.fd_di) == FAIL) |
14358 fudi.fd_newkey = NULL; | 14427 { |
14359 dict_add(fudi.fd_dict, fudi.fd_di); | 14428 vim_free(fudi.fd_di); |
14429 goto erret; | |
14430 } | |
14360 } | 14431 } |
14361 else | 14432 else |
14362 /* overwrite existing dict entry */ | 14433 /* overwrite existing dict entry */ |
14363 clear_tv(&fudi.fd_di->di_tv); | 14434 clear_tv(&fudi.fd_di->di_tv); |
14364 fudi.fd_di->di_tv.v_type = VAR_FUNC; | 14435 fudi.fd_di->di_tv.v_type = VAR_FUNC; |
14452 { | 14523 { |
14453 fdp->fd_dict = lv.ll_dict; | 14524 fdp->fd_dict = lv.ll_dict; |
14454 fdp->fd_newkey = lv.ll_newkey; | 14525 fdp->fd_newkey = lv.ll_newkey; |
14455 lv.ll_newkey = NULL; | 14526 lv.ll_newkey = NULL; |
14456 fdp->fd_di = lv.ll_di; | 14527 fdp->fd_di = lv.ll_di; |
14457 fdp->fd_pdi = lv.ll_pdi; | |
14458 } | 14528 } |
14459 if (lv.ll_tv->v_type == VAR_FUNC && lv.ll_tv->vval.v_string != NULL) | 14529 if (lv.ll_tv->v_type == VAR_FUNC && lv.ll_tv->vval.v_string != NULL) |
14460 { | 14530 { |
14461 name = vim_strsave(lv.ll_tv->vval.v_string); | 14531 name = vim_strsave(lv.ll_tv->vval.v_string); |
14462 *pp = end; | 14532 *pp = end; |
14463 } | 14533 } |
14464 else | 14534 else |
14465 { | 14535 { |
14466 if (!skip && !(flags & TFN_QUIET) | 14536 if (!skip && !(flags & TFN_QUIET) && (fdp == NULL |
14467 && (fdp == NULL || lv.ll_dict == NULL)) | 14537 || lv.ll_dict == NULL || fdp->fd_newkey == NULL)) |
14468 EMSG(_(e_funcref)); | 14538 EMSG(_(e_funcref)); |
14469 else | 14539 else |
14470 *pp = end; | 14540 *pp = end; |
14471 name = NULL; | 14541 name = NULL; |
14472 } | 14542 } |
14741 | 14811 |
14742 if (fudi.fd_dict != NULL) | 14812 if (fudi.fd_dict != NULL) |
14743 { | 14813 { |
14744 /* Delete the dict item that refers to the function, it will | 14814 /* Delete the dict item that refers to the function, it will |
14745 * invoke func_unref() and possibly delete the function. */ | 14815 * invoke func_unref() and possibly delete the function. */ |
14746 *fudi.fd_pdi = fudi.fd_di->di_next; | 14816 dictitem_remove(fudi.fd_dict, fudi.fd_di); |
14747 dictitem_free(fudi.fd_di); | |
14748 } | 14817 } |
14749 else | 14818 else |
14750 func_free(fp); | 14819 func_free(fp); |
14751 } | 14820 } |
14752 } | 14821 } |