mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	vim-patch:7.4.708
Problem:    gettext() is called too often.
Solution:   Do not call gettext() for messages until they are actually used.
            (idea by Yasuhiro Matsumoto)
77354e78a8
			
			
This commit is contained in:
		
							
								
								
									
										185
									
								
								src/nvim/eval.c
									
									
									
									
									
								
							
							
						
						
									
										185
									
								
								src/nvim/eval.c
									
									
									
									
									
								
							| @@ -2176,10 +2176,10 @@ get_lval ( | ||||
|         if (len == -1) | ||||
|           clear_tv(&var1); | ||||
|         break; | ||||
|       } | ||||
|       /* existing variable, need to check if it can be changed */ | ||||
|       else if (var_check_ro(lp->ll_di->di_flags, name)) | ||||
|       } else if (var_check_ro(lp->ll_di->di_flags, name, false)) { | ||||
|         // existing variable, need to check if it can be changed | ||||
|         return NULL; | ||||
|       } | ||||
|  | ||||
|       if (len == -1) | ||||
|         clear_tv(&var1); | ||||
| @@ -2287,15 +2287,16 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, ch | ||||
|     } | ||||
|   } else if (tv_check_lock(lp->ll_newkey == NULL | ||||
|                            ? lp->ll_tv->v_lock | ||||
|                  : lp->ll_tv->vval.v_dict->dv_lock, lp->ll_name)) | ||||
|     ; | ||||
|   else if (lp->ll_range) { | ||||
|                            : lp->ll_tv->vval.v_dict->dv_lock, | ||||
|                            lp->ll_name, false)) { | ||||
|   } else if (lp->ll_range) { | ||||
|     listitem_T *ll_li = lp->ll_li; | ||||
|     int ll_n1 = lp->ll_n1; | ||||
|  | ||||
|     // Check whether any of the list items is locked | ||||
|     for (listitem_T *ri = rettv->vval.v_list->lv_first; ri != NULL && ll_li != NULL; ) { | ||||
|       if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name)) { | ||||
|     for (listitem_T *ri = rettv->vval.v_list->lv_first; | ||||
|          ri != NULL && ll_li != NULL; ) { | ||||
|       if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name, false)) { | ||||
|         return; | ||||
|       } | ||||
|       ri = ri->li_next; | ||||
| @@ -2891,9 +2892,9 @@ static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit) | ||||
|       ret = FAIL; | ||||
|     *name_end = cc; | ||||
|   } else if ((lp->ll_list != NULL | ||||
|               && tv_check_lock(lp->ll_list->lv_lock, lp->ll_name)) | ||||
|               && tv_check_lock(lp->ll_list->lv_lock, lp->ll_name, false)) | ||||
|              || (lp->ll_dict != NULL | ||||
|                  && tv_check_lock(lp->ll_dict->dv_lock, lp->ll_name))) { | ||||
|                  && tv_check_lock(lp->ll_dict->dv_lock, lp->ll_name, false))) { | ||||
|     return FAIL; | ||||
|   } else if (lp->ll_range) { | ||||
|     listitem_T    *li; | ||||
| @@ -2902,7 +2903,7 @@ static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit) | ||||
|  | ||||
|     while (ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= ll_n1)) { | ||||
|       li = ll_li->li_next; | ||||
|       if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name)) { | ||||
|       if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name, false)) { | ||||
|         return false; | ||||
|       } | ||||
|       ll_li = li; | ||||
| @@ -2975,9 +2976,9 @@ int do_unlet(char_u *name, int forceit) | ||||
|     hi = hash_find(ht, varname); | ||||
|     if (!HASHITEM_EMPTY(hi)) { | ||||
|       di = HI2DI(hi); | ||||
|       if (var_check_fixed(di->di_flags, name) | ||||
|           || var_check_ro(di->di_flags, name) | ||||
|           || tv_check_lock(d->dv_lock, name)) { | ||||
|       if (var_check_fixed(di->di_flags, name, false) | ||||
|           || var_check_ro(di->di_flags, name, false) | ||||
|           || tv_check_lock(d->dv_lock, name, false)) { | ||||
|         return FAIL; | ||||
|       } | ||||
|       typval_T oldtv; | ||||
| @@ -7855,7 +7856,8 @@ static void f_add(typval_T *argvars, typval_T *rettv) | ||||
|   rettv->vval.v_number = 1;   /* Default: Failed */ | ||||
|   if (argvars[0].v_type == VAR_LIST) { | ||||
|     if ((l = argvars[0].vval.v_list) != NULL | ||||
|         && !tv_check_lock(l->lv_lock, (char_u *)_("add() argument"))) { | ||||
|         && !tv_check_lock(l->lv_lock, | ||||
|                           (char_u *)N_("add() argument"), true)) { | ||||
|       list_append_tv(l, &argvars[1]); | ||||
|       copy_tv(&argvars[0], rettv); | ||||
|     } | ||||
| @@ -9230,7 +9232,7 @@ void dict_extend(dict_T *d1, dict_T *d2, char_u *action) | ||||
|   hashitem_T  *hi2; | ||||
|   int todo; | ||||
|   bool watched = is_watched(d1); | ||||
|   char *arg_errmsg = N_("extend() argument"); | ||||
|   char_u *arg_errmsg = (char_u *)N_("extend() argument"); | ||||
|  | ||||
|   todo = (int)d2->dv_hashtab.ht_used; | ||||
|   for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2) { | ||||
| @@ -9264,8 +9266,8 @@ void dict_extend(dict_T *d1, dict_T *d2, char_u *action) | ||||
|       } else if (*action == 'f' && HI2DI(hi2) != di1) { | ||||
|         typval_T oldtv; | ||||
|  | ||||
|         if (tv_check_lock(di1->di_tv.v_lock, (char_u *)_(arg_errmsg)) | ||||
|             || var_check_ro(di1->di_flags, (char_u *)_(arg_errmsg))) { | ||||
|         if (tv_check_lock(di1->di_tv.v_lock, arg_errmsg, true) | ||||
|             || var_check_ro(di1->di_flags, arg_errmsg, true)) { | ||||
|           break; | ||||
|         } | ||||
|  | ||||
| @@ -9291,7 +9293,7 @@ void dict_extend(dict_T *d1, dict_T *d2, char_u *action) | ||||
|  */ | ||||
| static void f_extend(typval_T *argvars, typval_T *rettv) | ||||
| { | ||||
|   char      *arg_errmsg = N_("extend() argument"); | ||||
|   char_u *arg_errmsg = (char_u *)N_("extend() argument"); | ||||
|  | ||||
|   if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST) { | ||||
|     list_T          *l1, *l2; | ||||
| @@ -9301,7 +9303,7 @@ static void f_extend(typval_T *argvars, typval_T *rettv) | ||||
|  | ||||
|     l1 = argvars[0].vval.v_list; | ||||
|     l2 = argvars[1].vval.v_list; | ||||
|     if (l1 != NULL && !tv_check_lock(l1->lv_lock, (char_u *)_(arg_errmsg)) | ||||
|     if (l1 != NULL && !tv_check_lock(l1->lv_lock, arg_errmsg, true) | ||||
|         && l2 != NULL) { | ||||
|       if (argvars[2].v_type != VAR_UNKNOWN) { | ||||
|         before = get_tv_number_chk(&argvars[2], &error); | ||||
| @@ -9331,7 +9333,7 @@ static void f_extend(typval_T *argvars, typval_T *rettv) | ||||
|  | ||||
|     d1 = argvars[0].vval.v_dict; | ||||
|     d2 = argvars[1].vval.v_dict; | ||||
|     if (d1 != NULL && !tv_check_lock(d1->dv_lock, (char_u *)_(arg_errmsg)) | ||||
|     if (d1 != NULL && !tv_check_lock(d1->dv_lock, arg_errmsg, true) | ||||
|         && d2 != NULL) { | ||||
|       /* Check the third argument. */ | ||||
|       if (argvars[2].v_type != VAR_UNKNOWN) { | ||||
| @@ -9477,19 +9479,19 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map) | ||||
|   int rem; | ||||
|   int todo; | ||||
|   char_u      *ermsg = (char_u *)(map ? "map()" : "filter()"); | ||||
|   char        *arg_errmsg = (map ? N_("map() argument") | ||||
|   char_u      *arg_errmsg = (char_u *)(map ? N_("map() argument") | ||||
|                                        : N_("filter() argument")); | ||||
|   int save_did_emsg; | ||||
|   int idx = 0; | ||||
|  | ||||
|   if (argvars[0].v_type == VAR_LIST) { | ||||
|     if ((l = argvars[0].vval.v_list) == NULL | ||||
|         || (!map && tv_check_lock(l->lv_lock, (char_u *)_(arg_errmsg)))) { | ||||
|         || (!map && tv_check_lock(l->lv_lock, arg_errmsg, true))) { | ||||
|       return; | ||||
|     } | ||||
|   } else if (argvars[0].v_type == VAR_DICT) { | ||||
|     if ((d = argvars[0].vval.v_dict) == NULL | ||||
|         || (!map && tv_check_lock(d->dv_lock, (char_u *)_(arg_errmsg)))) { | ||||
|         || (!map && tv_check_lock(d->dv_lock, arg_errmsg, true))) { | ||||
|       return; | ||||
|     } | ||||
|   } else { | ||||
| @@ -9523,8 +9525,8 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map) | ||||
|  | ||||
|           di = HI2DI(hi); | ||||
|           if (map | ||||
|               && (tv_check_lock(di->di_tv.v_lock, (char_u *)_(arg_errmsg)) | ||||
|                   || var_check_ro(di->di_flags, (char_u *)_(arg_errmsg)))) { | ||||
|               && (tv_check_lock(di->di_tv.v_lock, arg_errmsg, true) | ||||
|                   || var_check_ro(di->di_flags, arg_errmsg, true))) { | ||||
|             break; | ||||
|           } | ||||
|  | ||||
| @@ -9534,8 +9536,8 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map) | ||||
|           if (r == FAIL || did_emsg) | ||||
|             break; | ||||
|           if (!map && rem) { | ||||
|             if (var_check_fixed(di->di_flags, (char_u *)_(arg_errmsg)) | ||||
|                 || var_check_ro(di->di_flags, (char_u *)_(arg_errmsg))) { | ||||
|             if (var_check_fixed(di->di_flags, arg_errmsg, true) | ||||
|                 || var_check_ro(di->di_flags, arg_errmsg, true)) { | ||||
|               break; | ||||
|             } | ||||
|             dictitem_remove(d, di); | ||||
| @@ -9547,7 +9549,7 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map) | ||||
|       vimvars[VV_KEY].vv_type = VAR_NUMBER; | ||||
|  | ||||
|       for (li = l->lv_first; li != NULL; li = nli) { | ||||
|         if (map && tv_check_lock(li->li_tv.v_lock, (char_u *)_(arg_errmsg))) { | ||||
|         if (map && tv_check_lock(li->li_tv.v_lock, arg_errmsg, true)) { | ||||
|           break; | ||||
|         } | ||||
|         nli = li->li_next; | ||||
| @@ -11442,14 +11444,18 @@ static void f_insert(typval_T *argvars, typval_T *rettv) | ||||
|   list_T      *l; | ||||
|   int error = FALSE; | ||||
|  | ||||
|   if (argvars[0].v_type != VAR_LIST) | ||||
|   if (argvars[0].v_type != VAR_LIST) { | ||||
|     EMSG2(_(e_listarg), "insert()"); | ||||
|   else if ((l = argvars[0].vval.v_list) != NULL | ||||
|            && !tv_check_lock(l->lv_lock, (char_u *)_("insert() argument"))) { | ||||
|     if (argvars[2].v_type != VAR_UNKNOWN) | ||||
|   } else if ((l = argvars[0].vval.v_list) != NULL | ||||
|              && !tv_check_lock(l->lv_lock, | ||||
|                                (char_u *)N_("insert() argument"), true)) { | ||||
|     if (argvars[2].v_type != VAR_UNKNOWN) { | ||||
|       before = get_tv_number_chk(&argvars[2], &error); | ||||
|     if (error) | ||||
|       return;                   /* type error; errmsg already given */ | ||||
|     } | ||||
|     if (error) { | ||||
|       // type error; errmsg already given | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     if (before == l->lv_len) | ||||
|       item = NULL; | ||||
| @@ -13903,20 +13909,20 @@ static void f_remove(typval_T *argvars, typval_T *rettv) | ||||
|   char_u      *key; | ||||
|   dict_T      *d; | ||||
|   dictitem_T  *di; | ||||
|   char        *arg_errmsg = N_("remove() argument"); | ||||
|   char_u      *arg_errmsg = (char_u *)N_("remove() argument"); | ||||
|  | ||||
|   if (argvars[0].v_type == VAR_DICT) { | ||||
|     if (argvars[2].v_type != VAR_UNKNOWN) | ||||
|     if (argvars[2].v_type != VAR_UNKNOWN) { | ||||
|       EMSG2(_(e_toomanyarg), "remove()"); | ||||
|     else if ((d = argvars[0].vval.v_dict) != NULL | ||||
|              && !tv_check_lock(d->dv_lock, (char_u *)_(arg_errmsg))) { | ||||
|     } else if ((d = argvars[0].vval.v_dict) != NULL | ||||
|                && !tv_check_lock(d->dv_lock, arg_errmsg, true)) { | ||||
|       key = get_tv_string_chk(&argvars[1]); | ||||
|       if (key != NULL) { | ||||
|         di = dict_find(d, key, -1); | ||||
|         if (di == NULL) { | ||||
|           EMSG2(_(e_dictkey), key); | ||||
|         } else if (!var_check_fixed(di->di_flags, (char_u *)_(arg_errmsg)) | ||||
|                    && !var_check_ro(di->di_flags, (char_u *)_(arg_errmsg))) { | ||||
|         } else if (!var_check_fixed(di->di_flags, arg_errmsg, true) | ||||
|                    && !var_check_ro(di->di_flags, arg_errmsg, true)) { | ||||
|           *rettv = di->di_tv; | ||||
|           init_tv(&di->di_tv); | ||||
|           dictitem_remove(d, di); | ||||
| @@ -13926,11 +13932,11 @@ static void f_remove(typval_T *argvars, typval_T *rettv) | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } else if (argvars[0].v_type != VAR_LIST) | ||||
|   } else if (argvars[0].v_type != VAR_LIST) { | ||||
|     EMSG2(_(e_listdictarg), "remove()"); | ||||
|   else if ((l = argvars[0].vval.v_list) != NULL | ||||
|            && !tv_check_lock(l->lv_lock, (char_u *)_(arg_errmsg))) { | ||||
|     int error = FALSE; | ||||
|   } else if ((l = argvars[0].vval.v_list) != NULL | ||||
|              && !tv_check_lock(l->lv_lock, arg_errmsg, true)) { | ||||
|     int error = (int)false; | ||||
|  | ||||
|     idx = get_tv_number_chk(&argvars[1], &error); | ||||
|     if (error) | ||||
| @@ -14204,10 +14210,11 @@ static void f_reverse(typval_T *argvars, typval_T *rettv) | ||||
|   list_T      *l; | ||||
|   listitem_T  *li, *ni; | ||||
|  | ||||
|   if (argvars[0].v_type != VAR_LIST) | ||||
|   if (argvars[0].v_type != VAR_LIST) { | ||||
|     EMSG2(_(e_listarg), "reverse()"); | ||||
|   else if ((l = argvars[0].vval.v_list) != NULL | ||||
|            && !tv_check_lock(l->lv_lock, (char_u *)_("reverse() argument"))) { | ||||
|   } else if ((l = argvars[0].vval.v_list) != NULL | ||||
|              && !tv_check_lock(l->lv_lock, | ||||
|                                (char_u *)N_("reverse() argument"), true)) { | ||||
|     li = l->lv_last; | ||||
|     l->lv_first = l->lv_last = NULL; | ||||
|     l->lv_len = 0; | ||||
| @@ -15741,8 +15748,12 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) | ||||
|     EMSG2(_(e_listarg), sort ? "sort()" : "uniq()"); | ||||
|   } else { | ||||
|     l = argvars[0].vval.v_list; | ||||
|     if (l == NULL || tv_check_lock(l->lv_lock, | ||||
|         (char_u *)(sort ? _("sort() argument") : _("uniq() argument")))) { | ||||
|     if (l == NULL || | ||||
|         tv_check_lock(l->lv_lock, | ||||
|                       (char_u *)(sort | ||||
|                                  ? N_("sort() argument") | ||||
|                                  : N_("uniq() argument")), | ||||
|                       true)) { | ||||
|       return; | ||||
|     } | ||||
|     rettv->vval.v_list = l; | ||||
| @@ -18848,10 +18859,11 @@ set_var ( | ||||
|     return; | ||||
|  | ||||
|   if (v != NULL) { | ||||
|     /* existing variable, need to clear the value */ | ||||
|     if (var_check_ro(v->di_flags, name) | ||||
|         || tv_check_lock(v->di_tv.v_lock, name)) | ||||
|     // existing variable, need to clear the value | ||||
|     if (var_check_ro(v->di_flags, name, false) | ||||
|         || tv_check_lock(v->di_tv.v_lock, name, false)) { | ||||
|       return; | ||||
|     } | ||||
|     if (v->di_tv.v_type != tv->v_type | ||||
|         && !((v->di_tv.v_type == VAR_STRING | ||||
|               || v->di_tv.v_type == VAR_NUMBER) | ||||
| @@ -18936,34 +18948,31 @@ set_var ( | ||||
|   } | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Return TRUE if di_flags "flags" indicates variable "name" is read-only. | ||||
|  * Also give an error message. | ||||
|  */ | ||||
| static int var_check_ro(int flags, char_u *name) | ||||
| // Return true if di_flags "flags" indicates variable "name" is read-only. | ||||
| // Also give an error message. | ||||
| static bool var_check_ro(int flags, char_u *name, bool use_gettext) | ||||
| { | ||||
|   if (flags & DI_FLAGS_RO) { | ||||
|     EMSG2(_(e_readonlyvar), name); | ||||
|     return TRUE; | ||||
|     EMSG2(_(e_readonlyvar), use_gettext ? (char_u *)_(name) : name); | ||||
|     return true; | ||||
|   } | ||||
|   if ((flags & DI_FLAGS_RO_SBX) && sandbox) { | ||||
|     EMSG2(_(e_readonlysbx), name); | ||||
|     return TRUE; | ||||
|     EMSG2(_(e_readonlysbx), use_gettext ? (char_u *)_(name) : name); | ||||
|     return true; | ||||
|   } | ||||
|   return FALSE; | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Return TRUE if di_flags "flags" indicates variable "name" is fixed. | ||||
|  * Also give an error message. | ||||
|  */ | ||||
| static int var_check_fixed(int flags, char_u *name) | ||||
| // Return true if di_flags "flags" indicates variable "name" is fixed. | ||||
| // Also give an error message. | ||||
| static bool var_check_fixed(int flags, char_u *name, bool use_gettext) | ||||
| { | ||||
|   if (flags & DI_FLAGS_FIX) { | ||||
|     EMSG2(_("E795: Cannot delete variable %s"), name); | ||||
|     return TRUE; | ||||
|     EMSG2(_("E795: Cannot delete variable %s"), | ||||
|           use_gettext ? (char_u *)_(name) : name); | ||||
|     return true; | ||||
|   } | ||||
|   return FALSE; | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| /* | ||||
| @@ -19011,23 +19020,28 @@ static int valid_varname(char_u *varname) | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Return TRUE if typeval "tv" is set to be locked (immutable). | ||||
|  * Also give an error message, using "name". | ||||
|  */ | ||||
| static int tv_check_lock(int lock, char_u *name) | ||||
| // Return true if typeval "tv" is set to be locked (immutable). | ||||
| // Also give an error message, using "name" or _("name") when use_gettext is | ||||
| // true. | ||||
| static bool tv_check_lock(int lock, char_u *name, bool use_gettext) | ||||
| { | ||||
|   if (lock & VAR_LOCKED) { | ||||
|     EMSG2(_("E741: Value is locked: %s"), | ||||
|         name == NULL ? (char_u *)_("Unknown") : name); | ||||
|     return TRUE; | ||||
|           name == NULL | ||||
|           ? (char_u *)_("Unknown") | ||||
|           : use_gettext ? (char_u *)_(name) | ||||
|           : name); | ||||
|     return true; | ||||
|   } | ||||
|   if (lock & VAR_FIXED) { | ||||
|     EMSG2(_("E742: Cannot change value of %s"), | ||||
|         name == NULL ? (char_u *)_("Unknown") : name); | ||||
|     return TRUE; | ||||
|           name == NULL | ||||
|           ? (char_u *)_("Unknown") | ||||
|           : use_gettext ? (char_u *)_(name) | ||||
|           : name); | ||||
|     return true; | ||||
|   } | ||||
|   return FALSE; | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| /* | ||||
| @@ -19844,13 +19858,14 @@ void ex_function(exarg_T *eap) | ||||
|       goto erret; | ||||
|     } | ||||
|     if (fudi.fd_di == NULL) { | ||||
|       /* Can't add a function to a locked dictionary */ | ||||
|       if (tv_check_lock(fudi.fd_dict->dv_lock, eap->arg)) | ||||
|       if (tv_check_lock(fudi.fd_dict->dv_lock, eap->arg, false)) { | ||||
|         // Can't add a function to a locked dictionary | ||||
|         goto erret; | ||||
|       } | ||||
|     /* Can't change an existing function if it is locked */ | ||||
|     else if (tv_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg)) | ||||
|     } else if (tv_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg, false)) { | ||||
|       // Can't change an existing function if it is locked | ||||
|       goto erret; | ||||
|     } | ||||
|  | ||||
|     /* Give the function a sequential number.  Can only be used with a | ||||
|      * Funcref! */ | ||||
|   | ||||
| @@ -580,7 +580,7 @@ static int included_patches[] = { | ||||
|   711, | ||||
|   710, | ||||
|   709, | ||||
|   // 708, | ||||
|   708, | ||||
|   707, | ||||
|   706, | ||||
|   // 705 NA | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 watiko
					watiko