changeset 7943:e875f0fbd9c0 v7.4.1267

commit https://github.com/vim/vim/commit/a03f23351588f04276469cd7742b7ec655bb604b Author: Bram Moolenaar <Bram@vim.org> Date: Sat Feb 6 18:09:59 2016 +0100 patch 7.4.1267 Problem: Easy to miss handling all types of variables. Solution: Change the variable type into an enum.
author Christian Brabandt <cb@256bit.org>
date Sat, 06 Feb 2016 18:15:04 +0100
parents 5d117679edcd
children f2d749f1d0ac
files src/eval.c src/structs.h src/version.c
diffstat 3 files changed, 151 insertions(+), 118 deletions(-) [+]
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -3065,6 +3065,7 @@ tv_op(typval_T *tv1, typval_T *tv2, char
 	    case VAR_DICT:
 	    case VAR_FUNC:
 	    case VAR_SPECIAL:
+	    case VAR_UNKNOWN:
 		break;
 
 	    case VAR_LIST:
@@ -3837,6 +3838,14 @@ item_lock(typval_T *tv, int deep, int lo
 
     switch (tv->v_type)
     {
+	case VAR_UNKNOWN:
+	case VAR_NUMBER:
+	case VAR_STRING:
+	case VAR_FUNC:
+	case VAR_FLOAT:
+	case VAR_SPECIAL:
+	    break;
+
 	case VAR_LIST:
 	    if ((l = tv->vval.v_list) != NULL)
 	    {
@@ -5317,23 +5326,32 @@ eval_index(
     char_u	*s;
     char_u	*key = NULL;
 
-    if (rettv->v_type == VAR_FUNC)
-    {
-	if (verbose)
-	    EMSG(_("E695: Cannot index a Funcref"));
-	return FAIL;
-    }
-#ifdef FEAT_FLOAT
-    else if (rettv->v_type == VAR_FLOAT)
-    {
-	if (verbose)
-	    EMSG(_(e_float_as_string));
-	return FAIL;
-    }
-#endif
-    else if (rettv->v_type == VAR_SPECIAL)
-    {
-	return FAIL;
+    switch (rettv->v_type)
+    {
+	case VAR_FUNC:
+	    if (verbose)
+		EMSG(_("E695: Cannot index a Funcref"));
+	    return FAIL;
+	case VAR_FLOAT:
+#ifdef FEAT_FLOAT
+	    if (verbose)
+		EMSG(_(e_float_as_string));
+	    return FAIL;
+#endif
+	case VAR_SPECIAL:
+	    if (verbose)
+		EMSG(_("E909: Cannot index a special variable"));
+	    return FAIL;
+	case VAR_UNKNOWN:
+	    if (evaluate)
+		return FAIL;
+	    /* FALLTHROUGH */
+
+	case VAR_STRING:
+	case VAR_NUMBER:
+	case VAR_LIST:
+	case VAR_DICT:
+	    break;
     }
 
     init_tv(&var1);
@@ -5428,6 +5446,12 @@ eval_index(
 
 	switch (rettv->v_type)
 	{
+	    case VAR_SPECIAL:
+	    case VAR_FUNC:
+	    case VAR_FLOAT:
+	    case VAR_UNKNOWN:
+		break; /* not evaluating, skipping over subscript */
+
 	    case VAR_NUMBER:
 	    case VAR_STRING:
 		s = get_tv_string(rettv);
@@ -6143,6 +6167,9 @@ tv_equal(
 
     switch (tv1->v_type)
     {
+	case VAR_UNKNOWN:
+	    break;
+
 	case VAR_LIST:
 	    ++recursive_cnt;
 	    r = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic, TRUE);
@@ -6177,8 +6204,9 @@ tv_equal(
 	    return tv1->vval.v_number == tv2->vval.v_number;
     }
 
-    EMSG2(_(e_intern2), "tv_equal()");
-    return TRUE;
+    /* VAR_UNKNOWN can be the result of a invalid expression, let's say it
+     * does not equal anything, not even itself. */
+    return FALSE;
 }
 
 /*
@@ -7047,59 +7075,56 @@ set_ref_in_item(
     list_T	*ll;
     int		abort = FALSE;
 
-    switch (tv->v_type)
-    {
-	case VAR_DICT:
-	    dd = tv->vval.v_dict;
-	    if (dd != NULL && dd->dv_copyID != copyID)
-	    {
-		/* Didn't see this dict yet. */
-		dd->dv_copyID = copyID;
-		if (ht_stack == NULL)
-		{
-		    abort = set_ref_in_ht(&dd->dv_hashtab, copyID, list_stack);
-		}
-		else
-		{
-		    ht_stack_T *newitem = (ht_stack_T*)malloc(
-							  sizeof(ht_stack_T));
-		    if (newitem == NULL)
-			abort = TRUE;
-		    else
-		    {
-			newitem->ht = &dd->dv_hashtab;
-			newitem->prev = *ht_stack;
-			*ht_stack = newitem;
-		    }
-		}
-	    }
-	    break;
-
-	case VAR_LIST:
-	    ll = tv->vval.v_list;
-	    if (ll != NULL && ll->lv_copyID != copyID)
-	    {
-		/* Didn't see this list yet. */
-		ll->lv_copyID = copyID;
-		if (list_stack == NULL)
-		{
-		    abort = set_ref_in_list(ll, copyID, ht_stack);
-		}
-		else
-		{
-		    list_stack_T *newitem = (list_stack_T*)malloc(
+    if (tv->v_type == VAR_DICT)
+    {
+	dd = tv->vval.v_dict;
+	if (dd != NULL && dd->dv_copyID != copyID)
+	{
+	    /* Didn't see this dict yet. */
+	    dd->dv_copyID = copyID;
+	    if (ht_stack == NULL)
+	    {
+		abort = set_ref_in_ht(&dd->dv_hashtab, copyID, list_stack);
+	    }
+	    else
+	    {
+		ht_stack_T *newitem = (ht_stack_T*)malloc(sizeof(ht_stack_T));
+		if (newitem == NULL)
+		    abort = TRUE;
+		else
+		{
+		    newitem->ht = &dd->dv_hashtab;
+		    newitem->prev = *ht_stack;
+		    *ht_stack = newitem;
+		}
+	    }
+	}
+    }
+    else if (tv->v_type == VAR_LIST)
+    {
+	ll = tv->vval.v_list;
+	if (ll != NULL && ll->lv_copyID != copyID)
+	{
+	    /* Didn't see this list yet. */
+	    ll->lv_copyID = copyID;
+	    if (list_stack == NULL)
+	    {
+		abort = set_ref_in_list(ll, copyID, ht_stack);
+	    }
+	    else
+	    {
+		list_stack_T *newitem = (list_stack_T*)malloc(
 							sizeof(list_stack_T));
-		    if (newitem == NULL)
-			abort = TRUE;
-		    else
-		    {
-			newitem->list = ll;
-			newitem->prev = *list_stack;
-			*list_stack = newitem;
-		    }
-		}
-	    }
-	    break;
+		if (newitem == NULL)
+		    abort = TRUE;
+		else
+		{
+		    newitem->list = ll;
+		    newitem->prev = *list_stack;
+		    *list_stack = newitem;
+		}
+	    }
+	}
     }
     return abort;
 }
@@ -7763,6 +7788,7 @@ echo_string(
 
 	case VAR_STRING:
 	case VAR_NUMBER:
+	case VAR_UNKNOWN:
 	    *tofree = NULL;
 	    r = get_tv_string_buf(tv, numbuf);
 	    break;
@@ -7779,10 +7805,6 @@ echo_string(
 	    *tofree = NULL;
 	    r = (char_u *)get_var_special_name(tv->vval.v_number);
 	    break;
-
-	default:
-	    EMSG2(_(e_intern2), "echo_string()");
-	    *tofree = NULL;
     }
 
     if (--recurse == 0)
@@ -7822,9 +7844,8 @@ tv2string(
 	case VAR_LIST:
 	case VAR_DICT:
 	case VAR_SPECIAL:
-	    break;
-	default:
-	    EMSG2(_(e_intern2), "tv2string()");
+	case VAR_UNKNOWN:
+	    break;
     }
     return echo_string(tv, tofree, numbuf, copyID);
 }
@@ -10528,9 +10549,10 @@ f_empty(typval_T *argvars, typval_T *ret
 	    n = argvars[0].vval.v_number != VVAL_TRUE;
 	    break;
 
-	default:
-	    EMSG2(_(e_intern2), "f_empty()");
-	    n = 0;
+	case VAR_UNKNOWN:
+	    EMSG2(_(e_intern2), "f_empty(UNKNOWN)");
+	    n = TRUE;
+	    break;
     }
 
     rettv->vval.v_number = n;
@@ -14266,7 +14288,10 @@ f_len(typval_T *argvars, typval_T *rettv
 	case VAR_DICT:
 	    rettv->vval.v_number = dict_len(argvars[0].vval.v_dict);
 	    break;
-	default:
+	case VAR_UNKNOWN:
+	case VAR_SPECIAL:
+	case VAR_FLOAT:
+	case VAR_FUNC:
 	    EMSG(_("E701: Invalid type for len()"));
 	    break;
     }
@@ -19624,13 +19649,16 @@ f_type(typval_T *argvars, typval_T *rett
 	case VAR_FLOAT:  n = 5; break;
 #endif
 	case VAR_SPECIAL:
-			 if (argvars[0].vval.v_number == VVAL_FALSE
-				 || argvars[0].vval.v_number == VVAL_TRUE)
-			     n = 6;
-			 else
-			     n = 7;
-			 break;
-	default: EMSG2(_(e_intern2), "f_type()"); n = 0; break;
+	     if (argvars[0].vval.v_number == VVAL_FALSE
+		     || argvars[0].vval.v_number == VVAL_TRUE)
+		 n = 6;
+	     else
+		 n = 7;
+	     break;
+	case VAR_UNKNOWN:
+	     EMSG2(_(e_intern2), "f_type(UNKNOWN)");
+	     n = -1;
+	     break;
     }
     rettv->vval.v_number = n;
 }
@@ -21000,9 +21028,6 @@ free_tv(typval_T *varp)
 	    case VAR_UNKNOWN:
 	    case VAR_SPECIAL:
 		break;
-	    default:
-		EMSG2(_(e_intern2), "free_tv()");
-		break;
 	}
 	vim_free(varp);
     }
@@ -21044,8 +21069,6 @@ clear_tv(typval_T *varp)
 #endif
 	    case VAR_UNKNOWN:
 		break;
-	    default:
-		EMSG2(_(e_intern2), "clear_tv()");
 	}
 	varp->v_lock = 0;
     }
@@ -21108,8 +21131,8 @@ get_tv_number_chk(typval_T *varp, int *d
 	case VAR_SPECIAL:
 	    return varp->vval.v_number == VVAL_TRUE ? 1 : 0;
 	    break;
-	default:
-	    EMSG2(_(e_intern2), "get_tv_number()");
+	case VAR_UNKNOWN:
+	    EMSG2(_(e_intern2), "get_tv_number(UNKNOWN)");
 	    break;
     }
     if (denote == NULL)		/* useful for values that must be unsigned */
@@ -21130,7 +21153,6 @@ get_tv_float(typval_T *varp)
 #ifdef FEAT_FLOAT
 	case VAR_FLOAT:
 	    return varp->vval.v_float;
-	    break;
 #endif
 	case VAR_FUNC:
 	    EMSG(_("E891: Using a Funcref as a Float"));
@@ -21144,8 +21166,11 @@ get_tv_float(typval_T *varp)
 	case VAR_DICT:
 	    EMSG(_("E894: Using a Dictionary as a Float"));
 	    break;
-	default:
-	    EMSG2(_(e_intern2), "get_tv_float()");
+	case VAR_SPECIAL:
+	    EMSG(_("E907: Using a special value as a Float"));
+	    break;
+	case VAR_UNKNOWN:
+	    EMSG2(_(e_intern2), "get_tv_float(UNKNOWN)");
 	    break;
     }
     return 0;
@@ -21256,9 +21281,8 @@ get_tv_string_buf_chk(typval_T *varp, ch
 	case VAR_SPECIAL:
 	    STRCPY(buf, get_var_special_name(varp->vval.v_number));
 	    return buf;
-
-	default:
-	    EMSG2(_(e_intern2), "get_tv_string_buf()");
+	case VAR_UNKNOWN:
+	    EMSG(_("E908: using an invalid value as a String"));
 	    break;
     }
     return NULL;
@@ -21910,8 +21934,8 @@ copy_tv(typval_T *from, typval_T *to)
 		++to->vval.v_dict->dv_refcount;
 	    }
 	    break;
-	default:
-	    EMSG2(_(e_intern2), "copy_tv()");
+	case VAR_UNKNOWN:
+	    EMSG2(_(e_intern2), "copy_tv(UNKNOWN)");
 	    break;
     }
 }
@@ -21983,8 +22007,8 @@ item_copy(
 	    if (to->vval.v_dict == NULL)
 		ret = FAIL;
 	    break;
-	default:
-	    EMSG2(_(e_intern2), "item_copy()");
+	case VAR_UNKNOWN:
+	    EMSG2(_(e_intern2), "item_copy(UNKNOWN)");
 	    ret = FAIL;
     }
     --recurse;
@@ -24532,6 +24556,7 @@ read_viminfo_varlist(vir_T *virp, int wr
 #endif
 		case 'D': type = VAR_DICT; break;
 		case 'L': type = VAR_LIST; break;
+		case 'X': type = VAR_SPECIAL; break;
 	    }
 
 	    tab = vim_strchr(tab, '\t');
@@ -24617,7 +24642,11 @@ write_viminfo_varlist(FILE *fp)
 #endif
 		    case VAR_DICT:   s = "DIC"; break;
 		    case VAR_LIST:   s = "LIS"; break;
-		    default: continue;
+		    case VAR_SPECIAL: s = "XPL"; break;
+
+		    case VAR_UNKNOWN:
+		    case VAR_FUNC:
+				     continue;
 		}
 		fprintf(fp, "!%s\t%s\t", this_var->di_key, s);
 		p = echo_string(&this_var->di_tv, &tofree, numbuf, 0);
--- a/src/structs.h
+++ b/src/structs.h
@@ -1111,12 +1111,24 @@ typedef double	float_T;
 typedef struct listvar_S list_T;
 typedef struct dictvar_S dict_T;
 
+typedef enum
+{
+    VAR_UNKNOWN = 0,
+    VAR_NUMBER,	/* "v_number" is used */
+    VAR_STRING,	/* "v_string" is used */
+    VAR_FUNC,	/* "v_string" is function name */
+    VAR_LIST,	/* "v_list" is used */
+    VAR_DICT,	/* "v_dict" is used */
+    VAR_FLOAT,	/* "v_float" is used */
+    VAR_SPECIAL	/* "v_number" is used */
+} vartype_T;
+
 /*
  * Structure to hold an internal variable without a name.
  */
 typedef struct
 {
-    char	v_type;	    /* see below: VAR_NUMBER, VAR_STRING, etc. */
+    vartype_T	v_type;
     char	v_lock;	    /* see below: VAR_LOCKED, VAR_FIXED */
     union
     {
@@ -1130,16 +1142,6 @@ typedef struct
     }		vval;
 } typval_T;
 
-/* Values for "v_type". */
-#define VAR_UNKNOWN 0
-#define VAR_NUMBER  1	/* "v_number" is used */
-#define VAR_STRING  2	/* "v_string" is used */
-#define VAR_FUNC    3	/* "v_string" is function name */
-#define VAR_LIST    4	/* "v_list" is used */
-#define VAR_DICT    5	/* "v_dict" is used */
-#define VAR_FLOAT   6	/* "v_float" is used */
-#define VAR_SPECIAL 7	/* "v_number" is used */
-
 /* Values for "dv_scope". */
 #define VAR_SCOPE     1	/* a:, v:, s:, etc. scope dictionaries */
 #define VAR_DEF_SCOPE 2	/* l:, g: scope dictionaries: here funcrefs are not
--- a/src/version.c
+++ b/src/version.c
@@ -743,6 +743,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1267,
+/**/
     1266,
 /**/
     1265,