Loading ...
Sorry, an error occurred while loading the content.

Re: [PATCH] Extended funcrefs: use func_T* structure in place of char_u* function names

Expand Messages
  • ZyX
    Added tests, added functype() function, a bit more fixes: - Two autoload function references when called for the first time caused script being loaded twice,
    Message 1 of 22 , Sep 28, 2013
    • 0 Attachment
      Added tests, added functype() function, a bit more fixes:

      - Two autoload function references when called for the first time caused script being loaded twice, no matter whether or not referenced function was defined.
      - It is now possible to save function references in autoload variables (variables with a hash) (assuming they start with a capital letter of course).
      - Ability to load function references from the variables was tested and fixed.
      - Added a check whether function name containing hash is a valid one when creating autoload function (this functionality is missing in default branch).

      diff -r 3a32cbcc2449 -r 419a14acd856 Filelist
      --- a/Filelist Wed Sep 25 23:24:58 2013 +0200
      +++ b/Filelist Sat Sep 28 22:24:12 2013 +0400
      @@ -83,6 +83,7 @@
      src/testdir/test[0-9]*.ok \
      src/testdir/test49.vim \
      src/testdir/test60.vim \
      + src/testdir/Test100.vim \
      src/testdir/test83-tags? \
      src/testdir/python2/*.py \
      src/testdir/python3/*.py \
      diff -r 3a32cbcc2449 -r 419a14acd856 runtime/doc/eval.txt
      --- a/runtime/doc/eval.txt Wed Sep 25 23:24:58 2013 +0200
      +++ b/runtime/doc/eval.txt Sat Sep 28 22:24:12 2013 +0400
      @@ -1772,7 +1772,8 @@
      foldtext( ) String line displayed for closed fold
      foldtextresult( {lnum}) String text for closed fold at {lnum}
      foreground( ) Number bring the Vim window to the foreground
      -function( {name}) Funcref reference to function {name}
      +function( {name}) Funcref reference to function {name}
      +functype( {func}) String type of function reference {func}
      garbagecollect( [{atexit}]) none free memory, breaking cyclic references
      get( {list}, {idx} [, {def}]) any get item {idx} from {list} or {def}
      get( {dict}, {key} [, {def}]) any get item {key} from {dict} or {def}
      @@ -3104,6 +3105,31 @@
      {name} can be a user defined function or an internal function.


      +functype({func}) *functype()*
      + Given a |Funcref| return string describing its type. Possible
      + values:
      + Value Description ~
      + internal Reference to one of the built-in |functions|.
      + Example: `function('tr')`.
      + user Reference to one of the |user-functions|.
      + Example: `function('NetrwStatusLine')`.
      + autoload Reference to one of the |autoload-functions|
      + that was not yet loaded.
      + Example: `function('zip#Browse')`.
      + autoload:{type} Same as above, but for functions that were
      + already loaded. For `function('zip#Browse')`
      + it will return "autoload:user". {type} may be
      + anything that |functype()| can return
      + (including e.g. "autoload:autoload:internal").
      + python:{type} Reference to some python function. {type} is
      + the python type name.
      + Example: `pyeval('id')` has function type
      + "python:builtin_function_or_method".
      + python3:{type} Same as above, but for python 3 functions.
      + Example: `py3eval('id')` has function type
      + "python3:builtin_function_or_method".
      +
      +
      garbagecollect([{atexit}]) *garbagecollect()*
      Cleanup unused |Lists| and |Dictionaries| that have circular
      references. There is hardly ever a need to invoke this
      diff -r 3a32cbcc2449 -r 419a14acd856 runtime/doc/if_pyth.txt
      --- a/runtime/doc/if_pyth.txt Wed Sep 25 23:24:58 2013 +0200
      +++ b/runtime/doc/if_pyth.txt Sat Sep 28 22:24:12 2013 +0400
      @@ -656,7 +656,11 @@
      Function-like object, acting like vim |Funcref| object. Supports `.name`
      attribute and is callable. Accepts special keyword argument `self`, see
      |Dictionary-function|. You can also use `vim.Function(name)` constructor,
      - it is the same as `vim.bindeval('function(%s)'%json.dumps(name))`.
      + it is the same as `vim.bindeval('function(%s)'%json.dumps(name))`. Object
      + supports the following attributes:
      + Attribute Description ~
      + name Function name.
      + repr Same as running `vim.bindeval("string(pyeval('func'))")`.

      Examples: >
      f = vim.Function('tr') # Constructor
      diff -r 3a32cbcc2449 -r 419a14acd856 runtime/doc/repeat.txt
      --- a/runtime/doc/repeat.txt Wed Sep 25 23:24:58 2013 +0200
      +++ b/runtime/doc/repeat.txt Sat Sep 28 22:24:12 2013 +0400
      @@ -668,12 +668,6 @@
      - The time of the lines added up is mostly less than the time of the whole
      function. There is some overhead in between.

      -- Functions that are deleted before Vim exits will not produce profiling
      - information. You can check the |v:profiling| variable if needed: >
      - :if !v:profiling
      - : delfunc MyFunc
      - :endif
      -<
      - Profiling may give weird results on multi-processor systems, when sleep
      mode kicks in or the processor frequency is reduced to save power.

      diff -r 3a32cbcc2449 -r 419a14acd856 src/Makefile
      --- a/src/Makefile Wed Sep 25 23:24:58 2013 +0200
      +++ b/src/Makefile Sat Sep 28 22:24:12 2013 +0400
      @@ -1882,7 +1882,8 @@
      test60 test61 test62 test63 test64 test65 test66 test67 test68 test69 \
      test70 test71 test72 test73 test74 test75 test76 test77 test78 test79 \
      test80 test81 test82 test83 test84 test85 test86 test87 test88 test89 \
      - test90 test91 test92 test93 test94 test95 test96 test97 test98 test99:
      + test90 test91 test92 test93 test94 test95 test96 test97 test98 test99 \
      + test100:
      cd testdir; rm $@.out; $(MAKE) -f Makefile $@.out VIMPROG=../$(VIMTARGET)

      testclean:
      diff -r 3a32cbcc2449 -r 419a14acd856 src/eval.c
      --- a/src/eval.c Wed Sep 25 23:24:58 2013 +0200
      +++ b/src/eval.c Sat Sep 28 22:24:12 2013 +0400
      @@ -115,6 +115,7 @@
      #ifdef FEAT_FLOAT
      static char *e_float_as_string = N_("E806: using Float as a String");
      #endif
      +static char *e_unknown_function = N_("E700: Unknown function: %s");

      static dictitem_T globvars_var; /* variable used for g: */
      #define globvarht globvardict.dv_hashtab
      @@ -153,10 +154,16 @@

      static int echo_attr = 0; /* attributes used for ":echo" */

      -/* Values for trans_function_name() argument: */
      +/* Values for trans_function_name() flags argument: */
      #define TFN_INT 1 /* internal function name OK */
      #define TFN_QUIET 2 /* no error messages */

      +/* Values for get_called_function() flags argument: */
      +#define GCF_AUTOLOAD 1 /* it is OK to create autoload functions */
      +#define GCF_RUN_EVENT 2 /* run FuncUndefined event */
      +#define GCF_QUIET 4 /* no error messages */
      +#define GCF_ANY_FUNC GCF_AUTOLOAD|GCF_RUN_EVENT
      +
      /*
      * Structure to hold info for a user function.
      */
      @@ -166,7 +173,6 @@
      {
      int uf_varargs; /* variable nr of arguments */
      int uf_flags;
      - int uf_calls; /* nr of active calls */
      garray_T uf_args; /* arguments */
      garray_T uf_lines; /* function lines */
      #ifdef FEAT_PROFILE
      @@ -185,19 +191,35 @@
      proftime_T uf_tml_wait; /* start wait time for current line */
      int uf_tml_idx; /* index of line being timed; -1 if none */
      int uf_tml_execed; /* line being timed was executed */
      + ufunc_T *uf_prof_next; /* next profiled function */
      #endif
      scid_T uf_script_ID; /* ID of script where function was defined,
      used for s: variables */
      - int uf_refcount; /* for numbered function: reference count */
      + func_T *uf_func; /* Reference to a func_T structure holding
      + reference to ufunc_T */
      char_u uf_name[1]; /* name of function (actually longer); can
      start with <SNR>123_ (<SNR> is K_SPECIAL
      KS_EXTRA KE_SNR) */
      };

      +/*
      + * Structure to hold info for autoloaded function.
      + */
      +typedef struct aufunc aufunc_T;
      +
      +struct aufunc
      +{
      + char_u *auf_name; /* Function name */
      + func_T *auf_func; /* If function was already autoloaded:
      + record pointer here, otherwise it will hold
      + NULL */
      +};
      +
      /* function flags */
      #define FC_ABORT 1 /* abort function on error */
      #define FC_RANGE 2 /* function accepts range */
      -#define FC_DICT 4 /* Dict function, uses "self" */
      +#define FC_DICT 4 /* Dict function, uses "self" */
      +#define FC_ANON 8 /* Anonymous, not stored in func_hashtab */

      /*
      * All user-defined functions are found in this hashtable.
      @@ -211,6 +233,12 @@
      static dict_T *first_dict = NULL; /* list of all dicts */
      static list_T *first_list = NULL; /* list of all lists */

      +#ifdef FEAT_PROFILE
      +/* Functions being profiled */
      +static ufunc_T *fp_profiled_first = NULL;
      +static ufunc_T *fp_profiled_last = NULL;
      +#endif
      +
      /* From user function to hashitem and back. */
      static ufunc_T dumuf;
      #define UF2HIKEY(fp) ((fp)->uf_name)
      @@ -269,9 +297,13 @@
      */
      typedef struct
      {
      - dict_T *fd_dict; /* Dictionary used */
      + dict_T *fd_dict; /* Dictionary used. Contains borrowed reference.
      + */
      char_u *fd_newkey; /* new key in "dict" in allocated memory */
      dictitem_T *fd_di; /* Dictionary item used */
      + func_T *fd_func; /* Function object, if it was obtained.
      + * Contains borrowed reference, no need to
      + * decref. */
      } funcdict_T;


      @@ -438,17 +470,16 @@
      static int get_dict_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
      static char_u *echo_string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf, int copyID));
      static char_u *tv2string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf, int copyID));
      -static char_u *string_quote __ARGS((char_u *str, int function));
      #ifdef FEAT_FLOAT
      static int string2float __ARGS((char_u *text, float_T *value));
      #endif
      static int get_env_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
      -static int find_internal_func __ARGS((char_u *name));
      -static char_u *deref_func_name __ARGS((char_u *name, int *lenp));
      -static int get_func_tv __ARGS((char_u *name, int len, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));
      -static int call_func __ARGS((char_u *funcname, int len, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));
      +static struct fst *find_internal_func __ARGS((char_u *name));
      +static int get_func_tv __ARGS((func_T *name, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));
      +static int call_func __ARGS((func_T *func, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, dict_T *selfdict));
      static void emsg_funcname __ARGS((char *ermsg, char_u *name));
      static int non_zero_arg __ARGS((typval_T *argvars));
      +static aufunc_T *aufunc_alloc __ARGS((void));

      #ifdef FEAT_FLOAT
      static void f_abs __ARGS((typval_T *argvars, typval_T *rettv));
      @@ -534,6 +565,7 @@
      static void f_foldtextresult __ARGS((typval_T *argvars, typval_T *rettv));
      static void f_foreground __ARGS((typval_T *argvars, typval_T *rettv));
      static void f_function __ARGS((typval_T *argvars, typval_T *rettv));
      +static void f_functype __ARGS((typval_T *argvars, typval_T *rettv));
      static void f_garbagecollect __ARGS((typval_T *argvars, typval_T *rettv));
      static void f_get __ARGS((typval_T *argvars, typval_T *rettv));
      static void f_getbufline __ARGS((typval_T *argvars, typval_T *rettv));
      @@ -790,10 +822,12 @@
      static int var_check_fixed __ARGS((int flags, char_u *name));
      static int var_check_func_name __ARGS((char_u *name, int new_var));
      static int valid_varname __ARGS((char_u *varname));
      +static int valid_autoload_name __ARGS((char_u *varname));
      static int tv_check_lock __ARGS((int lock, char_u *name));
      static int item_copy __ARGS((typval_T *from, typval_T *to, int deep, int copyID));
      static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags));
      static char_u *trans_function_name __ARGS((char_u **pp, int skip, int flags, funcdict_T *fd));
      +static func_T *get_called_function __ARGS((char_u **pp, int skip, funcdict_T *fd, int flags));
      static int eval_fname_script __ARGS((char_u *p));
      static int eval_fname_sid __ARGS((char_u *p));
      static void list_func_head __ARGS((ufunc_T *fp, int indent));
      @@ -802,6 +836,7 @@
      static int builtin_function __ARGS((char_u *name));
      #ifdef FEAT_PROFILE
      static void func_do_profile __ARGS((ufunc_T *fp));
      +static void func_clear_profile __ARGS((ufunc_T *fp));
      static void prof_sort_list __ARGS((FILE *fd, ufunc_T **sorttab, int st_len, char *title, int prefer_self));
      static void prof_func_line __ARGS((FILE *fd, int count, proftime_T *total, proftime_T *self, int prefer_self));
      static int
      @@ -818,8 +853,9 @@
      static int script_autoload __ARGS((char_u *name, int reload));
      static char_u *autoload_name __ARGS((char_u *name));
      static void cat_func_name __ARGS((char_u *buf, ufunc_T *fp));
      -static void func_free __ARGS((ufunc_T *fp));
      -static void call_user_func __ARGS((ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, linenr_T firstline, linenr_T lastline, dict_T *selfdict));
      +static void dealloc_user_func __ARGS((ufunc_T *fp));
      +static int call_user_func __ARGS((ufunc_T *fp, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, dict_T *selfdict));
      +static void remove_user_func __ARGS((ufunc_T *fp));
      static int can_free_funccal __ARGS((funccall_T *fc, int copyID)) ;
      static void free_funccal __ARGS((funccall_T *fc, int free_val));
      static void add_nr_var __ARGS((dict_T *dp, dictitem_T *v, char *name, varnumber_T nr));
      @@ -835,6 +871,11 @@
      static void sortFunctions __ARGS(());
      #endif

      +
      +static funcdef_T user_func_type;
      +static funcdef_T internal_func_type;
      +static funcdef_T autoload_func_type;
      +
      /*
      * Initialize the global and v: variables.
      */
      @@ -1559,10 +1600,10 @@
      * Returns OK or FAIL.
      */
      int
      -call_vim_function(func, argc, argv, safe, str_arg_only, rettv)
      - char_u *func;
      +call_vim_function(name, argc, argv, safe, str_arg_only, rettv)
      + char_u *name;
      int argc;
      - char_u **argv;
      + char_u **argv;
      int safe; /* use the sandbox */
      int str_arg_only; /* all arguments are strings */
      typval_T *rettv;
      @@ -1574,11 +1615,19 @@
      int doesrange;
      void *save_funccalp = NULL;
      int ret;
      + func_T *func;

      argvars = (typval_T *)alloc((unsigned)((argc + 1) * sizeof(typval_T)));
      if (argvars == NULL)
      return FAIL;

      + func = deref_func_name(name, STRLEN(name), DF_ALL);
      + if (func == NULL)
      + {
      + vim_free(argvars);
      + return FAIL;
      + }
      +
      for (i = 0; i < argc; i++)
      {
      /* Pass a NULL or empty argument as an empty string */
      @@ -1613,9 +1662,9 @@
      }

      rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */
      - ret = call_func(func, (int)STRLEN(func), rettv, argc, argvars,
      + ret = call_func(func, rettv, argc, argvars,
      curwin->w_cursor.lnum, curwin->w_cursor.lnum,
      - &doesrange, TRUE, NULL);
      + &doesrange, NULL);
      if (safe)
      {
      --sandbox;
      @@ -1626,6 +1675,8 @@
      if (ret == FAIL)
      clear_tv(rettv);

      + func_unref(func);
      +
      return ret;
      }

      @@ -3383,8 +3434,7 @@
      {
      char_u *arg = eap->arg;
      char_u *startarg;
      - char_u *name;
      - char_u *tofree;
      + func_T *func;
      int len;
      typval_T rettv;
      linenr_T lnum;
      @@ -3404,14 +3454,14 @@
      return;
      }

      - tofree = trans_function_name(&arg, eap->skip, TFN_INT, &fudi);
      + func = get_called_function(&arg, eap->skip, &fudi, GCF_ANY_FUNC);
      if (fudi.fd_newkey != NULL)
      {
      /* Still need to give an error message for missing key. */
      EMSG2(_(e_dictkey), fudi.fd_newkey);
      vim_free(fudi.fd_newkey);
      }
      - if (tofree == NULL)
      + if (func == NULL)
      return;

      /* Increase refcount on dictionary, it could get deleted when evaluating
      @@ -3419,10 +3469,6 @@
      if (fudi.fd_dict != NULL)
      ++fudi.fd_dict->dv_refcount;

      - /* If it is the name of a variable of type VAR_FUNC use its contents. */
      - len = (int)STRLEN(tofree);
      - name = deref_func_name(tofree, &len);
      -
      /* Skip white space to allow ":call func ()". Not good, but required for
      * backward compatibility. */
      startarg = skipwhite(arg);
      @@ -3458,7 +3504,7 @@
      #endif
      }
      arg = startarg;
      - if (get_func_tv(name, (int)STRLEN(name), &rettv, &arg,
      + if (get_func_tv(func, &rettv, &arg,
      eap->line1, eap->line2, &doesrange,
      !eap->skip, fudi.fd_dict) == FAIL)
      {
      @@ -3500,8 +3546,8 @@
      }

      end:
      + func_unref(func);
      dict_unref(fudi.fd_dict);
      - vim_free(tofree);
      }

      /*
      @@ -4472,12 +4518,17 @@
      else
      {
      /* Compare two Funcrefs for being equal or unequal. */
      - if (rettv->vval.v_string == NULL
      - || var2.vval.v_string == NULL)
      + if (rettv->vval.v_func == NULL
      + || var2.vval.v_func == NULL)
      + n1 = FALSE;
      + else if (rettv->vval.v_func->fv_type !=
      + var2.vval.v_func->fv_type)
      n1 = FALSE;
      else
      - n1 = STRCMP(rettv->vval.v_string,
      - var2.vval.v_string) == 0;
      + n1 = rettv->vval.v_func->fv_type->fd_compare(
      + rettv->vval.v_func->fv_data,
      + var2.vval.v_func->fv_data
      + );
      if (type == TYPE_NEQUAL)
      n1 = !n1;
      }
      @@ -5146,21 +5197,39 @@
      {
      if (**arg == '(') /* recursive! */
      {
      + func_T *func;
      /* If "s" is the name of a variable of type VAR_FUNC
      * use its contents. */
      - s = deref_func_name(s, &len);
      -
      - /* Invoke the function. */
      - ret = get_func_tv(s, len, rettv, arg,
      - curwin->w_cursor.lnum, curwin->w_cursor.lnum,
      - &len, evaluate, NULL);
      + if (evaluate)
      + func = deref_func_name(s, len, DF_ALL);
      + else
      + func = NULL;
      +
      + if (evaluate && func == NULL)
      + {
      + char_u cc;
      + ret = FAIL;
      + cc = s[len];
      + s[len] = '\0';
      + emsg_funcname(N_("E117: Unknown function: %s"), s);
      + s[len] = cc;
      + }
      + else
      + {
      + /* Invoke the function. */
      + ret = get_func_tv(func, rettv, arg,
      + curwin->w_cursor.lnum, curwin->w_cursor.lnum,
      + &len, evaluate, NULL);
      +
      + func_unref(func);
      + }

      /* If evaluate is FALSE rettv->v_type was not set in
      * get_func_tv, but it's needed in handle_subscript() to parse
      * what follows. So set it here. */
      if (rettv->v_type == VAR_UNKNOWN && !evaluate && **arg == '(')
      {
      - rettv->vval.v_string = vim_strsave((char_u *)"");
      + rettv->vval.v_func = NULL;
      rettv->v_type = VAR_FUNC;
      }

      @@ -6121,9 +6190,13 @@
      return r;

      case VAR_FUNC:
      - return (tv1->vval.v_string != NULL
      - && tv2->vval.v_string != NULL
      - && STRCMP(tv1->vval.v_string, tv2->vval.v_string) == 0);
      + return (tv1->vval.v_func != NULL
      + && tv2->vval.v_func != NULL
      + && tv1->vval.v_func->fv_type == tv2->vval.v_func->fv_type
      + && tv1->vval.v_func->fv_type->fd_compare(
      + tv1->vval.v_func->fv_data,
      + tv2->vval.v_func->fv_data
      + ));

      case VAR_NUMBER:
      return tv1->vval.v_number == tv2->vval.v_number;
      @@ -7415,7 +7488,7 @@
      else
      ga_concat(&ga, (char_u *)", ");

      - tofree = string_quote(hi->hi_key, FALSE);
      + tofree = string_quote(hi->hi_key, NULL);
      if (tofree != NULL)
      {
      ga_concat(&ga, tofree);
      @@ -7594,8 +7667,8 @@
      switch (tv->v_type)
      {
      case VAR_FUNC:
      - *tofree = NULL;
      - r = tv->vval.v_string;
      + r = FUNC_REPR(tv->vval.v_func);
      + *tofree = r;
      break;

      case VAR_LIST:
      @@ -7676,10 +7749,10 @@
      switch (tv->v_type)
      {
      case VAR_FUNC:
      - *tofree = string_quote(tv->vval.v_string, TRUE);
      + *tofree = FUNC_REPR(tv->vval.v_func);
      return *tofree;
      case VAR_STRING:
      - *tofree = string_quote(tv->vval.v_string, FALSE);
      + *tofree = string_quote(tv->vval.v_string, NULL);
      return *tofree;
      #ifdef FEAT_FLOAT
      case VAR_FLOAT:
      @@ -7700,17 +7773,25 @@
      /*
      * Return string "str" in ' quotes, doubling ' characters.
      * If "str" is NULL an empty string is assumed.
      - * If "function" is TRUE make it function('string').
      - */
      - static char_u *
      -string_quote(str, function)
      + * If "fname" is not NULL make it fname('string').
      + */
      + char_u *
      +string_quote(str, fname)
      char_u *str;
      - int function;
      + char *fname;
      {
      unsigned len;
      + unsigned flen = 0;
      char_u *p, *r, *s;
      -
      - len = (function ? 13 : 3);
      + char_u *fname_u = (char_u *) fname;
      +
      + if (fname_u != NULL)
      + flen = STRLEN(fname_u);
      +
      + /* +---+- 2 quotes and NUL *
      + * | | +- parenthesis *
      + * | | | */
      + len = (fname_u == NULL ? 3 : 3 + 2 + flen);
      if (str != NULL)
      {
      len += (unsigned)STRLEN(str);
      @@ -7721,13 +7802,13 @@
      s = r = alloc(len);
      if (r != NULL)
      {
      - if (function)
      - {
      - STRCPY(r, "function('");
      - r += 10;
      - }
      - else
      - *r++ = '\'';
      + if (fname_u)
      + {
      + mch_memmove(r, fname_u, flen);
      + r += flen;
      + *r++ = '(';
      + }
      + *r++ = '\'';
      if (str != NULL)
      for (p = str; *p != NUL; )
      {
      @@ -7736,7 +7817,7 @@
      MB_COPY_CHAR(p, r);
      }
      *r++ = '\'';
      - if (function)
      + if (fname_u)
      *r++ = ')';
      *r++ = NUL;
      }
      @@ -7829,321 +7910,324 @@
      char *f_name; /* function name */
      char f_min_argc; /* minimal number of arguments */
      char f_max_argc; /* maximal number of arguments */
      - void (*f_func) __ARGS((typval_T *args, typval_T *rvar));
      + void (*f_call) __ARGS((typval_T *args, typval_T *rvar));
      /* implementation of function */
      + func_T *f_func; /* reference to a func_T structure holding
      + reference to struct fst */
      } functions[] =
      {
      #ifdef FEAT_FLOAT
      - {"abs", 1, 1, f_abs},
      - {"acos", 1, 1, f_acos}, /* WJMc */
      -#endif
      - {"add", 2, 2, f_add},
      - {"and", 2, 2, f_and},
      - {"append", 2, 2, f_append},
      - {"argc", 0, 0, f_argc},
      - {"argidx", 0, 0, f_argidx},
      - {"argv", 0, 1, f_argv},
      -#ifdef FEAT_FLOAT
      - {"asin", 1, 1, f_asin}, /* WJMc */
      - {"atan", 1, 1, f_atan},
      - {"atan2", 2, 2, f_atan2},
      -#endif
      - {"browse", 4, 4, f_browse},
      - {"browsedir", 2, 2, f_browsedir},
      - {"bufexists", 1, 1, f_bufexists},
      - {"buffer_exists", 1, 1, f_bufexists}, /* obsolete */
      - {"buffer_name", 1, 1, f_bufname}, /* obsolete */
      - {"buffer_number", 1, 1, f_bufnr}, /* obsolete */
      - {"buflisted", 1, 1, f_buflisted},
      - {"bufloaded", 1, 1, f_bufloaded},
      - {"bufname", 1, 1, f_bufname},
      - {"bufnr", 1, 2, f_bufnr},
      - {"bufwinnr", 1, 1, f_bufwinnr},
      - {"byte2line", 1, 1, f_byte2line},
      - {"byteidx", 2, 2, f_byteidx},
      - {"call", 2, 3, f_call},
      -#ifdef FEAT_FLOAT
      - {"ceil", 1, 1, f_ceil},
      -#endif
      - {"changenr", 0, 0, f_changenr},
      - {"char2nr", 1, 2, f_char2nr},
      - {"cindent", 1, 1, f_cindent},
      - {"clearmatches", 0, 0, f_clearmatches},
      - {"col", 1, 1, f_col},
      + {"abs", 1, 1, f_abs, NULL},
      + {"acos", 1, 1, f_acos, NULL}, /* WJMc */
      +#endif
      + {"add", 2, 2, f_add, NULL},
      + {"and", 2, 2, f_and, NULL},
      + {"append", 2, 2, f_append, NULL},
      + {"argc", 0, 0, f_argc, NULL},
      + {"argidx", 0, 0, f_argidx, NULL},
      + {"argv", 0, 1, f_argv, NULL},
      +#ifdef FEAT_FLOAT
      + {"asin", 1, 1, f_asin, NULL}, /* WJMc */
      + {"atan", 1, 1, f_atan, NULL},
      + {"atan2", 2, 2, f_atan2, NULL},
      +#endif
      + {"browse", 4, 4, f_browse, NULL},
      + {"browsedir", 2, 2, f_browsedir, NULL},
      + {"bufexists", 1, 1, f_bufexists, NULL},
      + {"buffer_exists", 1, 1, f_bufexists, NULL}, /* obsolete */
      + {"buffer_name", 1, 1, f_bufname, NULL}, /* obsolete */
      + {"buffer_number", 1, 1, f_bufnr, NULL}, /* obsolete */
      + {"buflisted", 1, 1, f_buflisted, NULL},
      + {"bufloaded", 1, 1, f_bufloaded, NULL},
      + {"bufname", 1, 1, f_bufname, NULL},
      + {"bufnr", 1, 2, f_bufnr, NULL},
      + {"bufwinnr", 1, 1, f_bufwinnr, NULL},
      + {"byte2line", 1, 1, f_byte2line, NULL},
      + {"byteidx", 2, 2, f_byteidx, NULL},
      + {"call", 2, 3, f_call, NULL},
      +#ifdef FEAT_FLOAT
      + {"ceil", 1, 1, f_ceil, NULL},
      +#endif
      + {"changenr", 0, 0, f_changenr, NULL},
      + {"char2nr", 1, 2, f_char2nr, NULL},
      + {"cindent", 1, 1, f_cindent, NULL},
      + {"clearmatches", 0, 0, f_clearmatches, NULL},
      + {"col", 1, 1, f_col, NULL},
      #if defined(FEAT_INS_EXPAND)
      - {"complete", 2, 2, f_complete},
      - {"complete_add", 1, 1, f_complete_add},
      - {"complete_check", 0, 0, f_complete_check},
      -#endif
      - {"confirm", 1, 4, f_confirm},
      - {"copy", 1, 1, f_copy},
      -#ifdef FEAT_FLOAT
      - {"cos", 1, 1, f_cos},
      - {"cosh", 1, 1, f_cosh},
      -#endif
      - {"count", 2, 4, f_count},
      - {"cscope_connection",0,3, f_cscope_connection},
      - {"cursor", 1, 3, f_cursor},
      - {"deepcopy", 1, 2, f_deepcopy},
      - {"delete", 1, 1, f_delete},
      - {"did_filetype", 0, 0, f_did_filetype},
      - {"diff_filler", 1, 1, f_diff_filler},
      - {"diff_hlID", 2, 2, f_diff_hlID},
      - {"empty", 1, 1, f_empty},
      - {"escape", 2, 2, f_escape},
      - {"eval", 1, 1, f_eval},
      - {"eventhandler", 0, 0, f_eventhandler},
      - {"executable", 1, 1, f_executable},
      - {"exists", 1, 1, f_exists},
      -#ifdef FEAT_FLOAT
      - {"exp", 1, 1, f_exp},
      -#endif
      - {"expand", 1, 3, f_expand},
      - {"extend", 2, 3, f_extend},
      - {"feedkeys", 1, 2, f_feedkeys},
      - {"file_readable", 1, 1, f_filereadable}, /* obsolete */
      - {"filereadable", 1, 1, f_filereadable},
      - {"filewritable", 1, 1, f_filewritable},
      - {"filter", 2, 2, f_filter},
      - {"finddir", 1, 3, f_finddir},
      - {"findfile", 1, 3, f_findfile},
      -#ifdef FEAT_FLOAT
      - {"float2nr", 1, 1, f_float2nr},
      - {"floor", 1, 1, f_floor},
      - {"fmod", 2, 2, f_fmod},
      -#endif
      - {"fnameescape", 1, 1, f_fnameescape},
      - {"fnamemodify", 2, 2, f_fnamemodify},
      - {"foldclosed", 1, 1, f_foldclosed},
      - {"foldclosedend", 1, 1, f_foldclosedend},
      - {"foldlevel", 1, 1, f_foldlevel},
      - {"foldtext", 0, 0, f_foldtext},
      - {"foldtextresult", 1, 1, f_foldtextresult},
      - {"foreground", 0, 0, f_foreground},
      - {"function", 1, 1, f_function},
      - {"garbagecollect", 0, 1, f_garbagecollect},
      - {"get", 2, 3, f_get},
      - {"getbufline", 2, 3, f_getbufline},
      - {"getbufvar", 2, 3, f_getbufvar},
      - {"getchar", 0, 1, f_getchar},
      - {"getcharmod", 0, 0, f_getcharmod},
      - {"getcmdline", 0, 0, f_getcmdline},
      - {"getcmdpos", 0, 0, f_getcmdpos},
      - {"getcmdtype", 0, 0, f_getcmdtype},
      - {"getcwd", 0, 0, f_getcwd},
      - {"getfontname", 0, 1, f_getfontname},
      - {"getfperm", 1, 1, f_getfperm},
      - {"getfsize", 1, 1, f_getfsize},
      - {"getftime", 1, 1, f_getftime},
      - {"getftype", 1, 1, f_getftype},
      - {"getline", 1, 2, f_getline},
      - {"getloclist", 1, 1, f_getqflist},
      - {"getmatches", 0, 0, f_getmatches},
      - {"getpid", 0, 0, f_getpid},
      - {"getpos", 1, 1, f_getpos},
      - {"getqflist", 0, 0, f_getqflist},
      - {"getreg", 0, 2, f_getreg},
      - {"getregtype", 0, 1, f_getregtype},
      - {"gettabvar", 2, 3, f_gettabvar},
      - {"gettabwinvar", 3, 4, f_gettabwinvar},
      - {"getwinposx", 0, 0, f_getwinposx},
      - {"getwinposy", 0, 0, f_getwinposy},
      - {"getwinvar", 2, 3, f_getwinvar},
      - {"glob", 1, 3, f_glob},
      - {"globpath", 2, 3, f_globpath},
      - {"has", 1, 1, f_has},
      - {"has_key", 2, 2, f_has_key},
      - {"haslocaldir", 0, 0, f_haslocaldir},
      - {"hasmapto", 1, 3, f_hasmapto},
      - {"highlightID", 1, 1, f_hlID}, /* obsolete */
      - {"highlight_exists",1, 1, f_hlexists}, /* obsolete */
      - {"histadd", 2, 2, f_histadd},
      - {"histdel", 1, 2, f_histdel},
      - {"histget", 1, 2, f_histget},
      - {"histnr", 1, 1, f_histnr},
      - {"hlID", 1, 1, f_hlID},
      - {"hlexists", 1, 1, f_hlexists},
      - {"hostname", 0, 0, f_hostname},
      - {"iconv", 3, 3, f_iconv},
      - {"indent", 1, 1, f_indent},
      - {"index", 2, 4, f_index},
      - {"input", 1, 3, f_input},
      - {"inputdialog", 1, 3, f_inputdialog},
      - {"inputlist", 1, 1, f_inputlist},
      - {"inputrestore", 0, 0, f_inputrestore},
      - {"inputsave", 0, 0, f_inputsave},
      - {"inputsecret", 1, 2, f_inputsecret},
      - {"insert", 2, 3, f_insert},
      - {"invert", 1, 1, f_invert},
      - {"isdirectory", 1, 1, f_isdirectory},
      - {"islocked", 1, 1, f_islocked},
      - {"items", 1, 1, f_items},
      - {"join", 1, 2, f_join},
      - {"keys", 1, 1, f_keys},
      - {"last_buffer_nr", 0, 0, f_last_buffer_nr},/* obsolete */
      - {"len", 1, 1, f_len},
      - {"libcall", 3, 3, f_libcall},
      - {"libcallnr", 3, 3, f_libcallnr},
      - {"line", 1, 1, f_line},
      - {"line2byte", 1, 1, f_line2byte},
      - {"lispindent", 1, 1, f_lispindent},
      - {"localtime", 0, 0, f_localtime},
      -#ifdef FEAT_FLOAT
      - {"log", 1, 1, f_log},
      - {"log10", 1, 1, f_log10},
      + {"complete", 2, 2, f_complete, NULL},
      + {"complete_add", 1, 1, f_complete_add, NULL},
      + {"complete_check", 0, 0, f_complete_check, NULL},
      +#endif
      + {"confirm", 1, 4, f_confirm, NULL},
      + {"copy", 1, 1, f_copy, NULL},
      +#ifdef FEAT_FLOAT
      + {"cos", 1, 1, f_cos, NULL},
      + {"cosh", 1, 1, f_cosh, NULL},
      +#endif
      + {"count", 2, 4, f_count, NULL},
      + {"cscope_connection",0,3, f_cscope_connection, NULL},
      + {"cursor", 1, 3, f_cursor, NULL},
      + {"deepcopy", 1, 2, f_deepcopy, NULL},
      + {"delete", 1, 1, f_delete, NULL},
      + {"did_filetype", 0, 0, f_did_filetype, NULL},
      + {"diff_filler", 1, 1, f_diff_filler, NULL},
      + {"diff_hlID", 2, 2, f_diff_hlID, NULL},
      + {"empty", 1, 1, f_empty, NULL},
      + {"escape", 2, 2, f_escape, NULL},
      + {"eval", 1, 1, f_eval, NULL},
      + {"eventhandler", 0, 0, f_eventhandler, NULL},
      + {"executable", 1, 1, f_executable, NULL},
      + {"exists", 1, 1, f_exists, NULL},
      +#ifdef FEAT_FLOAT
      + {"exp", 1, 1, f_exp, NULL},
      +#endif
      + {"expand", 1, 3, f_expand, NULL},
      + {"extend", 2, 3, f_extend, NULL},
      + {"feedkeys", 1, 2, f_feedkeys, NULL},
      + {"file_readable", 1, 1, f_filereadable, NULL}, /* obsolete */
      + {"filereadable", 1, 1, f_filereadable, NULL},
      + {"filewritable", 1, 1, f_filewritable, NULL},
      + {"filter", 2, 2, f_filter, NULL},
      + {"finddir", 1, 3, f_finddir, NULL},
      + {"findfile", 1, 3, f_findfile, NULL},
      +#ifdef FEAT_FLOAT
      + {"float2nr", 1, 1, f_float2nr, NULL},
      + {"floor", 1, 1, f_floor, NULL},
      + {"fmod", 2, 2, f_fmod, NULL},
      +#endif
      + {"fnameescape", 1, 1, f_fnameescape, NULL},
      + {"fnamemodify", 2, 2, f_fnamemodify, NULL},
      + {"foldclosed", 1, 1, f_foldclosed, NULL},
      + {"foldclosedend", 1, 1, f_foldclosedend, NULL},
      + {"foldlevel", 1, 1, f_foldlevel, NULL},
      + {"foldtext", 0, 0, f_foldtext, NULL},
      + {"foldtextresult", 1, 1, f_foldtextresult, NULL},
      + {"foreground", 0, 0, f_foreground, NULL},
      + {"function", 1, 1, f_function, NULL},
      + {"functype", 1, 1, f_functype, NULL},
      + {"garbagecollect", 0, 1, f_garbagecollect, NULL},
      + {"get", 2, 3, f_get, NULL},
      + {"getbufline", 2, 3, f_getbufline, NULL},
      + {"getbufvar", 2, 3, f_getbufvar, NULL},
      + {"getchar", 0, 1, f_getchar, NULL},
      + {"getcharmod", 0, 0, f_getcharmod, NULL},
      + {"getcmdline", 0, 0, f_getcmdline, NULL},
      + {"getcmdpos", 0, 0, f_getcmdpos, NULL},
      + {"getcmdtype", 0, 0, f_getcmdtype, NULL},
      + {"getcwd", 0, 0, f_getcwd, NULL},
      + {"getfontname", 0, 1, f_getfontname, NULL},
      + {"getfperm", 1, 1, f_getfperm, NULL},
      + {"getfsize", 1, 1, f_getfsize, NULL},
      + {"getftime", 1, 1, f_getftime, NULL},
      + {"getftype", 1, 1, f_getftype, NULL},
      + {"getline", 1, 2, f_getline, NULL},
      + {"getloclist", 1, 1, f_getqflist, NULL},
      + {"getmatches", 0, 0, f_getmatches, NULL},
      + {"getpid", 0, 0, f_getpid, NULL},
      + {"getpos", 1, 1, f_getpos, NULL},
      + {"getqflist", 0, 0, f_getqflist, NULL},
      + {"getreg", 0, 2, f_getreg, NULL},
      + {"getregtype", 0, 1, f_getregtype, NULL},
      + {"gettabvar", 2, 3, f_gettabvar, NULL},
      + {"gettabwinvar", 3, 4, f_gettabwinvar, NULL},
      + {"getwinposx", 0, 0, f_getwinposx, NULL},
      + {"getwinposy", 0, 0, f_getwinposy, NULL},
      + {"getwinvar", 2, 3, f_getwinvar, NULL},
      + {"glob", 1, 3, f_glob, NULL},
      + {"globpath", 2, 3, f_globpath, NULL},
      + {"has", 1, 1, f_has, NULL},
      + {"has_key", 2, 2, f_has_key, NULL},
      + {"haslocaldir", 0, 0, f_haslocaldir, NULL},
      + {"hasmapto", 1, 3, f_hasmapto, NULL},
      + {"highlightID", 1, 1, f_hlID, NULL}, /* obsolete */
      + {"highlight_exists",1, 1, f_hlexists, NULL}, /* obsolete */
      + {"histadd", 2, 2, f_histadd, NULL},
      + {"histdel", 1, 2, f_histdel, NULL},
      + {"histget", 1, 2, f_histget, NULL},
      + {"histnr", 1, 1, f_histnr, NULL},
      + {"hlID", 1, 1, f_hlID, NULL},
      + {"hlexists", 1, 1, f_hlexists, NULL},
      + {"hostname", 0, 0, f_hostname, NULL},
      + {"iconv", 3, 3, f_iconv, NULL},
      + {"indent", 1, 1, f_indent, NULL},
      + {"index", 2, 4, f_index, NULL},
      + {"input", 1, 3, f_input, NULL},
      + {"inputdialog", 1, 3, f_inputdialog, NULL},
      + {"inputlist", 1, 1, f_inputlist, NULL},
      + {"inputrestore", 0, 0, f_inputrestore, NULL},
      + {"inputsave", 0, 0, f_inputsave, NULL},
      + {"inputsecret", 1, 2, f_inputsecret, NULL},
      + {"insert", 2, 3, f_insert, NULL},
      + {"invert", 1, 1, f_invert, NULL},
      + {"isdirectory", 1, 1, f_isdirectory, NULL},
      + {"islocked", 1, 1, f_islocked, NULL},
      + {"items", 1, 1, f_items, NULL},
      + {"join", 1, 2, f_join, NULL},
      + {"keys", 1, 1, f_keys, NULL},
      + {"last_buffer_nr", 0, 0, f_last_buffer_nr, NULL},/* obsolete */
      + {"len", 1, 1, f_len, NULL},
      + {"libcall", 3, 3, f_libcall, NULL},
      + {"libcallnr", 3, 3, f_libcallnr, NULL},
      + {"line", 1, 1, f_line, NULL},
      + {"line2byte", 1, 1, f_line2byte, NULL},
      + {"lispindent", 1, 1, f_lispindent, NULL},
      + {"localtime", 0, 0, f_localtime, NULL},
      +#ifdef FEAT_FLOAT
      + {"log", 1, 1, f_log, NULL},
      + {"log10", 1, 1, f_log10, NULL},
      #endif
      #ifdef FEAT_LUA
      - {"luaeval", 1, 2, f_luaeval},
      -#endif
      - {"map", 2, 2, f_map},
      - {"maparg", 1, 4, f_maparg},
      - {"mapcheck", 1, 3, f_mapcheck},
      - {"match", 2, 4, f_match},
      - {"matchadd", 2, 4, f_matchadd},
      - {"matcharg", 1, 1, f_matcharg},
      - {"matchdelete", 1, 1, f_matchdelete},
      - {"matchend", 2, 4, f_matchend},
      - {"matchlist", 2, 4, f_matchlist},
      - {"matchstr", 2, 4, f_matchstr},
      - {"max", 1, 1, f_max},
      - {"min", 1, 1, f_min},
      + {"luaeval", 1, 2, f_luaeval, NULL},
      +#endif
      + {"map", 2, 2, f_map, NULL},
      + {"maparg", 1, 4, f_maparg, NULL},
      + {"mapcheck", 1, 3, f_mapcheck, NULL},
      + {"match", 2, 4, f_match, NULL},
      + {"matchadd", 2, 4, f_matchadd, NULL},
      + {"matcharg", 1, 1, f_matcharg, NULL},
      + {"matchdelete", 1, 1, f_matchdelete, NULL},
      + {"matchend", 2, 4, f_matchend, NULL},
      + {"matchlist", 2, 4, f_matchlist, NULL},
      + {"matchstr", 2, 4, f_matchstr, NULL},
      + {"max", 1, 1, f_max, NULL},
      + {"min", 1, 1, f_min, NULL},
      #ifdef vim_mkdir
      - {"mkdir", 1, 3, f_mkdir},
      -#endif
      - {"mode", 0, 1, f_mode},
      + {"mkdir", 1, 3, f_mkdir, NULL},
      +#endif
      + {"mode", 0, 1, f_mode, NULL},
      #ifdef FEAT_MZSCHEME
      - {"mzeval", 1, 1, f_mzeval},
      -#endif
      - {"nextnonblank", 1, 1, f_nextnonblank},
      - {"nr2char", 1, 2, f_nr2char},
      - {"or", 2, 2, f_or},
      - {"pathshorten", 1, 1, f_pathshorten},
      -#ifdef FEAT_FLOAT
      - {"pow", 2, 2, f_pow},
      -#endif
      - {"prevnonblank", 1, 1, f_prevnonblank},
      - {"printf", 2, 19, f_printf},
      - {"pumvisible", 0, 0, f_pumvisible},
      + {"mzeval", 1, 1, f_mzeval, NULL},
      +#endif
      + {"nextnonblank", 1, 1, f_nextnonblank, NULL},
      + {"nr2char", 1, 2, f_nr2char, NULL},
      + {"or", 2, 2, f_or, NULL},
      + {"pathshorten", 1, 1, f_pathshorten, NULL},
      +#ifdef FEAT_FLOAT
      + {"pow", 2, 2, f_pow, NULL},
      +#endif
      + {"prevnonblank", 1, 1, f_prevnonblank, NULL},
      + {"printf", 2, 19, f_printf, NULL},
      + {"pumvisible", 0, 0, f_pumvisible, NULL},
      #ifdef FEAT_PYTHON3
      - {"py3eval", 1, 1, f_py3eval},
      + {"py3eval", 1, 1, f_py3eval, NULL},
      #endif
      #ifdef FEAT_PYTHON
      - {"pyeval", 1, 1, f_pyeval},
      -#endif
      - {"range", 1, 3, f_range},
      - {"readfile", 1, 3, f_readfile},
      - {"reltime", 0, 2, f_reltime},
      - {"reltimestr", 1, 1, f_reltimestr},
      - {"remote_expr", 2, 3, f_remote_expr},
      - {"remote_foreground", 1, 1, f_remote_foreground},
      - {"remote_peek", 1, 2, f_remote_peek},
      - {"remote_read", 1, 1, f_remote_read},
      - {"remote_send", 2, 3, f_remote_send},
      - {"remove", 2, 3, f_remove},
      - {"rename", 2, 2, f_rename},
      - {"repeat", 2, 2, f_repeat},
      - {"resolve", 1, 1, f_resolve},
      - {"reverse", 1, 1, f_reverse},
      -#ifdef FEAT_FLOAT
      - {"round", 1, 1, f_round},
      -#endif
      - {"screenattr", 2, 2, f_screenattr},
      - {"screenchar", 2, 2, f_screenchar},
      - {"screencol", 0, 0, f_screencol},
      - {"screenrow", 0, 0, f_screenrow},
      - {"search", 1, 4, f_search},
      - {"searchdecl", 1, 3, f_searchdecl},
      - {"searchpair", 3, 7, f_searchpair},
      - {"searchpairpos", 3, 7, f_searchpairpos},
      - {"searchpos", 1, 4, f_searchpos},
      - {"server2client", 2, 2, f_server2client},
      - {"serverlist", 0, 0, f_serverlist},
      - {"setbufvar", 3, 3, f_setbufvar},
      - {"setcmdpos", 1, 1, f_setcmdpos},
      - {"setline", 2, 2, f_setline},
      - {"setloclist", 2, 3, f_setloclist},
      - {"setmatches", 1, 1, f_setmatches},
      - {"setpos", 2, 2, f_setpos},
      - {"setqflist", 1, 2, f_setqflist},
      - {"setreg", 2, 3, f_setreg},
      - {"settabvar", 3, 3, f_settabvar},
      - {"settabwinvar", 4, 4, f_settabwinvar},
      - {"setwinvar", 3, 3, f_setwinvar},
      + {"pyeval", 1, 1, f_pyeval, NULL},
      +#endif
      + {"range", 1, 3, f_range, NULL},
      + {"readfile", 1, 3, f_readfile, NULL},
      + {"reltime", 0, 2, f_reltime, NULL},
      + {"reltimestr", 1, 1, f_reltimestr, NULL},
      + {"remote_expr", 2, 3, f_remote_expr, NULL},
      + {"remote_foreground", 1, 1, f_remote_foreground, NULL},
      + {"remote_peek", 1, 2, f_remote_peek, NULL},
      + {"remote_read", 1, 1, f_remote_read, NULL},
      + {"remote_send", 2, 3, f_remote_send, NULL},
      + {"remove", 2, 3, f_remove, NULL},
      + {"rename", 2, 2, f_rename, NULL},
      + {"repeat", 2, 2, f_repeat, NULL},
      + {"resolve", 1, 1, f_resolve, NULL},
      + {"reverse", 1, 1, f_reverse, NULL},
      +#ifdef FEAT_FLOAT
      + {"round", 1, 1, f_round, NULL},
      +#endif
      + {"screenattr", 2, 2, f_screenattr, NULL},
      + {"screenchar", 2, 2, f_screenchar, NULL},
      + {"screencol", 0, 0, f_screencol, NULL},
      + {"screenrow", 0, 0, f_screenrow, NULL},
      + {"search", 1, 4, f_search, NULL},
      + {"searchdecl", 1, 3, f_searchdecl, NULL},
      + {"searchpair", 3, 7, f_searchpair, NULL},
      + {"searchpairpos", 3, 7, f_searchpairpos, NULL},
      + {"searchpos", 1, 4, f_searchpos, NULL},
      + {"server2client", 2, 2, f_server2client, NULL},
      + {"serverlist", 0, 0, f_serverlist, NULL},
      + {"setbufvar", 3, 3, f_setbufvar, NULL},
      + {"setcmdpos", 1, 1, f_setcmdpos, NULL},
      + {"setline", 2, 2, f_setline, NULL},
      + {"setloclist", 2, 3, f_setloclist, NULL},
      + {"setmatches", 1, 1, f_setmatches, NULL},
      + {"setpos", 2, 2, f_setpos, NULL},
      + {"setqflist", 1, 2, f_setqflist, NULL},
      + {"setreg", 2, 3, f_setreg, NULL},
      + {"settabvar", 3, 3, f_settabvar, NULL},
      + {"settabwinvar", 4, 4, f_settabwinvar, NULL},
      + {"setwinvar", 3, 3, f_setwinvar, NULL},
      #ifdef FEAT_CRYPT
      - {"sha256", 1, 1, f_sha256},
      -#endif
      - {"shellescape", 1, 2, f_shellescape},
      - {"shiftwidth", 0, 0, f_shiftwidth},
      - {"simplify", 1, 1, f_simplify},
      -#ifdef FEAT_FLOAT
      - {"sin", 1, 1, f_sin},
      - {"sinh", 1, 1, f_sinh},
      -#endif
      - {"sort", 1, 3, f_sort},
      - {"soundfold", 1, 1, f_soundfold},
      - {"spellbadword", 0, 1, f_spellbadword},
      - {"spellsuggest", 1, 3, f_spellsuggest},
      - {"split", 1, 3, f_split},
      -#ifdef FEAT_FLOAT
      - {"sqrt", 1, 1, f_sqrt},
      - {"str2float", 1, 1, f_str2float},
      -#endif
      - {"str2nr", 1, 2, f_str2nr},
      - {"strchars", 1, 1, f_strchars},
      - {"strdisplaywidth", 1, 2, f_strdisplaywidth},
      + {"sha256", 1, 1, f_sha256, NULL},
      +#endif
      + {"shellescape", 1, 2, f_shellescape, NULL},
      + {"shiftwidth", 0, 0, f_shiftwidth, NULL},
      + {"simplify", 1, 1, f_simplify, NULL},
      +#ifdef FEAT_FLOAT
      + {"sin", 1, 1, f_sin, NULL},
      + {"sinh", 1, 1, f_sinh, NULL},
      +#endif
      + {"sort", 1, 3, f_sort, NULL},
      + {"soundfold", 1, 1, f_soundfold, NULL},
      + {"spellbadword", 0, 1, f_spellbadword, NULL},
      + {"spellsuggest", 1, 3, f_spellsuggest, NULL},
      + {"split", 1, 3, f_split, NULL},
      +#ifdef FEAT_FLOAT
      + {"sqrt", 1, 1, f_sqrt, NULL},
      + {"str2float", 1, 1, f_str2float, NULL},
      +#endif
      + {"str2nr", 1, 2, f_str2nr, NULL},
      + {"strchars", 1, 1, f_strchars, NULL},
      + {"strdisplaywidth", 1, 2, f_strdisplaywidth, NULL},
      #ifdef HAVE_STRFTIME
      - {"strftime", 1, 2, f_strftime},
      -#endif
      - {"stridx", 2, 3, f_stridx},
      - {"string", 1, 1, f_string},
      - {"strlen", 1, 1, f_strlen},
      - {"strpart", 2, 3, f_strpart},
      - {"strridx", 2, 3, f_strridx},
      - {"strtrans", 1, 1, f_strtrans},
      - {"strwidth", 1, 1, f_strwidth},
      - {"submatch", 1, 1, f_submatch},
      - {"substitute", 4, 4, f_substitute},
      - {"synID", 3, 3, f_synID},
      - {"synIDattr", 2, 3, f_synIDattr},
      - {"synIDtrans", 1, 1, f_synIDtrans},
      - {"synconcealed", 2, 2, f_synconcealed},
      - {"synstack", 2, 2, f_synstack},
      - {"system", 1, 2, f_system},
      - {"tabpagebuflist", 0, 1, f_tabpagebuflist},
      - {"tabpagenr", 0, 1, f_tabpagenr},
      - {"tabpagewinnr", 1, 2, f_tabpagewinnr},
      - {"tagfiles", 0, 0, f_tagfiles},
      - {"taglist", 1, 1, f_taglist},
      -#ifdef FEAT_FLOAT
      - {"tan", 1, 1, f_tan},
      - {"tanh", 1, 1, f_tanh},
      -#endif
      - {"tempname", 0, 0, f_tempname},
      - {"test", 1, 1, f_test},
      - {"tolower", 1, 1, f_tolower},
      - {"toupper", 1, 1, f_toupper},
      - {"tr", 3, 3, f_tr},
      -#ifdef FEAT_FLOAT
      - {"trunc", 1, 1, f_trunc},
      -#endif
      - {"type", 1, 1, f_type},
      - {"undofile", 1, 1, f_undofile},
      - {"undotree", 0, 0, f_undotree},
      - {"values", 1, 1, f_values},
      - {"virtcol", 1, 1, f_virtcol},
      - {"visualmode", 0, 1, f_visualmode},
      - {"wildmenumode", 0, 0, f_wildmenumode},
      - {"winbufnr", 1, 1, f_winbufnr},
      - {"wincol", 0, 0, f_wincol},
      - {"winheight", 1, 1, f_winheight},
      - {"winline", 0, 0, f_winline},
      - {"winnr", 0, 1, f_winnr},
      - {"winrestcmd", 0, 0, f_winrestcmd},
      - {"winrestview", 1, 1, f_winrestview},
      - {"winsaveview", 0, 0, f_winsaveview},
      - {"winwidth", 1, 1, f_winwidth},
      - {"writefile", 2, 3, f_writefile},
      - {"xor", 2, 2, f_xor},
      + {"strftime", 1, 2, f_strftime, NULL},
      +#endif
      + {"stridx", 2, 3, f_stridx, NULL},
      + {"string", 1, 1, f_string, NULL},
      + {"strlen", 1, 1, f_strlen, NULL},
      + {"strpart", 2, 3, f_strpart, NULL},
      + {"strridx", 2, 3, f_strridx, NULL},
      + {"strtrans", 1, 1, f_strtrans, NULL},
      + {"strwidth", 1, 1, f_strwidth, NULL},
      + {"submatch", 1, 1, f_submatch, NULL},
      + {"substitute", 4, 4, f_substitute, NULL},
      + {"synID", 3, 3, f_synID, NULL},
      + {"synIDattr", 2, 3, f_synIDattr, NULL},
      + {"synIDtrans", 1, 1, f_synIDtrans, NULL},
      + {"synconcealed", 2, 2, f_synconcealed, NULL},
      + {"synstack", 2, 2, f_synstack, NULL},
      + {"system", 1, 2, f_system, NULL},
      + {"tabpagebuflist", 0, 1, f_tabpagebuflist, NULL},
      + {"tabpagenr", 0, 1, f_tabpagenr, NULL},
      + {"tabpagewinnr", 1, 2, f_tabpagewinnr, NULL},
      + {"tagfiles", 0, 0, f_tagfiles, NULL},
      + {"taglist", 1, 1, f_taglist, NULL},
      +#ifdef FEAT_FLOAT
      + {"tan", 1, 1, f_tan, NULL},
      + {"tanh", 1, 1, f_tanh, NULL},
      +#endif
      + {"tempname", 0, 0, f_tempname, NULL},
      + {"test", 1, 1, f_test, NULL},
      + {"tolower", 1, 1, f_tolower, NULL},
      + {"toupper", 1, 1, f_toupper, NULL},
      + {"tr", 3, 3, f_tr, NULL},
      +#ifdef FEAT_FLOAT
      + {"trunc", 1, 1, f_trunc, NULL},
      +#endif
      + {"type", 1, 1, f_type, NULL},
      + {"undofile", 1, 1, f_undofile, NULL},
      + {"undotree", 0, 0, f_undotree, NULL},
      + {"values", 1, 1, f_values, NULL},
      + {"virtcol", 1, 1, f_virtcol, NULL},
      + {"visualmode", 0, 1, f_visualmode, NULL},
      + {"wildmenumode", 0, 0, f_wildmenumode, NULL},
      + {"winbufnr", 1, 1, f_winbufnr, NULL},
      + {"wincol", 0, 0, f_wincol, NULL},
      + {"winheight", 1, 1, f_winheight, NULL},
      + {"winline", 0, 0, f_winline, NULL},
      + {"winnr", 0, 1, f_winnr, NULL},
      + {"winrestcmd", 0, 0, f_winrestcmd, NULL},
      + {"winrestview", 1, 1, f_winrestview, NULL},
      + {"winsaveview", 0, 0, f_winsaveview, NULL},
      + {"winwidth", 1, 1, f_winwidth, NULL},
      + {"writefile", 2, 3, f_writefile, NULL},
      + {"xor", 2, 2, f_xor, NULL},
      };

      #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
      @@ -8237,9 +8321,9 @@

      /*
      * Find internal function in table above.
      - * Return index, or -1 if not found
      - */
      - static int
      + * Return pointer, or NULL if not found
      + */
      + static struct fst *
      find_internal_func(name)
      char_u *name; /* name of the function */
      {
      @@ -8260,39 +8344,170 @@
      else if (cmp > 0)
      first = x + 1;
      else
      - return x;
      - }
      - return -1;
      + return &functions[x];
      + }
      + return NULL;
      }

      /*
      * Check if "name" is a variable of type VAR_FUNC. If so, return the function
      - * name it contains, otherwise return "name".
      - */
      - static char_u *
      -deref_func_name(name, lenp)
      + * definition it contains, otherwise try to find internal or user-defined
      + * function with the given name. Returns NULL on failure.
      + *
      + * Flags:
      + * DF_CHECK_VAR : Try loading function from a variable.
      + * DF_RUN_EVENT : Run FuncUndefined event if function was not found
      + * DF_CREATE_AUTOLOAD: Create references to autoload function
      + * DF_NO_VAR : DF_RUN_EVENT and DF_CREATE_AUTOLOAD
      + * DF_ALL : All of the above
      + */
      + func_T *
      +deref_func_name(name, len, flags)
      char_u *name;
      - int *lenp;
      + const int len;
      + int flags;
      {
      dictitem_T *v;
      int cc;
      -
      - cc = name[*lenp];
      - name[*lenp] = NUL;
      - v = find_var(name, NULL);
      - name[*lenp] = cc;
      - if (v != NULL && v->di_tv.v_type == VAR_FUNC)
      - {
      - if (v->di_tv.vval.v_string == NULL)
      - {
      - *lenp = 0;
      - return (char_u *)""; /* just in case */
      - }
      - *lenp = (int)STRLEN(v->di_tv.vval.v_string);
      - return v->di_tv.vval.v_string;
      - }
      -
      - return name;
      + func_T *r = NULL;
      +
      + cc = name[len];
      + if (flags & DF_CHECK_VAR)
      + {
      + name[len] = NUL;
      + v = find_var(name, NULL);
      + name[len] = cc;
      +
      + if (v != NULL && v->di_tv.v_type == VAR_FUNC)
      + {
      + if (v->di_tv.vval.v_func == NULL)
      + return NULL;
      + ++v->di_tv.vval.v_func->fv_refcount;
      + return v->di_tv.vval.v_func;
      + }
      + }
      +
      + name[len] = NUL;
      + if (builtin_function(name))
      + {
      + struct fst *intfp;
      + intfp = find_internal_func(name);
      +
      + if (intfp != NULL)
      + {
      + if (intfp->f_func == NULL)
      + {
      + intfp->f_func = func_alloc();
      + if (intfp->f_func != NULL)
      + {
      + ++intfp->f_func->fv_refcount;
      + intfp->f_func->fv_data = intfp;
      + intfp->f_func->fv_type = &internal_func_type;
      + }
      + }
      +
      + r = intfp->f_func;
      + }
      + }
      + else
      + {
      + char_u *fname = NULL;
      + char_u *pp;
      + char_u sid_buf[20];
      + int lead;
      + int old_len;
      + int new_len = len;
      + ufunc_T *fp;
      +
      + lead = eval_fname_script(name);
      + new_len -= lead;
      + old_len = new_len;
      + pp = name + lead;
      +
      + if (lead)
      + {
      + lead = 3;
      + if (eval_fname_sid(name))
      + {
      + if (current_SID <= 0)
      + {
      + EMSG(_(e_usingsid));
      + new_len = 0;
      + }
      + else
      + {
      + sprintf((char *) sid_buf, "%ld_", (long) current_SID);
      + lead += STRLEN(sid_buf);
      + }
      + }
      + else
      + *sid_buf = NUL;
      +
      + if (new_len)
      + fname = (char_u *) alloc(new_len + lead + 1);
      + }
      + else
      + {
      + *sid_buf = NUL;
      + fname = name;
      + }
      +
      + if (fname != NULL)
      + {
      + if (lead)
      + {
      + fname[0] = K_SPECIAL;
      + fname[1] = KS_EXTRA;
      + fname[2] = (int) KE_SNR;
      +
      + if (*sid_buf != NUL)
      + mch_memmove(fname + 3, sid_buf, lead - 3);
      +
      + mch_memmove(fname + lead, pp, (size_t) old_len + 1);
      + }
      + fp = find_func(fname);
      +
      +#ifdef FEAT_AUTOCMD
      + /* Trigger FuncUndefined event, may load the function. */
      + if (flags & DF_RUN_EVENT
      + && fp == NULL
      + && apply_autocmds(EVENT_FUNCUNDEFINED,
      + fname, fname, TRUE, NULL)
      + && !aborting())
      + /* executed an autocommand, search for the function again */
      + fp = find_func(name);
      +#endif
      +
      + if (fp == NULL)
      + {
      + if (flags & DF_CREATE_AUTOLOAD
      + && vim_strchr(fname, AUTOLOAD_CHAR) != NULL
      + && valid_autoload_name(fname))
      + {
      + aufunc_T *aufp;
      +
      + if ((aufp = aufunc_alloc()) != NULL &&
      + (r = func_alloc()) != NULL)
      + {
      + aufp->auf_name = vim_strsave(fname);
      + r->fv_data = (void *) aufp;
      + r->fv_type = &autoload_func_type;
      + }
      + }
      + }
      + else
      + r = fp->uf_func;
      +
      + if (lead)
      + vim_free(fname);
      + }
      + }
      + name[len] = cc;
      +
      + if (r != NULL)
      + ++r->fv_refcount;
      +
      + return r;
      }

      /*
      @@ -8300,10 +8515,9 @@
      * Return OK or FAIL.
      */
      static int
      -get_func_tv(name, len, rettv, arg, firstline, lastline, doesrange,
      +get_func_tv(func, rettv, arg, firstline, lastline, doesrange,
      evaluate, selfdict)
      - char_u *name; /* name of the function */
      - int len; /* length of "name" */
      + func_T *func; /* function definition */
      typval_T *rettv;
      char_u **arg; /* argument, pointing to the '(' */
      linenr_T firstline; /* first line of range */
      @@ -8340,15 +8554,20 @@
      else
      ret = FAIL;

      - if (ret == OK)
      - ret = call_func(name, len, rettv, argcount, argvars,
      - firstline, lastline, doesrange, evaluate, selfdict);
      - else if (!aborting())
      - {
      - if (argcount == MAX_FUNC_ARGS)
      - emsg_funcname(N_("E740: Too many arguments for function %s"), name);
      - else
      - emsg_funcname(N_("E116: Invalid arguments for function %s"), name);
      + if (evaluate)
      + {
      + if (ret == OK)
      + ret = call_func(func, rettv, argcount, argvars,
      + firstline, lastline, doesrange, selfdict);
      + else if (!aborting())
      + {
      + if (argcount == MAX_FUNC_ARGS)
      + emsg_funcname(N_("E740: Too many arguments for function %s"),
      + FUNC_NAME(func));
      + else
      + emsg_funcname(N_("E116: Invalid arguments for function %s"),
      + FUNC_NAME(func));
      + }
      }

      while (--argcount >= 0)
      @@ -8358,17 +8577,86 @@
      return ret;
      }

      -
      -/*
      - * Call a function with its resolved parameters
      - * Return FAIL when the function can't be called, OK otherwise.
      - * Also returns OK when an error was encountered while executing the function.
      - */
      - static int
      -call_func(funcname, len, rettv, argcount, argvars, firstline, lastline,
      - doesrange, evaluate, selfdict)
      - char_u *funcname; /* name of the function */
      - int len; /* length of "name" */
      + static int
      +call_internal_func(intfp, rettv, argcount, argvars, firstline, lastline, doesrange, selfdict)
      + struct fst *intfp; /* pointer to function */
      + typval_T *rettv; /* return value */
      + int argcount; /* nr of args */
      + typval_T *argvars; /* arguments */
      + linenr_T firstline; /* first line of range */
      + linenr_T lastline; /* last line of range */
      + int *doesrange; /* is set to True if function handles range */
      + dict_T *selfdict; /* Dictionary for "self" */
      +{
      + if (argcount < intfp->f_min_argc)
      + return ERROR_TOOFEW;
      + else if (argcount > intfp->f_max_argc)
      + return ERROR_TOOMANY;
      +
      + argvars[argcount].v_type = VAR_UNKNOWN;
      + intfp->f_call(argvars, rettv);
      +
      + return ERROR_NONE;
      +}
      +
      + static char_u *
      +repr_internal_func(intfp)
      + struct fst *intfp;
      +{
      + return string_quote((char_u *) intfp->f_name, "function");
      +}
      +
      + static void
      +dealloc_internal_func(intfp)
      + struct fst *intfp;
      +{
      + intfp->f_func = NULL;
      + return;
      +}
      +
      + static int
      +compare_internal_funcs(intfp1, intfp2)
      + struct fst *intfp1;
      + struct fst *intfp2;
      +{
      + return intfp1 == intfp2;
      +}
      +
      + static char_u *
      +name_internal_func(intfp)
      + struct fst *intfp;
      +{
      + return (char_u *) intfp->f_name;
      +}
      +
      +static char_u *internal_func_type_name = "internal";
      +#define INTERNAL_FUNC_TYPE_LEN 8
      +
      + static char_u *
      +type_internal_func(intfp)
      + struct fst *intfp UNUSED;
      +{
      + return vim_strnsave(internal_func_type_name, INTERNAL_FUNC_TYPE_LEN);
      +}
      +
      +static funcdef_T internal_func_type = {
      + (function_caller) call_internal_func, /* fd_call */
      + (function_representer) repr_internal_func, /* fd_repr */
      + (function_destructor) dealloc_internal_func, /* fd_dealloc */
      + (function_cmp) compare_internal_funcs, /* fd_compare */
      + (function_representer) name_internal_func, /* fd_name */
      + (function_representer) type_internal_func, /* fd_type */
      +};
      +
      + static aufunc_T *
      +aufunc_alloc()
      +{
      + return (aufunc_T *) alloc_clear(sizeof(aufunc_T));
      +}
      +
      + static int
      +call_autoload_func(aufp, rettv, argcount, argvars, firstline, lastline, doesrange, selfdict)
      + aufunc_T *aufp;
      typval_T *rettv; /* return value goes here */
      int argcount; /* number of "argvars" */
      typval_T *argvars; /* vars for arguments, must have "argcount"
      @@ -8376,212 +8664,177 @@
      linenr_T firstline; /* first line of range */
      linenr_T lastline; /* last line of range */
      int *doesrange; /* return: function handled range */
      - int evaluate;
      dict_T *selfdict; /* Dictionary for "self" */
      {
      - int ret = FAIL;
      -#define ERROR_UNKNOWN 0
      -#define ERROR_TOOMANY 1
      -#define ERROR_TOOFEW 2
      -#define ERROR_SCRIPT 3
      -#define ERROR_DICT 4
      -#define ERROR_NONE 5
      -#define ERROR_OTHER 6
      - int error = ERROR_NONE;
      - int i;
      - int llen;
      - ufunc_T *fp;
      -#define FLEN_FIXED 40
      - char_u fname_buf[FLEN_FIXED + 1];
      - char_u *fname;
      - char_u *name;
      -
      - /* Make a copy of the name, if it comes from a funcref variable it could
      - * be changed or deleted in the called function. */
      - name = vim_strnsave(funcname, len);
      - if (name == NULL)
      - return ret;
      -
      - /*
      - * In a script change <SID>name() and s:name() to K_SNR 123_name().
      - * Change <SNR>123_name() to K_SNR 123_name().
      - * Use fname_buf[] when it fits, otherwise allocate memory (slow).
      - */
      - llen = eval_fname_script(name);
      - if (llen > 0)
      - {
      - fname_buf[0] = K_SPECIAL;
      - fname_buf[1] = KS_EXTRA;
      - fname_buf[2] = (int)KE_SNR;
      - i = 3;
      - if (eval_fname_sid(name)) /* "<SID>" or "s:" */
      - {
      - if (current_SID <= 0)
      - error = ERROR_SCRIPT;
      - else
      - {
      - sprintf((char *)fname_buf + 3, "%ld_", (long)current_SID);
      - i = (int)STRLEN(fname_buf);
      - }
      - }
      - if (i + STRLEN(name + llen) < FLEN_FIXED)
      - {
      - STRCPY(fname_buf + i, name + llen);
      - fname = fname_buf;
      - }
      - else
      - {
      - fname = alloc((unsigned)(i + STRLEN(name + llen) + 1));
      - if (fname == NULL)
      - error = ERROR_OTHER;
      - else
      - {
      - mch_memmove(fname, fname_buf, (size_t)i);
      - STRCPY(fname + i, name + llen);
      - }
      - }
      - }
      - else
      - fname = name;
      + /* First, check whether function was already loaded. */
      + if (aufp->auf_func == NULL && !aborting())
      + aufp->auf_func = deref_func_name(aufp->auf_name,
      + STRLEN(aufp->auf_name),
      + DF_CHECK_VAR|DF_RUN_EVENT);
      +
      + /* If not then try loading a package. */
      + if (aufp->auf_func == NULL && script_autoload(aufp->auf_name, TRUE) &&
      + !aborting())
      + /* loaded a package, search for the function again */
      + /* Note: it is allowed for loaded function to be defined in a variable
      + */
      + aufp->auf_func = deref_func_name(aufp->auf_name,
      + STRLEN(aufp->auf_name),
      + DF_CHECK_VAR);
      +
      + if (aufp->auf_func == NULL)
      + {
      + EMSG2(_(e_unknown_function), aufp->auf_name);
      + return ERROR_OTHER;
      + }
      +
      + return FUNC_CALL(aufp->auf_func, rettv, argcount, argvars,
      + firstline, lastline, doesrange, selfdict);
      +}
      +
      + static char_u *
      +repr_autoload_func(aufp)
      + aufunc_T *aufp;
      +{
      + return string_quote(aufp->auf_name, "function");
      +}
      +
      + static void
      +dealloc_autoload_func(aufp)
      + aufunc_T *aufp;
      +{
      + if (aufp->auf_func != NULL)
      + func_unref(aufp->auf_func);
      + vim_free(aufp->auf_name);
      + vim_free(aufp);
      +}
      +
      + static int
      +compare_autoload_funcs(aufp1, aufp2)
      + aufunc_T *aufp1;
      + aufunc_T *aufp2;
      +{
      + return STRCMP(aufp1->auf_name, aufp2->auf_name) == 0;
      +}
      +
      + static char_u *
      +name_autoload_func(aufp)
      + aufunc_T *aufp;
      +{
      + return aufp->auf_name;
      +}
      +
      +static char_u *autoload_func_type_name = "autoload";
      +#define AUTOLOAD_FUNC_TYPE_LEN 8
      +
      + static char_u *
      +type_autoload_func(aufp)
      + aufunc_T *aufp;
      +{
      + if (aufp->auf_func == NULL)
      + return vim_strnsave(autoload_func_type_name, AUTOLOAD_FUNC_TYPE_LEN);
      + else
      + {
      + char_u *loaded_type;
      + int loaded_type_len;
      + char_u *ret_type;
      +
      + if ((loaded_type = FUNC_TYPE(aufp->auf_func)) == NULL)
      + return NULL;
      +
      + loaded_type_len = STRLEN(loaded_type);
      +
      + /* 2: colon and NUL */
      + ret_type = (char_u*)alloc(loaded_type_len + 2 + AUTOLOAD_FUNC_TYPE_LEN);
      +
      + if (ret_type == NULL)
      + return NULL;
      +
      + mch_memmove(ret_type, autoload_func_type_name,
      + (size_t) AUTOLOAD_FUNC_TYPE_LEN);
      + ret_type[AUTOLOAD_FUNC_TYPE_LEN] = ':';
      + mch_memmove(ret_type + AUTOLOAD_FUNC_TYPE_LEN + 1, loaded_type,
      + loaded_type_len);
      + ret_type[AUTOLOAD_FUNC_TYPE_LEN + loaded_type_len + 1] = NUL;
      +
      + vim_free(loaded_type);
      + return ret_type;
      + }
      +}
      +
      +static funcdef_T autoload_func_type = {
      + (function_caller) call_autoload_func, /* fd_call */
      + (function_representer) repr_autoload_func, /* fd_repr */
      + (function_destructor) dealloc_autoload_func, /* fd_dealloc */
      + (function_cmp) compare_autoload_funcs, /* fd_compare */
      + (function_representer) name_autoload_func, /* fd_name */
      + (function_representer) type_autoload_func, /* fd_type */
      +};
      +
      +/*
      + * Call a function with its resolved parameters
      + * Return FAIL when the function can't be called, OK otherwise.
      + * Also returns OK when an error was encountered while executing the function.
      + */
      + static int
      +call_func(func, rettv, argcount, argvars, firstline, lastline, doesrange, selfdict)
      + func_T *func; /* function definition */
      + typval_T *rettv; /* return value goes here */
      + int argcount; /* number of "argvars" */
      + typval_T *argvars; /* vars for arguments, must have "argcount"
      + PLUS ONE elements! */
      + linenr_T firstline; /* first line of range */
      + linenr_T lastline; /* last line of range */
      + int *doesrange; /* return: function handled range */
      + dict_T *selfdict; /* Dictionary for "self" */
      +{
      + int error;

      *doesrange = FALSE;

      -
      - /* execute the function if no errors detected and executing */
      - if (evaluate && error == ERROR_NONE)
      - {
      - rettv->v_type = VAR_NUMBER; /* default rettv is number zero */
      - rettv->vval.v_number = 0;
      - error = ERROR_UNKNOWN;
      -
      - if (!builtin_function(fname))
      - {
      - /*
      - * User defined function.
      - */
      - fp = find_func(fname);
      -
      -#ifdef FEAT_AUTOCMD
      - /* Trigger FuncUndefined event, may load the function. */
      - if (fp == NULL
      - && apply_autocmds(EVENT_FUNCUNDEFINED,
      - fname, fname, TRUE, NULL)
      - && !aborting())
      - {
      - /* executed an autocommand, search for the function again */
      - fp = find_func(fname);
      - }
      -#endif
      - /* Try loading a package. */
      - if (fp == NULL && script_autoload(fname, TRUE) && !aborting())
      - {
      - /* loaded a package, search for the function again */
      - fp = find_func(fname);
      - }
      -
      - if (fp != NULL)
      - {
      - if (fp->uf_flags & FC_RANGE)
      - *doesrange = TRUE;
      - if (argcount < fp->uf_args.ga_len)
      - error = ERROR_TOOFEW;
      - else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len)
      - error = ERROR_TOOMANY;
      - else if ((fp->uf_flags & FC_DICT) && selfdict == NULL)
      - error = ERROR_DICT;
      - else
      - {
      - /*
      - * Call the user function.
      - * Save and restore search patterns, script variables and
      - * redo buffer.
      - */
      - save_search_patterns();
      - saveRedobuff();
      - ++fp->uf_calls;
      - call_user_func(fp, argcount, argvars, rettv,
      - firstline, lastline,
      - (fp->uf_flags & FC_DICT) ? selfdict : NULL);
      - if (--fp->uf_calls <= 0 && isdigit(*fp->uf_name)
      - && fp->uf_refcount <= 0)
      - /* Function was unreferenced while being used, free it
      - * now. */
      - func_free(fp);
      - restoreRedobuff();
      - restore_search_patterns();
      - error = ERROR_NONE;
      - }
      - }
      - }
      - else
      - {
      - /*
      - * Find the function name in the table, call its implementation.
      - */
      - i = find_internal_func(fname);
      - if (i >= 0)
      - {
      - if (argcount < functions[i].f_min_argc)
      - error = ERROR_TOOFEW;
      - else if (argcount > functions[i].f_max_argc)
      - error = ERROR_TOOMANY;
      - else
      - {
      - argvars[argcount].v_type = VAR_UNKNOWN;
      - functions[i].f_func(argvars, rettv);
      - error = ERROR_NONE;
      - }
      - }
      - }
      - /*
      - * The function call (or "FuncUndefined" autocommand sequence) might
      - * have been aborted by an error, an interrupt, or an explicitly thrown
      - * exception that has not been caught so far. This situation can be
      - * tested for by calling aborting(). For an error in an internal
      - * function or for the "E132" error in call_user_func(), however, the
      - * throw point at which the "force_abort" flag (temporarily reset by
      - * emsg()) is normally updated has not been reached yet. We need to
      - * update that flag first to make aborting() reliable.
      - */
      - update_force_abort();
      - }
      - if (error == ERROR_NONE)
      - ret = OK;
      -
      - /*
      - * Report an error unless the argument evaluation or function call has been
      - * cancelled due to an aborting error, an interrupt, or an exception.
      - */
      + if (func == NULL)
      + return FAIL;
      +
      + rettv->v_type = VAR_NUMBER; /* default rettv is number zero */
      + rettv->vval.v_number = 0;
      + error = func->fv_type->fd_call(func->fv_data, rettv, argcount, argvars,
      + firstline, lastline, doesrange, selfdict);
      +
      + /*
      + * The function call (or "FuncUndefined" autocommand sequence) might
      + * have been aborted by an error, an interrupt, or an explicitly thrown
      + * exception that has not been caught so far. This situation can be
      + * tested for by calling aborting(). For an error in an internal
      + * function or for the "E132" error in call_user_func(), however, the
      + * throw point at which the "force_abort" flag (temporarily reset by
      + * emsg()) is normally updated has not been reached yet. We need to
      + * update that flag first to make aborting() reliable.
      + */
      + update_force_abort();
      +
      if (!aborting())
      {
      switch (error)
      {
      - case ERROR_UNKNOWN:
      - emsg_funcname(N_("E117: Unknown function: %s"), name);
      - break;
      case ERROR_TOOMANY:
      - emsg_funcname(e_toomanyarg, name);
      + emsg_funcname(e_toomanyarg, FUNC_NAME(func));
      break;
      case ERROR_TOOFEW:
      emsg_funcname(N_("E119: Not enough arguments for function: %s"),
      - name);
      + FUNC_NAME(func));
      break;
      case ERROR_SCRIPT:
      emsg_funcname(N_("E120: Using <SID> not in a script context: %s"),
      - name);
      + FUNC_NAME(func));
      break;
      case ERROR_DICT:
      emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"),
      - name);
      - break;
      - }
      - }
      -
      - if (fname != name && fname != fname_buf)
      - vim_free(fname);
      - vim_free(name);
      -
      - return ret;
      + FUNC_NAME(func));
      + break;
      + }
      + }
      +
      + return error == ERROR_NONE ? OK : FAIL;
      }

      /*
      @@ -9213,8 +9466,8 @@
      }

      int
      -func_call(name, args, selfdict, rettv)
      - char_u *name;
      +func_call(func, args, selfdict, rettv)
      + func_T *func;
      typval_T *args;
      dict_T *selfdict;
      typval_T *rettv;
      @@ -9240,9 +9493,9 @@
      }

      if (item == NULL)
      - r = call_func(name, (int)STRLEN(name), rettv, argc, argv,
      + r = call_func(func, rettv, argc, argv,
      curwin->w_cursor.lnum, curwin->w_cursor.lnum,
      - &dummy, TRUE, selfdict);
      + &dummy, selfdict);

      /* Free the arguments. */
      while (argc > 0)
      @@ -9259,7 +9512,7 @@
      typval_T *argvars;
      typval_T *rettv;
      {
      - char_u *func;
      + func_T *func;
      dict_T *selfdict = NULL;

      if (argvars[1].v_type != VAR_LIST)
      @@ -9271,11 +9524,18 @@
      return;

      if (argvars[0].v_type == VAR_FUNC)
      - func = argvars[0].vval.v_string;
      - else
      - func = get_tv_string(&argvars[0]);
      - if (*func == NUL)
      - return; /* type error or empty name */
      + {
      + func = argvars[0].vval.v_func;
      + ++func->fv_refcount;
      + }
      + else
      + {
      + char_u *name;
      + name = get_tv_string(&argvars[0]);
      + if (name == NUL)
      + return; /* type error or empty name */
      + func = deref_func_name(name, STRLEN(name), DF_NO_VAR);
      + }

      if (argvars[2].v_type != VAR_UNKNOWN)
      {
      @@ -9288,6 +9548,8 @@
      }

      (void)func_call(func, &argvars[1], selfdict, rettv);
      +
      + func_unref(func);
      }

      #ifdef FEAT_FLOAT
      @@ -10978,37 +11240,38 @@
      typval_T *rettv;
      {
      char_u *s;
      + func_T *func;

      s = get_tv_string(&argvars[0]);
      - if (s == NULL || *s == NUL || VIM_ISDIGIT(*s))
      - EMSG2(_(e_invarg2), s);
      - /* Don't check an autoload name for existence here. */
      - else if (vim_strchr(s, AUTOLOAD_CHAR) == NULL && !function_exists(s))
      - EMSG2(_("E700: Unknown function: %s"), s);
      - else
      - {
      - if (STRNCMP(s, "s:", 2) == 0 || STRNCMP(s, "<SID>", 5) == 0)
      - {
      - char sid_buf[25];
      - int off = *s == 's' ? 2 : 5;
      -
      - /* Expand s: and <SID> into <SNR>nr_, so that the function can
      - * also be called from another script. Using trans_function_name()
      - * would also work, but some plugins depend on the name being
      - * printable text. */
      - sprintf(sid_buf, "<SNR>%ld_", (long)current_SID);
      - rettv->vval.v_string =
      - alloc((int)(STRLEN(sid_buf) + STRLEN(s + off) + 1));
      - if (rettv->vval.v_string != NULL)
      - {
      - STRCPY(rettv->vval.v_string, sid_buf);
      - STRCAT(rettv->vval.v_string, s + off);
      - }
      - }
      - else
      - rettv->vval.v_string = vim_strsave(s);
      +
      + func = deref_func_name(s, STRLEN(s), DF_CREATE_AUTOLOAD);
      +<br/><br/>(Message over 64 KB, truncated)
    • ZyX
      Some updates: fixed mzscheme and merged with upstream. diff -r c7bcb04f613e -r a5a312aafd97 Filelist ... +++ b/Filelist Sun Dec 15 16:21:59 2013 +0400 @@ -84,6
      Message 2 of 22 , Dec 15, 2013
      • 0 Attachment
        Some updates: fixed mzscheme and merged with upstream.

        diff -r c7bcb04f613e -r a5a312aafd97 Filelist
        --- a/Filelist Sat Dec 14 13:06:17 2013 +0100
        +++ b/Filelist Sun Dec 15 16:21:59 2013 +0400
        @@ -84,6 +84,8 @@
        src/testdir/test49.vim \
        src/testdir/test60.vim \
        src/testdir/test83-tags? \
        + src/testdir/Test104.vim \
        + src/testdir/test104/autoload/*.vim \
        src/testdir/python2/*.py \
        src/testdir/python3/*.py \
        src/testdir/pythonx/*.py \
        diff -r c7bcb04f613e -r a5a312aafd97 runtime/doc/eval.txt
        --- a/runtime/doc/eval.txt Sat Dec 14 13:06:17 2013 +0100
        +++ b/runtime/doc/eval.txt Sun Dec 15 16:21:59 2013 +0400
        @@ -1780,7 +1780,8 @@
        foldtext( ) String line displayed for closed fold
        foldtextresult( {lnum}) String text for closed fold at {lnum}
        foreground( ) Number bring the Vim window to the foreground
        -function( {name}) Funcref reference to function {name}
        +function( {name}) Funcref reference to function {name}
        +functype( {func}) String type of function reference {func}
        garbagecollect( [{atexit}]) none free memory, breaking cyclic references
        get( {list}, {idx} [, {def}]) any get item {idx} from {list} or {def}
        get( {dict}, {key} [, {def}]) any get item {key} from {dict} or {def}
        @@ -3128,6 +3129,31 @@
        {name} can be a user defined function or an internal function.


        +functype({func}) *functype()*
        + Given a |Funcref| return string describing its type. Possible
        + values:
        + Value Description ~
        + internal Reference to one of the built-in |functions|.
        + Example: `function('tr')`.
        + user Reference to one of the |user-functions|.
        + Example: `function('NetrwStatusLine')`.
        + autoload Reference to one of the |autoload-functions|
        + that was not yet loaded.
        + Example: `function('zip#Browse')`.
        + autoload:{type} Same as above, but for functions that were
        + already loaded. For `function('zip#Browse')`
        + it will return "autoload:user". {type} may be
        + anything that |functype()| can return
        + (including e.g. "autoload:autoload:internal").
        + python:{type} Reference to some python function. {type} is
        + the python type name.
        + Example: `pyeval('id')` has function type
        + "python:builtin_function_or_method".
        + python3:{type} Same as above, but for python 3 functions.
        + Example: `py3eval('id')` has function type
        + "python3:builtin_function_or_method".
        +
        +
        garbagecollect([{atexit}]) *garbagecollect()*
        Cleanup unused |Lists| and |Dictionaries| that have circular
        references. There is hardly ever a need to invoke this
        diff -r c7bcb04f613e -r a5a312aafd97 runtime/doc/if_pyth.txt
        --- a/runtime/doc/if_pyth.txt Sat Dec 14 13:06:17 2013 +0100
        +++ b/runtime/doc/if_pyth.txt Sun Dec 15 16:21:59 2013 +0400
        @@ -656,7 +656,11 @@
        Function-like object, acting like vim |Funcref| object. Supports `.name`
        attribute and is callable. Accepts special keyword argument `self`, see
        |Dictionary-function|. You can also use `vim.Function(name)` constructor,
        - it is the same as `vim.bindeval('function(%s)'%json.dumps(name))`.
        + it is the same as `vim.bindeval('function(%s)'%json.dumps(name))`. Object
        + supports the following attributes:
        + Attribute Description ~
        + name Function name.
        + repr Same as running `vim.bindeval("string(pyeval('func'))")`.

        Examples: >
        f = vim.Function('tr') # Constructor
        diff -r c7bcb04f613e -r a5a312aafd97 runtime/doc/repeat.txt
        --- a/runtime/doc/repeat.txt Sat Dec 14 13:06:17 2013 +0100
        +++ b/runtime/doc/repeat.txt Sun Dec 15 16:21:59 2013 +0400
        @@ -668,12 +668,6 @@
        - The time of the lines added up is mostly less than the time of the whole
        function. There is some overhead in between.

        -- Functions that are deleted before Vim exits will not produce profiling
        - information. You can check the |v:profiling| variable if needed: >
        - :if !v:profiling
        - : delfunc MyFunc
        - :endif
        -<
        - Profiling may give weird results on multi-processor systems, when sleep
        mode kicks in or the processor frequency is reduced to save power.

        diff -r c7bcb04f613e -r a5a312aafd97 src/eval.c
        --- a/src/eval.c Sat Dec 14 13:06:17 2013 +0100
        +++ b/src/eval.c Sun Dec 15 16:21:59 2013 +0400
        @@ -115,6 +115,7 @@
        #ifdef FEAT_FLOAT
        static char *e_float_as_string = N_("E806: using Float as a String");
        #endif
        +static char *e_unknown_function = N_("E700: Unknown function: %s");

        static dictitem_T globvars_var; /* variable used for g: */
        #define globvarht globvardict.dv_hashtab
        @@ -153,10 +154,16 @@

        static int echo_attr = 0; /* attributes used for ":echo" */

        -/* Values for trans_function_name() argument: */
        +/* Values for trans_function_name() flags argument: */
        #define TFN_INT 1 /* internal function name OK */
        #define TFN_QUIET 2 /* no error messages */

        +/* Values for get_called_function() flags argument: */
        +#define GCF_AUTOLOAD 1 /* it is OK to create autoload functions */
        +#define GCF_RUN_EVENT 2 /* run FuncUndefined event */
        +#define GCF_QUIET 4 /* no error messages */
        +#define GCF_ANY_FUNC GCF_AUTOLOAD|GCF_RUN_EVENT
        +
        /*
        * Structure to hold info for a user function.
        */
        @@ -166,7 +173,6 @@
        {
        int uf_varargs; /* variable nr of arguments */
        int uf_flags;
        - int uf_calls; /* nr of active calls */
        garray_T uf_args; /* arguments */
        garray_T uf_lines; /* function lines */
        #ifdef FEAT_PROFILE
        @@ -185,19 +191,35 @@
        proftime_T uf_tml_wait; /* start wait time for current line */
        int uf_tml_idx; /* index of line being timed; -1 if none */
        int uf_tml_execed; /* line being timed was executed */
        + ufunc_T *uf_prof_next; /* next profiled function */
        #endif
        scid_T uf_script_ID; /* ID of script where function was defined,
        used for s: variables */
        - int uf_refcount; /* for numbered function: reference count */
        + func_T *uf_func; /* Reference to a func_T structure holding
        + reference to ufunc_T */
        char_u uf_name[1]; /* name of function (actually longer); can
        start with <SNR>123_ (<SNR> is K_SPECIAL
        KS_EXTRA KE_SNR) */
        };

        +/*
        + * Structure to hold info for autoloaded function.
        + */
        +typedef struct aufunc aufunc_T;
        +
        +struct aufunc
        +{
        + char_u *auf_name; /* Function name */
        + func_T *auf_func; /* If function was already autoloaded:
        + record pointer here, otherwise it will hold
        + NULL */
        +};
        +
        /* function flags */
        #define FC_ABORT 1 /* abort function on error */
        #define FC_RANGE 2 /* function accepts range */
        -#define FC_DICT 4 /* Dict function, uses "self" */
        +#define FC_DICT 4 /* Dict function, uses "self" */
        +#define FC_ANON 8 /* Anonymous, not stored in func_hashtab */

        /*
        * All user-defined functions are found in this hashtable.
        @@ -211,6 +233,12 @@
        static dict_T *first_dict = NULL; /* list of all dicts */
        static list_T *first_list = NULL; /* list of all lists */

        +#ifdef FEAT_PROFILE
        +/* Functions being profiled */
        +static ufunc_T *fp_profiled_first = NULL;
        +static ufunc_T *fp_profiled_last = NULL;
        +#endif
        +
        /* From user function to hashitem and back. */
        static ufunc_T dumuf;
        #define UF2HIKEY(fp) ((fp)->uf_name)
        @@ -269,9 +297,13 @@
        */
        typedef struct
        {
        - dict_T *fd_dict; /* Dictionary used */
        + dict_T *fd_dict; /* Dictionary used. Contains borrowed reference.
        + */
        char_u *fd_newkey; /* new key in "dict" in allocated memory */
        dictitem_T *fd_di; /* Dictionary item used */
        + func_T *fd_func; /* Function object, if it was obtained.
        + * Contains borrowed reference, no need to
        + * decref. */
        } funcdict_T;


        @@ -439,17 +471,16 @@
        static int get_dict_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
        static char_u *echo_string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf, int copyID));
        static char_u *tv2string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf, int copyID));
        -static char_u *string_quote __ARGS((char_u *str, int function));
        #ifdef FEAT_FLOAT
        static int string2float __ARGS((char_u *text, float_T *value));
        #endif
        static int get_env_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
        -static int find_internal_func __ARGS((char_u *name));
        -static char_u *deref_func_name __ARGS((char_u *name, int *lenp));
        -static int get_func_tv __ARGS((char_u *name, int len, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));
        -static int call_func __ARGS((char_u *funcname, int len, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));
        +static struct fst *find_internal_func __ARGS((char_u *name));
        +static int get_func_tv __ARGS((func_T *name, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));
        +static int call_func __ARGS((func_T *func, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, dict_T *selfdict));
        static void emsg_funcname __ARGS((char *ermsg, char_u *name));
        static int non_zero_arg __ARGS((typval_T *argvars));
        +static aufunc_T *aufunc_alloc __ARGS((void));

        #ifdef FEAT_FLOAT
        static void f_abs __ARGS((typval_T *argvars, typval_T *rettv));
        @@ -537,6 +568,7 @@
        static void f_foldtextresult __ARGS((typval_T *argvars, typval_T *rettv));
        static void f_foreground __ARGS((typval_T *argvars, typval_T *rettv));
        static void f_function __ARGS((typval_T *argvars, typval_T *rettv));
        +static void f_functype __ARGS((typval_T *argvars, typval_T *rettv));
        static void f_garbagecollect __ARGS((typval_T *argvars, typval_T *rettv));
        static void f_get __ARGS((typval_T *argvars, typval_T *rettv));
        static void f_getbufline __ARGS((typval_T *argvars, typval_T *rettv));
        @@ -793,10 +825,12 @@
        static int var_check_fixed __ARGS((int flags, char_u *name));
        static int var_check_func_name __ARGS((char_u *name, int new_var));
        static int valid_varname __ARGS((char_u *varname));
        +static int valid_autoload_name __ARGS((char_u *varname));
        static int tv_check_lock __ARGS((int lock, char_u *name));
        static int item_copy __ARGS((typval_T *from, typval_T *to, int deep, int copyID));
        static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags));
        static char_u *trans_function_name __ARGS((char_u **pp, int skip, int flags, funcdict_T *fd));
        +static func_T *get_called_function __ARGS((char_u **pp, int skip, funcdict_T *fd, int flags));
        static int eval_fname_script __ARGS((char_u *p));
        static int eval_fname_sid __ARGS((char_u *p));
        static void list_func_head __ARGS((ufunc_T *fp, int indent));
        @@ -805,6 +839,7 @@
        static int builtin_function __ARGS((char_u *name));
        #ifdef FEAT_PROFILE
        static void func_do_profile __ARGS((ufunc_T *fp));
        +static void func_clear_profile __ARGS((ufunc_T *fp));
        static void prof_sort_list __ARGS((FILE *fd, ufunc_T **sorttab, int st_len, char *title, int prefer_self));
        static void prof_func_line __ARGS((FILE *fd, int count, proftime_T *total, proftime_T *self, int prefer_self));
        static int
        @@ -821,8 +856,9 @@
        static int script_autoload __ARGS((char_u *name, int reload));
        static char_u *autoload_name __ARGS((char_u *name));
        static void cat_func_name __ARGS((char_u *buf, ufunc_T *fp));
        -static void func_free __ARGS((ufunc_T *fp));
        -static void call_user_func __ARGS((ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, linenr_T firstline, linenr_T lastline, dict_T *selfdict));
        +static void dealloc_user_func __ARGS((ufunc_T *fp));
        +static int call_user_func __ARGS((ufunc_T *fp, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, dict_T *selfdict));
        +static void remove_user_func __ARGS((ufunc_T *fp));
        static int can_free_funccal __ARGS((funccall_T *fc, int copyID)) ;
        static void free_funccal __ARGS((funccall_T *fc, int free_val));
        static void add_nr_var __ARGS((dict_T *dp, dictitem_T *v, char *name, varnumber_T nr));
        @@ -838,6 +874,11 @@
        static void sortFunctions __ARGS(());
        #endif

        +
        +static funcdef_T user_func_type;
        +static funcdef_T internal_func_type;
        +static funcdef_T autoload_func_type;
        +
        /*
        * Initialize the global and v: variables.
        */
        @@ -1563,10 +1604,10 @@
        * Returns OK or FAIL.
        */
        int
        -call_vim_function(func, argc, argv, safe, str_arg_only, rettv)
        - char_u *func;
        +call_vim_function(name, argc, argv, safe, str_arg_only, rettv)
        + char_u *name;
        int argc;
        - char_u **argv;
        + char_u **argv;
        int safe; /* use the sandbox */
        int str_arg_only; /* all arguments are strings */
        typval_T *rettv;
        @@ -1578,11 +1619,19 @@
        int doesrange;
        void *save_funccalp = NULL;
        int ret;
        + func_T *func;

        argvars = (typval_T *)alloc((unsigned)((argc + 1) * sizeof(typval_T)));
        if (argvars == NULL)
        return FAIL;

        + func = deref_func_name(name, STRLEN(name), DF_ALL);
        + if (func == NULL)
        + {
        + vim_free(argvars);
        + return FAIL;
        + }
        +
        for (i = 0; i < argc; i++)
        {
        /* Pass a NULL or empty argument as an empty string */
        @@ -1617,9 +1666,9 @@
        }

        rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */
        - ret = call_func(func, (int)STRLEN(func), rettv, argc, argvars,
        + ret = call_func(func, rettv, argc, argvars,
        curwin->w_cursor.lnum, curwin->w_cursor.lnum,
        - &doesrange, TRUE, NULL);
        + &doesrange, NULL);
        if (safe)
        {
        --sandbox;
        @@ -1630,6 +1679,8 @@
        if (ret == FAIL)
        clear_tv(rettv);

        + func_unref(func);
        +
        return ret;
        }

        @@ -3387,8 +3438,7 @@
        {
        char_u *arg = eap->arg;
        char_u *startarg;
        - char_u *name;
        - char_u *tofree;
        + func_T *func;
        int len;
        typval_T rettv;
        linenr_T lnum;
        @@ -3408,14 +3458,14 @@
        return;
        }

        - tofree = trans_function_name(&arg, eap->skip, TFN_INT, &fudi);
        + func = get_called_function(&arg, eap->skip, &fudi, GCF_ANY_FUNC);
        if (fudi.fd_newkey != NULL)
        {
        /* Still need to give an error message for missing key. */
        EMSG2(_(e_dictkey), fudi.fd_newkey);
        vim_free(fudi.fd_newkey);
        }
        - if (tofree == NULL)
        + if (func == NULL)
        return;

        /* Increase refcount on dictionary, it could get deleted when evaluating
        @@ -3423,10 +3473,6 @@
        if (fudi.fd_dict != NULL)
        ++fudi.fd_dict->dv_refcount;

        - /* If it is the name of a variable of type VAR_FUNC use its contents. */
        - len = (int)STRLEN(tofree);
        - name = deref_func_name(tofree, &len);
        -
        /* Skip white space to allow ":call func ()". Not good, but required for
        * backward compatibility. */
        startarg = skipwhite(arg);
        @@ -3462,7 +3508,7 @@
        #endif
        }
        arg = startarg;
        - if (get_func_tv(name, (int)STRLEN(name), &rettv, &arg,
        + if (get_func_tv(func, &rettv, &arg,
        eap->line1, eap->line2, &doesrange,
        !eap->skip, fudi.fd_dict) == FAIL)
        {
        @@ -3504,8 +3550,8 @@
        }

        end:
        + func_unref(func);
        dict_unref(fudi.fd_dict);
        - vim_free(tofree);
        }

        /*
        @@ -4476,12 +4522,17 @@
        else
        {
        /* Compare two Funcrefs for being equal or unequal. */
        - if (rettv->vval.v_string == NULL
        - || var2.vval.v_string == NULL)
        + if (rettv->vval.v_func == NULL
        + || var2.vval.v_func == NULL)
        + n1 = FALSE;
        + else if (rettv->vval.v_func->fv_type !=
        + var2.vval.v_func->fv_type)
        n1 = FALSE;
        else
        - n1 = STRCMP(rettv->vval.v_string,
        - var2.vval.v_string) == 0;
        + n1 = rettv->vval.v_func->fv_type->fd_compare(
        + rettv->vval.v_func->fv_data,
        + var2.vval.v_func->fv_data
        + );
        if (type == TYPE_NEQUAL)
        n1 = !n1;
        }
        @@ -5150,21 +5201,39 @@
        {
        if (**arg == '(') /* recursive! */
        {
        + func_T *func;
        /* If "s" is the name of a variable of type VAR_FUNC
        * use its contents. */
        - s = deref_func_name(s, &len);
        -
        - /* Invoke the function. */
        - ret = get_func_tv(s, len, rettv, arg,
        - curwin->w_cursor.lnum, curwin->w_cursor.lnum,
        - &len, evaluate, NULL);
        + if (evaluate)
        + func = deref_func_name(s, len, DF_ALL);
        + else
        + func = NULL;
        +
        + if (evaluate && func == NULL)
        + {
        + char_u cc;
        + ret = FAIL;
        + cc = s[len];
        + s[len] = '\0';
        + emsg_funcname(N_("E117: Unknown function: %s"), s);
        + s[len] = cc;
        + }
        + else
        + {
        + /* Invoke the function. */
        + ret = get_func_tv(func, rettv, arg,
        + curwin->w_cursor.lnum, curwin->w_cursor.lnum,
        + &len, evaluate, NULL);
        +
        + func_unref(func);
        + }

        /* If evaluate is FALSE rettv->v_type was not set in
        * get_func_tv, but it's needed in handle_subscript() to parse
        * what follows. So set it here. */
        if (rettv->v_type == VAR_UNKNOWN && !evaluate && **arg == '(')
        {
        - rettv->vval.v_string = vim_strsave((char_u *)"");
        + rettv->vval.v_func = NULL;
        rettv->v_type = VAR_FUNC;
        }

        @@ -6125,9 +6194,13 @@
        return r;

        case VAR_FUNC:
        - return (tv1->vval.v_string != NULL
        - && tv2->vval.v_string != NULL
        - && STRCMP(tv1->vval.v_string, tv2->vval.v_string) == 0);
        + return (tv1->vval.v_func != NULL
        + && tv2->vval.v_func != NULL
        + && tv1->vval.v_func->fv_type == tv2->vval.v_func->fv_type
        + && tv1->vval.v_func->fv_type->fd_compare(
        + tv1->vval.v_func->fv_data,
        + tv2->vval.v_func->fv_data
        + ));

        case VAR_NUMBER:
        return tv1->vval.v_number == tv2->vval.v_number;
        @@ -7419,7 +7492,7 @@
        else
        ga_concat(&ga, (char_u *)", ");

        - tofree = string_quote(hi->hi_key, FALSE);
        + tofree = string_quote(hi->hi_key, NULL);
        if (tofree != NULL)
        {
        ga_concat(&ga, tofree);
        @@ -7598,8 +7671,8 @@
        switch (tv->v_type)
        {
        case VAR_FUNC:
        - *tofree = NULL;
        - r = tv->vval.v_string;
        + r = FUNC_REPR(tv->vval.v_func);
        + *tofree = r;
        break;

        case VAR_LIST:
        @@ -7680,10 +7753,10 @@
        switch (tv->v_type)
        {
        case VAR_FUNC:
        - *tofree = string_quote(tv->vval.v_string, TRUE);
        + *tofree = FUNC_REPR(tv->vval.v_func);
        return *tofree;
        case VAR_STRING:
        - *tofree = string_quote(tv->vval.v_string, FALSE);
        + *tofree = string_quote(tv->vval.v_string, NULL);
        return *tofree;
        #ifdef FEAT_FLOAT
        case VAR_FLOAT:
        @@ -7704,17 +7777,25 @@
        /*
        * Return string "str" in ' quotes, doubling ' characters.
        * If "str" is NULL an empty string is assumed.
        - * If "function" is TRUE make it function('string').
        - */
        - static char_u *
        -string_quote(str, function)
        + * If "fname" is not NULL make it fname('string').
        + */
        + char_u *
        +string_quote(str, fname)
        char_u *str;
        - int function;
        + char *fname;
        {
        unsigned len;
        + unsigned flen = 0;
        char_u *p, *r, *s;
        -
        - len = (function ? 13 : 3);
        + char_u *fname_u = (char_u *) fname;
        +
        + if (fname_u != NULL)
        + flen = STRLEN(fname_u);
        +
        + /* +---+- 2 quotes and NUL *
        + * | | +- parenthesis *
        + * | | | */
        + len = (fname_u == NULL ? 3 : 3 + 2 + flen);
        if (str != NULL)
        {
        len += (unsigned)STRLEN(str);
        @@ -7725,13 +7806,13 @@
        s = r = alloc(len);
        if (r != NULL)
        {
        - if (function)
        - {
        - STRCPY(r, "function('");
        - r += 10;
        - }
        - else
        - *r++ = '\'';
        + if (fname_u)
        + {
        + mch_memmove(r, fname_u, flen);
        + r += flen;
        + *r++ = '(';
        + }
        + *r++ = '\'';
        if (str != NULL)
        for (p = str; *p != NUL; )
        {
        @@ -7740,7 +7821,7 @@
        MB_COPY_CHAR(p, r);
        }
        *r++ = '\'';
        - if (function)
        + if (fname_u)
        *r++ = ')';
        *r++ = NUL;
        }
        @@ -7833,322 +7914,325 @@
        char *f_name; /* function name */
        char f_min_argc; /* minimal number of arguments */
        char f_max_argc; /* maximal number of arguments */
        - void (*f_func) __ARGS((typval_T *args, typval_T *rvar));
        + void (*f_call) __ARGS((typval_T *args, typval_T *rvar));
        /* implementation of function */
        + func_T *f_func; /* reference to a func_T structure holding
        + reference to struct fst */
        } functions[] =
        {
        #ifdef FEAT_FLOAT
        - {"abs", 1, 1, f_abs},
        - {"acos", 1, 1, f_acos}, /* WJMc */
        -#endif
        - {"add", 2, 2, f_add},
        - {"and", 2, 2, f_and},
        - {"append", 2, 2, f_append},
        - {"argc", 0, 0, f_argc},
        - {"argidx", 0, 0, f_argidx},
        - {"argv", 0, 1, f_argv},
        -#ifdef FEAT_FLOAT
        - {"asin", 1, 1, f_asin}, /* WJMc */
        - {"atan", 1, 1, f_atan},
        - {"atan2", 2, 2, f_atan2},
        -#endif
        - {"browse", 4, 4, f_browse},
        - {"browsedir", 2, 2, f_browsedir},
        - {"bufexists", 1, 1, f_bufexists},
        - {"buffer_exists", 1, 1, f_bufexists}, /* obsolete */
        - {"buffer_name", 1, 1, f_bufname}, /* obsolete */
        - {"buffer_number", 1, 1, f_bufnr}, /* obsolete */
        - {"buflisted", 1, 1, f_buflisted},
        - {"bufloaded", 1, 1, f_bufloaded},
        - {"bufname", 1, 1, f_bufname},
        - {"bufnr", 1, 2, f_bufnr},
        - {"bufwinnr", 1, 1, f_bufwinnr},
        - {"byte2line", 1, 1, f_byte2line},
        - {"byteidx", 2, 2, f_byteidx},
        - {"byteidxcomp", 2, 2, f_byteidxcomp},
        - {"call", 2, 3, f_call},
        -#ifdef FEAT_FLOAT
        - {"ceil", 1, 1, f_ceil},
        -#endif
        - {"changenr", 0, 0, f_changenr},
        - {"char2nr", 1, 2, f_char2nr},
        - {"cindent", 1, 1, f_cindent},
        - {"clearmatches", 0, 0, f_clearmatches},
        - {"col", 1, 1, f_col},
        + {"abs", 1, 1, f_abs, NULL},
        + {"acos", 1, 1, f_acos, NULL}, /* WJMc */
        +#endif
        + {"add", 2, 2, f_add, NULL},
        + {"and", 2, 2, f_and, NULL},
        + {"append", 2, 2, f_append, NULL},
        + {"argc", 0, 0, f_argc, NULL},
        + {"argidx", 0, 0, f_argidx, NULL},
        + {"argv", 0, 1, f_argv, NULL},
        +#ifdef FEAT_FLOAT
        + {"asin", 1, 1, f_asin, NULL}, /* WJMc */
        + {"atan", 1, 1, f_atan, NULL},
        + {"atan2", 2, 2, f_atan2, NULL},
        +#endif
        + {"browse", 4, 4, f_browse, NULL},
        + {"browsedir", 2, 2, f_browsedir, NULL},
        + {"bufexists", 1, 1, f_bufexists, NULL},
        + {"buffer_exists", 1, 1, f_bufexists, NULL}, /* obsolete */
        + {"buffer_name", 1, 1, f_bufname, NULL}, /* obsolete */
        + {"buffer_number", 1, 1, f_bufnr, NULL}, /* obsolete */
        + {"buflisted", 1, 1, f_buflisted, NULL},
        + {"bufloaded", 1, 1, f_bufloaded, NULL},
        + {"bufname", 1, 1, f_bufname, NULL},
        + {"bufnr", 1, 2, f_bufnr, NULL},
        + {"bufwinnr", 1, 1, f_bufwinnr, NULL},
        + {"byte2line", 1, 1, f_byte2line, NULL},
        + {"byteidx", 2, 2, f_byteidx, NULL},
        + {"byteidxcomp", 2, 2, f_byteidxcomp, NULL},
        + {"call", 2, 3, f_call, NULL},
        +#ifdef FEAT_FLOAT
        + {"ceil", 1, 1, f_ceil, NULL},
        +#endif
        + {"changenr", 0, 0, f_changenr, NULL},
        + {"char2nr", 1, 2, f_char2nr, NULL},
        + {"cindent", 1, 1, f_cindent, NULL},
        + {"clearmatches", 0, 0, f_clearmatches, NULL},
        + {"col", 1, 1, f_col, NULL},
        #if defined(FEAT_INS_EXPAND)
        - {"complete", 2, 2, f_complete},
        - {"complete_add", 1, 1, f_complete_add},
        - {"complete_check", 0, 0, f_complete_check},
        -#endif
        - {"confirm", 1, 4, f_confirm},
        - {"copy", 1, 1, f_copy},
        -#ifdef FEAT_FLOAT
        - {"cos", 1, 1, f_cos},
        - {"cosh", 1, 1, f_cosh},
        -#endif
        - {"count", 2, 4, f_count},
        - {"cscope_connection",0,3, f_cscope_connection},
        - {"cursor", 1, 3, f_cursor},
        - {"deepcopy", 1, 2, f_deepcopy},
        - {"delete", 1, 1, f_delete},
        - {"did_filetype", 0, 0, f_did_filetype},
        - {"diff_filler", 1, 1, f_diff_filler},
        - {"diff_hlID", 2, 2, f_diff_hlID},
        - {"empty", 1, 1, f_empty},
        - {"escape", 2, 2, f_escape},
        - {"eval", 1, 1, f_eval},
        - {"eventhandler", 0, 0, f_eventhandler},
        - {"executable", 1, 1, f_executable},
        - {"exists", 1, 1, f_exists},
        -#ifdef FEAT_FLOAT
        - {"exp", 1, 1, f_exp},
        -#endif
        - {"expand", 1, 3, f_expand},
        - {"extend", 2, 3, f_extend},
        - {"feedkeys", 1, 2, f_feedkeys},
        - {"file_readable", 1, 1, f_filereadable}, /* obsolete */
        - {"filereadable", 1, 1, f_filereadable},
        - {"filewritable", 1, 1, f_filewritable},
        - {"filter", 2, 2, f_filter},
        - {"finddir", 1, 3, f_finddir},
        - {"findfile", 1, 3, f_findfile},
        -#ifdef FEAT_FLOAT
        - {"float2nr", 1, 1, f_float2nr},
        - {"floor", 1, 1, f_floor},
        - {"fmod", 2, 2, f_fmod},
        -#endif
        - {"fnameescape", 1, 1, f_fnameescape},
        - {"fnamemodify", 2, 2, f_fnamemodify},
        - {"foldclosed", 1, 1, f_foldclosed},
        - {"foldclosedend", 1, 1, f_foldclosedend},
        - {"foldlevel", 1, 1, f_foldlevel},
        - {"foldtext", 0, 0, f_foldtext},
        - {"foldtextresult", 1, 1, f_foldtextresult},
        - {"foreground", 0, 0, f_foreground},
        - {"function", 1, 1, f_function},
        - {"garbagecollect", 0, 1, f_garbagecollect},
        - {"get", 2, 3, f_get},
        - {"getbufline", 2, 3, f_getbufline},
        - {"getbufvar", 2, 3, f_getbufvar},
        - {"getchar", 0, 1, f_getchar},
        - {"getcharmod", 0, 0, f_getcharmod},
        - {"getcmdline", 0, 0, f_getcmdline},
        - {"getcmdpos", 0, 0, f_getcmdpos},
        - {"getcmdtype", 0, 0, f_getcmdtype},
        - {"getcwd", 0, 0, f_getcwd},
        - {"getfontname", 0, 1, f_getfontname},
        - {"getfperm", 1, 1, f_getfperm},
        - {"getfsize", 1, 1, f_getfsize},
        - {"getftime", 1, 1, f_getftime},
        - {"getftype", 1, 1, f_getftype},
        - {"getline", 1, 2, f_getline},
        - {"getloclist", 1, 1, f_getqflist},
        - {"getmatches", 0, 0, f_getmatches},
        - {"getpid", 0, 0, f_getpid},
        - {"getpos", 1, 1, f_getpos},
        - {"getqflist", 0, 0, f_getqflist},
        - {"getreg", 0, 2, f_getreg},
        - {"getregtype", 0, 1, f_getregtype},
        - {"gettabvar", 2, 3, f_gettabvar},
        - {"gettabwinvar", 3, 4, f_gettabwinvar},
        - {"getwinposx", 0, 0, f_getwinposx},
        - {"getwinposy", 0, 0, f_getwinposy},
        - {"getwinvar", 2, 3, f_getwinvar},
        - {"glob", 1, 3, f_glob},
        - {"globpath", 2, 3, f_globpath},
        - {"has", 1, 1, f_has},
        - {"has_key", 2, 2, f_has_key},
        - {"haslocaldir", 0, 0, f_haslocaldir},
        - {"hasmapto", 1, 3, f_hasmapto},
        - {"highlightID", 1, 1, f_hlID}, /* obsolete */
        - {"highlight_exists",1, 1, f_hlexists}, /* obsolete */
        - {"histadd", 2, 2, f_histadd},
        - {"histdel", 1, 2, f_histdel},
        - {"histget", 1, 2, f_histget},
        - {"histnr", 1, 1, f_histnr},
        - {"hlID", 1, 1, f_hlID},
        - {"hlexists", 1, 1, f_hlexists},
        - {"hostname", 0, 0, f_hostname},
        - {"iconv", 3, 3, f_iconv},
        - {"indent", 1, 1, f_indent},
        - {"index", 2, 4, f_index},
        - {"input", 1, 3, f_input},
        - {"inputdialog", 1, 3, f_inputdialog},
        - {"inputlist", 1, 1, f_inputlist},
        - {"inputrestore", 0, 0, f_inputrestore},
        - {"inputsave", 0, 0, f_inputsave},
        - {"inputsecret", 1, 2, f_inputsecret},
        - {"insert", 2, 3, f_insert},
        - {"invert", 1, 1, f_invert},
        - {"isdirectory", 1, 1, f_isdirectory},
        - {"islocked", 1, 1, f_islocked},
        - {"items", 1, 1, f_items},
        - {"join", 1, 2, f_join},
        - {"keys", 1, 1, f_keys},
        - {"last_buffer_nr", 0, 0, f_last_buffer_nr},/* obsolete */
        - {"len", 1, 1, f_len},
        - {"libcall", 3, 3, f_libcall},
        - {"libcallnr", 3, 3, f_libcallnr},
        - {"line", 1, 1, f_line},
        - {"line2byte", 1, 1, f_line2byte},
        - {"lispindent", 1, 1, f_lispindent},
        - {"localtime", 0, 0, f_localtime},
        -#ifdef FEAT_FLOAT
        - {"log", 1, 1, f_log},
        - {"log10", 1, 1, f_log10},
        + {"complete", 2, 2, f_complete, NULL},
        + {"complete_add", 1, 1, f_complete_add, NULL},
        + {"complete_check", 0, 0, f_complete_check, NULL},
        +#endif
        + {"confirm", 1, 4, f_confirm, NULL},
        + {"copy", 1, 1, f_copy, NULL},
        +#ifdef FEAT_FLOAT
        + {"cos", 1, 1, f_cos, NULL},
        + {"cosh", 1, 1, f_cosh, NULL},
        +#endif
        + {"count", 2, 4, f_count, NULL},
        + {"cscope_connection",0,3, f_cscope_connection, NULL},
        + {"cursor", 1, 3, f_cursor, NULL},
        + {"deepcopy", 1, 2, f_deepcopy, NULL},
        + {"delete", 1, 1, f_delete, NULL},
        + {"did_filetype", 0, 0, f_did_filetype, NULL},
        + {"diff_filler", 1, 1, f_diff_filler, NULL},
        + {"diff_hlID", 2, 2, f_diff_hlID, NULL},
        + {"empty", 1, 1, f_empty, NULL},
        + {"escape", 2, 2, f_escape, NULL},
        + {"eval", 1, 1, f_eval, NULL},
        + {"eventhandler", 0, 0, f_eventhandler, NULL},
        + {"executable", 1, 1, f_executable, NULL},
        + {"exists", 1, 1, f_exists, NULL},
        +#ifdef FEAT_FLOAT
        + {"exp", 1, 1, f_exp, NULL},
        +#endif
        + {"expand", 1, 3, f_expand, NULL},
        + {"extend", 2, 3, f_extend, NULL},
        + {"feedkeys", 1, 2, f_feedkeys, NULL},
        + {"file_readable", 1, 1, f_filereadable, NULL}, /* obsolete */
        + {"filereadable", 1, 1, f_filereadable, NULL},
        + {"filewritable", 1, 1, f_filewritable, NULL},
        + {"filter", 2, 2, f_filter, NULL},
        + {"finddir", 1, 3, f_finddir, NULL},
        + {"findfile", 1, 3, f_findfile, NULL},
        +#ifdef FEAT_FLOAT
        + {"float2nr", 1, 1, f_float2nr, NULL},
        + {"floor", 1, 1, f_floor, NULL},
        + {"fmod", 2, 2, f_fmod, NULL},
        +#endif
        + {"fnameescape", 1, 1, f_fnameescape, NULL},
        + {"fnamemodify", 2, 2, f_fnamemodify, NULL},
        + {"foldclosed", 1, 1, f_foldclosed, NULL},
        + {"foldclosedend", 1, 1, f_foldclosedend, NULL},
        + {"foldlevel", 1, 1, f_foldlevel, NULL},
        + {"foldtext", 0, 0, f_foldtext, NULL},
        + {"foldtextresult", 1, 1, f_foldtextresult, NULL},
        + {"foreground", 0, 0, f_foreground, NULL},
        + {"function", 1, 1, f_function, NULL},
        + {"functype", 1, 1, f_functype, NULL},
        + {"garbagecollect", 0, 1, f_garbagecollect, NULL},
        + {"get", 2, 3, f_get, NULL},
        + {"getbufline", 2, 3, f_getbufline, NULL},
        + {"getbufvar", 2, 3, f_getbufvar, NULL},
        + {"getchar", 0, 1, f_getchar, NULL},
        + {"getcharmod", 0, 0, f_getcharmod, NULL},
        + {"getcmdline", 0, 0, f_getcmdline, NULL},
        + {"getcmdpos", 0, 0, f_getcmdpos, NULL},
        + {"getcmdtype", 0, 0, f_getcmdtype, NULL},
        + {"getcwd", 0, 0, f_getcwd, NULL},
        + {"getfontname", 0, 1, f_getfontname, NULL},
        + {"getfperm", 1, 1, f_getfperm, NULL},
        + {"getfsize", 1, 1, f_getfsize, NULL},
        + {"getftime", 1, 1, f_getftime, NULL},
        + {"getftype", 1, 1, f_getftype, NULL},
        + {"getline", 1, 2, f_getline, NULL},
        + {"getloclist", 1, 1, f_getqflist, NULL},
        + {"getmatches", 0, 0, f_getmatches, NULL},
        + {"getpid", 0, 0, f_getpid, NULL},
        + {"getpos", 1, 1, f_getpos, NULL},
        + {"getqflist", 0, 0, f_getqflist, NULL},
        + {"getreg", 0, 2, f_getreg, NULL},
        + {"getregtype", 0, 1, f_getregtype, NULL},
        + {"gettabvar", 2, 3, f_gettabvar, NULL},
        + {"gettabwinvar", 3, 4, f_gettabwinvar, NULL},
        + {"getwinposx", 0, 0, f_getwinposx, NULL},
        + {"getwinposy", 0, 0, f_getwinposy, NULL},
        + {"getwinvar", 2, 3, f_getwinvar, NULL},
        + {"glob", 1, 3, f_glob, NULL},
        + {"globpath", 2, 3, f_globpath, NULL},
        + {"has", 1, 1, f_has, NULL},
        + {"has_key", 2, 2, f_has_key, NULL},
        + {"haslocaldir", 0, 0, f_haslocaldir, NULL},
        + {"hasmapto", 1, 3, f_hasmapto, NULL},
        + {"highlightID", 1, 1, f_hlID, NULL}, /* obsolete */
        + {"highlight_exists",1, 1, f_hlexists, NULL}, /* obsolete */
        + {"histadd", 2, 2, f_histadd, NULL},
        + {"histdel", 1, 2, f_histdel, NULL},
        + {"histget", 1, 2, f_histget, NULL},
        + {"histnr", 1, 1, f_histnr, NULL},
        + {"hlID", 1, 1, f_hlID, NULL},
        + {"hlexists", 1, 1, f_hlexists, NULL},
        + {"hostname", 0, 0, f_hostname, NULL},
        + {"iconv", 3, 3, f_iconv, NULL},
        + {"indent", 1, 1, f_indent, NULL},
        + {"index", 2, 4, f_index, NULL},
        + {"input", 1, 3, f_input, NULL},
        + {"inputdialog", 1, 3, f_inputdialog, NULL},
        + {"inputlist", 1, 1, f_inputlist, NULL},
        + {"inputrestore", 0, 0, f_inputrestore, NULL},
        + {"inputsave", 0, 0, f_inputsave, NULL},
        + {"inputsecret", 1, 2, f_inputsecret, NULL},
        + {"insert", 2, 3, f_insert, NULL},
        + {"invert", 1, 1, f_invert, NULL},
        + {"isdirectory", 1, 1, f_isdirectory, NULL},
        + {"islocked", 1, 1, f_islocked, NULL},
        + {"items", 1, 1, f_items, NULL},
        + {"join", 1, 2, f_join, NULL},
        + {"keys", 1, 1, f_keys, NULL},
        + {"last_buffer_nr", 0, 0, f_last_buffer_nr, NULL},/* obsolete */
        + {"len", 1, 1, f_len, NULL},
        + {"libcall", 3, 3, f_libcall, NULL},
        + {"libcallnr", 3, 3, f_libcallnr, NULL},
        + {"line", 1, 1, f_line, NULL},
        + {"line2byte", 1, 1, f_line2byte, NULL},
        + {"lispindent", 1, 1, f_lispindent, NULL},
        + {"localtime", 0, 0, f_localtime, NULL},
        +#ifdef FEAT_FLOAT
        + {"log", 1, 1, f_log, NULL},
        + {"log10", 1, 1, f_log10, NULL},
        #endif
        #ifdef FEAT_LUA
        - {"luaeval", 1, 2, f_luaeval},
        -#endif
        - {"map", 2, 2, f_map},
        - {"maparg", 1, 4, f_maparg},
        - {"mapcheck", 1, 3, f_mapcheck},
        - {"match", 2, 4, f_match},
        - {"matchadd", 2, 4, f_matchadd},
        - {"matcharg", 1, 1, f_matcharg},
        - {"matchdelete", 1, 1, f_matchdelete},
        - {"matchend", 2, 4, f_matchend},
        - {"matchlist", 2, 4, f_matchlist},
        - {"matchstr", 2, 4, f_matchstr},
        - {"max", 1, 1, f_max},
        - {"min", 1, 1, f_min},
        + {"luaeval", 1, 2, f_luaeval, NULL},
        +#endif
        + {"map", 2, 2, f_map, NULL},
        + {"maparg", 1, 4, f_maparg, NULL},
        + {"mapcheck", 1, 3, f_mapcheck, NULL},
        + {"match", 2, 4, f_match, NULL},
        + {"matchadd", 2, 4, f_matchadd, NULL},
        + {"matcharg", 1, 1, f_matcharg, NULL},
        + {"matchdelete", 1, 1, f_matchdelete, NULL},
        + {"matchend", 2, 4, f_matchend, NULL},
        + {"matchlist", 2, 4, f_matchlist, NULL},
        + {"matchstr", 2, 4, f_matchstr, NULL},
        + {"max", 1, 1, f_max, NULL},
        + {"min", 1, 1, f_min, NULL},
        #ifdef vim_mkdir
        - {"mkdir", 1, 3, f_mkdir},
        -#endif
        - {"mode", 0, 1, f_mode},
        + {"mkdir", 1, 3, f_mkdir, NULL},
        +#endif
        + {"mode", 0, 1, f_mode, NULL},
        #ifdef FEAT_MZSCHEME
        - {"mzeval", 1, 1, f_mzeval},
        -#endif
        - {"nextnonblank", 1, 1, f_nextnonblank},
        - {"nr2char", 1, 2, f_nr2char},
        - {"or", 2, 2, f_or},
        - {"pathshorten", 1, 1, f_pathshorten},
        -#ifdef FEAT_FLOAT
        - {"pow", 2, 2, f_pow},
        -#endif
        - {"prevnonblank", 1, 1, f_prevnonblank},
        - {"printf", 2, 19, f_printf},
        - {"pumvisible", 0, 0, f_pumvisible},
        + {"mzeval", 1, 1, f_mzeval, NULL},
        +#endif
        + {"nextnonblank", 1, 1, f_nextnonblank, NULL},
        + {"nr2char", 1, 2, f_nr2char, NULL},
        + {"or", 2, 2, f_or, NULL},
        + {"pathshorten", 1, 1, f_pathshorten, NULL},
        +#ifdef FEAT_FLOAT
        + {"pow", 2, 2, f_pow, NULL},
        +#endif
        + {"prevnonblank", 1, 1, f_prevnonblank, NULL},
        + {"printf", 2, 19, f_printf, NULL},
        + {"pumvisible", 0, 0, f_pumvisible, NULL},
        #ifdef FEAT_PYTHON3
        - {"py3eval", 1, 1, f_py3eval},
        + {"py3eval", 1, 1, f_py3eval, NULL},
        #endif
        #ifdef FEAT_PYTHON
        - {"pyeval", 1, 1, f_pyeval},
        -#endif
        - {"range", 1, 3, f_range},
        - {"readfile", 1, 3, f_readfile},
        - {"reltime", 0, 2, f_reltime},
        - {"reltimestr", 1, 1, f_reltimestr},
        - {"remote_expr", 2, 3, f_remote_expr},
        - {"remote_foreground", 1, 1, f_remote_foreground},
        - {"remote_peek", 1, 2, f_remote_peek},
        - {"remote_read", 1, 1, f_remote_read},
        - {"remote_send", 2, 3, f_remote_send},
        - {"remove", 2, 3, f_remove},
        - {"rename", 2, 2, f_rename},
        - {"repeat", 2, 2, f_repeat},
        - {"resolve", 1, 1, f_resolve},
        - {"reverse", 1, 1, f_reverse},
        -#ifdef FEAT_FLOAT
        - {"round", 1, 1, f_round},
        -#endif
        - {"screenattr", 2, 2, f_screenattr},
        - {"screenchar", 2, 2, f_screenchar},
        - {"screencol", 0, 0, f_screencol},
        - {"screenrow", 0, 0, f_screenrow},
        - {"search", 1, 4, f_search},
        - {"searchdecl", 1, 3, f_searchdecl},
        - {"searchpair", 3, 7, f_searchpair},
        - {"searchpairpos", 3, 7, f_searchpairpos},
        - {"searchpos", 1, 4, f_searchpos},
        - {"server2client", 2, 2, f_server2client},
        - {"serverlist", 0, 0, f_serverlist},
        - {"setbufvar", 3, 3, f_setbufvar},
        - {"setcmdpos", 1, 1, f_setcmdpos},
        - {"setline", 2, 2, f_setline},
        - {"setloclist", 2, 3, f_setloclist},
        - {"setmatches", 1, 1, f_setmatches},
        - {"setpos", 2, 2, f_setpos},
        - {"setqflist", 1, 2, f_setqflist},
        - {"setreg", 2, 3, f_setreg},
        - {"settabvar", 3, 3, f_settabvar},
        - {"settabwinvar", 4, 4, f_settabwinvar},
        - {"setwinvar", 3, 3, f_setwinvar},
        + {"pyeval", 1, 1, f_pyeval, NULL},
        +#endif
        + {"range", 1, 3, f_range, NULL},
        + {"readfile", 1, 3, f_readfile, NULL},
        + {"reltime", 0, 2, f_reltime, NULL},
        + {"reltimestr", 1, 1, f_reltimestr, NULL},
        + {"remote_expr", 2, 3, f_remote_expr, NULL},
        + {"remote_foreground", 1, 1, f_remote_foreground, NULL},
        + {"remote_peek", 1, 2, f_remote_peek, NULL},
        + {"remote_read", 1, 1, f_remote_read, NULL},
        + {"remote_send", 2, 3, f_remote_send, NULL},
        + {"remove", 2, 3, f_remove, NULL},
        + {"rename", 2, 2, f_rename, NULL},
        + {"repeat", 2, 2, f_repeat, NULL},
        + {"resolve", 1, 1, f_resolve, NULL},
        + {"reverse", 1, 1, f_reverse, NULL},
        +#ifdef FEAT_FLOAT
        + {"round", 1, 1, f_round, NULL},
        +#endif
        + {"screenattr", 2, 2, f_screenattr, NULL},
        + {"screenchar", 2, 2, f_screenchar, NULL},
        + {"screencol", 0, 0, f_screencol, NULL},
        + {"screenrow", 0, 0, f_screenrow, NULL},
        + {"search", 1, 4, f_search, NULL},
        + {"searchdecl", 1, 3, f_searchdecl, NULL},
        + {"searchpair", 3, 7, f_searchpair, NULL},
        + {"searchpairpos", 3, 7, f_searchpairpos, NULL},
        + {"searchpos", 1, 4, f_searchpos, NULL},
        + {"server2client", 2, 2, f_server2client, NULL},
        + {"serverlist", 0, 0, f_serverlist, NULL},
        + {"setbufvar", 3, 3, f_setbufvar, NULL},
        + {"setcmdpos", 1, 1, f_setcmdpos, NULL},
        + {"setline", 2, 2, f_setline, NULL},
        + {"setloclist", 2, 3, f_setloclist, NULL},
        + {"setmatches", 1, 1, f_setmatches, NULL},
        + {"setpos", 2, 2, f_setpos, NULL},
        + {"setqflist", 1, 2, f_setqflist, NULL},
        + {"setreg", 2, 3, f_setreg, NULL},
        + {"settabvar", 3, 3, f_settabvar, NULL},
        + {"settabwinvar", 4, 4, f_settabwinvar, NULL},
        + {"setwinvar", 3, 3, f_setwinvar, NULL},
        #ifdef FEAT_CRYPT
        - {"sha256", 1, 1, f_sha256},
        -#endif
        - {"shellescape", 1, 2, f_shellescape},
        - {"shiftwidth", 0, 0, f_shiftwidth},
        - {"simplify", 1, 1, f_simplify},
        -#ifdef FEAT_FLOAT
        - {"sin", 1, 1, f_sin},
        - {"sinh", 1, 1, f_sinh},
        -#endif
        - {"sort", 1, 3, f_sort},
        - {"soundfold", 1, 1, f_soundfold},
        - {"spellbadword", 0, 1, f_spellbadword},
        - {"spellsuggest", 1, 3, f_spellsuggest},
        - {"split", 1, 3, f_split},
        -#ifdef FEAT_FLOAT
        - {"sqrt", 1, 1, f_sqrt},
        - {"str2float", 1, 1, f_str2float},
        -#endif
        - {"str2nr", 1, 2, f_str2nr},
        - {"strchars", 1, 1, f_strchars},
        - {"strdisplaywidth", 1, 2, f_strdisplaywidth},
        + {"sha256", 1, 1, f_sha256, NULL},
        +#endif
        + {"shellescape", 1, 2, f_shellescape, NULL},
        + {"shiftwidth", 0, 0, f_shiftwidth, NULL},
        + {"simplify", 1, 1, f_simplify, NULL},
        +#ifdef FEAT_FLOAT
        + {"sin", 1, 1, f_sin, NULL},
        + {"sinh", 1, 1, f_sinh, NULL},
        +#endif
        + {"sort", 1, 3, f_sort, NULL},
        + {"soundfold", 1, 1, f_soundfold, NULL},
        + {"spellbadword", 0, 1, f_spellbadword, NULL},
        + {"spellsuggest", 1, 3, f_spellsuggest, NULL},
        + {"split", 1, 3, f_split, NULL},
        +#ifdef FEAT_FLOAT
        + {"sqrt", 1, 1, f_sqrt, NULL},
        + {"str2float", 1, 1, f_str2float, NULL},
        +#endif
        + {"str2nr", 1, 2, f_str2nr, NULL},
        + {"strchars", 1, 1, f_strchars, NULL},
        + {"strdisplaywidth", 1, 2, f_strdisplaywidth, NULL},
        #ifdef HAVE_STRFTIME
        - {"strftime", 1, 2, f_strftime},
        -#endif
        - {"stridx", 2, 3, f_stridx},
        - {"string", 1, 1, f_string},
        - {"strlen", 1, 1, f_strlen},
        - {"strpart", 2, 3, f_strpart},
        - {"strridx", 2, 3, f_strridx},
        - {"strtrans", 1, 1, f_strtrans},
        - {"strwidth", 1, 1, f_strwidth},
        - {"submatch", 1, 1, f_submatch},
        - {"substitute", 4, 4, f_substitute},
        - {"synID", 3, 3, f_synID},
        - {"synIDattr", 2, 3, f_synIDattr},
        - {"synIDtrans", 1, 1, f_synIDtrans},
        - {"synconcealed", 2, 2, f_synconcealed},
        - {"synstack", 2, 2, f_synstack},
        - {"system", 1, 2, f_system},
        - {"tabpagebuflist", 0, 1, f_tabpagebuflist},
        - {"tabpagenr", 0, 1, f_tabpagenr},
        - {"tabpagewinnr", 1, 2, f_tabpagewinnr},
        - {"tagfiles", 0, 0, f_tagfiles},
        - {"taglist", 1, 1, f_taglist},
        -#ifdef FEAT_FLOAT
        - {"tan", 1, 1, f_tan},
        - {"tanh", 1, 1, f_tanh},
        -#endif
        - {"tempname", 0, 0, f_tempname},
        - {"test", 1, 1, f_test},
        - {"tolower", 1, 1, f_tolower},
        - {"toupper", 1, 1, f_toupper},
        - {"tr", 3, 3, f_tr},
        -#ifdef FEAT_FLOAT
        - {"trunc", 1, 1, f_trunc},
        -#endif
        - {"type", 1, 1, f_type},
        - {"undofile", 1, 1, f_undofile},
        - {"undotree", 0, 0, f_undotree},
        - {"values", 1, 1, f_values},
        - {"virtcol", 1, 1, f_virtcol},
        - {"visualmode", 0, 1, f_visualmode},
        - {"wildmenumode", 0, 0, f_wildmenumode},
        - {"winbufnr", 1, 1, f_winbufnr},
        - {"wincol", 0, 0, f_wincol},
        - {"winheight", 1, 1, f_winheight},
        - {"winline", 0, 0, f_winline},
        - {"winnr", 0, 1, f_winnr},
        - {"winrestcmd", 0, 0, f_winrestcmd},
        - {"winrestview", 1, 1, f_winrestview},
        - {"winsaveview", 0, 0, f_winsaveview},
        - {"winwidth", 1, 1, f_winwidth},
        - {"writefile", 2, 3, f_writefile},
        - {"xor", 2, 2, f_xor},
        + {"strftime", 1, 2, f_strftime, NULL},
        +#endif
        + {"stridx", 2, 3, f_stridx, NULL},
        + {"string", 1, 1, f_string, NULL},
        + {"strlen", 1, 1, f_strlen, NULL},
        + {"strpart", 2, 3, f_strpart, NULL},
        + {"strridx", 2, 3, f_strridx, NULL},
        + {"strtrans", 1, 1, f_strtrans, NULL},
        + {"strwidth", 1, 1, f_strwidth, NULL},
        + {"submatch", 1, 1, f_submatch, NULL},
        + {"substitute", 4, 4, f_substitute, NULL},
        + {"synID", 3, 3, f_synID, NULL},
        + {"synIDattr", 2, 3, f_synIDattr, NULL},
        + {"synIDtrans", 1, 1, f_synIDtrans, NULL},
        + {"synconcealed", 2, 2, f_synconcealed, NULL},
        + {"synstack", 2, 2, f_synstack, NULL},
        + {"system", 1, 2, f_system, NULL},
        + {"tabpagebuflist", 0, 1, f_tabpagebuflist, NULL},
        + {"tabpagenr", 0, 1, f_tabpagenr, NULL},
        + {"tabpagewinnr", 1, 2, f_tabpagewinnr, NULL},
        + {"tagfiles", 0, 0, f_tagfiles, NULL},
        + {"taglist", 1, 1, f_taglist, NULL},
        +#ifdef FEAT_FLOAT
        + {"tan", 1, 1, f_tan, NULL},
        + {"tanh", 1, 1, f_tanh, NULL},
        +#endif
        + {"tempname", 0, 0, f_tempname, NULL},
        + {"test", 1, 1, f_test, NULL},
        + {"tolower", 1, 1, f_tolower, NULL},
        + {"toupper", 1, 1, f_toupper, NULL},
        + {"tr", 3, 3, f_tr, NULL},
        +#ifdef FEAT_FLOAT
        + {"trunc", 1, 1, f_trunc, NULL},
        +#endif
        + {"type", 1, 1, f_type, NULL},
        + {"undofile", 1, 1, f_undofile, NULL},
        + {"undotree", 0, 0, f_undotree, NULL},
        + {"values", 1, 1, f_values, NULL},
        + {"virtcol", 1, 1, f_virtcol, NULL},
        + {"visualmode", 0, 1, f_visualmode, NULL},
        + {"wildmenumode", 0, 0, f_wildmenumode, NULL},
        + {"winbufnr", 1, 1, f_winbufnr, NULL},
        + {"wincol", 0, 0, f_wincol, NULL},
        + {"winheight", 1, 1, f_winheight, NULL},
        + {"winline", 0, 0, f_winline, NULL},
        + {"winnr", 0, 1, f_winnr, NULL},
        + {"winrestcmd", 0, 0, f_winrestcmd, NULL},
        + {"winrestview", 1, 1, f_winrestview, NULL},
        + {"winsaveview", 0, 0, f_winsaveview, NULL},
        + {"winwidth", 1, 1, f_winwidth, NULL},
        + {"writefile", 2, 3, f_writefile, NULL},
        + {"xor", 2, 2, f_xor, NULL},
        };

        #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
        @@ -8242,9 +8326,9 @@

        /*
        * Find internal function in table above.
        - * Return index, or -1 if not found
        - */
        - static int
        + * Return pointer, or NULL if not found
        + */
        + static struct fst *
        find_internal_func(name)
        char_u *name; /* name of the function */
        {
        @@ -8265,39 +8349,170 @@
        else if (cmp > 0)
        first = x + 1;
        else
        - return x;
        - }
        - return -1;
        + return &functions[x];
        + }
        + return NULL;
        }

        /*
        * Check if "name" is a variable of type VAR_FUNC. If so, return the function
        - * name it contains, otherwise return "name".
        - */
        - static char_u *
        -deref_func_name(name, lenp)
        + * definition it contains, otherwise try to find internal or user-defined
        + * function with the given name. Returns NULL on failure.
        + *
        + * Flags:
        + * DF_CHECK_VAR : Try loading function from a variable.
        + * DF_RUN_EVENT : Run FuncUndefined event if function was not found
        + * DF_CREATE_AUTOLOAD: Create references to autoload function
        + * DF_NO_VAR : DF_RUN_EVENT and DF_CREATE_AUTOLOAD
        + * DF_ALL : All of the above
        + */
        + func_T *
        +deref_func_name(name, len, flags)
        char_u *name;
        - int *lenp;
        + const int len;
        + int flags;
        {
        dictitem_T *v;
        int cc;
        -
        - cc = name[*lenp];
        - name[*lenp] = NUL;
        - v = find_var(name, NULL);
        - name[*lenp] = cc;
        - if (v != NULL && v->di_tv.v_type == VAR_FUNC)
        - {
        - if (v->di_tv.vval.v_string == NULL)
        - {
        - *lenp = 0;
        - return (char_u *)""; /* just in case */
        - }
        - *lenp = (int)STRLEN(v->di_tv.vval.v_string);
        - return v->di_tv.vval.v_string;
        - }
        -
        - return name;
        + func_T *r = NULL;
        +
        + cc = name[len];
        + if (flags & DF_CHECK_VAR)
        + {
        + name[len] = NUL;
        + v = find_var(name, NULL);
        + name[len] = cc;
        +
        + if (v != NULL && v->di_tv.v_type == VAR_FUNC)
        + {
        + if (v->di_tv.vval.v_func == NULL)
        + return NULL;
        + ++v->di_tv.vval.v_func->fv_refcount;
        + return v->di_tv.vval.v_func;
        + }
        + }
        +
        + name[len] = NUL;
        + if (builtin_function(name))
        + {
        + struct fst *intfp;
        + intfp = find_internal_func(name);
        +
        + if (intfp != NULL)
        + {
        + if (intfp->f_func == NULL)
        + {
        + intfp->f_func = func_alloc();
        + if (intfp->f_func != NULL)
        + {
        + ++intfp->f_func->fv_refcount;
        + intfp->f_func->fv_data = intfp;
        + intfp->f_func->fv_type = &internal_func_type;
        + }
        + }
        +
        + r = intfp->f_func;
        + }
        + }
        + else
        + {
        + char_u *fname = NULL;
        + char_u *pp;
        + char_u sid_buf[20];
        + int lead;
        + int old_len;
        + int new_len = len;
        + ufunc_T *fp;
        +
        + lead = eval_fname_script(name);
        + new_len -= lead;
        + old_len = new_len;
        + pp = name + lead;
        +
        + if (lead)
        + {
        + lead = 3;
        + if (eval_fname_sid(name))
        + {
        + if (current_SID <= 0)
        + {
        + EMSG(_(e_usingsid));
        + new_len = 0;
        + }
        + else
        + {
        + sprintf((char *) sid_buf, "%ld_", (long) current_SID);
        + lead += STRLEN(sid_buf);
        + }
        + }
        + else
        + *sid_buf = NUL;
        +
        + if (new_len)
        + fname = (char_u *) alloc(new_len + lead + 1);
        + }
        + else
        + {
        + *sid_buf = NUL;
        + fname = name;
        + }
        +
        + if (fname != NULL)
        + {
        + if (lead)
        + {
        + fname[0] = K_SPECIAL;
        + fname[1] = KS_EXTRA;
        + fname[2] = (int) KE_SNR;
        +
        + if (*sid_buf != NUL)
        + mch_memmove(fname + 3, sid_buf, lead - 3);
        +
        + mch_memmove(fname + lead, pp, (size_t) old_len + 1);
        + }
        + fp = find_func(fname);
        +
        +#ifdef FEAT_AUTOCMD
        + /* Trigger FuncUndefined event, may load the function. */
        + if (flags & DF_RUN_EVENT
        + && fp == NULL
        + && apply_autocmds(EVENT_FUNCUNDEFINED,
        + fname, fname, TRUE, NULL)
        + && !aborting())
        + /* executed an autocommand, search for the function again */
        + fp = find_func(name);
        +#endif
        +
        + if (fp == NULL)
        + {
        + if (flags & DF_CREATE_AUTOLOAD
        + && vim_strchr(fname, AUTOLOAD_CHAR) != NULL
        + && valid_autoload_name(fname))
        + {
        + aufunc_T *aufp;
        +
        + if ((aufp = aufunc_alloc()) != NULL &&
        + (r = func_alloc()) != NULL)
        + {
        + aufp->auf_name = vim_strsave(fname);
        + r->fv_data = (void *) aufp;
        + r->fv_type = &autoload_func_type;
        + }
        + }
        + }
        + else
        + r = fp->uf_func;
        +
        + if (lead)
        + vim_free(fname);
        + }
        + }
        + name[len] = cc;
        +
        + if (r != NULL)
        + ++r->fv_refcount;
        +
        + return r;
        }

        /*
        @@ -8305,10 +8520,9 @@
        * Return OK or FAIL.
        */
        static int
        -get_func_tv(name, len, rettv, arg, firstline, lastline, doesrange,
        +get_func_tv(func, rettv, arg, firstline, lastline, doesrange,
        evaluate, selfdict)
        - char_u *name; /* name of the function */
        - int len; /* length of "name" */
        + func_T *func; /* function definition */
        typval_T *rettv;
        char_u **arg; /* argument, pointing to the '(' */
        linenr_T firstline; /* first line of range */
        @@ -8345,15 +8559,20 @@
        else
        ret = FAIL;

        - if (ret == OK)
        - ret = call_func(name, len, rettv, argcount, argvars,
        - firstline, lastline, doesrange, evaluate, selfdict);
        - else if (!aborting())
        - {
        - if (argcount == MAX_FUNC_ARGS)
        - emsg_funcname(N_("E740: Too many arguments for function %s"), name);
        - else
        - emsg_funcname(N_("E116: Invalid arguments for function %s"), name);
        + if (evaluate)
        + {
        + if (ret == OK)
        + ret = call_func(func, rettv, argcount, argvars,
        + firstline, lastline, doesrange, selfdict);
        + else if (!aborting())
        + {
        + if (argcount == MAX_FUNC_ARGS)
        + emsg_funcname(N_("E740: Too many arguments for function %s"),
        + FUNC_NAME(func));
        + else
        + emsg_funcname(N_("E116: Invalid arguments for function %s"),
        + FUNC_NAME(func));
        + }
        }

        while (--argcount >= 0)
        @@ -8363,17 +8582,86 @@
        return ret;
        }

        -
        -/*
        - * Call a function with its resolved parameters
        - * Return FAIL when the function can't be called, OK otherwise.
        - * Also returns OK when an error was encountered while executing the function.
        - */
        - static int
        -call_func(funcname, len, rettv, argcount, argvars, firstline, lastline,
        - doesrange, evaluate, selfdict)
        - char_u *funcname; /* name of the function */
        - int len; /* length of "name" */
        + static int
        +call_internal_func(intfp, rettv, argcount, argvars, firstline, lastline, doesrange, selfdict)
        + struct fst *intfp; /* pointer to function */
        + typval_T *rettv; /* return value */
        + int argcount; /* nr of args */
        + typval_T *argvars; /* arguments */
        + linenr_T firstline; /* first line of range */
        + linenr_T lastline; /* last line of range */
        + int *doesrange; /* is set to True if function handles range */
        + dict_T *selfdict; /* Dictionary for "self" */
        +{
        + if (argcount < intfp->f_min_argc)
        + return ERROR_TOOFEW;
        + else if (argcount > intfp->f_max_argc)
        + return ERROR_TOOMANY;
        +
        + argvars[argcount].v_type = VAR_UNKNOWN;
        + intfp->f_call(argvars, rettv);
        +
        + return ERROR_NONE;
        +}
        +
        + static char_u *
        +repr_internal_func(intfp)
        + struct fst *intfp;
        +{
        + return string_quote((char_u *) intfp->f_name, "function");
        +}
        +
        + static void
        +dealloc_internal_func(intfp)
        + struct fst *intfp;
        +{
        + intfp->f_func = NULL;
        + return;
        +}
        +
        + static int
        +compare_internal_funcs(intfp1, intfp2)
        + struct fst *intfp1;
        + struct fst *intfp2;
        +{
        + return intfp1 == intfp2;
        +}
        +
        + static char_u *
        +name_internal_func(intfp)
        + struct fst *intfp;
        +{
        + return (char_u *) intfp->f_name;
        +}
        +
        +static char_u *internal_func_type_name = "internal";
        +#define INTERNAL_FUNC_TYPE_LEN 8
        +
        + static char_u *
        +type_internal_func(intfp)
        + struct fst *intfp UNUSED;
        +{
        + return vim_strnsave(internal_func_type_name, INTERNAL_FUNC_TYPE_LEN);
        +}
        +
        +static funcdef_T internal_func_type = {
        + (function_caller) call_internal_func, /* fd_call */
        + (function_representer) repr_internal_func, /* fd_repr */
        + (function_destructor) dealloc_internal_func, /* fd_dealloc */
        + (function_cmp) compare_internal_funcs, /* fd_compare */
        + (function_representer) name_internal_func, /* fd_name */
        + (function_representer) type_internal_func, /* fd_type */
        +};
        +
        + static aufunc_T *
        +aufunc_alloc()
        +{
        + return (aufunc_T *) alloc_clear(sizeof(aufunc_T));
        +}
        +
        + static int
        +call_autoload_func(aufp, rettv, argcount, argvars, firstline, lastline, doesrange, selfdict)
        + aufunc_T *aufp;
        typval_T *rettv; /* return value goes here */
        int argcount; /* number of "argvars" */
        typval_T *argvars; /* vars for arguments, must have "argcount"
        @@ -8381,212 +8669,177 @@
        linenr_T firstline; /* first line of range */
        linenr_T lastline; /* last line of range */
        int *doesrange; /* return: function handled range */
        - int evaluate;
        dict_T *selfdict; /* Dictionary for "self" */
        {
        - int ret = FAIL;
        -#define ERROR_UNKNOWN 0
        -#define ERROR_TOOMANY 1
        -#define ERROR_TOOFEW 2
        -#define ERROR_SCRIPT 3
        -#define ERROR_DICT 4
        -#define ERROR_NONE 5
        -#define ERROR_OTHER 6
        - int error = ERROR_NONE;
        - int i;
        - int llen;
        - ufunc_T *fp;
        -#define FLEN_FIXED 40
        - char_u fname_buf[FLEN_FIXED + 1];
        - char_u *fname;
        - char_u *name;
        -
        - /* Make a copy of the name, if it comes from a funcref variable it could
        - * be changed or deleted in the called function. */
        - name = vim_strnsave(funcname, len);
        - if (name == NULL)
        - return ret;
        -
        - /*
        - * In a script change <SID>name() and s:name() to K_SNR 123_name().
        - * Change <SNR>123_name() to K_SNR 123_name().
        - * Use fname_buf[] when it fits, otherwise allocate memory (slow).
        - */
        - llen = eval_fname_script(name);
        - if (llen > 0)
        - {
        - fname_buf[0] = K_SPECIAL;
        - fname_buf[1] = KS_EXTRA;
        - fname_buf[2] = (int)KE_SNR;
        - i = 3;
        - if (eval_fname_sid(name)) /* "<SID>" or "s:" */
        - {
        - if (current_SID <= 0)
        - error = ERROR_SCRIPT;
        - else
        - {
        - sprintf((char *)fname_buf + 3, "%ld_", (long)current_SID);
        - i = (int)STRLEN(fname_buf);
        - }
        - }
        - if (i + STRLEN(name + llen) < FLEN_FIXED)
        - {
        - STRCPY(fname_buf + i, name + llen);
        - fname = fname_buf;
        - }
        - else
        - {
        - fname = alloc((unsigned)(i + STRLEN(name + llen) + 1));
        - if (fname == NULL)
        - error = ERROR_OTHER;
        - else
        - {
        - mch_memmove(fname, fname_buf, (size_t)i);
        - STRCPY(fname + i, name + llen);
        - }
        - }
        - }
        - else
        - fname = name;
        + /* First, check whether function was already loaded. */
        + if (aufp->auf_func == NULL && !aborting())
        + aufp->auf_func = deref_func_name(aufp->auf_name,
        + STRLEN(aufp->auf_name),
        + DF_CHECK_VAR|DF_RUN_EVENT);
        +
        + /* If not then try loading a package. */
        + if (aufp->auf_func == NULL && script_autoload(aufp->auf_name, TRUE) &&
        + !aborting())
        + /* loaded a package, search for the function again */
        + /* Note: it is allowed for loaded function to be defined in a variable
        + */
        + aufp->auf_func = deref_func_name(aufp->auf_name,
        + STRLEN(aufp->auf_name),
        + DF_CHECK_VAR);
        +
        + if (aufp->auf_func == NULL)
        + {
        + EMSG2(_(e_unknown_function), aufp->auf_name);
        + return ERROR_OTHER;
        + }
        +
        + return FUNC_CALL(aufp->auf_func, rettv, argcount, argvars,
        + firstline, lastline, doesrange, selfdict);
        +}
        +
        + static char_u *
        +repr_autoload_func(aufp)
        + aufunc_T *aufp;
        +{
        + return string_quote(aufp->auf_name, "function");
        +}
        +
        + static void
        +dealloc_autoload_func(aufp)
        + aufunc_T *aufp;
        +{
        + if (aufp->auf_func != NULL)
        + func_unref(aufp->auf_func);
        + vim_free(aufp->auf_name);
        + vim_free(aufp);
        +}
        +
        + static int
        +compare_autoload_funcs(aufp1, aufp2)
        + aufunc_T *aufp1;
        + aufunc_T *aufp2;
        +{
        + return STRCMP(aufp1->auf_name, aufp2->auf_name) == 0;
        +}
        +
        + static char_u *
        +name_autoload_func(aufp)
        + aufunc_T *aufp;
        +{
        + return aufp->auf_name;
        +}
        +
        +static char_u *autoload_func_type_name = "autoload";
        +#define AUTOLOAD_FUNC_TYPE_LEN 8
        +
        + static char_u *
        +type_autoload_func(aufp)
        + aufunc_T *aufp;
        +{
        + if (aufp->auf_func == NULL)
        + return vim_strnsave(autoload_func_type_name, AUTOLOAD_FUNC_TYPE_LEN);
        + else
        + {
        + char_u *loaded_type;
        + int loaded_type_len;
        + char_u *ret_type;
        +
        + if ((loaded_type = FUNC_TYPE(aufp->auf_func)) == NULL)
        + return NULL;
        +
        + loaded_type_len = STRLEN(loaded_type);
        +
        + /* 2: colon and NUL */
        + ret_type = (char_u*)alloc(loaded_type_len + 2 + AUTOLOAD_FUNC_TYPE_LEN);
        +
        + if (ret_type == NULL)
        + return NULL;
        +
        + mch_memmove(ret_type, autoload_func_type_name,
        + (size_t) AUTOLOAD_FUNC_TYPE_LEN);
        + ret_type[AUTOLOAD_FUNC_TYPE_LEN] = ':';
        + mch_memmove(ret_type + AUTOLOAD_FUNC_TYPE_LEN + 1, loaded_type,
        + loaded_type_len);
        + ret_type[AUTOLOAD_FUNC_TYPE_LEN + loaded_type_len + 1] = NUL;
        +
        + vim_free(loaded_type);
        + return ret_type;
        + }
        +}
        +
        +static funcdef_T autoload_func_type = {
        + (function_caller) call_autoload_func, /* fd_call */
        + (function_representer) repr_autoload_func, /* fd_repr */
        + (function_destructor) dealloc_autoload_func, /* fd_dealloc */
        + (function_cmp) compare_autoload_funcs, /* fd_compare */
        + (function_representer) name_autoload_func, /* fd_name */
        + (function_representer) type_autoload_func, /* fd_type */
        +};
        +
        +/*
        + * Call a function with its resolved parameters
        + * Return FAIL when the function can't be called, OK otherwise.
        + * Also returns OK when an error was encountered while executing the function.
        + */
        + static int
        +call_func(func, rettv, argcount, argvars, firstline, lastline, doesrange, selfdict)
        + func_T *func; /* function definition */
        + typval_T *rettv; /* return value goes here */
        + int argcount; /* number of "argvars" */
        + typval_T *argvars; /* vars for arguments, must have "argcount"
        + PLUS ONE elements! */
        + linenr_T firstline; /* first line of range */
        + linenr_T lastline; /* last line of range */
        + int *doesrange; /* return: function handled range */
        + dict_T *selfdict; /* Dictionary for "self" */
        +{
        + int error;

        *doesrange = FALSE;

        -
        - /* execute the function if no errors detected and executing */
        - if (evaluate && error == ERROR_NONE)
        - {
        - rettv->v_type = VAR_NUMBER; /* default rettv is number zero */
        - rettv->vval.v_number = 0;
        - error = ERROR_UNKNOWN;
        -
        - if (!builtin_function(fname))
        - {
        - /*
        - * User defined function.
        - */
        - fp = find_func(fname);
        -
        -#ifdef FEAT_AUTOCMD
        - /* Trigger FuncUndefined event, may load the function. */
        - if (fp == NULL
        - && apply_autocmds(EVENT_FUNCUNDEFINED,
        - fname, fname, TRUE, NULL)
        - && !aborting())
        - {
        - /* executed an autocommand, search for the function again */
        - fp = find_func(fname);
        - }
        -#endif
        - /* Try loading a package. */
        - if (fp == NULL && script_autoload(fname, TRUE) && !aborting())
        - {
        - /* loaded a package, search for the function again */
        - fp = find_func(fname);
        - }
        -
        - if (fp != NULL)
        - {
        - if (fp->uf_flags & FC_RANGE)
        - *doesrange = TRUE;
        - if (argcount < fp->uf_args.ga_len)
        - error = ERROR_TOOFEW;
        - else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len)
        - error = ERROR_TOOMANY;
        - else if ((fp->uf_flags & FC_DICT) && selfdict == NULL)
        - error = ERROR_DICT;
        - else
        - {
        - /*
        - * Call the user function.
        - * Save and restore search patterns, script variables and
        - * redo buffer.
        - */
        - save_search_patterns();
        - saveRedobuff();
        - ++fp->uf_calls;
        - call_user_func(fp, argcount, argvars, rettv,
        - firstline, lastline,
        - (fp->uf_flags & FC_DICT) ? selfdict : NULL);
        - if (--fp->uf_calls <= 0 && isdigit(*fp->uf_name)
        - && fp->uf_refcount <= 0)
        - /* Function was unreferenced while being used, free it
        - * now. */
        - func_free(fp);
        - restoreRedobuff();
        - restore_search_patterns();
        - error = ERROR_NONE;
        - }
        - }
        - }
        - else
        - {
        - /*
        - * Find the function name in the table, call its implementation.
        - */
        - i = find_internal_func(fname);
        - if (i >= 0)
        - {
        - if (argcount < functions[i].f_min_argc)
        - error = ERROR_TOOFEW;
        - else if (argcount > functions[i].f_max_argc)
        - error = ERROR_TOOMANY;
        - else
        - {
        - argvars[argcount].v_type = VAR_UNKNOWN;
        - functions[i].f_func(argvars, rettv);
        - error = ERROR_NONE;
        - }
        - }
        - }
        - /*
        - * The function call (or "FuncUndefined" autocommand sequence) might
        - * have been aborted by an error, an interrupt, or an explicitly thrown
        - * exception that has not been caught so far. This situation can be
        - * tested for by calling aborting(). For an error in an internal
        - * function or for the "E132" error in call_user_func(), however, the
        - * throw point at which the "force_abort" flag (temporarily reset by
        - * emsg()) is normally updated has not been reached yet. We need to
        - * update that flag first to make aborting() reliable.
        - */
        - update_force_abort();
        - }
        - if (error == ERROR_NONE)
        - ret = OK;
        -
        - /*
        - * Report an error unless the argument evaluation or function call has been
        - * cancelled due to an aborting error, an interrupt, or an exception.
        - */
        + if (func == NULL)
        + return FAIL;
        +
        + rettv->v_type = VAR_NUMBER; /* default rettv is number zero */
        + rettv->vval.v_number = 0;
        + error = func->fv_type->fd_call(func->fv_data, rettv, argcount, argvars,
        + firstline, lastline, doesrange, selfdict);
        +
        + /*
        + * The function call (or "FuncUndefined" autocommand sequence) might
        + * have been aborted by an error, an interrupt, or an explicitly thrown
        + * exception that has not been caught so far. This situation can be
        + * tested for by calling aborting(). For an error in an internal
        + * function or for the "E132" error in call_user_func(), however, the
        + * throw point at which the "force_abort" flag (temporarily reset by
        + * emsg()) is normally updated has not been reached yet. We need to
        + * update that flag first to make aborting() reliable.
        + */
        + update_force_abort();
        +
        if (!aborting())
        {
        switch (error)
        {
        - case ERROR_UNKNOWN:
        - emsg_funcname(N_("E117: Unknown function: %s"), name);
        - break;
        case ERROR_TOOMANY:
        - emsg_funcname(e_toomanyarg, name);
        + emsg_funcname(e_toomanyarg, FUNC_NAME(func));
        break;
        case ERROR_TOOFEW:
        emsg_funcname(N_("E119: Not enough arguments for function: %s"),
        - name);
        + FUNC_NAME(func));
        break;
        case ERROR_SCRIPT:
        emsg_funcname(N_("E120: Using <SID> not in a script context: %s"),
        - name);
        + FUNC_NAME(func));
        break;
        case ERROR_DICT:
        emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"),
        - name);
        - break;
        - }
        - }
        -
        - if (fname != name && fname != fname_buf)
        - vim_free(fname);
        - vim_free(name);
        -
        - return ret;
        + FUNC_NAME(func));
        + break;
        + }
        + }
        +
        + return error == ERROR_NONE ? OK : FAIL;
        }

        /*
        @@ -9241,8 +9494,8 @@
        }

        int
        -func_call(name, args, selfdict, rettv)
        - char_u *name;
        +func_call(func, args, selfdict, rettv)
        + func_T *func;
        typval_T *args;
        dict_T *selfdict;
        typval_T *rettv;
        @@ -9268,9 +9521,9 @@
        }

        if (item == NULL)
        - r = call_func(name, (int)STRLEN(name), rettv, argc, argv,
        + r = call_func(func, rettv, argc, argv,
        curwin->w_cursor.lnum, curwin->w_cursor.lnum,
        - &dummy, TRUE, selfdict);
        + &dummy, selfdict);

        /* Free the arguments. */
        while (argc > 0)
        @@ -9287,7 +9540,7 @@
        typval_T *argvars;
        typval_T *rettv;
        {
        - char_u *func;
        + func_T *func;
        dict_T *selfdict = NULL;

        if (argvars[1].v_type != VAR_LIST)
        @@ -9299,11 +9552,18 @@
        return;

        if (argvars[0].v_type == VAR_FUNC)
        - func = argvars[0].vval.v_string;
        - else
        - func = get_tv_string(&argvars[0]);
        - if (*func == NUL)
        - return; /* type error or empty name */
        + {
        + func = argvars[0].vval.v_func;
        + ++func->fv_refcount;
        + }
        + else
        + {
        + char_u *name;
        + name = get_tv_string(&argvars[0]);
        + if (name == NUL)
        + return; /* type error or empty name */
        + func = deref_func_name(name, STRLEN(name), DF_NO_VAR);
        + }

        if (argvars[2].v_type != VAR_UNKNOWN)
        {
        @@ -9316,6 +9576,8 @@
        }

        (void)func_call(func, &argvars[1], selfdict, rettv);
        +
        + func_unref(func);
        }

        #ifdef FEAT_FLOAT
        @@ -11006,37 +11268,38 @@
        typval_T *rettv;
        {
        char_u *s;
        + func_T *func;

        s = get_tv_string(&argvars[0]);
        - if (s == NULL || *s == NUL || VIM_ISDIGIT(*s))
        - EMSG2(_(e_invarg2), s);
        - /* Don't check an autoload name for existence here. */
        - else if (vim_strchr(s, AUTOLOAD_CHAR) == NULL && !function_exists(s))
        - EMSG2(_("E700: Unknown function: %s"), s);
        - else
        - {
        - if (STRNCMP(s, "s:", 2) == 0 || STRNCMP(s, "<SID>", 5) == 0)
        - {
        - char sid_buf[25];
        - int off = *s == 's' ? 2 : 5;
        -
        - /* Expand s: and <SID> into <SNR>nr_, so that the function can
        - * also be called from another script. Using trans_function_name()
        - * would also work, but some plugins depend on the name being
        - * printable text. */
        - sprintf(sid_buf, "<SNR>%ld_", (long)current_SID);
        - rettv->vval.v_string =
        - alloc((int)(STRLEN(sid_buf) + STRLEN(s + off) + 1));
        - if (rettv->vval.v_string != NULL)
        - {
        - STRCPY(rettv->vval.v_string, sid_buf);
        - STRCAT(rettv->vval.v_string, s + off);
        - }
        - }
        - else
        - rettv->vval.v_string = vim_strsave(s);
        +
        + func = deref_func_name(s, STRLEN(s), DF_CREATE_AUTOLOAD);
        +
        + if (func != NULL)
        + {
        rettv->v_type = VAR_FUNC;
        - }
        + rettv->vval.v_func = func;
        + }
        + else
        + EMSG2(_(e_unknown_function), s);
        +}
        +
        +/*
        + * "functype()" function
        + */
        + static void
        +f_functype(argvars, rettv)
        + typval_T *argvars;
        + typval_T *rettv;
        +{
        + if (argvars[0].v_type != VAR_FUNC || argvars[0].vval.v_func == NULL)
        + {
        + EMSG(_(e_funcref));
        + return;
        + }
        +
        + if ((rettv->vval.v_string = FUNC_TYPE(argvars[0].vval.v_func)) == NULL)
        + return;
        + rettv->v_type = VAR_STRING;
        }

        /*
        @@ -14451,15 +14714,15 @@
        }

        void
        -mzscheme_call_vim(name, args, rettv)
        - char_u *name;
        +mzscheme_call_vim(func, args, rettv)
        + func_T *func;
        typval_T *args;
        typval_T *rettv;
        {
        typval_T argvars[3];

        - argvars[0].v_type = VAR_STRING;
        - argvars[0].vval.v_string = name;
        + argvars[0].v_type = VAR_FUNC;
        + argvars[0].vval.v_func = func;
        copy_tv(args, &argvars[1]);
        argvars[2].v_type = VAR_UNKNOWN;
        f_call(argvars, rettv);
        @@ -17003,7 +17266,7 @@
        item_compare2 __ARGS(<br/><br/>(Message over 64 KB, truncated)
      • ZyX
        Merged with upstream, removed no_autoload global, made islocked() and :lockvar no longer trigger script autoloading. Also fixed some compilation warnings. diff
        Message 3 of 22 , Jan 6, 2014
        • 0 Attachment
          Merged with upstream, removed no_autoload global, made islocked() and :lockvar no longer trigger script autoloading.

          Also fixed some compilation warnings.

          diff -r bc19475ed196 -r fd7e081faea4 Filelist
          --- a/Filelist Mon Jan 06 15:51:55 2014 +0100
          +++ b/Filelist Tue Jan 07 01:35:53 2014 +0400
          @@ -84,6 +84,8 @@
          src/testdir/test49.vim \
          src/testdir/test60.vim \
          src/testdir/test83-tags? \
          + src/testdir/Test104.vim \
          + src/testdir/test104/autoload/*.vim \
          src/testdir/python2/*.py \
          src/testdir/python3/*.py \
          src/testdir/pythonx/*.py \
          @@ -93,6 +95,7 @@
          src/testdir/pythonx/topmodule/submodule/subsubmodule/subsubsubmodule.py \
          src/testdir/python_after/*.py \
          src/testdir/python_before/*.py \
          + src/testdir/sautest/autoload/*.vim \
          src/proto.h \
          src/proto/blowfish.pro \
          src/proto/buffer.pro \
          diff -r bc19475ed196 -r fd7e081faea4 runtime/doc/eval.txt
          --- a/runtime/doc/eval.txt Mon Jan 06 15:51:55 2014 +0100
          +++ b/runtime/doc/eval.txt Tue Jan 07 01:35:53 2014 +0400
          @@ -1780,7 +1780,8 @@
          foldtext( ) String line displayed for closed fold
          foldtextresult( {lnum}) String text for closed fold at {lnum}
          foreground( ) Number bring the Vim window to the foreground
          -function( {name}) Funcref reference to function {name}
          +function( {name}) Funcref reference to function {name}
          +functype( {func}) String type of function reference {func}
          garbagecollect( [{atexit}]) none free memory, breaking cyclic references
          get( {list}, {idx} [, {def}]) any get item {idx} from {list} or {def}
          get( {dict}, {key} [, {def}]) any get item {key} from {dict} or {def}
          @@ -3128,6 +3129,31 @@
          {name} can be a user defined function or an internal function.


          +functype({func}) *functype()*
          + Given a |Funcref| return string describing its type. Possible
          + values:
          + Value Description ~
          + internal Reference to one of the built-in |functions|.
          + Example: `function('tr')`.
          + user Reference to one of the |user-functions|.
          + Example: `function('NetrwStatusLine')`.
          + autoload Reference to one of the |autoload-functions|
          + that was not yet loaded.
          + Example: `function('zip#Browse')`.
          + autoload:{type} Same as above, but for functions that were
          + already loaded. For `function('zip#Browse')`
          + it will return "autoload:user". {type} may be
          + anything that |functype()| can return
          + (including e.g. "autoload:autoload:internal").
          + python:{type} Reference to some python function. {type} is
          + the python type name.
          + Example: `pyeval('id')` has function type
          + "python:builtin_function_or_method".
          + python3:{type} Same as above, but for python 3 functions.
          + Example: `py3eval('id')` has function type
          + "python3:builtin_function_or_method".
          +
          +
          garbagecollect([{atexit}]) *garbagecollect()*
          Cleanup unused |Lists| and |Dictionaries| that have circular
          references. There is hardly ever a need to invoke this
          diff -r bc19475ed196 -r fd7e081faea4 runtime/doc/if_pyth.txt
          --- a/runtime/doc/if_pyth.txt Mon Jan 06 15:51:55 2014 +0100
          +++ b/runtime/doc/if_pyth.txt Tue Jan 07 01:35:53 2014 +0400
          @@ -656,7 +656,11 @@
          Function-like object, acting like vim |Funcref| object. Supports `.name`
          attribute and is callable. Accepts special keyword argument `self`, see
          |Dictionary-function|. You can also use `vim.Function(name)` constructor,
          - it is the same as `vim.bindeval('function(%s)'%json.dumps(name))`.
          + it is the same as `vim.bindeval('function(%s)'%json.dumps(name))`. Object
          + supports the following attributes:
          + Attribute Description ~
          + name Function name.
          + repr Same as running `vim.bindeval("string(pyeval('func'))")`.

          Examples: >
          f = vim.Function('tr') # Constructor
          diff -r bc19475ed196 -r fd7e081faea4 runtime/doc/repeat.txt
          --- a/runtime/doc/repeat.txt Mon Jan 06 15:51:55 2014 +0100
          +++ b/runtime/doc/repeat.txt Tue Jan 07 01:35:53 2014 +0400
          @@ -668,12 +668,6 @@
          - The time of the lines added up is mostly less than the time of the whole
          function. There is some overhead in between.

          -- Functions that are deleted before Vim exits will not produce profiling
          - information. You can check the |v:profiling| variable if needed: >
          - :if !v:profiling
          - : delfunc MyFunc
          - :endif
          -<
          - Profiling may give weird results on multi-processor systems, when sleep
          mode kicks in or the processor frequency is reduced to save power.

          diff -r bc19475ed196 -r fd7e081faea4 src/eval.c
          --- a/src/eval.c Mon Jan 06 15:51:55 2014 +0100
          +++ b/src/eval.c Tue Jan 07 01:35:53 2014 +0400
          @@ -115,6 +115,7 @@
          #ifdef FEAT_FLOAT
          static char *e_float_as_string = N_("E806: using Float as a String");
          #endif
          +static char *e_unknown_function = N_("E700: Unknown function: %s");

          static dictitem_T globvars_var; /* variable used for g: */
          #define globvarht globvardict.dv_hashtab
          @@ -125,9 +126,6 @@
          */
          static hashtab_T compat_hashtab;

          -/* When using exists() don't auto-load a script. */
          -static int no_autoload = FALSE;
          -
          /*
          * When recursively copying lists and dicts we need to remember which ones we
          * have done to avoid endless recursiveness. This unique ID is used for that.
          @@ -153,10 +151,20 @@

          static int echo_attr = 0; /* attributes used for ":echo" */

          -/* Values for trans_function_name() argument: */
          +/* Values for trans_function_name() flags argument: */
          #define TFN_INT 1 /* internal function name OK */
          #define TFN_QUIET 2 /* no error messages */

          +/* Values for get_called_function() flags argument: */
          +#define GCF_AUTOLOAD 1 /* it is OK to create autoload functions */
          +#define GCF_RUN_EVENT 2 /* run FuncUndefined event */
          +#define GCF_QUIET 4 /* no error messages */
          +#define GCF_ANY_FUNC GCF_AUTOLOAD|GCF_RUN_EVENT
          +
          +/* Values for get_var_tv() flags argument: */
          +#define GVT_VERBOSE 1 /* may give error messages */
          +#define GVT_NO_AUTOLOAD 2 /* disable script autoloading */
          +
          /*
          * Structure to hold info for a user function.
          */
          @@ -166,7 +174,6 @@
          {
          int uf_varargs; /* variable nr of arguments */
          int uf_flags;
          - int uf_calls; /* nr of active calls */
          garray_T uf_args; /* arguments */
          garray_T uf_lines; /* function lines */
          #ifdef FEAT_PROFILE
          @@ -185,19 +192,35 @@
          proftime_T uf_tml_wait; /* start wait time for current line */
          int uf_tml_idx; /* index of line being timed; -1 if none */
          int uf_tml_execed; /* line being timed was executed */
          + ufunc_T *uf_prof_next; /* next profiled function */
          #endif
          scid_T uf_script_ID; /* ID of script where function was defined,
          used for s: variables */
          - int uf_refcount; /* for numbered function: reference count */
          + func_T *uf_func; /* Reference to a func_T structure holding
          + reference to ufunc_T */
          char_u uf_name[1]; /* name of function (actually longer); can
          start with <SNR>123_ (<SNR> is K_SPECIAL
          KS_EXTRA KE_SNR) */
          };

          +/*
          + * Structure to hold info for autoloaded function.
          + */
          +typedef struct aufunc aufunc_T;
          +
          +struct aufunc
          +{
          + char_u *auf_name; /* Function name */
          + func_T *auf_func; /* If function was already autoloaded:
          + record pointer here, otherwise it will hold
          + NULL */
          +};
          +
          /* function flags */
          #define FC_ABORT 1 /* abort function on error */
          #define FC_RANGE 2 /* function accepts range */
          -#define FC_DICT 4 /* Dict function, uses "self" */
          +#define FC_DICT 4 /* Dict function, uses "self" */
          +#define FC_ANON 8 /* Anonymous, not stored in func_hashtab */

          /*
          * All user-defined functions are found in this hashtable.
          @@ -211,6 +234,12 @@
          static dict_T *first_dict = NULL; /* list of all dicts */
          static list_T *first_list = NULL; /* list of all lists */

          +#ifdef FEAT_PROFILE
          +/* Functions being profiled */
          +static ufunc_T *fp_profiled_first = NULL;
          +static ufunc_T *fp_profiled_last = NULL;
          +#endif
          +
          /* From user function to hashitem and back. */
          static ufunc_T dumuf;
          #define UF2HIKEY(fp) ((fp)->uf_name)
          @@ -269,9 +298,13 @@
          */
          typedef struct
          {
          - dict_T *fd_dict; /* Dictionary used */
          + dict_T *fd_dict; /* Dictionary used. Contains borrowed reference.
          + */
          char_u *fd_newkey; /* new key in "dict" in allocated memory */
          dictitem_T *fd_di; /* Dictionary item used */
          + func_T *fd_func; /* Function object, if it was obtained.
          + * Contains borrowed reference, no need to
          + * decref. */
          } funcdict_T;


          @@ -439,17 +472,16 @@
          static int get_dict_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
          static char_u *echo_string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf, int copyID));
          static char_u *tv2string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf, int copyID));
          -static char_u *string_quote __ARGS((char_u *str, int function));
          #ifdef FEAT_FLOAT
          static int string2float __ARGS((char_u *text, float_T *value));
          #endif
          static int get_env_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
          -static int find_internal_func __ARGS((char_u *name));
          -static char_u *deref_func_name __ARGS((char_u *name, int *lenp));
          -static int get_func_tv __ARGS((char_u *name, int len, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));
          -static int call_func __ARGS((char_u *funcname, int len, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));
          +static struct fst *find_internal_func __ARGS((char_u *name));
          +static int get_func_tv __ARGS((func_T *name, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));
          +static int call_func __ARGS((func_T *func, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, dict_T *selfdict));
          static void emsg_funcname __ARGS((char *ermsg, char_u *name));
          static int non_zero_arg __ARGS((typval_T *argvars));
          +static aufunc_T *aufunc_alloc __ARGS((void));

          #ifdef FEAT_FLOAT
          static void f_abs __ARGS((typval_T *argvars, typval_T *rettv));
          @@ -537,6 +569,7 @@
          static void f_foldtextresult __ARGS((typval_T *argvars, typval_T *rettv));
          static void f_foreground __ARGS((typval_T *argvars, typval_T *rettv));
          static void f_function __ARGS((typval_T *argvars, typval_T *rettv));
          +static void f_functype __ARGS((typval_T *argvars, typval_T *rettv));
          static void f_garbagecollect __ARGS((typval_T *argvars, typval_T *rettv));
          static void f_get __ARGS((typval_T *argvars, typval_T *rettv));
          static void f_getbufline __ARGS((typval_T *argvars, typval_T *rettv));
          @@ -770,7 +803,7 @@
          static char_u * make_expanded_name __ARGS((char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end));
          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 get_var_tv __ARGS((char_u *name, int len, typval_T *rettv, int flags));
          static int handle_subscript __ARGS((char_u **arg, typval_T *rettv, int evaluate, int verbose));
          static typval_T *alloc_tv __ARGS((void));
          static typval_T *alloc_string_tv __ARGS((char_u *string));
          @@ -781,8 +814,8 @@
          static char_u *get_tv_string __ARGS((typval_T *varp));
          static char_u *get_tv_string_buf __ARGS((typval_T *varp, char_u *buf));
          static char_u *get_tv_string_buf_chk __ARGS((typval_T *varp, char_u *buf));
          -static dictitem_T *find_var __ARGS((char_u *name, hashtab_T **htp));
          -static dictitem_T *find_var_in_ht __ARGS((hashtab_T *ht, int htname, char_u *varname, int writing));
          +static dictitem_T *find_var __ARGS((char_u *name, hashtab_T **htp, int no_autoload));
          +static dictitem_T *find_var_in_ht __ARGS((hashtab_T *ht, int htname, char_u *varname, int no_autoload));
          static hashtab_T *find_var_ht __ARGS((char_u *name, char_u **varname));
          static void vars_clear_ext __ARGS((hashtab_T *ht, int free_val));
          static void delete_var __ARGS((hashtab_T *ht, hashitem_T *hi));
          @@ -793,10 +826,12 @@
          static int var_check_fixed __ARGS((int flags, char_u *name));
          static int var_check_func_name __ARGS((char_u *name, int new_var));
          static int valid_varname __ARGS((char_u *varname));
          +static int valid_autoload_name __ARGS((char_u *varname));
          static int tv_check_lock __ARGS((int lock, char_u *name));
          static int item_copy __ARGS((typval_T *from, typval_T *to, int deep, int copyID));
          static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags));
          static char_u *trans_function_name __ARGS((char_u **pp, int skip, int flags, funcdict_T *fd));
          +static func_T *get_called_function __ARGS((char_u **pp, int skip, funcdict_T *fd, int flags));
          static int eval_fname_script __ARGS((char_u *p));
          static int eval_fname_sid __ARGS((char_u *p));
          static void list_func_head __ARGS((ufunc_T *fp, int indent));
          @@ -805,6 +840,7 @@
          static int builtin_function __ARGS((char_u *name));
          #ifdef FEAT_PROFILE
          static void func_do_profile __ARGS((ufunc_T *fp));
          +static void func_clear_profile __ARGS((ufunc_T *fp));
          static void prof_sort_list __ARGS((FILE *fd, ufunc_T **sorttab, int st_len, char *title, int prefer_self));
          static void prof_func_line __ARGS((FILE *fd, int count, proftime_T *total, proftime_T *self, int prefer_self));
          static int
          @@ -821,8 +857,9 @@
          static int script_autoload __ARGS((char_u *name, int reload));
          static char_u *autoload_name __ARGS((char_u *name));
          static void cat_func_name __ARGS((char_u *buf, ufunc_T *fp));
          -static void func_free __ARGS((ufunc_T *fp));
          -static void call_user_func __ARGS((ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, linenr_T firstline, linenr_T lastline, dict_T *selfdict));
          +static void dealloc_user_func __ARGS((ufunc_T *fp));
          +static int call_user_func __ARGS((ufunc_T *fp, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, dict_T *selfdict));
          +static void remove_user_func __ARGS((ufunc_T *fp));
          static int can_free_funccal __ARGS((funccall_T *fc, int copyID)) ;
          static void free_funccal __ARGS((funccall_T *fc, int free_val));
          static void add_nr_var __ARGS((dict_T *dp, dictitem_T *v, char *name, varnumber_T nr));
          @@ -838,6 +875,11 @@
          static void sortFunctions __ARGS(());
          #endif

          +
          +static funcdef_T user_func_type;
          +static funcdef_T internal_func_type;
          +static funcdef_T autoload_func_type;
          +
          /*
          * Initialize the global and v: variables.
          */
          @@ -1563,10 +1605,10 @@
          * Returns OK or FAIL.
          */
          int
          -call_vim_function(func, argc, argv, safe, str_arg_only, rettv)
          - char_u *func;
          +call_vim_function(name, argc, argv, safe, str_arg_only, rettv)
          + char_u *name;
          int argc;
          - char_u **argv;
          + char_u **argv;
          int safe; /* use the sandbox */
          int str_arg_only; /* all arguments are strings */
          typval_T *rettv;
          @@ -1578,11 +1620,19 @@
          int doesrange;
          void *save_funccalp = NULL;
          int ret;
          + func_T *func;

          argvars = (typval_T *)alloc((unsigned)((argc + 1) * sizeof(typval_T)));
          if (argvars == NULL)
          return FAIL;

          + func = deref_func_name(name, STRLEN(name), DF_ALL);
          + if (func == NULL)
          + {
          + vim_free(argvars);
          + return FAIL;
          + }
          +
          for (i = 0; i < argc; i++)
          {
          /* Pass a NULL or empty argument as an empty string */
          @@ -1617,9 +1667,9 @@
          }

          rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */
          - ret = call_func(func, (int)STRLEN(func), rettv, argc, argvars,
          + ret = call_func(func, rettv, argc, argvars,
          curwin->w_cursor.lnum, curwin->w_cursor.lnum,
          - &doesrange, TRUE, NULL);
          + &doesrange, NULL);
          if (safe)
          {
          --sandbox;
          @@ -1630,6 +1680,8 @@
          if (ret == FAIL)
          clear_tv(rettv);

          + func_unref(func);
          +
          return ret;
          }

          @@ -2239,7 +2291,7 @@
          {
          if (tofree != NULL)
          name = tofree;
          - if (get_var_tv(name, len, &tv, TRUE) == FAIL)
          + if (get_var_tv(name, len, &tv, GVT_VERBOSE) == FAIL)
          error = TRUE;
          else
          {
          @@ -2591,7 +2643,7 @@

          cc = *p;
          *p = NUL;
          - v = find_var(lp->ll_name, &ht);
          + v = find_var(lp->ll_name, &ht, FALSE);
          if (v == NULL && !quiet)
          EMSG2(_(e_undefvar), lp->ll_name);
          *p = cc;
          @@ -2903,8 +2955,8 @@
          typval_T tv;

          /* handle +=, -= and .= */
          - if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name),
          - &tv, TRUE) == OK)
          + if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name), &tv,
          + GVT_VERBOSE) == OK)
          {
          if (tv_op(&tv, rettv, op) == OK)
          set_var(lp->ll_name, &tv, FALSE);
          @@ -3387,8 +3439,7 @@
          {
          char_u *arg = eap->arg;
          char_u *startarg;
          - char_u *name;
          - char_u *tofree;
          + func_T *func;
          int len;
          typval_T rettv;
          linenr_T lnum;
          @@ -3408,14 +3459,14 @@
          return;
          }

          - tofree = trans_function_name(&arg, eap->skip, TFN_INT, &fudi);
          + func = get_called_function(&arg, eap->skip, &fudi, GCF_ANY_FUNC);
          if (fudi.fd_newkey != NULL)
          {
          /* Still need to give an error message for missing key. */
          EMSG2(_(e_dictkey), fudi.fd_newkey);
          vim_free(fudi.fd_newkey);
          }
          - if (tofree == NULL)
          + if (func == NULL)
          return;

          /* Increase refcount on dictionary, it could get deleted when evaluating
          @@ -3423,10 +3474,6 @@
          if (fudi.fd_dict != NULL)
          ++fudi.fd_dict->dv_refcount;

          - /* If it is the name of a variable of type VAR_FUNC use its contents. */
          - len = (int)STRLEN(tofree);
          - name = deref_func_name(tofree, &len);
          -
          /* Skip white space to allow ":call func ()". Not good, but required for
          * backward compatibility. */
          startarg = skipwhite(arg);
          @@ -3462,7 +3509,7 @@
          #endif
          }
          arg = startarg;
          - if (get_func_tv(name, (int)STRLEN(name), &rettv, &arg,
          + if (get_func_tv(func, &rettv, &arg,
          eap->line1, eap->line2, &doesrange,
          !eap->skip, fudi.fd_dict) == FAIL)
          {
          @@ -3504,8 +3551,8 @@
          }

          end:
          + func_unref(func);
          dict_unref(fudi.fd_dict);
          - vim_free(tofree);
          }

          /*
          @@ -3709,7 +3756,7 @@
          ret = FAIL;
          else
          {
          - di = find_var(lp->ll_name, NULL);
          + di = find_var(lp->ll_name, NULL, TRUE);
          if (di == NULL)
          ret = FAIL;
          else
          @@ -4476,12 +4523,17 @@
          else
          {
          /* Compare two Funcrefs for being equal or unequal. */
          - if (rettv->vval.v_string == NULL
          - || var2.vval.v_string == NULL)
          + if (rettv->vval.v_func == NULL
          + || var2.vval.v_func == NULL)
          + n1 = FALSE;
          + else if (rettv->vval.v_func->fv_type !=
          + var2.vval.v_func->fv_type)
          n1 = FALSE;
          else
          - n1 = STRCMP(rettv->vval.v_string,
          - var2.vval.v_string) == 0;
          + n1 = rettv->vval.v_func->fv_type->fd_compare(
          + rettv->vval.v_func->fv_data,
          + var2.vval.v_func->fv_data
          + );
          if (type == TYPE_NEQUAL)
          n1 = !n1;
          }
          @@ -5150,21 +5202,39 @@
          {
          if (**arg == '(') /* recursive! */
          {
          + func_T *func;
          /* If "s" is the name of a variable of type VAR_FUNC
          * use its contents. */
          - s = deref_func_name(s, &len);
          -
          - /* Invoke the function. */
          - ret = get_func_tv(s, len, rettv, arg,
          - curwin->w_cursor.lnum, curwin->w_cursor.lnum,
          - &len, evaluate, NULL);
          + if (evaluate)
          + func = deref_func_name(s, len, DF_ALL);
          + else
          + func = NULL;
          +
          + if (evaluate && func == NULL)
          + {
          + char_u cc;
          + ret = FAIL;
          + cc = s[len];
          + s[len] = '\0';
          + emsg_funcname(N_("E117: Unknown function: %s"), s);
          + s[len] = cc;
          + }
          + else
          + {
          + /* Invoke the function. */
          + ret = get_func_tv(func, rettv, arg,
          + curwin->w_cursor.lnum, curwin->w_cursor.lnum,
          + &len, evaluate, NULL);
          +
          + func_unref(func);
          + }

          /* If evaluate is FALSE rettv->v_type was not set in
          * get_func_tv, but it's needed in handle_subscript() to parse
          * what follows. So set it here. */
          if (rettv->v_type == VAR_UNKNOWN && !evaluate && **arg == '(')
          {
          - rettv->vval.v_string = vim_strsave((char_u *)"");
          + rettv->vval.v_func = NULL;
          rettv->v_type = VAR_FUNC;
          }

          @@ -5179,7 +5249,7 @@
          }
          }
          else if (evaluate)
          - ret = get_var_tv(s, len, rettv, TRUE);
          + ret = get_var_tv(s, len, rettv, GVT_VERBOSE);
          else
          ret = OK;
          }
          @@ -6125,9 +6195,13 @@
          return r;

          case VAR_FUNC:
          - return (tv1->vval.v_string != NULL
          - && tv2->vval.v_string != NULL
          - && STRCMP(tv1->vval.v_string, tv2->vval.v_string) == 0);
          + return (tv1->vval.v_func != NULL
          + && tv2->vval.v_func != NULL
          + && tv1->vval.v_func->fv_type == tv2->vval.v_func->fv_type
          + && tv1->vval.v_func->fv_type->fd_compare(
          + tv1->vval.v_func->fv_data,
          + tv2->vval.v_func->fv_data
          + ));

          case VAR_NUMBER:
          return tv1->vval.v_number == tv2->vval.v_number;
          @@ -7419,7 +7493,7 @@
          else
          ga_concat(&ga, (char_u *)", ");

          - tofree = string_quote(hi->hi_key, FALSE);
          + tofree = string_quote(hi->hi_key, NULL);
          if (tofree != NULL)
          {
          ga_concat(&ga, tofree);
          @@ -7598,8 +7672,8 @@
          switch (tv->v_type)
          {
          case VAR_FUNC:
          - *tofree = NULL;
          - r = tv->vval.v_string;
          + r = FUNC_REPR(tv->vval.v_func);
          + *tofree = r;
          break;

          case VAR_LIST:
          @@ -7680,10 +7754,10 @@
          switch (tv->v_type)
          {
          case VAR_FUNC:
          - *tofree = string_quote(tv->vval.v_string, TRUE);
          + *tofree = FUNC_REPR(tv->vval.v_func);
          return *tofree;
          case VAR_STRING:
          - *tofree = string_quote(tv->vval.v_string, FALSE);
          + *tofree = string_quote(tv->vval.v_string, NULL);
          return *tofree;
          #ifdef FEAT_FLOAT
          case VAR_FLOAT:
          @@ -7704,17 +7778,25 @@
          /*
          * Return string "str" in ' quotes, doubling ' characters.
          * If "str" is NULL an empty string is assumed.
          - * If "function" is TRUE make it function('string').
          - */
          - static char_u *
          -string_quote(str, function)
          + * If "fname" is not NULL make it fname('string').
          + */
          + char_u *
          +string_quote(str, fname)
          char_u *str;
          - int function;
          + char *fname;
          {
          unsigned len;
          + unsigned flen = 0;
          char_u *p, *r, *s;
          -
          - len = (function ? 13 : 3);
          + char_u *fname_u = (char_u *) fname;
          +
          + if (fname_u != NULL)
          + flen = STRLEN(fname_u);
          +
          + /* +---+- 2 quotes and NUL *
          + * | | +- parenthesis *
          + * | | | */
          + len = (fname_u == NULL ? 3 : 3 + 2 + flen);
          if (str != NULL)
          {
          len += (unsigned)STRLEN(str);
          @@ -7725,13 +7807,13 @@
          s = r = alloc(len);
          if (r != NULL)
          {
          - if (function)
          - {
          - STRCPY(r, "function('");
          - r += 10;
          - }
          - else
          - *r++ = '\'';
          + if (fname_u)
          + {
          + mch_memmove(r, fname_u, flen);
          + r += flen;
          + *r++ = '(';
          + }
          + *r++ = '\'';
          if (str != NULL)
          for (p = str; *p != NUL; )
          {
          @@ -7740,7 +7822,7 @@
          MB_COPY_CHAR(p, r);
          }
          *r++ = '\'';
          - if (function)
          + if (fname_u)
          *r++ = ')';
          *r++ = NUL;
          }
          @@ -7833,322 +7915,325 @@
          char *f_name; /* function name */
          char f_min_argc; /* minimal number of arguments */
          char f_max_argc; /* maximal number of arguments */
          - void (*f_func) __ARGS((typval_T *args, typval_T *rvar));
          + void (*f_call) __ARGS((typval_T *args, typval_T *rvar));
          /* implementation of function */
          + func_T *f_func; /* reference to a func_T structure holding
          + reference to struct fst */
          } functions[] =
          {
          #ifdef FEAT_FLOAT
          - {"abs", 1, 1, f_abs},
          - {"acos", 1, 1, f_acos}, /* WJMc */
          -#endif
          - {"add", 2, 2, f_add},
          - {"and", 2, 2, f_and},
          - {"append", 2, 2, f_append},
          - {"argc", 0, 0, f_argc},
          - {"argidx", 0, 0, f_argidx},
          - {"argv", 0, 1, f_argv},
          -#ifdef FEAT_FLOAT
          - {"asin", 1, 1, f_asin}, /* WJMc */
          - {"atan", 1, 1, f_atan},
          - {"atan2", 2, 2, f_atan2},
          -#endif
          - {"browse", 4, 4, f_browse},
          - {"browsedir", 2, 2, f_browsedir},
          - {"bufexists", 1, 1, f_bufexists},
          - {"buffer_exists", 1, 1, f_bufexists}, /* obsolete */
          - {"buffer_name", 1, 1, f_bufname}, /* obsolete */
          - {"buffer_number", 1, 1, f_bufnr}, /* obsolete */
          - {"buflisted", 1, 1, f_buflisted},
          - {"bufloaded", 1, 1, f_bufloaded},
          - {"bufname", 1, 1, f_bufname},
          - {"bufnr", 1, 2, f_bufnr},
          - {"bufwinnr", 1, 1, f_bufwinnr},
          - {"byte2line", 1, 1, f_byte2line},
          - {"byteidx", 2, 2, f_byteidx},
          - {"byteidxcomp", 2, 2, f_byteidxcomp},
          - {"call", 2, 3, f_call},
          -#ifdef FEAT_FLOAT
          - {"ceil", 1, 1, f_ceil},
          -#endif
          - {"changenr", 0, 0, f_changenr},
          - {"char2nr", 1, 2, f_char2nr},
          - {"cindent", 1, 1, f_cindent},
          - {"clearmatches", 0, 0, f_clearmatches},
          - {"col", 1, 1, f_col},
          + {"abs", 1, 1, f_abs, NULL},
          + {"acos", 1, 1, f_acos, NULL}, /* WJMc */
          +#endif
          + {"add", 2, 2, f_add, NULL},
          + {"and", 2, 2, f_and, NULL},
          + {"append", 2, 2, f_append, NULL},
          + {"argc", 0, 0, f_argc, NULL},
          + {"argidx", 0, 0, f_argidx, NULL},
          + {"argv", 0, 1, f_argv, NULL},
          +#ifdef FEAT_FLOAT
          + {"asin", 1, 1, f_asin, NULL}, /* WJMc */
          + {"atan", 1, 1, f_atan, NULL},
          + {"atan2", 2, 2, f_atan2, NULL},
          +#endif
          + {"browse", 4, 4, f_browse, NULL},
          + {"browsedir", 2, 2, f_browsedir, NULL},
          + {"bufexists", 1, 1, f_bufexists, NULL},
          + {"buffer_exists", 1, 1, f_bufexists, NULL}, /* obsolete */
          + {"buffer_name", 1, 1, f_bufname, NULL}, /* obsolete */
          + {"buffer_number", 1, 1, f_bufnr, NULL}, /* obsolete */
          + {"buflisted", 1, 1, f_buflisted, NULL},
          + {"bufloaded", 1, 1, f_bufloaded, NULL},
          + {"bufname", 1, 1, f_bufname, NULL},
          + {"bufnr", 1, 2, f_bufnr, NULL},
          + {"bufwinnr", 1, 1, f_bufwinnr, NULL},
          + {"byte2line", 1, 1, f_byte2line, NULL},
          + {"byteidx", 2, 2, f_byteidx, NULL},
          + {"byteidxcomp", 2, 2, f_byteidxcomp, NULL},
          + {"call", 2, 3, f_call, NULL},
          +#ifdef FEAT_FLOAT
          + {"ceil", 1, 1, f_ceil, NULL},
          +#endif
          + {"changenr", 0, 0, f_changenr, NULL},
          + {"char2nr", 1, 2, f_char2nr, NULL},
          + {"cindent", 1, 1, f_cindent, NULL},
          + {"clearmatches", 0, 0, f_clearmatches, NULL},
          + {"col", 1, 1, f_col, NULL},
          #if defined(FEAT_INS_EXPAND)
          - {"complete", 2, 2, f_complete},
          - {"complete_add", 1, 1, f_complete_add},
          - {"complete_check", 0, 0, f_complete_check},
          -#endif
          - {"confirm", 1, 4, f_confirm},
          - {"copy", 1, 1, f_copy},
          -#ifdef FEAT_FLOAT
          - {"cos", 1, 1, f_cos},
          - {"cosh", 1, 1, f_cosh},
          -#endif
          - {"count", 2, 4, f_count},
          - {"cscope_connection",0,3, f_cscope_connection},
          - {"cursor", 1, 3, f_cursor},
          - {"deepcopy", 1, 2, f_deepcopy},
          - {"delete", 1, 1, f_delete},
          - {"did_filetype", 0, 0, f_did_filetype},
          - {"diff_filler", 1, 1, f_diff_filler},
          - {"diff_hlID", 2, 2, f_diff_hlID},
          - {"empty", 1, 1, f_empty},
          - {"escape", 2, 2, f_escape},
          - {"eval", 1, 1, f_eval},
          - {"eventhandler", 0, 0, f_eventhandler},
          - {"executable", 1, 1, f_executable},
          - {"exists", 1, 1, f_exists},
          -#ifdef FEAT_FLOAT
          - {"exp", 1, 1, f_exp},
          -#endif
          - {"expand", 1, 3, f_expand},
          - {"extend", 2, 3, f_extend},
          - {"feedkeys", 1, 2, f_feedkeys},
          - {"file_readable", 1, 1, f_filereadable}, /* obsolete */
          - {"filereadable", 1, 1, f_filereadable},
          - {"filewritable", 1, 1, f_filewritable},
          - {"filter", 2, 2, f_filter},
          - {"finddir", 1, 3, f_finddir},
          - {"findfile", 1, 3, f_findfile},
          -#ifdef FEAT_FLOAT
          - {"float2nr", 1, 1, f_float2nr},
          - {"floor", 1, 1, f_floor},
          - {"fmod", 2, 2, f_fmod},
          -#endif
          - {"fnameescape", 1, 1, f_fnameescape},
          - {"fnamemodify", 2, 2, f_fnamemodify},
          - {"foldclosed", 1, 1, f_foldclosed},
          - {"foldclosedend", 1, 1, f_foldclosedend},
          - {"foldlevel", 1, 1, f_foldlevel},
          - {"foldtext", 0, 0, f_foldtext},
          - {"foldtextresult", 1, 1, f_foldtextresult},
          - {"foreground", 0, 0, f_foreground},
          - {"function", 1, 1, f_function},
          - {"garbagecollect", 0, 1, f_garbagecollect},
          - {"get", 2, 3, f_get},
          - {"getbufline", 2, 3, f_getbufline},
          - {"getbufvar", 2, 3, f_getbufvar},
          - {"getchar", 0, 1, f_getchar},
          - {"getcharmod", 0, 0, f_getcharmod},
          - {"getcmdline", 0, 0, f_getcmdline},
          - {"getcmdpos", 0, 0, f_getcmdpos},
          - {"getcmdtype", 0, 0, f_getcmdtype},
          - {"getcwd", 0, 0, f_getcwd},
          - {"getfontname", 0, 1, f_getfontname},
          - {"getfperm", 1, 1, f_getfperm},
          - {"getfsize", 1, 1, f_getfsize},
          - {"getftime", 1, 1, f_getftime},
          - {"getftype", 1, 1, f_getftype},
          - {"getline", 1, 2, f_getline},
          - {"getloclist", 1, 1, f_getqflist},
          - {"getmatches", 0, 0, f_getmatches},
          - {"getpid", 0, 0, f_getpid},
          - {"getpos", 1, 1, f_getpos},
          - {"getqflist", 0, 0, f_getqflist},
          - {"getreg", 0, 2, f_getreg},
          - {"getregtype", 0, 1, f_getregtype},
          - {"gettabvar", 2, 3, f_gettabvar},
          - {"gettabwinvar", 3, 4, f_gettabwinvar},
          - {"getwinposx", 0, 0, f_getwinposx},
          - {"getwinposy", 0, 0, f_getwinposy},
          - {"getwinvar", 2, 3, f_getwinvar},
          - {"glob", 1, 3, f_glob},
          - {"globpath", 2, 3, f_globpath},
          - {"has", 1, 1, f_has},
          - {"has_key", 2, 2, f_has_key},
          - {"haslocaldir", 0, 0, f_haslocaldir},
          - {"hasmapto", 1, 3, f_hasmapto},
          - {"highlightID", 1, 1, f_hlID}, /* obsolete */
          - {"highlight_exists",1, 1, f_hlexists}, /* obsolete */
          - {"histadd", 2, 2, f_histadd},
          - {"histdel", 1, 2, f_histdel},
          - {"histget", 1, 2, f_histget},
          - {"histnr", 1, 1, f_histnr},
          - {"hlID", 1, 1, f_hlID},
          - {"hlexists", 1, 1, f_hlexists},
          - {"hostname", 0, 0, f_hostname},
          - {"iconv", 3, 3, f_iconv},
          - {"indent", 1, 1, f_indent},
          - {"index", 2, 4, f_index},
          - {"input", 1, 3, f_input},
          - {"inputdialog", 1, 3, f_inputdialog},
          - {"inputlist", 1, 1, f_inputlist},
          - {"inputrestore", 0, 0, f_inputrestore},
          - {"inputsave", 0, 0, f_inputsave},
          - {"inputsecret", 1, 2, f_inputsecret},
          - {"insert", 2, 3, f_insert},
          - {"invert", 1, 1, f_invert},
          - {"isdirectory", 1, 1, f_isdirectory},
          - {"islocked", 1, 1, f_islocked},
          - {"items", 1, 1, f_items},
          - {"join", 1, 2, f_join},
          - {"keys", 1, 1, f_keys},
          - {"last_buffer_nr", 0, 0, f_last_buffer_nr},/* obsolete */
          - {"len", 1, 1, f_len},
          - {"libcall", 3, 3, f_libcall},
          - {"libcallnr", 3, 3, f_libcallnr},
          - {"line", 1, 1, f_line},
          - {"line2byte", 1, 1, f_line2byte},
          - {"lispindent", 1, 1, f_lispindent},
          - {"localtime", 0, 0, f_localtime},
          -#ifdef FEAT_FLOAT
          - {"log", 1, 1, f_log},
          - {"log10", 1, 1, f_log10},
          + {"complete", 2, 2, f_complete, NULL},
          + {"complete_add", 1, 1, f_complete_add, NULL},
          + {"complete_check", 0, 0, f_complete_check, NULL},
          +#endif
          + {"confirm", 1, 4, f_confirm, NULL},
          + {"copy", 1, 1, f_copy, NULL},
          +#ifdef FEAT_FLOAT
          + {"cos", 1, 1, f_cos, NULL},
          + {"cosh", 1, 1, f_cosh, NULL},
          +#endif
          + {"count", 2, 4, f_count, NULL},
          + {"cscope_connection",0,3, f_cscope_connection, NULL},
          + {"cursor", 1, 3, f_cursor, NULL},
          + {"deepcopy", 1, 2, f_deepcopy, NULL},
          + {"delete", 1, 1, f_delete, NULL},
          + {"did_filetype", 0, 0, f_did_filetype, NULL},
          + {"diff_filler", 1, 1, f_diff_filler, NULL},
          + {"diff_hlID", 2, 2, f_diff_hlID, NULL},
          + {"empty", 1, 1, f_empty, NULL},
          + {"escape", 2, 2, f_escape, NULL},
          + {"eval", 1, 1, f_eval, NULL},
          + {"eventhandler", 0, 0, f_eventhandler, NULL},
          + {"executable", 1, 1, f_executable, NULL},
          + {"exists", 1, 1, f_exists, NULL},
          +#ifdef FEAT_FLOAT
          + {"exp", 1, 1, f_exp, NULL},
          +#endif
          + {"expand", 1, 3, f_expand, NULL},
          + {"extend", 2, 3, f_extend, NULL},
          + {"feedkeys", 1, 2, f_feedkeys, NULL},
          + {"file_readable", 1, 1, f_filereadable, NULL}, /* obsolete */
          + {"filereadable", 1, 1, f_filereadable, NULL},
          + {"filewritable", 1, 1, f_filewritable, NULL},
          + {"filter", 2, 2, f_filter, NULL},
          + {"finddir", 1, 3, f_finddir, NULL},
          + {"findfile", 1, 3, f_findfile, NULL},
          +#ifdef FEAT_FLOAT
          + {"float2nr", 1, 1, f_float2nr, NULL},
          + {"floor", 1, 1, f_floor, NULL},
          + {"fmod", 2, 2, f_fmod, NULL},
          +#endif
          + {"fnameescape", 1, 1, f_fnameescape, NULL},
          + {"fnamemodify", 2, 2, f_fnamemodify, NULL},
          + {"foldclosed", 1, 1, f_foldclosed, NULL},
          + {"foldclosedend", 1, 1, f_foldclosedend, NULL},
          + {"foldlevel", 1, 1, f_foldlevel, NULL},
          + {"foldtext", 0, 0, f_foldtext, NULL},
          + {"foldtextresult", 1, 1, f_foldtextresult, NULL},
          + {"foreground", 0, 0, f_foreground, NULL},
          + {"function", 1, 1, f_function, NULL},
          + {"functype", 1, 1, f_functype, NULL},
          + {"garbagecollect", 0, 1, f_garbagecollect, NULL},
          + {"get", 2, 3, f_get, NULL},
          + {"getbufline", 2, 3, f_getbufline, NULL},
          + {"getbufvar", 2, 3, f_getbufvar, NULL},
          + {"getchar", 0, 1, f_getchar, NULL},
          + {"getcharmod", 0, 0, f_getcharmod, NULL},
          + {"getcmdline", 0, 0, f_getcmdline, NULL},
          + {"getcmdpos", 0, 0, f_getcmdpos, NULL},
          + {"getcmdtype", 0, 0, f_getcmdtype, NULL},
          + {"getcwd", 0, 0, f_getcwd, NULL},
          + {"getfontname", 0, 1, f_getfontname, NULL},
          + {"getfperm", 1, 1, f_getfperm, NULL},
          + {"getfsize", 1, 1, f_getfsize, NULL},
          + {"getftime", 1, 1, f_getftime, NULL},
          + {"getftype", 1, 1, f_getftype, NULL},
          + {"getline", 1, 2, f_getline, NULL},
          + {"getloclist", 1, 1, f_getqflist, NULL},
          + {"getmatches", 0, 0, f_getmatches, NULL},
          + {"getpid", 0, 0, f_getpid, NULL},
          + {"getpos", 1, 1, f_getpos, NULL},
          + {"getqflist", 0, 0, f_getqflist, NULL},
          + {"getreg", 0, 2, f_getreg, NULL},
          + {"getregtype", 0, 1, f_getregtype, NULL},
          + {"gettabvar", 2, 3, f_gettabvar, NULL},
          + {"gettabwinvar", 3, 4, f_gettabwinvar, NULL},
          + {"getwinposx", 0, 0, f_getwinposx, NULL},
          + {"getwinposy", 0, 0, f_getwinposy, NULL},
          + {"getwinvar", 2, 3, f_getwinvar, NULL},
          + {"glob", 1, 3, f_glob, NULL},
          + {"globpath", 2, 3, f_globpath, NULL},
          + {"has", 1, 1, f_has, NULL},
          + {"has_key", 2, 2, f_has_key, NULL},
          + {"haslocaldir", 0, 0, f_haslocaldir, NULL},
          + {"hasmapto", 1, 3, f_hasmapto, NULL},
          + {"highlightID", 1, 1, f_hlID, NULL}, /* obsolete */
          + {"highlight_exists",1, 1, f_hlexists, NULL}, /* obsolete */
          + {"histadd", 2, 2, f_histadd, NULL},
          + {"histdel", 1, 2, f_histdel, NULL},
          + {"histget", 1, 2, f_histget, NULL},
          + {"histnr", 1, 1, f_histnr, NULL},
          + {"hlID", 1, 1, f_hlID, NULL},
          + {"hlexists", 1, 1, f_hlexists, NULL},
          + {"hostname", 0, 0, f_hostname, NULL},
          + {"iconv", 3, 3, f_iconv, NULL},
          + {"indent", 1, 1, f_indent, NULL},
          + {"index", 2, 4, f_index, NULL},
          + {"input", 1, 3, f_input, NULL},
          + {"inputdialog", 1, 3, f_inputdialog, NULL},
          + {"inputlist", 1, 1, f_inputlist, NULL},
          + {"inputrestore", 0, 0, f_inputrestore, NULL},
          + {"inputsave", 0, 0, f_inputsave, NULL},
          + {"inputsecret", 1, 2, f_inputsecret, NULL},
          + {"insert", 2, 3, f_insert, NULL},
          + {"invert", 1, 1, f_invert, NULL},
          + {"isdirectory", 1, 1, f_isdirectory, NULL},
          + {"islocked", 1, 1, f_islocked, NULL},
          + {"items", 1, 1, f_items, NULL},
          + {"join", 1, 2, f_join, NULL},
          + {"keys", 1, 1, f_keys, NULL},
          + {"last_buffer_nr", 0, 0, f_last_buffer_nr, NULL},/* obsolete */
          + {"len", 1, 1, f_len, NULL},
          + {"libcall", 3, 3, f_libcall, NULL},
          + {"libcallnr", 3, 3, f_libcallnr, NULL},
          + {"line", 1, 1, f_line, NULL},
          + {"line2byte", 1, 1, f_line2byte, NULL},
          + {"lispindent", 1, 1, f_lispindent, NULL},
          + {"localtime", 0, 0, f_localtime, NULL},
          +#ifdef FEAT_FLOAT
          + {"log", 1, 1, f_log, NULL},
          + {"log10", 1, 1, f_log10, NULL},
          #endif
          #ifdef FEAT_LUA
          - {"luaeval", 1, 2, f_luaeval},
          -#endif
          - {"map", 2, 2, f_map},
          - {"maparg", 1, 4, f_maparg},
          - {"mapcheck", 1, 3, f_mapcheck},
          - {"match", 2, 4, f_match},
          - {"matchadd", 2, 4, f_matchadd},
          - {"matcharg", 1, 1, f_matcharg},
          - {"matchdelete", 1, 1, f_matchdelete},
          - {"matchend", 2, 4, f_matchend},
          - {"matchlist", 2, 4, f_matchlist},
          - {"matchstr", 2, 4, f_matchstr},
          - {"max", 1, 1, f_max},
          - {"min", 1, 1, f_min},
          + {"luaeval", 1, 2, f_luaeval, NULL},
          +#endif
          + {"map", 2, 2, f_map, NULL},
          + {"maparg", 1, 4, f_maparg, NULL},
          + {"mapcheck", 1, 3, f_mapcheck, NULL},
          + {"match", 2, 4, f_match, NULL},
          + {"matchadd", 2, 4, f_matchadd, NULL},
          + {"matcharg", 1, 1, f_matcharg, NULL},
          + {"matchdelete", 1, 1, f_matchdelete, NULL},
          + {"matchend", 2, 4, f_matchend, NULL},
          + {"matchlist", 2, 4, f_matchlist, NULL},
          + {"matchstr", 2, 4, f_matchstr, NULL},
          + {"max", 1, 1, f_max, NULL},
          + {"min", 1, 1, f_min, NULL},
          #ifdef vim_mkdir
          - {"mkdir", 1, 3, f_mkdir},
          -#endif
          - {"mode", 0, 1, f_mode},
          + {"mkdir", 1, 3, f_mkdir, NULL},
          +#endif
          + {"mode", 0, 1, f_mode, NULL},
          #ifdef FEAT_MZSCHEME
          - {"mzeval", 1, 1, f_mzeval},
          -#endif
          - {"nextnonblank", 1, 1, f_nextnonblank},
          - {"nr2char", 1, 2, f_nr2char},
          - {"or", 2, 2, f_or},
          - {"pathshorten", 1, 1, f_pathshorten},
          -#ifdef FEAT_FLOAT
          - {"pow", 2, 2, f_pow},
          -#endif
          - {"prevnonblank", 1, 1, f_prevnonblank},
          - {"printf", 2, 19, f_printf},
          - {"pumvisible", 0, 0, f_pumvisible},
          + {"mzeval", 1, 1, f_mzeval, NULL},
          +#endif
          + {"nextnonblank", 1, 1, f_nextnonblank, NULL},
          + {"nr2char", 1, 2, f_nr2char, NULL},
          + {"or", 2, 2, f_or, NULL},
          + {"pathshorten", 1, 1, f_pathshorten, NULL},
          +#ifdef FEAT_FLOAT
          + {"pow", 2, 2, f_pow, NULL},
          +#endif
          + {"prevnonblank", 1, 1, f_prevnonblank, NULL},
          + {"printf", 2, 19, f_printf, NULL},
          + {"pumvisible", 0, 0, f_pumvisible, NULL},
          #ifdef FEAT_PYTHON3
          - {"py3eval", 1, 1, f_py3eval},
          + {"py3eval", 1, 1, f_py3eval, NULL},
          #endif
          #ifdef FEAT_PYTHON
          - {"pyeval", 1, 1, f_pyeval},
          -#endif
          - {"range", 1, 3, f_range},
          - {"readfile", 1, 3, f_readfile},
          - {"reltime", 0, 2, f_reltime},
          - {"reltimestr", 1, 1, f_reltimestr},
          - {"remote_expr", 2, 3, f_remote_expr},
          - {"remote_foreground", 1, 1, f_remote_foreground},
          - {"remote_peek", 1, 2, f_remote_peek},
          - {"remote_read", 1, 1, f_remote_read},
          - {"remote_send", 2, 3, f_remote_send},
          - {"remove", 2, 3, f_remove},
          - {"rename", 2, 2, f_rename},
          - {"repeat", 2, 2, f_repeat},
          - {"resolve", 1, 1, f_resolve},
          - {"reverse", 1, 1, f_reverse},
          -#ifdef FEAT_FLOAT
          - {"round", 1, 1, f_round},
          -#endif
          - {"screenattr", 2, 2, f_screenattr},
          - {"screenchar", 2, 2, f_screenchar},
          - {"screencol", 0, 0, f_screencol},
          - {"screenrow", 0, 0, f_screenrow},
          - {"search", 1, 4, f_search},
          - {"searchdecl", 1, 3, f_searchdecl},
          - {"searchpair", 3, 7, f_searchpair},
          - {"searchpairpos", 3, 7, f_searchpairpos},
          - {"searchpos", 1, 4, f_searchpos},
          - {"server2client", 2, 2, f_server2client},
          - {"serverlist", 0, 0, f_serverlist},
          - {"setbufvar", 3, 3, f_setbufvar},
          - {"setcmdpos", 1, 1, f_setcmdpos},
          - {"setline", 2, 2, f_setline},
          - {"setloclist", 2, 3, f_setloclist},
          - {"setmatches", 1, 1, f_setmatches},
          - {"setpos", 2, 2, f_setpos},
          - {"setqflist", 1, 2, f_setqflist},
          - {"setreg", 2, 3, f_setreg},
          - {"settabvar", 3, 3, f_settabvar},
          - {"settabwinvar", 4, 4, f_settabwinvar},
          - {"setwinvar", 3, 3, f_setwinvar},
          + {"pyeval", 1, 1, f_pyeval, NULL},
          +#endif
          + {"range", 1, 3, f_range, NULL},
          + {"readfile", 1, 3, f_readfile, NULL},
          + {"reltime", 0, 2, f_reltime, NULL},
          + {"reltimestr", 1, 1, f_reltimestr, NULL},
          + {"remote_expr", 2, 3, f_remote_expr, NULL},
          + {"remote_foreground", 1, 1, f_remote_foreground, NULL},
          + {"remote_peek", 1, 2, f_remote_peek, NULL},
          + {"remote_read", 1, 1, f_remote_read, NULL},
          + {"remote_send", 2, 3, f_remote_send, NULL},
          + {"remove", 2, 3, f_remove, NULL},
          + {"rename", 2, 2, f_rename, NULL},
          + {"repeat", 2, 2, f_repeat, NULL},
          + {"resolve", 1, 1, f_resolve, NULL},
          + {"reverse", 1, 1, f_reverse, NULL},
          +#ifdef FEAT_FLOAT
          + {"round", 1, 1, f_round, NULL},
          +#endif
          + {"screenattr", 2, 2, f_screenattr, NULL},
          + {"screenchar", 2, 2, f_screenchar, NULL},
          + {"screencol", 0, 0, f_screencol, NULL},
          + {"screenrow", 0, 0, f_screenrow, NULL},
          + {"search", 1, 4, f_search, NULL},
          + {"searchdecl", 1, 3, f_searchdecl, NULL},
          + {"searchpair", 3, 7, f_searchpair, NULL},
          + {"searchpairpos", 3, 7, f_searchpairpos, NULL},
          + {"searchpos", 1, 4, f_searchpos, NULL},
          + {"server2client", 2, 2, f_server2client, NULL},
          + {"serverlist", 0, 0, f_serverlist, NULL},
          + {"setbufvar", 3, 3, f_setbufvar, NULL},
          + {"setcmdpos", 1, 1, f_setcmdpos, NULL},
          + {"setline", 2, 2, f_setline, NULL},
          + {"setloclist", 2, 3, f_setloclist, NULL},
          + {"setmatches", 1, 1, f_setmatches, NULL},
          + {"setpos", 2, 2, f_setpos, NULL},
          + {"setqflist", 1, 2, f_setqflist, NULL},
          + {"setreg", 2, 3, f_setreg, NULL},
          + {"settabvar", 3, 3, f_settabvar, NULL},
          + {"settabwinvar", 4, 4, f_settabwinvar, NULL},
          + {"setwinvar", 3, 3, f_setwinvar, NULL},
          #ifdef FEAT_CRYPT
          - {"sha256", 1, 1, f_sha256},
          -#endif
          - {"shellescape", 1, 2, f_shellescape},
          - {"shiftwidth", 0, 0, f_shiftwidth},
          - {"simplify", 1, 1, f_simplify},
          -#ifdef FEAT_FLOAT
          - {"sin", 1, 1, f_sin},
          - {"sinh", 1, 1, f_sinh},
          -#endif
          - {"sort", 1, 3, f_sort},
          - {"soundfold", 1, 1, f_soundfold},
          - {"spellbadword", 0, 1, f_spellbadword},
          - {"spellsuggest", 1, 3, f_spellsuggest},
          - {"split", 1, 3, f_split},
          -#ifdef FEAT_FLOAT
          - {"sqrt", 1, 1, f_sqrt},
          - {"str2float", 1, 1, f_str2float},
          -#endif
          - {"str2nr", 1, 2, f_str2nr},
          - {"strchars", 1, 1, f_strchars},
          - {"strdisplaywidth", 1, 2, f_strdisplaywidth},
          + {"sha256", 1, 1, f_sha256, NULL},
          +#endif
          + {"shellescape", 1, 2, f_shellescape, NULL},
          + {"shiftwidth", 0, 0, f_shiftwidth, NULL},
          + {"simplify", 1, 1, f_simplify, NULL},
          +#ifdef FEAT_FLOAT
          + {"sin", 1, 1, f_sin, NULL},
          + {"sinh", 1, 1, f_sinh, NULL},
          +#endif
          + {"sort", 1, 3, f_sort, NULL},
          + {"soundfold", 1, 1, f_soundfold, NULL},
          + {"spellbadword", 0, 1, f_spellbadword, NULL},
          + {"spellsuggest", 1, 3, f_spellsuggest, NULL},
          + {"split", 1, 3, f_split, NULL},
          +#ifdef FEAT_FLOAT
          + {"sqrt", 1, 1, f_sqrt, NULL},
          + {"str2float", 1, 1, f_str2float, NULL},
          +#endif
          + {"str2nr", 1, 2, f_str2nr, NULL},
          + {"strchars", 1, 1, f_strchars, NULL},
          + {"strdisplaywidth", 1, 2, f_strdisplaywidth, NULL},
          #ifdef HAVE_STRFTIME
          - {"strftime", 1, 2, f_strftime},
          -#endif
          - {"stridx", 2, 3, f_stridx},
          - {"string", 1, 1, f_string},
          - {"strlen", 1, 1, f_strlen},
          - {"strpart", 2, 3, f_strpart},
          - {"strridx", 2, 3, f_strridx},
          - {"strtrans", 1, 1, f_strtrans},
          - {"strwidth", 1, 1, f_strwidth},
          - {"submatch", 1, 1, f_submatch},
          - {"substitute", 4, 4, f_substitute},
          - {"synID", 3, 3, f_synID},
          - {"synIDattr", 2, 3, f_synIDattr},
          - {"synIDtrans", 1, 1, f_synIDtrans},
          - {"synconcealed", 2, 2, f_synconcealed},
          - {"synstack", 2, 2, f_synstack},
          - {"system", 1, 2, f_system},
          - {"tabpagebuflist", 0, 1, f_tabpagebuflist},
          - {"tabpagenr", 0, 1, f_tabpagenr},
          - {"tabpagewinnr", 1, 2, f_tabpagewinnr},
          - {"tagfiles", 0, 0, f_tagfiles},
          - {"taglist", 1, 1, f_taglist},
          -#ifdef FEAT_FLOAT
          - {"tan", 1, 1, f_tan},
          - {"tanh", 1, 1, f_tanh},
          -#endif
          - {"tempname", 0, 0, f_tempname},
          - {"test", 1, 1, f_test},
          - {"tolower", 1, 1, f_tolower},
          - {"toupper", 1, 1, f_toupper},
          - {"tr", 3, 3, f_tr},
          -#ifdef FEAT_FLOAT
          - {"trunc", 1, 1, f_trunc},
          -#endif
          - {"type", 1, 1, f_type},
          - {"undofile", 1, 1, f_undofile},
          - {"undotree", 0, 0, f_undotree},
          - {"values", 1, 1, f_values},
          - {"virtcol", 1, 1, f_virtcol},
          - {"visualmode", 0, 1, f_visualmode},
          - {"wildmenumode", 0, 0, f_wildmenumode},
          - {"winbufnr", 1, 1, f_winbufnr},
          - {"wincol", 0, 0, f_wincol},
          - {"winheight", 1, 1, f_winheight},
          - {"winline", 0, 0, f_winline},
          - {"winnr", 0, 1, f_winnr},
          - {"winrestcmd", 0, 0, f_winrestcmd},
          - {"winrestview", 1, 1, f_winrestview},
          - {"winsaveview", 0, 0, f_winsaveview},
          - {"winwidth", 1, 1, f_winwidth},
          - {"writefile", 2, 3, f_writefile},
          - {"xor", 2, 2, f_xor},
          + {"strftime", 1, 2, f_strftime, NULL},
          +#endif
          + {"stridx", 2, 3, f_stridx, NULL},
          + {"string", 1, 1, f_string, NULL},
          + {"strlen", 1, 1, f_strlen, NULL},
          + {"strpart", 2, 3, f_strpart, NULL},
          + {"strridx", 2, 3, f_strridx, NULL},
          + {"strtrans", 1, 1, f_strtrans, NULL},
          + {"strwidth", 1, 1, f_strwidth, NULL},
          + {"submatch", 1, 1, f_submatch, NULL},
          + {"substitute", 4, 4, f_substitute, NULL},
          + {"synID", 3, 3, f_synID, NULL},
          + {"synIDattr", 2, 3, f_synIDattr, NULL},
          + {"synIDtrans", 1, 1, f_synIDtrans, NULL},
          + {"synconcealed", 2, 2, f_synconcealed, NULL},
          + {"synstack", 2, 2, f_synstack, NULL},
          + {"system", 1, 2, f_system, NULL},
          + {"tabpagebuflist", 0, 1, f_tabpagebuflist, NULL},
          + {"tabpagenr", 0, 1, f_tabpagenr, NULL},
          + {"tabpagewinnr", 1, 2, f_tabpagewinnr, NULL},
          + {"tagfiles", 0, 0, f_tagfiles, NULL},
          + {"taglist", 1, 1, f_taglist, NULL},
          +#ifdef FEAT_FLOAT
          + {"tan", 1, 1, f_tan, NULL},
          + {"tanh", 1, 1, f_tanh, NULL},
          +#endif
          + {"tempname", 0, 0, f_tempname, NULL},
          + {"test", 1, 1, f_test, NULL},
          + {"tolower", 1, 1, f_tolower, NULL},
          + {"toupper", 1, 1, f_toupper, NULL},
          + {"tr", 3, 3, f_tr, NULL},
          +#ifdef FEAT_FLOAT
          + {"trunc", 1, 1, f_trunc, NULL},
          +#endif
          + {"type", 1, 1, f_type, NULL},
          + {"undofile", 1, 1, f_undofile, NULL},
          + {"undotree", 0, 0, f_undotree, NULL},
          + {"values", 1, 1, f_values, NULL},
          + {"virtcol", 1, 1, f_virtcol, NULL},
          + {"visualmode", 0, 1, f_visualmode, NULL},
          + {"wildmenumode", 0, 0, f_wildmenumode, NULL},
          + {"winbufnr", 1, 1, f_winbufnr, NULL},
          + {"wincol", 0, 0, f_wincol, NULL},
          + {"winheight", 1, 1, f_winheight, NULL},
          + {"winline", 0, 0, f_winline, NULL},
          + {"winnr", 0, 1, f_winnr, NULL},
          + {"winrestcmd", 0, 0, f_winrestcmd, NULL},
          + {"winrestview", 1, 1, f_winrestview, NULL},
          + {"winsaveview", 0, 0, f_winsaveview, NULL},
          + {"winwidth", 1, 1, f_winwidth, NULL},
          + {"writefile", 2, 3, f_writefile, NULL},
          + {"xor", 2, 2, f_xor, NULL},
          };

          #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
          @@ -8242,9 +8327,9 @@

          /*
          * Find internal function in table above.
          - * Return index, or -1 if not found
          - */
          - static int
          + * Return pointer, or NULL if not found
          + */
          + static struct fst *
          find_internal_func(name)
          char_u *name; /* name of the function */
          {
          @@ -8265,39 +8350,170 @@
          else if (cmp > 0)
          first = x + 1;
          else
          - return x;
          - }
          - return -1;
          + return &functions[x];
          + }
          + return NULL;
          }

          /*
          * Check if "name" is a variable of type VAR_FUNC. If so, return the function
          - * name it contains, otherwise return "name".
          - */
          - static char_u *
          -deref_func_name(name, lenp)
          + * definition it contains, otherwise try to find internal or user-defined
          + * function with the given name. Returns NULL on failure.
          + *
          + * Flags:
          + * DF_CHECK_VAR : Try loading function from a variable.
          + * DF_RUN_EVENT : Run FuncUndefined event if function was not found
          + * DF_CREATE_AUTOLOAD: Create references to autoload function
          + * DF_NO_VAR : DF_RUN_EVENT and DF_CREATE_AUTOLOAD
          + * DF_ALL : All of the above
          + */
          + func_T *
          +deref_func_name(name, len, flags)
          char_u *name;
          - int *lenp;
          + const int len;
          + int flags;
          {
          dictitem_T *v;
          int cc;
          -
          - cc = name[*lenp];
          - name[*lenp] = NUL;
          - v = find_var(name, NULL);
          - name[*lenp] = cc;
          - if (v != NULL && v->di_tv.v_type == VAR_FUNC)
          - {
          - if (v->di_tv.vval.v_string == NULL)
          - {
          - *lenp = 0;
          - return (char_u *)""; /* just in case */
          - }
          - *lenp = (int)STRLEN(v->di_tv.vval.v_string);
          - return v->di_tv.vval.v_string;
          - }
          -
          - return name;
          + func_T *r = NULL;
          +
          + cc = name[len];
          + if (flags & DF_CHECK_VAR)
          + {
          + name[len] = NUL;
          + v = find_var(name, NULL, FALSE);
          + name[len] = cc;
          +
          + if (v != NULL && v->di_tv.v_type == VAR_FUNC)
          + {
          + if (v->di_tv.vval.v_func == NULL)
          + return NULL;
          + ++v->di_tv.vval.v_func->fv_refcount;
          + return v->di_tv.vval.v_func;
          + }
          + }
          +
          + name[len] = NUL;
          + if (builtin_function(name))
          + {
          + struct fst *intfp;
          + intfp = find_internal_func(name);
          +
          + if (intfp != NULL)
          + {
          + if (intfp->f_func == NULL)
          + {
          + intfp->f_func = func_alloc();
          + if (intfp->f_func != NULL)
          + {
          + ++intfp->f_func->fv_refcount;
          + intfp->f_func->fv_data = intfp;
          + intfp->f_func->fv_type = &internal_func_type;
          + }
          + }
          +
          + r = intfp->f_func;
          + }
          + }
          + else
          + {
          + char_u *fname = NULL;
          + char_u *pp;
          + char_u sid_buf[20];
          + int lead;
          + int old_len;
          + int new_len = len;
          + ufunc_T *fp;
          +
          + lead = eval_fname_script(name);
          + new_len -= lead;
          + old_len = new_len;
          + pp = name + lead;
          +
          + if (lead)
          + {
          + lead = 3;
          + if (eval_fname_sid(name))
          + {
          + if (current_SID <= 0)
          + {
          + EMSG(_(e_usingsid));
          + new_len = 0;
          + }
          + else
          + {
          + sprintf((char *) sid_buf, "%ld_", (long) current_SID);
          + lead += STRLEN(sid_buf);
          + }
          + }
          + else
          + *sid_buf = NUL;
          +
          + if (new_len)
          + fname = (char_u *) alloc(new_len + lead + 1);
          + }
          + else
          + {
          + *sid_buf = NUL;
          + fname = name;
          + }
          +
          + if (fname != NULL)
          + {
          + if (lead)
          + {
          + fname[0] = K_SPECIAL;
          + fname[1] = KS_EXTRA;
          + fname[2] = (int) KE_SNR;
          +
          + if (*sid_buf != NUL)
          + mch_memmove(fname + 3, sid_buf, lead - 3);
          +
          + mch_memmove(fname + lead, pp, (size_t) old_len + 1);
          + }
          + fp = find_func(fname);
          +
          +#ifdef FEAT_AUTOCMD
          + /* Trigger FuncUndefined event, may load the function. */
          + if (flags & DF_RUN_EVENT
          + && fp == NULL
          + && apply_autocmds(EVENT_FUNCUNDEFINED,
          + fname, fname, TRUE, NULL)
          + && !aborting())
          + /* executed an autocommand, search for the function again */
          + fp = find_func(name);
          +#endif
          +
          + if (fp == NULL)
          + {
          + if (flags & DF_CREATE_AUTOLOAD
          + && vim_strchr(fname, AUTOLOAD_CHAR) != NULL
          + && valid_autoload_name(fname))
          + {
          + aufunc_T *aufp;
          +
          + if ((aufp = aufunc_alloc()) != NULL &&
          + (r = func_alloc()) != NULL)
          + {
          + aufp->auf_name = vim_strsave(fname);
          + r->fv_data = (void *) aufp;
          + r->fv_type = &autoload_func_type;
          + }
          + }
          + }
          + else
          + r = fp->uf_func;
          +
          + if (lead)
          + vim_free(fname);
          + }
          + }
          + name[len] = cc;
          +
          + if (r != NULL)
          + ++r->fv_refcount;
          +
          + return r;
          }

          /*
          @@ -8305,10 +8521,9 @@
          * Return OK or FAIL.
          */
          static int
          -get_func_tv(name, len, rettv, arg, firstline, lastline, doesrange,
          +get_func_tv(func, rettv, arg, firstline, lastline, doesrange,
          evaluate, selfdict)
          - char_u *name; /* name of the function */
          - int len; /* length of "name" */
          + func_T *func; /* function definition */
          typval_T *rettv;
          char_u **arg; /* argument, pointing to the '(' */
          linenr_T firstline; /* first line of range */
          @@ -8345,15 +8560,20 @@
          else
          ret = FAIL;

          - if (ret == OK)
          - ret = call_func(name, len, rettv, argcount, argvars,
          - firstline, lastline, doesrange, evaluate, selfdict);
          - else if (!aborting())
          - {
          - if (argcount == MAX_FUNC_ARGS)
          - emsg_funcname(N_("E740: Too many arguments for function %s"), name);
          - else
          - emsg_funcname(N_("E116: Invalid arguments for function %s"), name);
          + if (evaluate)
          + {
          + if (ret == OK)
          + ret = call_func(func, rettv, argcount, argvars,
          + firstline, lastline, doesrange, selfdict);
          + else if (!aborting())
          + {
          + if (argcount == MAX_FUNC_ARGS)
          + emsg_funcname(N_("E740: Too many arguments for function %s"),
          + FUNC_NAME(func));
          + else
          + emsg_funcname(N_("E116: Invalid arguments for function %s"),
          + FUNC_NAME(func));
          + }
          }

          while (--argcount >= 0)
          @@ -8363,17 +8583,86 @@
          return ret;
          }

          -
          -/*
          - * Call a function with its resolved parameters
          - * Return FAIL when the function can't be called, OK otherwise.
          - * Also returns OK when an error was encountered while executing the function.
          - */
          - static int
          -call_func(funcname, len, rettv, argcount, argvars, firstline, lastline,
          - doesrange, evaluate, selfdict)
          - char_u *funcname; /* name of the function */
          - int len; /* length of "name" */
          + static int
          +call_internal_func(intfp, rettv, argcount, argvars, firstline, lastline, doesrange, selfdict)
          + struct fst *intfp; /* pointer to function */
          + typval_T *rettv; /* return value */
          + int argcount; /* nr of args */
          + typval_T *argvars; /* arguments */
          + linenr_T firstline; /* first line of range */
          + linenr_T lastline; /* last line of range */
          + int *doesrange; /* is set to True if function handles range */
          + dict_T *selfdict; /* Dictionary for "self" */
          +{
          + if (argcount < intfp->f_min_argc)
          + return ERROR_TOOFEW;
          + else if (argcount > intfp->f_max_argc)
          + return ERROR_TOOMANY;
          +
          + argvars[argcount].v_type = VAR_UNKNOWN;
          + intfp->f_call(argvars, rettv);
          +
          + return ERROR_NONE;
          +}
          +
          + static char_u *
          +repr_internal_func(intfp)
          + struct fst *intfp;
          +{
          + return string_quote((char_u *) intfp->f_name, "function");
          +}
          +
          + static void
          +dealloc_internal_func(intfp)
          + struct fst *intfp;
          +{
          + intfp->f_func = NULL;
          + return;
          +}
          +
          + static int
          +compare_internal_funcs(intfp1, intfp2)
          + struct fst *intfp1;
          + struct fst *intfp2;
          +{
          + return intfp1 == intfp2;
          +}
          +
          + static char_u *
          +name_internal_func(intfp)
          + struct fst *intfp;
          +{
          + return (char_u *) intfp->f_name;
          +}
          +
          +static char_u *internal_func_type_name = (char_u *) "internal";
          +#define INTERNAL_FUNC_TYPE_LEN 8
          +
          + static char_u *
          +type_internal_func(intfp)
          + struct fst *intfp UNUSED;
          +{
          + return vim_strnsave(internal_func_type_name, INTERNAL_FUNC_TYPE_LEN);
          +}
          +
          +static funcdef_T internal_func_type = {
          + (function_caller) call_internal_func, /* fd_call */
          + (function_representer) repr_internal_func, /* fd_repr */
          + (function_destructor) dealloc_internal_func, /* fd_dealloc */
          + (function_cmp) compare_internal_funcs, /* fd_compare */
          + (function_representer) name_internal_func, /* fd_name */
          + (function_representer) type_internal_func, /* fd_type */
          +};
          +
          + static aufunc_T *
          +aufunc_alloc()
          +{
          + return (aufunc_T *) alloc_clear(sizeof(aufunc_T));
          +}
          +
          + static int
          +call_autoload_func(aufp, rettv, argcount, argvars, firstline, lastline, doesrange, selfdict)
          + aufunc_T *aufp;
          typval_T *rettv; /* return value goes here */
          int argcount; /* number of "argvars" */
          typval_T *argvars; /* vars for arguments, must have "argcount"
          @@ -8381,212 +8670,177 @@
          linenr_T firstline; /* first line of range */
          linenr_T lastline; /* last line of range */
          int *doesrange; /* return: function handled range */
          - int evaluate;
          dict_T *selfdict; /* Dictionary for "self" */
          {
          - int ret = FAIL;
          -#define ERROR_UNKNOWN 0
          -#define ERROR_TOOMANY 1
          -#define ERROR_TOOFEW 2
          -#define ERROR_SCRIPT 3
          -#define ERROR_DICT 4
          -#define ERROR_NONE 5
          -#define ERROR_OTHER 6
          - int error = ERROR_NONE;
          - int i;
          - int llen;
          - ufunc_T *fp;
          -#define FLEN_FIXED 40
          - char_u fname_buf[FLEN_FIXED + 1];
          - char_u *fname;
          - char_u *name;
          -
          - /* Make a copy of the name, if it comes from a funcref variable it could
          - * be changed or deleted in the called function. */
          - name = vim_strnsave(funcname, len);
          - if (name == NULL)
          - return ret;
          -
          - /*
          - * In a script change <SID>name() and s:name() to K_SNR 123_name().
          - * Change <SNR>123_name() to K_SNR 123_name().
          - * Use fname_buf[] when it fits, otherwise allocate memory (slow).
          - */
          - llen = eval_fname_script(name);
          - if (llen > 0)
          - {
          - fname_buf[0] = K_SPECIAL;
          - fname_buf[1] = KS_EXTRA;
          - fname_buf[2] = (int)KE_SNR;
          - i = 3;
          - if (eval_fname_sid(name)) /* "<SID>" or "s:" */
          - {
          - if (current_SID <= 0)
          - error = ERROR_SCRIPT;
          - else
          - {
          - sprintf((char *)fname_buf + 3, "%ld_", (long)current_SID);
          - i = (int)STRLEN(fname_buf);
          - }
          - }
          - if (i + STRLEN(name + llen) < FLEN_FIXED)
          - {
          - STRCPY(fname_buf + i, name + llen);
          - fname = fname_buf;
          - }
          - else
          - {
          - fname = alloc((unsigned)(i + STRLEN(name + llen) + 1));
          - if (fname == NULL)
          - error = ERROR_OTHER;
          - else
          - {
          - mch_memmove(fname, fname_buf, (size_t)i);
          - STRCPY(fname + i, name + llen);
          - }
          - }
          - }
          - else
          - fname = name;
          + /* First, check whether function was already loaded. */
          + if (aufp->auf_func == NULL && !aborting())
          + aufp->auf_func = deref_func_name(aufp->auf_name,
          + STRLEN(aufp->auf_name),
          + DF_CHECK_VAR|DF_RUN_EVENT);
          +
          + /* If not then try loading a package. */
          + if (aufp->auf_func == NULL && script_autoload(aufp->auf_name, TRUE) &&
          + !aborting())
          + /* loaded a package, search for the function again */
          + /* Note: it is allowed for loaded function to be defined in a variable
          + */
          + aufp->auf_func = deref_func_name(aufp->auf_name,
          + STRLEN(aufp->auf_name),
          + DF_CHECK_VAR);
          +
          + if (aufp->auf_func == NULL)
          + {
          + EMSG2(_(e_unknown_function), aufp->auf_name);
          + return ERROR_OTHER;
          + }
          +
          + return FUNC_CALL(aufp->auf_func, rettv, argcount, argvars,
          + firstline, lastline, doesrange, selfdict);
          +}
          +
          + static char_u *
          +repr_autoload_func(aufp)
          + aufunc_T *aufp;
          +{
          + return string_quote(aufp->auf_name, "function");
          +}
          +
          + static void
          +dealloc_autoload_func(aufp)
          + aufunc_T *aufp;
          +{
          + if (aufp->auf_func != NULL)
          + func_unref(aufp->auf_func);
          + vim_free(aufp->auf_name);
          + vim_free(aufp);
          +}
          +
          + static int
          +compare_autoload_funcs(aufp1, aufp2)
          + aufunc_T *aufp1;
          + aufunc_T *aufp2;
          +{
          + return STRCMP(aufp1->auf_name, aufp2->auf_name) == 0;
          +}
          +
          + static char_u *
          +name_autoload_func(aufp)
          + aufunc_T *aufp;
          +{
          + return aufp->auf_name;
          +}
          +
          +static char_u *autoload_func_type_name = (char_u *) "autoload";
          +#define AUTOLOAD_FUNC_TYPE_LEN 8
          +
          + static char_u *
          +type_autoload_func(aufp)
          + aufunc_T *aufp;
          +{
          + if (aufp->auf_func == NULL)
          + return vim_strnsave(autoload_func_type_name, AUTOLOAD_FUNC_TYPE_LEN);
          + else
          + {
          + char_u *loaded_type;
          + int loaded_type_len;
          + char_u *ret_type;
          +
          + if ((loaded_type = FUNC_TYPE(aufp->auf_func)) == NULL)
          + return NULL;
          +
          + loaded_type_len = STRLEN(loaded_type);
          +
          + /* 2: colon and NUL */
          + ret_type = (char_u*)alloc(loaded_type_len + 2 + AUTOLOAD_FUNC_TYPE_LEN);
          +
          + if (ret_type == NULL)
          + return NULL;
          +
          + mch_memmove(ret_type, autoload_func_type_name,
          + (size_t) AUTOLOAD_FUNC_TYPE_LEN);
          + ret_type[AUTOLOAD_FUNC_TYPE_LEN] = ':';
          + mch_memmove(ret_type + AUTOLOAD_FUNC_TYPE_LEN + 1, loaded_type,
          + loaded_type_len);
          + ret_type[AUTOLOAD_FUNC_TYPE_LEN + loaded_type_len + 1] = NUL;
          +
          + vim_free(loaded_type);
          + return ret_type;
          + }
          +}
          +
          +static funcdef_T autoload_func_type = {
          + (function_caller) call_autoload_func, /* fd_call */
          + (function_representer) repr_autoload_func, /* fd_repr */
          + (function_destructor) dealloc_autoload_func, /* fd_dealloc */
          + (function_cmp) compare_autoload_funcs, /* fd_compare */
          + (function_representer) name_autoload_func, /* fd_name */
          + (function_representer) type_autoload_func, /* fd_type */
          +};
          +
          +/*
          + * Call a function with its resolved parameters
          + * Return FAIL when the function can't be called, OK otherwise.
          + * Also returns OK when an error was encountered while executing the function.
          + */
          + static int
          +call_func(func, rettv, argcount, argvars, firstline, lastline, doesrange, selfdict)
          + func_T *func; /* function definition */
          + typval_T *rettv; /* return value goes here */
          + int argcount; /* number of "argvars" */
          + typval_T *argvars; /* vars for arguments, must have "argcount"
          + PLUS ONE elements! */
          + linenr_T firstline; /* first line of range */
          + linenr_T lastline; /* last line of range */
          + int *doesrange; /* return: function handled range */
          + dict_T *selfdict; /* Dictionary for "self" */
          +{
          + int error;

          *doesrange = FALSE;

          -
          - /* execute the function if no errors detected and executing */
          - if (evaluate && error == ERROR_NONE)
          - {
          - rettv->v_type = VAR_NUMBER; /* default rettv is number zero */
          - rettv->vval.v_number = 0;
          - error = ERROR_UNKNOWN;
          -
          - if (!builtin_function(fname))
          - {
          - /*
          - * User defined function.
          - */
          - fp = find_func(fname);
          -
          -#ifdef FEAT_AUTOCMD
          - /* Trigger FuncUndefined event, may load the function. */
          - if (fp == NULL
          - && apply_autocmds(EVENT_FUNCUNDEFINED,
          - fname, fname, TRUE, NULL)
          - && !aborting())
          - {
          - /* executed an autocommand, search for the function again */
          - fp = find_func(fname);
          - }
          -#endif
          - /* Try loading a package. */
          - if (fp == NULL && script_autoload(fname, TRUE) && !aborting())
          - {
          - /* loaded a package, search for the function again */
          - fp = find_func(fname);
          - }
          -
          - if (fp != NULL)
          - {
          - if (fp->uf_flags & FC_RANGE)
          - *doesrange = TRUE;
          - if (argcount < fp->uf_args.ga_len)
          - error = ERROR_TOOFEW;
          - else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len)
          - error = ERROR_TOOMANY;
          - else if ((fp->uf_flags & FC_DICT) && selfdict == NULL)
          - error = ERROR_DICT;
          - else
          - {
          - /*
          - * Call the user function.
          - * Save and restore search patterns, script variables and
          - * redo buffer.
          - */
          - save_search_patterns();
          - saveRedobuff();
          - ++fp->uf_calls;
          - call_user_func(fp, argcount, argvars, rettv,
          - firstline, lastline,
          - (fp->uf_flags & FC_DICT) ? selfdict : NULL);
          - if (--fp->uf_calls <= 0 && isdigit(*fp->uf_name)
          - && fp->uf_refcount <= 0)
          - /* Function was unreferenced while being used, free it
          - * now. */
          - func_free(fp);
          - restoreRedobuff();
          - restore_search_patterns();
          - error = ERROR_NONE;
          - }
          - }
          - }
          - else
          - {
          - /*
          - * Find the function name in the table, call its implementation.
          - */
          - i = find_internal_func(fname);
          - if (i >= 0)
          - {
          - if (argcount < functions[i].f_min_argc)
          - error = ERROR_TOOFEW;
          - else if (argcount > functions[i].f_max_argc)
          - error = ERROR_TOOMANY;
          - else
          - {
          - argvars[argcount].v_type = VAR_UNKNOWN;
          - functions[i].f_func(argvars, rettv);
          - error = ERROR_NONE;
          - }
          - }
          - }
          - /*
          - * The function call (or "FuncUndefined" autocommand sequence) might
          - * have been aborted by an error, an interrupt, or an explicitly thrown
          - * exception that has not been caught so far. This situation can be
          - * tested for by calling aborting(). For an error in an internal
          - * function or for the "E132" error in call_user_func(), however, the
          - * throw point at which the "force_abort" flag (temporarily reset by
          - * emsg()) is normally updated has not been reached yet. We need to
          - * update that flag first to make aborting() reliable.
          - */
          - update_force_abort();
          - }
          - if (error == ERROR_NONE)
          - ret = OK;
          -
          - /*
          - * Report an error unless the argument evaluation or function call has been
          - * cancelled due to an aborting error, an interrupt, or an exception.
          - */
          + if (func == NULL)
          + return FAIL;
          +
          + rettv->v_type = VAR_NUMBER; /* default rettv is number zero */
          + rettv->vval.v_number = 0;
          + error = func->fv_type->fd_call(func->fv_data, rettv, argcount, argvars,
          + firstline, lastline, doesrange, selfdict);
          +
          + /*
          + * The function call (or "FuncUndefined" autocommand sequence) might
          + * have been aborted by an error, an interrupt, or an explicitly thrown
          + * exception that has not been caught so far. This situation can be
          + * tested for by calling aborting(). For an error in an internal
          + * function or for the "E132" error in call_user_func(), however, the
          + * throw point at which the "force_abort" flag (temporarily reset by
          + * emsg()) is normally updated has not been reached yet. We need to
          + * update that flag first to make aborting() reliable.
          + */
          + update_force_abort();
          +
          if (!aborting())
          {
          switch (error)
          {
          - case ERROR_UNKNOWN:
          - emsg_funcname(N_("E117: Unknown function: %s"), name);
          - break;
          case ERROR_TOOMANY:
          - emsg_funcname(e_toomanyarg, name);
          + emsg_funcname(e_toomanyarg, FUNC_NAME(func));
          break;
          case ERROR_TOOFEW:
          emsg_funcname(N_("E119: Not enough arguments for function: %s"),
          - name);
          + FUNC_NAME(func));
          break;
          case ERROR_SCRIPT:
          emsg_funcname(N_("E120: Using <SID> not in a script context: %s"),
          - name);
          + FUNC_NAME(func));
          break;
          case ERROR_DICT:
          emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"),
          - name);
          - break;
          - }
          - }
          -
          - if (fname != name && fname != fname_buf)
          - vim_free(fname);
          - vim_free(name);
          -
          - return ret;
          + FUNC_NAME(func));
          + break;
          + }
          + }
          +
          + return error == ERROR_NONE ? OK : FAIL;
          }

          /*
          @@ -9241,8 +9495,8 @@
          }

          int
          -func_call(name, args, selfdict, rettv)
          - char_u *name;
          +func_call(func, args, selfdict, rettv)
          + func_T *func;
          typval_T *args;
          dict_T *selfdict;
          typval_T *rettv;
          @@ -9268,9 +9522,9 @@
          }
          <br/><br/>(Message over 64 KB, truncated)
        Your message has been successfully submitted and would be delivered to recipients shortly.