diff src/eval.c @ 271:8d34af900bae v7.0072

updated for version 7.0072
author vimboss
date Wed, 18 May 2005 22:24:46 +0000
parents e7904492cb75
children 8fa8d7964cf1
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -580,8 +580,12 @@ static pos_T *var2fpos __ARGS((typval_T 
 static int get_env_len __ARGS((char_u **arg));
 static int get_id_len __ARGS((char_u **arg));
 static int get_name_len __ARGS((char_u **arg, char_u **alias, int evaluate, int verbose));
-static char_u *find_name_end __ARGS((char_u *arg, char_u **expr_start, char_u **expr_end, int incl_br));
+static char_u *find_name_end __ARGS((char_u *arg, char_u **expr_start, char_u **expr_end, int flags));
+#define FNE_INCL_BR	1	/* find_name_end(): include [] in name */
+#define FNE_CHECK_START	2	/* find_name_end(): check name starts with
+				   valid character */
 static int eval_isnamec __ARGS((int c));
+static int eval_isnamec1 __ARGS((int c));
 static int get_var_tv __ARGS((char_u *name, int len, typval_T *rettv, int verbose));
 static int handle_subscript __ARGS((char_u **arg, typval_T *rettv, int evaluate, int verbose));
 static typval_T *alloc_tv __ARGS((void));
@@ -650,7 +654,7 @@ static void list_vim_vars __ARGS((void))
 static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg));
 static char_u *ex_let_one __ARGS((char_u *arg, typval_T *tv, int copy, char_u *endchars, char_u *op));
 static int check_changedtick __ARGS((char_u *arg));
-static char_u *get_lval __ARGS((char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int quiet));
+static char_u *get_lval __ARGS((char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int quiet, int fne_flags));
 static void clear_lval __ARGS((lval_T *lp));
 static void set_var_lval __ARGS((lval_T *lp, char_u *endp, typval_T *rettv, int copy, char_u *op));
 static int tv_op __ARGS((typval_T *tv1, typval_T *tv2, char_u  *op));
@@ -663,6 +667,9 @@ static int do_lock_var __ARGS((lval_T *l
 static void item_lock __ARGS((typval_T *tv, int deep, int lock));
 static int tv_islocked __ARGS((typval_T *tv));
 
+/* Character used as separated in autoload function/variable names. */
+#define AUTOLOAD_CHAR '#'
+
 /*
  * Initialize the global and v: variables.
  */
@@ -792,7 +799,7 @@ var_redir_start(name, append)
     typval_T	tv;
 
     /* Make sure a valid variable name is specified */
-    if (!eval_isnamec(*name) || VIM_ISDIGIT(*name))
+    if (!eval_isnamec1(*name))
     {
 	EMSG(_(e_invarg));
 	return FAIL;
@@ -810,7 +817,8 @@ var_redir_start(name, append)
     }
 
     /* Parse the variable name (can be a dict or list entry). */
-    redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, FALSE);
+    redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, FALSE,
+							     FNE_CHECK_START);
     if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != NUL)
     {
 	if (redir_endp != NULL && *redir_endp != NUL)
@@ -1551,7 +1559,7 @@ skip_var_one(arg)
 {
     if (vim_strchr((char_u *)"$@&", *arg) != NULL)
 	++arg;
-    return find_name_end(arg, NULL, NULL, TRUE);
+    return find_name_end(arg, NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
 }
 
 /*
@@ -1643,7 +1651,7 @@ list_arg_vars(eap, arg)
     {
 	if (error || eap->skip)
 	{
-	    arg = find_name_end(arg, NULL, NULL, TRUE);
+	    arg = find_name_end(arg, NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
 	    if (!vim_iswhite(*arg) && !ends_excmd(*arg))
 	    {
 		emsg_severe = TRUE;
@@ -1888,11 +1896,11 @@ ex_let_one(arg, tv, copy, endchars, op)
      * ":let var = expr": Set internal variable.
      * ":let {expr} = expr": Idem, name made with curly braces
      */
-    else if ((eval_isnamec(*arg) && !VIM_ISDIGIT(*arg)) || *arg == '{')
+    else if (eval_isnamec1(*arg) || *arg == '{')
     {
 	lval_T	lv;
 
-	p = get_lval(arg, tv, &lv, FALSE, FALSE, FALSE);
+	p = get_lval(arg, tv, &lv, FALSE, FALSE, FALSE, FNE_CHECK_START);
 	if (p != NULL && lv.ll_name != NULL)
 	{
 	    if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL)
@@ -1942,13 +1950,14 @@ check_changedtick(arg)
  * Returns NULL for a parsing error.  Still need to free items in "lp"!
  */
     static char_u *
-get_lval(name, rettv, lp, unlet, skip, quiet)
+get_lval(name, rettv, lp, unlet, skip, quiet, fne_flags)
     char_u	*name;
     typval_T	*rettv;
     lval_T	*lp;
     int		unlet;
     int		skip;
     int		quiet;	    /* don't give error messages */
+    int		fne_flags;  /* flags for find_name_end() */
 {
     char_u	*p;
     char_u	*expr_start, *expr_end;
@@ -1969,11 +1978,11 @@ get_lval(name, rettv, lp, unlet, skip, q
     {
 	/* When skipping just find the end of the name. */
 	lp->ll_name = name;
-	return find_name_end(name, NULL, NULL, TRUE);
+	return find_name_end(name, NULL, NULL, FNE_INCL_BR | fne_flags);
     }
 
     /* Find the end of the name. */
-    p = find_name_end(name, &expr_start, &expr_end, FALSE);
+    p = find_name_end(name, &expr_start, &expr_end, fne_flags);
     if (expr_start != NULL)
     {
 	/* Don't expand the name when we already know there is an error. */
@@ -2842,7 +2851,8 @@ ex_unletlock(eap, argstart, deep)
     do
     {
 	/* Parse the name and find the end. */
-	name_end = get_lval(arg, NULL, &lv, TRUE, eap->skip || error, FALSE);
+	name_end = get_lval(arg, NULL, &lv, TRUE, eap->skip || error, FALSE,
+							     FNE_CHECK_START);
 	if (lv.ll_name == NULL)
 	    error = TRUE;	    /* error but continue parsing */
 	if (name_end == NULL || (!vim_iswhite(*name_end)
@@ -10178,7 +10188,8 @@ f_islocked(argvars, rettv)
     dictitem_T	*di;
 
     rettv->vval.v_number = -1;
-    end = get_lval(get_tv_string(&argvars[0]), NULL, &lv, FALSE, FALSE, FALSE);
+    end = get_lval(get_tv_string(&argvars[0]), NULL, &lv, FALSE, FALSE, FALSE,
+							     FNE_CHECK_START);
     if (end != NULL && lv.ll_name != NULL)
     {
 	if (*end != NUL)
@@ -13967,7 +13978,8 @@ get_name_len(arg, alias, evaluate, verbo
     /*
      * Find the end of the name; check for {} construction.
      */
-    p = find_name_end(*arg, &expr_start, &expr_end, FALSE);
+    p = find_name_end(*arg, &expr_start, &expr_end,
+					       len > 0 ? 0 : FNE_CHECK_START);
     if (expr_start != NULL)
     {
 	char_u	*temp_string;
@@ -14002,15 +14014,16 @@ get_name_len(arg, alias, evaluate, verbo
  * Find the end of a variable or function name, taking care of magic braces.
  * If "expr_start" is not NULL then "expr_start" and "expr_end" are set to the
  * start and end of the first magic braces item.
+ * "flags" can have FNE_INCL_BR and FNE_CHECK_START.
  * Return a pointer to just after the name.  Equal to "arg" if there is no
  * valid name.
  */
     static char_u *
-find_name_end(arg, expr_start, expr_end, incl_br)
+find_name_end(arg, expr_start, expr_end, flags)
     char_u	*arg;
     char_u	**expr_start;
     char_u	**expr_end;
-    int		incl_br;	/* Include [] indexes and .name */
+    int		flags;
 {
     int		mb_nest = 0;
     int		br_nest = 0;
@@ -14022,10 +14035,14 @@ find_name_end(arg, expr_start, expr_end,
 	*expr_end = NULL;
     }
 
+    /* Quick check for valid starting character. */
+    if ((flags & FNE_CHECK_START) && !eval_isnamec1(*arg) && *arg != '{')
+	return arg;
+
     for (p = arg; *p != NUL
 		    && (eval_isnamec(*p)
 			|| *p == '{'
-			|| (incl_br && (*p == '[' || *p == '.'))
+			|| ((flags & FNE_INCL_BR) && (*p == '[' || *p == '.'))
 			|| mb_nest != 0
 			|| br_nest != 0); ++p)
     {
@@ -14108,7 +14125,7 @@ make_expanded_name(in_start, expr_start,
 
     if (retval != NULL)
     {
-	temp_result = find_name_end(retval, &expr_start, &expr_end, FALSE);
+	temp_result = find_name_end(retval, &expr_start, &expr_end, 0);
 	if (expr_start != NULL)
 	{
 	    /* Further expansion! */
@@ -14130,7 +14147,18 @@ make_expanded_name(in_start, expr_start,
 eval_isnamec(c)
     int	    c;
 {
-    return (ASCII_ISALNUM(c) || c == '_' || c == ':');
+    return (ASCII_ISALNUM(c) || c == '_' || c == ':' || c == AUTOLOAD_CHAR);
+}
+
+/*
+ * Return TRUE if character "c" can be used as the first character in a
+ * variable or function name (excluding '{' and '}').
+ */
+    static int
+eval_isnamec1(c)
+    int	    c;
+{
+    return (ASCII_ISALPHA(c) || c == '_');
 }
 
 /*
@@ -14729,8 +14757,8 @@ find_var_ht(name, varname)
 {
     if (name[1] != ':')
     {
-	/* The name must not start with a colon. */
-	if (name[0] == ':')
+	/* The name must not start with a colon or #. */
+	if (name[0] == ':' || name[0] == AUTOLOAD_CHAR)
 	    return NULL;
 	*varname = name;
 
@@ -14745,8 +14773,10 @@ find_var_ht(name, varname)
     *varname = name + 2;
     if (*name == 'g')				/* global variable */
 	return &globvarht;
-    /* There must be no ':' in the rest of the name, unless g: is used */
-    if (vim_strchr(name + 2, ':') != NULL)
+    /* There must be no ':' or '#' in the rest of the name, unless g: is used
+     */
+    if (vim_strchr(name + 2, ':') != NULL
+			       || vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL)
 	return NULL;
     if (*name == 'b')				/* buffer variable */
 	return &curbuf->b_vars.dv_hashtab;
@@ -15886,7 +15916,7 @@ ex_function(eap)
 
     if (fp == NULL)
     {
-	if (fudi.fd_dict == NULL && vim_strchr(name, ':') != NULL)
+	if (fudi.fd_dict == NULL && vim_strchr(name, AUTOLOAD_CHAR) != NULL)
 	{
 	    int	    slen, plen;
 	    char_u  *scriptname;
@@ -16018,7 +16048,8 @@ trans_function_name(pp, skip, flags, fdp
     if (lead > 2)
 	start += lead;
 
-    end = get_lval(start, NULL, &lv, FALSE, skip, flags & TFN_QUIET);
+    end = get_lval(start, NULL, &lv, FALSE, skip, flags & TFN_QUIET,
+					      lead > 2 ? 0 : FNE_CHECK_START);
     if (end == start)
     {
 	if (!skip)
@@ -16038,7 +16069,7 @@ trans_function_name(pp, skip, flags, fdp
 		EMSG2(_(e_invarg2), start);
 	}
 	else
-	    *pp = find_name_end(start, NULL, NULL, TRUE);
+	    *pp = find_name_end(start, NULL, NULL, FNE_INCL_BR);
 	goto theend;
     }
 
@@ -16236,13 +16267,14 @@ function_exists(name)
 
 /*
  * Return TRUE if "name" looks like a builtin function name: starts with a
- * lower case letter and doesn't contain a ':'.
+ * lower case letter and doesn't contain a ':' or AUTOLOAD_CHAR.
  */
     static int
 builtin_function(name)
     char_u *name;
 {
-    return ASCII_ISLOWER(name[0]) && vim_strchr(name, ':') == NULL;
+    return ASCII_ISLOWER(name[0]) && vim_strchr(name, ':') == NULL
+				   && vim_strchr(name, AUTOLOAD_CHAR) == NULL;
 }
 
 #if defined(FEAT_PROFILE) || defined(PROTO)
@@ -16440,7 +16472,7 @@ script_autoload(name)
     int		ret = FALSE;
 
     /* If there is no colon after name[1] there is no package name. */
-    p = vim_strchr(name, ':');
+    p = vim_strchr(name, AUTOLOAD_CHAR);
     if (p == NULL || p <= name + 2)
 	return FALSE;
 
@@ -16464,15 +16496,15 @@ autoload_name(name)
     char_u	*p;
     char_u	*scriptname;
 
-    /* Get the script file name: replace ':' with '/', append ".vim". */
+    /* Get the script file name: replace '#' with '/', append ".vim". */
     scriptname = alloc((unsigned)(STRLEN(name) + 14));
     if (scriptname == NULL)
 	return FALSE;
     STRCPY(scriptname, "autoload/");
     STRCAT(scriptname, name);
-    *vim_strrchr(scriptname, ':') = NUL;
+    *vim_strrchr(scriptname, AUTOLOAD_CHAR) = NUL;
     STRCAT(scriptname, ".vim");
-    while ((p = vim_strchr(scriptname, ':')) != NULL)
+    while ((p = vim_strchr(scriptname, AUTOLOAD_CHAR)) != NULL)
 	*p = '/';
     return scriptname;
 }
@@ -16852,7 +16884,7 @@ call_user_func(fp, argcount, argvars, re
 		    else
 		    {
 			trunc_string(tv2string(&argvars[i], &tofree, numbuf),
-							    buf, MSG_BUF_LEN);
+							    buf, MSG_BUF_CLEN);
 			msg_puts(buf);
 			vim_free(tofree);
 		    }
@@ -16940,7 +16972,7 @@ call_user_func(fp, argcount, argvars, re
 	    char_u	*tofree;
 
 	    trunc_string(tv2string(fc.rettv, &tofree, numbuf),
-							    buf, MSG_BUF_LEN);
+							   buf, MSG_BUF_CLEN);
 	    smsg((char_u *)_("%s returning %s"), sn, buf);
 	    vim_free(tofree);
 	}