diff options
Diffstat (limited to 'src/nvim/eval.c')
| -rw-r--r-- | src/nvim/eval.c | 1280 | 
1 files changed, 617 insertions, 663 deletions
| diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 65bb90fc15..3a0075e48a 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -173,7 +173,6 @@ static char *e_funcref = N_("E718: Funcref required");  static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary");  static char *e_nofunc = N_("E130: Unknown function: %s");  static char *e_illvar = N_("E461: Illegal variable name: %s"); -static char *e_float_as_string = N_("E806: using Float as a String");  static const char *e_readonlyvar = N_(      "E46: Cannot change read-only variable \"%.*s\""); @@ -1852,7 +1851,6 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv,                            const char_u *const op)    FUNC_ATTR_NONNULL_ARG(1, 2) FUNC_ATTR_WARN_UNUSED_RESULT  { -  char_u *name;    char_u *arg_end = NULL;    int len;    int opt_flags; @@ -1864,7 +1862,7 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv,    if (*arg == '$') {      // Find the end of the name.      arg++; -    name = arg; +    char *name = (char *)arg;      len = get_env_len((const char_u **)&arg);      if (len == 0) {        EMSG2(_(e_invarg2), name - 1); @@ -1875,26 +1873,28 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv,                   && vim_strchr(endchars, *skipwhite(arg)) == NULL) {          EMSG(_(e_letunexp));        } else if (!check_secure()) { -        const char_u c1 = name[len]; +        const char c1 = name[len];          name[len] = NUL; -        char_u *p = get_tv_string_chk(tv); +        const char *p = tv_get_string_chk(tv);          if (p != NULL && op != NULL && *op == '.') { -          char *s = vim_getenv((char *)name); +          char *s = vim_getenv(name);            if (s != NULL) { -            p = tofree = concat_str((char_u *)s, p); +            tofree = concat_str((const char_u *)s, (const char_u *)p); +            p = (const char *)tofree;              xfree(s);            }          }          if (p != NULL) { -          vim_setenv((char *)name, (char *)p); -          if (STRICMP(name, "HOME") == 0) +          vim_setenv(name, p); +          if (STRICMP(name, "HOME") == 0) {              init_homedir(); -          else if (didset_vim && STRICMP(name, "VIM") == 0) -            didset_vim = FALSE; -          else if (didset_vimruntime -                   && STRICMP(name, "VIMRUNTIME") == 0) -            didset_vimruntime = FALSE; +          } else if (didset_vim && STRICMP(name, "VIM") == 0) { +            didset_vim = false; +          } else if (didset_vimruntime +                     && STRICMP(name, "VIMRUNTIME") == 0) { +            didset_vimruntime = false; +          }            arg_end = arg;          }          name[len] = c1; @@ -1914,16 +1914,16 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv,      } else {        int opt_type;        long numval; -      char_u *stringval = NULL; -      char_u *s; +      char *stringval = NULL;        const char c1 = *p;        *p = NUL;        varnumber_T n = tv_get_number(tv); -      s = get_tv_string_chk(tv);  // != NULL if number or string. +      const char *s = tv_get_string_chk(tv);  // != NULL if number or string.        if (s != NULL && op != NULL && *op != '=') { -        opt_type = get_option_value(arg, &numval, &stringval, opt_flags); +        opt_type = get_option_value(arg, &numval, (char_u **)&stringval, +                                    opt_flags);          if ((opt_type == 1 && *op == '.')              || (opt_type == 0 && *op != '.')) {            EMSG2(_(e_letwrong), op); @@ -1935,44 +1935,45 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv,                n = numval - n;              }            } else if (opt_type == 0 && stringval != NULL) {  // string -            s = concat_str(stringval, s); -            xfree(stringval); -            stringval = s; +            char *const oldstringval = stringval; +            stringval = (char *)concat_str((const char_u *)stringval, +                                           (const char_u *)s); +            xfree(oldstringval); +            s = stringval;            }          }        }        if (s != NULL) { -        set_option_value((const char *)arg, n, (char *)s, opt_flags); +        set_option_value((const char *)arg, n, s, opt_flags);          arg_end = (char_u *)p;        }        *p = c1;        xfree(stringval);      } -  } -  /* -   * ":let @r = expr": Set register contents. -   */ -  else if (*arg == '@') { -    ++arg; -    if (op != NULL && (*op == '+' || *op == '-')) -      EMSG2(_(e_letwrong), op); -    else if (endchars != NULL -             && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL) -      EMSG(_(e_letunexp)); -    else { -      char_u      *ptofree = NULL; +  // ":let @r = expr": Set register contents. +  } else if (*arg == '@') { +    arg++; +    if (op != NULL && (*op == '+' || *op == '-')) { +      emsgf(_(e_letwrong), op); +    } else if (endchars != NULL +               && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL) { +      emsgf(_(e_letunexp)); +    } else {        char_u      *s; -      char_u *p = get_tv_string_chk(tv); +      char_u *ptofree = NULL; +      const char *p = tv_get_string_chk(tv);        if (p != NULL && op != NULL && *op == '.') {          s = get_reg_contents(*arg == '@' ? '"' : *arg, kGRegExprSrc);          if (s != NULL) { -          p = ptofree = concat_str(s, p); +          ptofree = concat_str(s, (const char_u *)p); +          p = (const char *)ptofree;            xfree(s);          }        }        if (p != NULL) { -        write_reg_contents(*arg == '@' ? '"' : *arg, p, STRLEN(p), false); +        write_reg_contents(*arg == '@' ? '"' : *arg, +                           (const char_u *)p, STRLEN(p), false);          arg_end = arg + 1;        }        xfree(ptofree); @@ -2129,13 +2130,14 @@ static char_u *get_lval(char_u *const name, typval_T *const rettv,      } else {        /* Get the index [expr] or the first index [expr: ]. */        p = skipwhite(p + 1); -      if (*p == ':') -        empty1 = TRUE; -      else { -        empty1 = FALSE; -        if (eval1(&p, &var1, TRUE) == FAIL)             /* recursive! */ +      if (*p == ':') { +        empty1 = true; +      } else { +        empty1 = false; +        if (eval1(&p, &var1, true) == FAIL) {  // Recursive!            return NULL; -        if (get_tv_string_chk(&var1) == NULL) { +        } +        if (!tv_check_str(&var1)) {            // Not a number or string.            tv_clear(&var1);            return NULL; @@ -2174,7 +2176,7 @@ static char_u *get_lval(char_u *const name, typval_T *const rettv,              }              return NULL;            } -          if (get_tv_string_chk(&var2) == NULL) { +          if (!tv_check_str(&var2)) {              // Not a number or string.              if (!empty1) {                tv_clear(&var1); @@ -3810,16 +3812,15 @@ static int eval5(char_u **arg, typval_T *rettv, int evaluate)        break;      if ((op != '+' || rettv->v_type != VAR_LIST) -        && (op == '.' || rettv->v_type != VAR_FLOAT) -        ) { -      /* For "list + ...", an illegal use of the first operand as -       * a number cannot be determined before evaluating the 2nd -       * operand: if this is also a list, all is ok. -       * For "something . ...", "something - ..." or "non-list + ...", -       * we know that the first operand needs to be a string or number -       * without evaluating the 2nd operand.  So check before to avoid -       * side effects after an error. */ -      if (evaluate && get_tv_string_chk(rettv) == NULL) { +        && (op == '.' || rettv->v_type != VAR_FLOAT)) { +      // For "list + ...", an illegal use of the first operand as +      // a number cannot be determined before evaluating the 2nd +      // operand: if this is also a list, all is ok. +      // For "something . ...", "something - ..." or "non-list + ...", +      // we know that the first operand needs to be a string or number +      // without evaluating the 2nd operand.  So check before to avoid +      // side effects after an error. +      if (evaluate && !tv_check_str(rettv)) {          tv_clear(rettv);          return FAIL;        } @@ -3840,10 +3841,10 @@ static int eval5(char_u **arg, typval_T *rettv, int evaluate)         */        if (op == '.') {          char buf1[NUMBUFLEN]; -        char_u buf2[NUMBUFLEN]; +        char buf2[NUMBUFLEN];          // s1 already checked          const char *const s1 = tv_get_string_buf(rettv, buf1); -        const char *const s2 = (const char *)get_tv_string_buf_chk(&var2, buf2); +        const char *const s2 = tv_get_string_buf_chk(&var2, buf2);          if (s2 == NULL) {  // Type error?            tv_clear(rettv);            tv_clear(&var2); @@ -4411,7 +4412,7 @@ eval_index (        empty1 = true;      } else if (eval1(arg, &var1, evaluate) == FAIL) {  // Recursive!        return FAIL; -    } else if (evaluate && get_tv_string_chk(&var1) == NULL) { +    } else if (evaluate && !tv_check_str(&var1)) {        // Not a number or string.        tv_clear(&var1);        return FAIL; @@ -4430,7 +4431,7 @@ eval_index (            tv_clear(&var1);          }          return FAIL; -      } else if (evaluate && get_tv_string_chk(&var2) == NULL) { +      } else if (evaluate && !tv_check_str(&var2)) {          // Not a number or string.          if (!empty1) {            tv_clear(&var1); @@ -4566,7 +4567,7 @@ eval_index (          }          if (len == -1) { -          key = get_tv_string_chk(&var1); +          key = (char_u *)tv_get_string_chk(&var1);            if (key == NULL) {              tv_clear(&var1);              return FAIL; @@ -5570,7 +5571,7 @@ static int get_dict_tv(char_u **arg, typval_T *rettv, int evaluate)    char_u      *key = NULL;    dictitem_T  *item;    char_u      *start = skipwhite(*arg + 1); -  char_u buf[NUMBUFLEN]; +  char buf[NUMBUFLEN];    /*     * First check if it's not a curly-braces thing: {expr}. @@ -5602,9 +5603,9 @@ static int get_dict_tv(char_u **arg, typval_T *rettv, int evaluate)        goto failret;      }      if (evaluate) { -      key = get_tv_string_buf_chk(&tvkey, buf); +      key = (char_u *)tv_get_string_buf_chk(&tvkey, buf);        if (key == NULL) { -        // "key" is NULL when get_tv_string_buf_chk() gave an errmsg +        // "key" is NULL when tv_get_string_buf_chk() gave an errmsg          tv_clear(&tvkey);          goto failret;        } @@ -6598,7 +6599,6 @@ static void f_api_info(typval_T *argvars, typval_T *rettv, FunPtr fptr)  static void f_append(typval_T *argvars, typval_T *rettv, FunPtr fptr)  {    long lnum; -  char_u      *line;    list_T      *l = NULL;    listitem_T  *li = NULL;    typval_T    *tv; @@ -6622,21 +6622,23 @@ static void f_append(typval_T *argvars, typval_T *rettv, FunPtr fptr)        li = l->lv_first;      }      for (;; ) { -      if (l == NULL) -        tv = &argvars[1];               /* append a string */ -      else if (li == NULL) -        break;                          /* end of list */ -      else -        tv = &li->li_tv;                /* append item from list */ -      line = get_tv_string_chk(tv); -      if (line == NULL) {               /* type error */ -        rettv->vval.v_number = 1;               /* Failed */ +      if (l == NULL) { +        tv = &argvars[1];  // Append a string. +      } else if (li == NULL) { +        break;  // End of list. +      } else { +        tv = &li->li_tv;  // Append item from list. +      } +      const char *const line = tv_get_string_chk(tv); +      if (line == NULL) {  // Type error. +        rettv->vval.v_number = 1;  // Failed.          break;        } -      ml_append(lnum + added, line, (colnr_T)0, FALSE); -      ++added; -      if (l == NULL) +      ml_append(lnum + added, (char_u *)line, (colnr_T)0, false); +      added++; +      if (l == NULL) {          break; +      }        li = li->li_next;      } @@ -6802,7 +6804,7 @@ static void f_assert_exception(typval_T *argvars, typval_T *rettv, FunPtr fptr)  {    garray_T ga; -  char *error = (char *)get_tv_string_chk(&argvars[0]); +  const char *const error = tv_get_string_chk(&argvars[0]);    if (vimvars[VV_EXCEPTION].vv_str == NULL) {      prepare_assert_error(&ga);      ga_concat(&ga, (char_u *)"v:exception is not set"); @@ -6821,22 +6823,22 @@ static void f_assert_exception(typval_T *argvars, typval_T *rettv, FunPtr fptr)  /// "assert_fails(cmd [, error])" function  static void f_assert_fails(typval_T *argvars, typval_T *rettv, FunPtr fptr)  { -  char_u *cmd = get_tv_string_chk(&argvars[0]); +  const char *const cmd = tv_get_string_chk(&argvars[0]);    garray_T    ga;    called_emsg = false;    suppress_errthrow = true;    emsg_silent = true; -  do_cmdline_cmd((char *)cmd); +  do_cmdline_cmd(cmd);    if (!called_emsg) {      prepare_assert_error(&ga); -    ga_concat(&ga, (char_u *)"command did not fail: "); -    ga_concat(&ga, cmd); +    ga_concat(&ga, (const char_u *)"command did not fail: "); +    ga_concat(&ga, (const char_u *)cmd);      assert_error(&ga);      ga_clear(&ga);    } else if (argvars[1].v_type != VAR_UNKNOWN) { -    char_u buf[NUMBUFLEN]; -    char *error = (char *)get_tv_string_buf_chk(&argvars[1], buf); +    char buf[NUMBUFLEN]; +    const char *const error = tv_get_string_buf_chk(&argvars[1], buf);      if (error == NULL          || strstr((char *)vimvars[VV_ERRMSG].vv_str, error) == NULL) { @@ -6911,14 +6913,15 @@ static void f_assert_false(typval_T *argvars, typval_T *rettv, FunPtr fptr)  static void assert_match_common(typval_T *argvars, assert_type_T atype)  { -  char_u buf1[NUMBUFLEN]; -  char_u buf2[NUMBUFLEN]; -  char_u *pat = get_tv_string_buf_chk(&argvars[0], buf1); -  char_u *text = get_tv_string_buf_chk(&argvars[1], buf2); +  char buf1[NUMBUFLEN]; +  char buf2[NUMBUFLEN]; +  const char *const pat = tv_get_string_buf_chk(&argvars[0], buf1); +  const char *const text = tv_get_string_buf_chk(&argvars[1], buf2);    if (pat == NULL || text == NULL) {      EMSG(_(e_invarg)); -  } else if (pattern_match(pat, text, false) != (atype == ASSERT_MATCH)) { +  } else if (pattern_match((char_u *)pat, (char_u *)text, false) +             != (atype == ASSERT_MATCH)) {      garray_T ga;      prepare_assert_error(&ga);      fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1], atype); @@ -7107,7 +7110,6 @@ static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr)  static void f_bufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)  {    bool error = false; -  char_u *name;    rettv->vval.v_number = -1;    if (!tv_check_str_or_nr(&argvars[0])) { @@ -7119,13 +7121,14 @@ static void f_bufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)    // If the buffer isn't found and the second argument is not zero create a    // new buffer. +  const char *name;    if (buf == NULL        && argvars[1].v_type != VAR_UNKNOWN        && tv_get_number_chk(&argvars[1], &error) != 0        && !error -      && (name = get_tv_string_chk(&argvars[0])) != NULL +      && (name = tv_get_string_chk(&argvars[0])) != NULL        && !error) { -    buf = buflist_new(name, NULL, (linenr_T)1, 0); +    buf = buflist_new((char_u *)name, NULL, 1, 0);    }    if (buf != NULL) { @@ -7190,24 +7193,23 @@ static void f_byte2line(typval_T *argvars, typval_T *rettv, FunPtr fptr)  static void byteidx(typval_T *argvars, typval_T *rettv, int comp)  { -  char_u      *t; -  char_u      *str; -  long idx; - -  str = get_tv_string_chk(&argvars[0]); -  idx = tv_get_number_chk(&argvars[1], NULL); +  const char *const str = tv_get_string_chk(&argvars[0]); +  varnumber_T idx = tv_get_number_chk(&argvars[1], NULL);    rettv->vval.v_number = -1; -  if (str == NULL || idx < 0) +  if (str == NULL || idx < 0) {      return; +  } -  t = str; +  const char *t = str;    for (; idx > 0; idx--) { -    if (*t == NUL)              /* EOL reached */ +    if (*t == NUL) {  // EOL reached.        return; -    if (enc_utf8 && comp) -      t += utf_ptr2len(t); -    else -      t += (*mb_ptr2len)(t); +    } +    if (enc_utf8 && comp) { +      t += utf_ptr2len((const char_u *)t); +    } else { +      t += (*mb_ptr2len)((const char_u *)t); +    }    }    rettv->vval.v_number = (varnumber_T)(t - str);  } @@ -7444,47 +7446,51 @@ static void f_complete_check(typval_T *argvars, typval_T *rettv, FunPtr fptr)   */  static void f_confirm(typval_T *argvars, typval_T *rettv, FunPtr fptr)  { -  char_u      *message; -  char_u      *buttons = NULL; -  char_u buf[NUMBUFLEN]; -  char_u buf2[NUMBUFLEN]; +  char buf[NUMBUFLEN]; +  char buf2[NUMBUFLEN]; +  const char *message; +  const char *buttons = NULL;    int def = 1;    int type = VIM_GENERIC; -  char_u *typestr; +  const char *typestr;    bool error = false; -  message = get_tv_string_chk(&argvars[0]); -  if (message == NULL) -    error = TRUE; +  message = tv_get_string_chk(&argvars[0]); +  if (message == NULL) { +    error = true; +  }    if (argvars[1].v_type != VAR_UNKNOWN) { -    buttons = get_tv_string_buf_chk(&argvars[1], buf); -    if (buttons == NULL) -      error = TRUE; +    buttons = tv_get_string_buf_chk(&argvars[1], buf); +    if (buttons == NULL) { +      error = true; +    }      if (argvars[2].v_type != VAR_UNKNOWN) {        def = tv_get_number_chk(&argvars[2], &error);        if (argvars[3].v_type != VAR_UNKNOWN) { -        typestr = get_tv_string_buf_chk(&argvars[3], buf2); -        if (typestr == NULL) -          error = TRUE; -        else { +        typestr = tv_get_string_buf_chk(&argvars[3], buf2); +        if (typestr == NULL) { +          error = true; +        } else {            switch (TOUPPER_ASC(*typestr)) { -          case 'E': type = VIM_ERROR; break; -          case 'Q': type = VIM_QUESTION; break; -          case 'I': type = VIM_INFO; break; -          case 'W': type = VIM_WARNING; break; -          case 'G': type = VIM_GENERIC; break; +            case 'E': type = VIM_ERROR; break; +            case 'Q': type = VIM_QUESTION; break; +            case 'I': type = VIM_INFO; break; +            case 'W': type = VIM_WARNING; break; +            case 'G': type = VIM_GENERIC; break;            }          }        }      }    } -  if (buttons == NULL || *buttons == NUL) -    buttons = (char_u *)_("&Ok"); +  if (buttons == NULL || *buttons == NUL) { +    buttons = _("&Ok"); +  } -  if (!error) -    rettv->vval.v_number = do_dialog(type, NULL, message, buttons, -        def, NULL, FALSE); +  if (!error) { +    rettv->vval.v_number = do_dialog( +        type, NULL, (char_u *)message, (char_u *)buttons, def, NULL, false); +  }  }  /* @@ -7708,32 +7714,29 @@ static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv, FunPtr fptr)    }    if (argvars[0].v_type != VAR_DICT) { -    EMSG2(e_invarg2, "dict"); +    emsgf(_(e_invarg2), "dict");      return;    }    if (argvars[1].v_type != VAR_STRING && argvars[1].v_type != VAR_NUMBER) { -    EMSG2(e_invarg2, "key"); +    emsgf(_(e_invarg2), "key");      return;    } -  char *key_pattern = (char *)get_tv_string_chk(argvars + 1); -  assert(key_pattern); -  const size_t key_len = STRLEN(argvars[1].vval.v_string); - -  if (key_len == 0) { -    EMSG(_(e_emptykey)); +  const char *const key_pattern = tv_get_string_chk(argvars + 1); +  if (key_pattern == NULL) {      return;    } +  const size_t key_pattern_len = strlen(key_pattern);    Callback callback;    if (!callback_from_typval(&callback, &argvars[2])) { -    EMSG2(e_invarg2, "funcref"); +    emsgf(_(e_invarg2), "funcref");      return;    }    DictWatcher *watcher = xmalloc(sizeof(DictWatcher)); -  watcher->key_pattern = xmemdupz(key_pattern, key_len); +  watcher->key_pattern = xmemdupz(key_pattern, key_pattern_len);    watcher->callback = callback;    watcher->busy = false;    QUEUE_INSERT_TAIL(&argvars[0].vval.v_dict->watchers, &watcher->node); @@ -7747,26 +7750,17 @@ static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, FunPtr fptr)    }    if (argvars[0].v_type != VAR_DICT) { -    EMSG2(e_invarg2, "dict"); -    return; -  } - -  if (argvars[1].v_type != VAR_STRING && argvars[1].v_type != VAR_NUMBER) { -    EMSG2(e_invarg2, "key"); +    emsgf(_(e_invarg2), "dict");      return;    }    if (argvars[2].v_type != VAR_FUNC && argvars[2].v_type != VAR_STRING) { -    EMSG2(e_invarg2, "funcref"); +    emsgf(_(e_invarg2), "funcref");      return;    } -  char *key_pattern = (char *)get_tv_string_chk(argvars + 1); -  assert(key_pattern); -  const size_t key_len = STRLEN(argvars[1].vval.v_string); - -  if (key_len == 0) { -    EMSG(_(e_emptykey)); +  const char *const key_pattern = tv_get_string_chk(argvars + 1); +  if (key_pattern == NULL) {      return;    } @@ -7924,16 +7918,15 @@ static void f_escape(typval_T *argvars, typval_T *rettv, FunPtr fptr)   */  static void f_eval(typval_T *argvars, typval_T *rettv, FunPtr fptr)  { -  char_u      *s; - -  s = get_tv_string_chk(&argvars[0]); -  if (s != NULL) -    s = skipwhite(s); +  const char *s = tv_get_string_chk(&argvars[0]); +  if (s != NULL) { +    s = (const char *)skipwhite((const char_u *)s); +  } -  char_u *p = s; -  if (s == NULL || eval1(&s, rettv, TRUE) == FAIL) { -    if (p != NULL && !aborting()) { -      EMSG2(_(e_invexpr2), p); +  const char *const expr_start = s; +  if (s == NULL || eval1((char_u **)&s, rettv, true) == FAIL) { +    if (expr_start != NULL && !aborting()) { +      EMSG2(_(e_invexpr2), expr_start);      }      need_clr_eos = FALSE;      rettv->v_type = VAR_NUMBER; @@ -7965,75 +7958,74 @@ static void f_executable(typval_T *argvars, typval_T *rettv, FunPtr fptr)            && os_can_exe((const char_u *)name, NULL, false)));  } -static char_u * get_list_line(int c, void *cookie, int indent) +static char_u *get_list_line(int c, void *cookie, int indent)  { -  listitem_T **p = (listitem_T **)cookie; -  listitem_T *item = *p; -  char_u buf[NUMBUFLEN]; -  char_u *s; +  const listitem_T **const p = (const listitem_T **)cookie; +  const listitem_T *item = *p;    if (item == NULL) {      return NULL;    } -  s = get_tv_string_buf_chk(&item->li_tv, buf); +  char buf[NUMBUFLEN]; +  const char *const s = tv_get_string_buf_chk(&item->li_tv, buf);    *p = item->li_next; -  return s == NULL ? NULL : vim_strsave(s); +  return (char_u *)(s == NULL ? NULL : xstrdup(s));  }  // "execute(command)" function  static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)  { -    int save_msg_silent = msg_silent; -    int save_emsg_silent = emsg_silent; -    bool save_emsg_noredir = emsg_noredir; -    garray_T *save_capture_ga = capture_ga; +  const int save_msg_silent = msg_silent; +  const int save_emsg_silent = emsg_silent; +  const bool save_emsg_noredir = emsg_noredir; +  garray_T *const save_capture_ga = capture_ga; -    if (check_secure()) { -      return; -    } +  if (check_secure()) { +    return; +  } -    if (argvars[1].v_type != VAR_UNKNOWN) { -      char_u buf[NUMBUFLEN]; -      char_u *s = get_tv_string_buf_chk(&argvars[1], buf); +  if (argvars[1].v_type != VAR_UNKNOWN) { +    char buf[NUMBUFLEN]; +    const char *const s = tv_get_string_buf_chk(&argvars[1], buf); -      if (s == NULL) { -        return; -      } -      if (STRNCMP(s, "silent", 6) == 0) { -        msg_silent++; -      } -      if (STRCMP(s, "silent!") == 0) { -        emsg_silent = true; -        emsg_noredir = true; -      } -    } else { +    if (s == NULL) { +      return; +    } +    if (strncmp(s, S_LEN("silent")) == 0) {        msg_silent++;      } - -    garray_T capture_local; -    ga_init(&capture_local, (int)sizeof(char), 80); -    capture_ga = &capture_local; - -    if (argvars[0].v_type != VAR_LIST) { -      do_cmdline_cmd(tv_get_string(&argvars[0])); -    } else if (argvars[0].vval.v_list != NULL) { -      list_T *const list = argvars[0].vval.v_list; -      list->lv_refcount++; -      listitem_T *const item = list->lv_first; -      do_cmdline(NULL, get_list_line, (void *)&item, -                 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT|DOCMD_KEYTYPED); -      list->lv_refcount--; +    if (strcmp(s, "silent!") == 0) { +      emsg_silent = true; +      emsg_noredir = true;      } -    msg_silent = save_msg_silent; -    emsg_silent = save_emsg_silent; -    emsg_noredir = save_emsg_noredir; +  } else { +    msg_silent++; +  } -    ga_append(capture_ga, NUL); -    rettv->v_type = VAR_STRING; -    rettv->vval.v_string = vim_strsave(capture_ga->ga_data); -    ga_clear(capture_ga); +  garray_T capture_local; +  ga_init(&capture_local, (int)sizeof(char), 80); +  capture_ga = &capture_local; -    capture_ga = save_capture_ga; +  if (argvars[0].v_type != VAR_LIST) { +    do_cmdline_cmd(tv_get_string(&argvars[0])); +  } else if (argvars[0].vval.v_list != NULL) { +    list_T *const list = argvars[0].vval.v_list; +    list->lv_refcount++; +    listitem_T *const item = list->lv_first; +    do_cmdline(NULL, get_list_line, (void *)&item, +               DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT|DOCMD_KEYTYPED); +    list->lv_refcount--; +  } +  msg_silent = save_msg_silent; +  emsg_silent = save_emsg_silent; +  emsg_noredir = save_emsg_noredir; + +  ga_append(capture_ga, NUL); +  rettv->v_type = VAR_STRING; +  rettv->vval.v_string = vim_strsave(capture_ga->ga_data); +  ga_clear(capture_ga); + +  capture_ga = save_capture_ga;  }  /// "exepath()" function @@ -8231,7 +8223,7 @@ static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr)        if (argvars[2].v_type != VAR_UNKNOWN) {          const char *const av[] = { "keep", "force", "error" }; -        action = (const char *)get_tv_string_chk(&argvars[2]); +        action = tv_get_string_chk(&argvars[2]);          if (action == NULL) {            return;  // Type error; error message already given.          } @@ -8300,10 +8292,8 @@ static void f_filewritable(typval_T *argvars, typval_T *rettv, FunPtr fptr)  static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what)  { -  char_u      *fresult = NULL; -  char_u      *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path; -  char_u      *p; -  char_u pathbuf[NUMBUFLEN]; +  char_u *fresult = NULL; +  char_u *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;    int count = 1;    bool first = true;    bool error = false; @@ -8313,13 +8303,15 @@ static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what)    const char *fname = tv_get_string(&argvars[0]); +  char pathbuf[NUMBUFLEN];    if (argvars[1].v_type != VAR_UNKNOWN) { -    p = get_tv_string_buf_chk(&argvars[1], pathbuf); -    if (p == NULL) -      error = TRUE; -    else { -      if (*p != NUL) -        path = p; +    const char *p = tv_get_string_buf_chk(&argvars[1], pathbuf); +    if (p == NULL) { +      error = true; +    } else { +      if (*p != NUL) { +        path = (char_u *)p; +      }        if (argvars[2].v_type != VAR_UNKNOWN) {          count = tv_get_number_chk(&argvars[2], &error); @@ -8473,8 +8465,6 @@ static int filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp)  {    typval_T rettv;    typval_T argv[3]; -  char_u buf[NUMBUFLEN]; -  char_u      *s;    int retval = FAIL;    int dummy; @@ -8482,7 +8472,7 @@ static int filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp)    argv[0] = vimvars[VV_KEY].vv_tv;    argv[1] = vimvars[VV_VAL].vv_tv;    if (expr->v_type == VAR_FUNC) { -    s = expr->vval.v_string; +    const char_u *const s = expr->vval.v_string;      if (call_func(s, (int)STRLEN(s), &rettv, 2, argv, NULL,                    0L, 0L, &dummy, true, NULL, NULL) == FAIL) {        goto theend; @@ -8490,23 +8480,24 @@ static int filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp)    } else if (expr->v_type == VAR_PARTIAL) {      partial_T *partial = expr->vval.v_partial; -    s = partial_name(partial); +    const char_u *const s = partial_name(partial);      if (call_func(s, (int)STRLEN(s), &rettv, 2, argv, NULL,                    0L, 0L, &dummy, true, partial, NULL) == FAIL) {        goto theend;      }    } else { -    s = get_tv_string_buf_chk(expr, buf); +    char buf[NUMBUFLEN]; +    const char *s = tv_get_string_buf_chk(expr, buf);      if (s == NULL) {        goto theend;      } -    s = skipwhite(s); -    if (eval1(&s, &rettv, true) == FAIL) { +    s = (const char *)skipwhite((const char_u *)s); +    if (eval1((char_u **)&s, &rettv, true) == FAIL) {        goto theend;      }      if (*s != NUL) {  // check for trailing chars after expr -      EMSG2(_(e_invexpr2), s); +      emsgf(_(e_invexpr2), s);        goto theend;      }    } @@ -8606,27 +8597,26 @@ static void f_fnameescape(typval_T *argvars, typval_T *rettv, FunPtr fptr)   */  static void f_fnamemodify(typval_T *argvars, typval_T *rettv, FunPtr fptr)  { -  char_u      *fname; -  char_u      *mods; -  size_t usedlen = 0; +  char_u *fbuf = NULL;    size_t len; -  char_u      *fbuf = NULL; -  char_u buf[NUMBUFLEN]; - -  fname = get_tv_string_chk(&argvars[0]); -  mods = get_tv_string_buf_chk(&argvars[1], buf); -  if (fname == NULL || mods == NULL) +  char buf[NUMBUFLEN]; +  const char *fname = tv_get_string_chk(&argvars[0]); +  const char *const mods = tv_get_string_buf_chk(&argvars[1], buf); +  if (fname == NULL || mods == NULL) {      fname = NULL; -  else { -    len = STRLEN(fname); -    (void)modify_fname(mods, &usedlen, &fname, &fbuf, &len); +  } else { +    len = strlen(fname); +    size_t usedlen = 0; +    (void)modify_fname((char_u *)mods, &usedlen, (char_u **)&fname, &fbuf, +                       &len);    }    rettv->v_type = VAR_STRING; -  if (fname == NULL) +  if (fname == NULL) {      rettv->vval.v_string = NULL; -  else -    rettv->vval.v_string = vim_strnsave(fname, len); +  } else { +    rettv->vval.v_string = (char_u *)xmemdupz(fname, len); +  }    xfree(fbuf);  } @@ -9257,7 +9247,7 @@ static void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)      goto f_getbufvar_end;    } -  const char *varname = (const char *)get_tv_string_chk(&argvars[1]); +  const char *varname = tv_get_string_chk(&argvars[1]);    emsg_off++;    buf_T *const buf = get_buf_tv(&argvars[0], false); @@ -9970,14 +9960,13 @@ static void f_getqflist(typval_T *argvars, typval_T *rettv, FunPtr fptr)  /// "getreg()" function  static void f_getreg(typval_T *argvars, typval_T *rettv, FunPtr fptr)  { -  char_u      *strregname; -  int regname; +  const char *strregname;    int arg2 = false;    bool return_list = false;    bool error = false;    if (argvars[0].v_type != VAR_UNKNOWN) { -    strregname = get_tv_string_chk(&argvars[0]); +    strregname = tv_get_string_chk(&argvars[0]);      error = strregname == NULL;      if (argvars[1].v_type != VAR_UNKNOWN) {        arg2 = tv_get_number_chk(&argvars[1], &error); @@ -9986,16 +9975,17 @@ static void f_getreg(typval_T *argvars, typval_T *rettv, FunPtr fptr)        }      }    } else { -    strregname = vimvars[VV_REG].vv_str; +    strregname = (const char *)vimvars[VV_REG].vv_str;    }    if (error) {      return;    } -  regname = (strregname == NULL ? '"' : *strregname); -  if (regname == 0) +  int regname = (uint8_t)(strregname == NULL ? '"' : *strregname); +  if (regname == 0) {      regname = '"'; +  }    if (return_list) {      rettv->v_type = VAR_LIST; @@ -10016,23 +10006,24 @@ static void f_getreg(typval_T *argvars, typval_T *rettv, FunPtr fptr)   */  static void f_getregtype(typval_T *argvars, typval_T *rettv, FunPtr fptr)  { -  char_u      *strregname; -  int regname; +  const char *strregname;    if (argvars[0].v_type != VAR_UNKNOWN) { -    strregname = get_tv_string_chk(&argvars[0]); -    if (strregname == NULL) {       /* type error; errmsg already given */ +    strregname = tv_get_string_chk(&argvars[0]); +    if (strregname == NULL) {  // Type error; errmsg already given.        rettv->v_type = VAR_STRING;        rettv->vval.v_string = NULL;        return;      } -  } else -    /* Default to v:register */ -    strregname = vimvars[VV_REG].vv_str; +  } else { +    // Default to v:register. +    strregname = (const char *)vimvars[VV_REG].vv_str; +  } -  regname = (strregname == NULL ? '"' : *strregname); -  if (regname == 0) +  int regname = (uint8_t)(strregname == NULL ? '"' : *strregname); +  if (regname == 0) {      regname = '"'; +  }    colnr_T reglen = 0;    char buf[NUMBUFLEN + 2]; @@ -10108,7 +10099,7 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)    rettv->v_type = VAR_STRING;    rettv->vval.v_string = NULL; -  const char *const varname = (const char *)get_tv_string_chk(&argvars[1]); +  const char *const varname = tv_get_string_chk(&argvars[1]);    tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));    if (tp != NULL && varname != NULL) {      // Set tp to be our tabpage, temporarily.  Also set the window to the @@ -10307,8 +10298,7 @@ getwinvar (      tp = curtab;    }    win = find_win_by_nr(&argvars[off], tp); -  const char *varname = (const char *)get_tv_string_chk( -      &argvars[off + 1]); +  const char *varname = tv_get_string_chk(&argvars[off + 1]);    rettv->v_type = VAR_STRING;    rettv->vval.v_string = NULL; @@ -10438,12 +10428,12 @@ static void f_globpath(typval_T *argvars, typval_T *rettv, FunPtr fptr)      }    } -  char_u buf1[NUMBUFLEN]; -  char_u *file = get_tv_string_buf_chk(&argvars[1], buf1); +  char buf1[NUMBUFLEN]; +  const char *const file = tv_get_string_buf_chk(&argvars[1], buf1);    if (file != NULL && !error) {      garray_T ga;      ga_init(&ga, (int)sizeof(char_u *), 10); -    globpath((char_u *)tv_get_string(&argvars[0]), file, &ga, flags); +    globpath((char_u *)tv_get_string(&argvars[0]), (char_u *)file, &ga, flags);      if (rettv->v_type == VAR_STRING) {        rettv->vval.v_string = ga_concat_strings_sep(&ga, "\n"); @@ -10464,12 +10454,13 @@ static void f_globpath(typval_T *argvars, typval_T *rettv, FunPtr fptr)  // "glob2regpat()" function  static void f_glob2regpat(typval_T *argvars, typval_T *rettv, FunPtr fptr)  { -  char_u *pat = get_tv_string_chk(&argvars[0]);  // NULL on type error +  const char *const pat = tv_get_string_chk(&argvars[0]);  // NULL on type error    rettv->v_type = VAR_STRING; -  rettv->vval.v_string = (pat == NULL) -    ? NULL -    : file_pat_to_reg_pat(pat, NULL, NULL, false); +  rettv->vval.v_string = ((pat == NULL) +                          ? NULL +                          : file_pat_to_reg_pat((char_u *)pat, NULL, NULL, +                                                false));  }  /// "has()" function @@ -10797,14 +10788,14 @@ static void f_histadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)    if (check_restricted() || check_secure()) {      return;    } -  char_u *str = get_tv_string_chk(&argvars[0]);  // NULL on type error -  histype = str != NULL ? get_histtype(str, STRLEN(str), false) : HIST_INVALID; +  const char *str = tv_get_string_chk(&argvars[0]);  // NULL on type error +  histype = str != NULL ? get_histtype(str, strlen(str), false) : HIST_INVALID;    if (histype != HIST_INVALID) {      char buf[NUMBUFLEN]; -    str = (char_u *)tv_get_string_buf(&argvars[1], buf); +    str = tv_get_string_buf(&argvars[1], buf);      if (*str != NUL) {        init_history(); -      add_to_history(histype, str, false, NUL); +      add_to_history(histype, (char_u *)str, false, NUL);        rettv->vval.v_number = true;        return;      } @@ -10817,22 +10808,20 @@ static void f_histadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)  static void f_histdel(typval_T *argvars, typval_T *rettv, FunPtr fptr)  {    int n; -  char_u      *str; - -  str = get_tv_string_chk(&argvars[0]);  // NULL on type error +  const char *const str = tv_get_string_chk(&argvars[0]);  // NULL on type error    if (str == NULL) {      n = 0;    } else if (argvars[1].v_type == VAR_UNKNOWN) {      // only one argument: clear entire history -    n = clr_history(get_histtype(str, STRLEN(str), false)); +    n = clr_history(get_histtype(str, strlen(str), false));    } else if (argvars[1].v_type == VAR_NUMBER) {      // index given: remove that entry -    n = del_history_idx(get_histtype(str, STRLEN(str), false), +    n = del_history_idx(get_histtype(str, strlen(str), false),                          (int)tv_get_number(&argvars[1]));    } else {      // string given: remove all matching entries      char buf[NUMBUFLEN]; -    n = del_history_entry(get_histtype(str, STRLEN(str), false), +    n = del_history_entry(get_histtype(str, strlen(str), false),                            (char_u *)tv_get_string_buf(&argvars[1], buf));    }    rettv->vval.v_number = n; @@ -10845,13 +10834,12 @@ static void f_histget(typval_T *argvars, typval_T *rettv, FunPtr fptr)  {    HistoryType type;    int idx; -  char_u      *str; -  str = get_tv_string_chk(&argvars[0]);  // NULL on type error +  const char *const str = tv_get_string_chk(&argvars[0]);  // NULL on type error    if (str == NULL) {      rettv->vval.v_string = NULL;    } else { -    type = get_histtype(str, STRLEN(str), false); +    type = get_histtype(str, strlen(str), false);      if (argvars[1].v_type == VAR_UNKNOWN) {        idx = get_history_idx(type);      } else { @@ -10870,9 +10858,9 @@ static void f_histnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)  {    int i; -  char_u      *history = get_tv_string_chk(&argvars[0]); +  const char *const history = tv_get_string_chk(&argvars[0]); -  i = history == NULL ? HIST_CMD - 1 : get_histtype(history, STRLEN(history), +  i = history == NULL ? HIST_CMD - 1 : get_histtype(history, strlen(history),                                                      false);    if (i != HIST_INVALID) {      i = get_history_idx(i); @@ -11009,11 +10997,8 @@ static int inputsecret_flag = 0;   */  static void get_user_input(typval_T *argvars, typval_T *rettv, int inputdialog)  { -  char_u      *prompt = get_tv_string_chk(&argvars[0]); -  char_u      *p = NULL; -  int c; +  const char *prompt = tv_get_string_chk(&argvars[0]);    int cmd_silent_save = cmd_silent; -  char_u      *defstr = (char_u *)"";    int xp_type = EXPAND_NOTHING;    char_u      *xp_arg = NULL; @@ -11022,49 +11007,45 @@ static void get_user_input(typval_T *argvars, typval_T *rettv, int inputdialog)    cmd_silent = FALSE;           /* Want to see the prompt. */    if (prompt != NULL) { -    /* Only the part of the message after the last NL is considered as -     * prompt for the command line */ -    p = vim_strrchr(prompt, '\n'); -    if (p == NULL) +    // Only the part of the message after the last NL is considered as +    // prompt for the command line. +    const char *p = strrchr(prompt, '\n'); +    if (p == NULL) {        p = prompt; -    else { -      ++p; -      c = *p; -      *p = NUL; +    } else { +      p++;        msg_start();        msg_clr_eos(); -      msg_puts_attr((const char *)prompt, echo_attr); +      msg_puts_attr_len(prompt, p - prompt, echo_attr);        msg_didout = false;        msg_starthere(); -      *p = c;      }      cmdline_row = msg_row; +    const char *defstr = "";      if (argvars[1].v_type != VAR_UNKNOWN) { -      char_u buf[NUMBUFLEN]; -      defstr = get_tv_string_buf_chk(&argvars[1], buf); +      char buf[NUMBUFLEN]; +      defstr = tv_get_string_buf_chk(&argvars[1], buf);        if (defstr != NULL) {          stuffReadbuffSpec(defstr);        }        if (!inputdialog && argvars[2].v_type != VAR_UNKNOWN) { -        char_u  *xp_name; -        int xp_namelen; -        uint32_t argt; - -        /* input() with a third argument: completion */ +        // input() with a third argument: completion          rettv->vval.v_string = NULL; -        xp_name = get_tv_string_buf_chk(&argvars[2], buf); +        const char *const xp_name = tv_get_string_buf_chk(&argvars[2], buf);          if (xp_name == NULL) {            return;          } -        xp_namelen = (int)STRLEN(xp_name); +        const int xp_namelen = (int)strlen(xp_name); -        if (parse_compl_arg(xp_name, xp_namelen, &xp_type, &argt, -                &xp_arg) == FAIL) +        uint32_t argt; +        if (parse_compl_arg((char_u *)xp_name, xp_namelen, &xp_type, &argt, +                            &xp_arg) == FAIL) {            return; +        }        }      } @@ -11072,8 +11053,8 @@ static void get_user_input(typval_T *argvars, typval_T *rettv, int inputdialog)        int save_ex_normal_busy = ex_normal_busy;        ex_normal_busy = 0;        rettv->vval.v_string = -        getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr, -            xp_type, xp_arg); +        getcmdline_prompt(inputsecret_flag ? NUL : '@', (char_u *)p, echo_attr, +                          xp_type, xp_arg);        ex_normal_busy = save_ex_normal_busy;      }      if (inputdialog && rettv->vval.v_string == NULL @@ -11544,8 +11525,8 @@ static char **tv_to_argv(typval_T *cmd_tv, const char **cmd, bool *executable)    assert(argl->lv_first); -  const char_u *exe = get_tv_string_chk(&argl->lv_first->li_tv); -  if (!exe || !os_can_exe(exe, NULL, true)) { +  const char *exe = tv_get_string_chk(&argl->lv_first->li_tv); +  if (!exe || !os_can_exe((const char_u *)exe, NULL, true)) {      if (exe && executable) {        *executable = false;      } @@ -11553,14 +11534,14 @@ static char **tv_to_argv(typval_T *cmd_tv, const char **cmd, bool *executable)    }    if (cmd) { -    *cmd = (char *)exe; +    *cmd = exe;    }    // Build the argument vector    int i = 0;    char **argv = xcalloc(argc + 1, sizeof(char *));    for (listitem_T *arg = argl->lv_first; arg != NULL; arg = arg->li_next) { -    char *a = (char *)get_tv_string_chk(&arg->li_tv); +    const char *a = tv_get_string_chk(&arg->li_tv);      if (!a) {        // Did emsg in tv_get_string_chk; just deallocate argv.        shell_free_argv(argv); @@ -11803,50 +11784,49 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr)   */  static void f_join(typval_T *argvars, typval_T *rettv, FunPtr fptr)  { -  garray_T ga; -  char_u      *sep; -    if (argvars[0].v_type != VAR_LIST) {      EMSG(_(e_listreq));      return;    } -  if (argvars[0].vval.v_list == NULL) +  if (argvars[0].vval.v_list == NULL) {      return; -  if (argvars[1].v_type == VAR_UNKNOWN) -    sep = (char_u *)" "; -  else -    sep = get_tv_string_chk(&argvars[1]); +  } +  const char *const sep = (argvars[1].v_type == VAR_UNKNOWN +                           ? " " +                           : tv_get_string_chk(&argvars[1]));    rettv->v_type = VAR_STRING;    if (sep != NULL) { +    garray_T ga;      ga_init(&ga, (int)sizeof(char), 80); -    tv_list_join(&ga, argvars[0].vval.v_list, (const char *)sep); +    tv_list_join(&ga, argvars[0].vval.v_list, sep);      ga_append(&ga, NUL);      rettv->vval.v_string = (char_u *)ga.ga_data; -  } else +  } else {      rettv->vval.v_string = NULL; +  }  }  /// json_decode() function  static void f_json_decode(typval_T *argvars, typval_T *rettv, FunPtr fptr)  {    char numbuf[NUMBUFLEN]; -  char *s = NULL; +  const char *s = NULL;    char *tofree = NULL;    size_t len;    if (argvars[0].v_type == VAR_LIST) { -    if (!encode_vim_list_to_buf(argvars[0].vval.v_list, &len, &s)) { +    if (!encode_vim_list_to_buf(argvars[0].vval.v_list, &len, &tofree)) {        EMSG(_("E474: Failed to convert list to string"));        return;      } -    tofree = s; +    s = tofree;      if (s == NULL) {        assert(len == 0);        s = "";      }    } else { -    s = (char *) get_tv_string_buf_chk(&argvars[0], (char_u *) numbuf); +    s = tv_get_string_buf_chk(&argvars[0], numbuf);      if (s) {        len = strlen(s);      } else { @@ -12043,10 +12023,8 @@ static void f_localtime(typval_T *argvars, typval_T *rettv, FunPtr fptr)  static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)  { -  char_u      *which; -  char_u buf[NUMBUFLEN]; -  char_u      *keys_buf = NULL; -  char_u      *rhs; +  char_u *keys_buf = NULL; +  char_u *rhs;    int mode;    int abbr = FALSE;    int get_dict = FALSE; @@ -12062,20 +12040,24 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)      return;    } +  char buf[NUMBUFLEN]; +  const char *which;    if (argvars[1].v_type != VAR_UNKNOWN) { -    which = get_tv_string_buf_chk(&argvars[1], buf); +    which = tv_get_string_buf_chk(&argvars[1], buf);      if (argvars[2].v_type != VAR_UNKNOWN) {        abbr = tv_get_number(&argvars[2]);        if (argvars[3].v_type != VAR_UNKNOWN) {          get_dict = tv_get_number(&argvars[3]);        }      } -  } else -    which = (char_u *)""; -  if (which == NULL) +  } else { +    which = ""; +  } +  if (which == NULL) {      return; +  } -  mode = get_map_mode(&which, 0); +  mode = get_map_mode((char_u **)&which, 0);    keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, true, true, false,                             CPO_TO_CPO_FLAGS); @@ -12141,9 +12123,7 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type)    char_u      *str = NULL;    long        len = 0;    char_u      *expr = NULL; -  char_u      *pat;    regmatch_T regmatch; -  char_u patbuf[NUMBUFLEN];    char_u      *save_cpo;    long start = 0;    long nth = 1; @@ -12183,9 +12163,11 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type)      len = (long)STRLEN(str);    } -  pat = get_tv_string_buf_chk(&argvars[1], patbuf); -  if (pat == NULL) +  char patbuf[NUMBUFLEN]; +  const char *const pat = tv_get_string_buf_chk(&argvars[1], patbuf); +  if (pat == NULL) {      goto theend; +  }    if (argvars[2].v_type != VAR_UNKNOWN) {      bool error = false; @@ -12224,7 +12206,7 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type)      }    } -  regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); +  regmatch.regprog = vim_regcomp((char_u *)pat, RE_MAGIC + RE_STRING);    if (regmatch.regprog != NULL) {      regmatch.rm_ic = p_ic; @@ -12336,18 +12318,20 @@ static void f_match(typval_T *argvars, typval_T *rettv, FunPtr fptr)   */  static void f_matchadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)  { -  char_u buf[NUMBUFLEN]; -  char_u      *grp = get_tv_string_buf_chk(&argvars[0], buf);   /* group */ -  char_u      *pat = get_tv_string_buf_chk(&argvars[1], buf);   /* pattern */ -  int prio = 10;                /* default priority */ +  char grpbuf[NUMBUFLEN]; +  char patbuf[NUMBUFLEN]; +  const char *const grp = tv_get_string_buf_chk(&argvars[0], grpbuf); +  const char *const pat = tv_get_string_buf_chk(&argvars[1], patbuf); +  int prio = 10;    int id = -1;    bool error = false;    const char *conceal_char = NULL;    rettv->vval.v_number = -1; -  if (grp == NULL || pat == NULL) +  if (grp == NULL || pat == NULL) {      return; +  }    if (argvars[2].v_type != VAR_UNKNOWN) {      prio = tv_get_number_chk(&argvars[2], &error);      if (argvars[3].v_type != VAR_UNKNOWN) { @@ -12365,7 +12349,7 @@ static void f_matchadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)        }      }    } -  if (error == true) { +  if (error) {      return;    }    if (id >= 1 && id <= 3) { @@ -12373,17 +12357,16 @@ static void f_matchadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)      return;    } -  rettv->vval.v_number = match_add(curwin, (const char *)grp, -                                   (const char *)pat, prio, id, -                                   NULL, conceal_char); +  rettv->vval.v_number = match_add(curwin, grp, pat, prio, id, NULL, +                                   conceal_char);  }  static void f_matchaddpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)  {      rettv->vval.v_number = -1; -     -    char_u buf[NUMBUFLEN]; -    const char_u *const group = get_tv_string_buf_chk(&argvars[0], buf); + +    char buf[NUMBUFLEN]; +    const char *const group = tv_get_string_buf_chk(&argvars[0], buf);      if (group == NULL) {          return;      } @@ -12431,8 +12414,8 @@ static void f_matchaddpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)          return;      } -  rettv->vval.v_number = match_add(curwin, (const char *)group, NULL, prio, id, -                                   l, conceal_char); +  rettv->vval.v_number = match_add(curwin, group, NULL, prio, id, l, +                                   conceal_char);  }  /* @@ -12833,11 +12816,11 @@ static void f_or(typval_T *argvars, typval_T *rettv, FunPtr fptr)  static void f_pathshorten(typval_T *argvars, typval_T *rettv, FunPtr fptr)  {    rettv->v_type = VAR_STRING; -  rettv->vval.v_string = get_tv_string_chk(&argvars[0]); -  if (!rettv->vval.v_string) { +  const char *const s = tv_get_string_chk(&argvars[0]); +  if (!s) {      return;    } -  rettv->vval.v_string = shorten_dir(vim_strsave(rettv->vval.v_string)); +  rettv->vval.v_string = shorten_dir((char_u *)xstrdup(s));  }  /* @@ -13240,7 +13223,7 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr)        EMSG2(_(e_toomanyarg), "remove()");      } else if ((d = argvars[0].vval.v_dict) != NULL                 && !tv_check_lock(d->dv_lock, arg_errmsg, arg_errmsg_len)) { -      const char *key = (const char *)get_tv_string_chk(&argvars[1]); +      const char *key = tv_get_string_chk(&argvars[1]);        if (key != NULL) {          di = tv_dict_find(d, key, -1);          if (di == NULL) { @@ -13572,40 +13555,45 @@ static void f_reverse(typval_T *argvars, typval_T *rettv, FunPtr fptr)  static int get_search_arg(typval_T *varp, int *flagsp)  {    int dir = FORWARD; -  char_u      *flags; -  char_u nbuf[NUMBUFLEN];    int mask;    if (varp->v_type != VAR_UNKNOWN) { -    flags = get_tv_string_buf_chk(varp, nbuf); -    if (flags == NULL) -      return 0;                 /* type error; errmsg already given */ +    char nbuf[NUMBUFLEN]; +    const char *flags = tv_get_string_buf_chk(varp, nbuf); +    if (flags == NULL) { +      return 0;  // Type error; errmsg already given. +    }      while (*flags != NUL) {        switch (*flags) { -      case 'b': dir = BACKWARD; break; -      case 'w': p_ws = true; break; -      case 'W': p_ws = false; break; -      default:  mask = 0; -        if (flagsp != NULL) -          switch (*flags) { -            case 'c': mask = SP_START; break; -            case 'e': mask = SP_END; break; -            case 'm': mask = SP_RETCOUNT; break; -            case 'n': mask = SP_NOMOVE; break; -            case 'p': mask = SP_SUBPAT; break; -            case 'r': mask = SP_REPEAT; break; -            case 's': mask = SP_SETPCMARK; break; -            case 'z': mask = SP_COLUMN; break; +        case 'b': dir = BACKWARD; break; +        case 'w': p_ws = true; break; +        case 'W': p_ws = false; break; +        default: { +          mask = 0; +          if (flagsp != NULL) { +            switch (*flags) { +              case 'c': mask = SP_START; break; +              case 'e': mask = SP_END; break; +              case 'm': mask = SP_RETCOUNT; break; +              case 'n': mask = SP_NOMOVE; break; +              case 'p': mask = SP_SUBPAT; break; +              case 'r': mask = SP_REPEAT; break; +              case 's': mask = SP_SETPCMARK; break; +              case 'z': mask = SP_COLUMN; break; +            }            } -        if (mask == 0) { -          EMSG2(_(e_invarg2), flags); -          dir = 0; -        } else -          *flagsp |= mask; +          if (mask == 0) { +            emsgf(_(e_invarg2), flags); +            dir = 0; +          } else { +            *flagsp |= mask; +          } +        }        } -      if (dir == 0) +      if (dir == 0) {          break; -      ++flags; +      } +      flags++;      }    }    return dir; @@ -13989,16 +13977,17 @@ static void f_searchdecl(typval_T *argvars, typval_T *rettv, FunPtr fptr)    rettv->vval.v_number = 1;     /* default: FAIL */ -  char_u *name = get_tv_string_chk(&argvars[0]); +  const char *const name = tv_get_string_chk(&argvars[0]);    if (argvars[1].v_type != VAR_UNKNOWN) {      locally = tv_get_number_chk(&argvars[1], &error) == 0;      if (!error && argvars[2].v_type != VAR_UNKNOWN) {        thisblock = tv_get_number_chk(&argvars[2], &error) != 0;      }    } -  if (!error && name != NULL) -    rettv->vval.v_number = find_decl(name, STRLEN(name), locally, +  if (!error && name != NULL) { +    rettv->vval.v_number = find_decl((char_u *)name, strlen(name), locally,                                       thisblock, SEARCH_KEEP) == FAIL; +  }  }  /* @@ -14006,49 +13995,53 @@ static void f_searchdecl(typval_T *argvars, typval_T *rettv, FunPtr fptr)   */  static int searchpair_cmn(typval_T *argvars, pos_T *match_pos)  { -  char_u      *spat, *mpat, *epat; -  char_u      *skip;    bool save_p_ws = p_ws;    int dir;    int flags = 0; -  char_u nbuf1[NUMBUFLEN]; -  char_u nbuf2[NUMBUFLEN]; -  char_u nbuf3[NUMBUFLEN]; -  int retval = 0;                       /* default: FAIL */ +  int retval = 0;  // default: FAIL    long lnum_stop = 0;    long time_limit = 0; -  /* Get the three pattern arguments: start, middle, end. */ -  spat = get_tv_string_chk(&argvars[0]); -  mpat = get_tv_string_buf_chk(&argvars[1], nbuf1); -  epat = get_tv_string_buf_chk(&argvars[2], nbuf2); -  if (spat == NULL || mpat == NULL || epat == NULL) -    goto theend;            /* type error */ +  // Get the three pattern arguments: start, middle, end. +  char nbuf1[NUMBUFLEN]; +  char nbuf2[NUMBUFLEN]; +  char nbuf3[NUMBUFLEN]; +  const char *spat = tv_get_string_chk(&argvars[0]); +  const char *mpat = tv_get_string_buf_chk(&argvars[1], nbuf1); +  const char *epat = tv_get_string_buf_chk(&argvars[2], nbuf2); +  if (spat == NULL || mpat == NULL || epat == NULL) { +    goto theend;  // Type error. +  } -  /* Handle the optional fourth argument: flags */ -  dir = get_search_arg(&argvars[3], &flags);   /* may set p_ws */ -  if (dir == 0) +  // Handle the optional fourth argument: flags. +  dir = get_search_arg(&argvars[3], &flags);   // may set p_ws. +  if (dir == 0) {      goto theend; +  } -  /* Don't accept SP_END or SP_SUBPAT. -   * Only one of the SP_NOMOVE or SP_SETPCMARK flags can be set. -   */ +  // Don't accept SP_END or SP_SUBPAT. +  // Only one of the SP_NOMOVE or SP_SETPCMARK flags can be set.    if ((flags & (SP_END | SP_SUBPAT)) != 0        || ((flags & SP_NOMOVE) && (flags & SP_SETPCMARK))) {      EMSG2(_(e_invarg2), tv_get_string(&argvars[3]));      goto theend;    } -  /* Using 'r' implies 'W', otherwise it doesn't work. */ -  if (flags & SP_REPEAT) +  // Using 'r' implies 'W', otherwise it doesn't work. +  if (flags & SP_REPEAT) {      p_ws = false; +  } -  /* Optional fifth argument: skip expression */ +  // Optional fifth argument: skip expression. +  const char *skip;    if (argvars[3].v_type == VAR_UNKNOWN -      || argvars[4].v_type == VAR_UNKNOWN) -    skip = (char_u *)""; -  else { -    skip = get_tv_string_buf_chk(&argvars[4], nbuf3); +      || argvars[4].v_type == VAR_UNKNOWN) { +    skip = ""; +  } else { +    skip = tv_get_string_buf_chk(&argvars[4], nbuf3); +    if (skip == NULL) { +      goto theend;  // Type error. +    }      if (argvars[5].v_type != VAR_UNKNOWN) {        lnum_stop = tv_get_number_chk(&argvars[5], NULL);        if (lnum_stop < 0) { @@ -14062,11 +14055,10 @@ static int searchpair_cmn(typval_T *argvars, pos_T *match_pos)        }      }    } -  if (skip == NULL) -    goto theend;            /* type error */ -  retval = do_searchpair(spat, mpat, epat, dir, skip, flags, -      match_pos, lnum_stop, time_limit); +  retval = do_searchpair( +      (char_u *)spat, (char_u *)mpat, (char_u *)epat, dir, (char_u *)skip, +      flags, match_pos, lnum_stop, time_limit);  theend:    p_ws = save_p_ws; @@ -14341,14 +14333,12 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)   */  static void f_setbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)  { -  char_u nbuf[NUMBUFLEN]; -    if (check_restricted()        || check_secure()        || !tv_check_str_or_nr(&argvars[0])) {      return;    } -  const char *varname = (const char *)get_tv_string_chk(&argvars[1]); +  const char *varname = tv_get_string_chk(&argvars[1]);    buf_T *const buf = get_buf_tv(&argvars[0], false);    typval_T *varp = &argvars[2]; @@ -14363,7 +14353,8 @@ static void f_setbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)        varname++;        numval = tv_get_number_chk(varp, &error); -      char *const strval = (char *)get_tv_string_buf_chk(varp, nbuf); +      char nbuf[NUMBUFLEN]; +      const char *const strval = tv_get_string_buf_chk(varp, nbuf);        if (!error && strval != NULL) {          set_option_value(varname, numval, strval, OPT_LOCAL);        } @@ -14438,17 +14429,17 @@ static void f_setfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr)  {    rettv->vval.v_number = 0; -  char_u *fname = get_tv_string_chk(&argvars[0]); +  const char *const fname = tv_get_string_chk(&argvars[0]);    if (fname == NULL) {      return;    } -  char_u modebuf[NUMBUFLEN]; -  char_u *mode_str = get_tv_string_buf_chk(&argvars[1], modebuf); +  char modebuf[NUMBUFLEN]; +  const char *const mode_str = tv_get_string_buf_chk(&argvars[1], modebuf);    if (mode_str == NULL) {      return;    } -  if (STRLEN(mode_str) != 9) { +  if (strlen(mode_str) != 9) {      EMSG2(_(e_invarg2), mode_str);      return;    } @@ -14469,26 +14460,28 @@ static void f_setfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr)   */  static void f_setline(typval_T *argvars, typval_T *rettv, FunPtr fptr)  { -  char_u      *line = NULL;    list_T      *l = NULL;    listitem_T  *li = NULL;    long added = 0;    linenr_T lcount = curbuf->b_ml.ml_line_count;    linenr_T lnum = tv_get_lnum(&argvars[0]); +  const char *line = NULL;    if (argvars[1].v_type == VAR_LIST) {      l = argvars[1].vval.v_list;      li = l->lv_first; -  } else -    line = get_tv_string_chk(&argvars[1]); +  } else { +    line = tv_get_string_chk(&argvars[1]); +  }    /* default result is zero == OK */    for (;; ) {      if (l != NULL) { -      /* list argument, get next string */ -      if (li == NULL) +      // List argument, get next string. +      if (li == NULL) {          break; -      line = get_tv_string_chk(&li->li_tv); +      } +      line = tv_get_string_chk(&li->li_tv);        li = li->li_next;      } @@ -14504,18 +14497,20 @@ static void f_setline(typval_T *argvars, typval_T *rettv, FunPtr fptr)      }      if (lnum <= curbuf->b_ml.ml_line_count) { -      /* existing line, replace it */ -      if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK) { +      // Existing line, replace it. +      if (u_savesub(lnum) == OK +          && ml_replace(lnum, (char_u *)line, true) == OK) {          changed_bytes(lnum, 0);          if (lnum == curwin->w_cursor.lnum)            check_cursor_col();          rettv->vval.v_number = 0;               /* OK */        }      } else if (added > 0 || u_save(lnum - 1, lnum) == OK) { -      /* lnum is one past the last line, append the line */ -      ++added; -      if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK) -        rettv->vval.v_number = 0;               /* OK */ +      // lnum is one past the last line, append the line. +      added++; +      if (ml_append(lnum - 1, (char_u *)line, 0, false) == OK) { +        rettv->vval.v_number = 0;  // OK +      }      }      if (l == NULL)                      /* only one string argument */ @@ -14544,7 +14539,7 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv)    FUNC_ATTR_NONNULL_ARG(2, 3)  {    static char *e_invact = N_("E927: Invalid action: '%s'"); -  char_u *title = NULL; +  const char *title = NULL;    int action = ' ';    rettv->vval.v_number = -1;    dict_T *d = NULL; @@ -14563,7 +14558,7 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv)      EMSG(_(e_stringreq));      return;    } -  char_u *act = get_tv_string_chk(action_arg); +  const char *const act = tv_get_string_chk(action_arg);    if ((*act == 'a' || *act == 'r' || *act == ' ') && act[1] == NUL) {      action = *act;    } else { @@ -14576,7 +14571,7 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv)      // Option argument was not given.      goto skip_args;    } else if (title_arg->v_type == VAR_STRING) { -    title = get_tv_string_chk(title_arg); +    title = tv_get_string_chk(title_arg);      if (!title) {        // Type error. Error already printed by get_tv_string_chk().        return; @@ -14584,17 +14579,17 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv)    } else if (title_arg->v_type == VAR_DICT) {      d = title_arg->vval.v_dict;    } else { -    EMSG(_(e_dictreq)); +    emsgf(_(e_dictreq));      return;    }  skip_args:    if (!title) { -    title = (char_u*)(wp ? "setloclist()" : "setqflist()"); +    title = (wp ? "setloclist()" : "setqflist()");    }    list_T *l = list_arg->vval.v_list; -  if (l && set_errorlist(wp, l, action, title, d) == OK) { +  if (l && set_errorlist(wp, l, action, (char_u *)title, d) == OK) {      rettv->vval.v_number = 0;    }  } @@ -14728,11 +14723,10 @@ static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)  {    pos_T pos;    int fnum; -  char_u      *name;    colnr_T     curswant = -1;    rettv->vval.v_number = -1; -  name = get_tv_string_chk(argvars); +  const char *const name = tv_get_string_chk(argvars);    if (name != NULL) {      if (list2fpos(&argvars[1], &pos, &fnum, &curswant) == OK) {        if (--pos.col < 0) { @@ -14753,7 +14747,7 @@ static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)          }        } else if (name[0] == '\'' && name[1] != NUL && name[2] == NUL)   {          // set mark -        if (setmark_pos(name[1], &pos, fnum) == OK) { +        if (setmark_pos((uint8_t)name[1], &pos, fnum) == OK) {            rettv->vval.v_number = 0;          }        } else { @@ -14777,8 +14771,6 @@ static void f_setqflist(typval_T *argvars, typval_T *rettv, FunPtr fptr)  static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr)  {    int regname; -  char_u      *strregname; -  char_u      *stropt;    bool append = false;    MotionType yank_type;    long block_len; @@ -14786,39 +14778,47 @@ static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr)    block_len = -1;    yank_type = kMTUnknown; -  strregname = get_tv_string_chk(argvars); -  rettv->vval.v_number = 1;             /* FAIL is default */ +  rettv->vval.v_number = 1;  // FAIL is default. -  if (strregname == NULL) -    return;             /* type error; errmsg already given */ -  regname = *strregname; -  if (regname == 0 || regname == '@') +  const char *const strregname = tv_get_string_chk(argvars); +  if (strregname == NULL) { +    return;  // Type error; errmsg already given. +  } +  regname = (uint8_t)(*strregname); +  if (regname == 0 || regname == '@') {      regname = '"'; +  }    if (argvars[2].v_type != VAR_UNKNOWN) { -    stropt = get_tv_string_chk(&argvars[2]); -    if (stropt == NULL) -      return;                   /* type error */ -    for (; *stropt != NUL; ++stropt) +    const char *stropt = tv_get_string_chk(&argvars[2]); +    if (stropt == NULL) { +      return;  // Type error. +    } +    for (; *stropt != NUL; stropt++) {        switch (*stropt) { -      case 'a': case 'A':  // append -        append = true; -        break; -      case 'v': case 'c':  // character-wise selection -        yank_type = kMTCharWise; -        break; -      case 'V': case 'l':  // line-wise selection -        yank_type = kMTLineWise; -        break; -      case 'b': case Ctrl_V:  // block-wise selection -        yank_type = kMTBlockWise; -        if (ascii_isdigit(stropt[1])) { -          ++stropt; -          block_len = getdigits_long(&stropt) - 1; -          --stropt; +        case 'a': case 'A': {  // append +          append = true; +          break; +        } +        case 'v': case 'c': {  // character-wise selection +          yank_type = kMTCharWise; +          break; +        } +        case 'V': case 'l': {  // line-wise selection +          yank_type = kMTLineWise; +          break; +        } +        case 'b': case Ctrl_V: {  // block-wise selection +          yank_type = kMTBlockWise; +          if (ascii_isdigit(stropt[1])) { +            stropt++; +            block_len = getdigits_long((char_u **)&stropt) - 1; +            stropt--; +          } +          break;          } -        break;        } +    }    }    if (argvars[1].v_type == VAR_LIST) { @@ -14828,42 +14828,44 @@ static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr)      // First half: use for pointers to result lines; second half: use for      // pointers to allocated copies. -    char_u **lstval = xmalloc(sizeof(char_u *) * ((len + 1) * 2)); -    char_u **curval = lstval; -    char_u **allocval = lstval + len + 2; -    char_u **curallocval = allocval; +    char **lstval = xmalloc(sizeof(char *) * ((len + 1) * 2)); +    const char **curval = (const char **)lstval; +    char **allocval = lstval + len + 2; +    char **curallocval = allocval; -    char_u buf[NUMBUFLEN];      for (listitem_T *li = ll == NULL ? NULL : ll->lv_first;           li != NULL;           li = li->li_next) { -      char_u *strval = get_tv_string_buf_chk(&li->li_tv, buf); -      if (strval == NULL) { +      char buf[NUMBUFLEN]; +      *curval = tv_get_string_buf_chk(&li->li_tv, buf); +      if (*curval == NULL) {          goto free_lstval;        } -      if (strval == buf) { +      if (*curval == buf) {          // Need to make a copy, -        // next get_tv_string_buf_chk() will overwrite the string. -        strval = vim_strsave(buf); -        *curallocval++ = strval; +        // next tv_get_string_buf_chk() will overwrite the string. +        *curallocval = xstrdup(*curval); +        *curval = *curallocval; +        curallocval++;        } -      *curval++ = strval; +      curval++;      }      *curval++ = NULL; -    write_reg_contents_lst(regname, lstval, STRLEN(lstval), -                           append, yank_type, block_len); +    write_reg_contents_lst(regname, (char_u **)lstval, append, yank_type, +                           block_len);  free_lstval: -    while (curallocval > allocval) -        xfree(*--curallocval); +    while (curallocval > allocval) { +      xfree(*--curallocval); +    }      xfree(lstval);    } else { -    char_u *strval = get_tv_string_chk(&argvars[1]); +    const char *strval = tv_get_string_chk(&argvars[1]);      if (strval == NULL) {        return;      } -    write_reg_contents_ex(regname, strval, STRLEN(strval), +    write_reg_contents_ex(regname, (const char_u *)strval, STRLEN(strval),                            append, yank_type, block_len);    }    rettv->vval.v_number = 0; @@ -14881,7 +14883,7 @@ static void f_settabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)    }    tabpage_T *const tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL)); -  const char *const varname = (const char *)get_tv_string_chk(&argvars[1]); +  const char *const varname = tv_get_string_chk(&argvars[1]);    typval_T *const varp = &argvars[2];    if (varname != NULL && varp != NULL && tp != NULL) { @@ -14935,7 +14937,7 @@ static void setwinvar(typval_T *argvars, typval_T *rettv, int off)      tp = curtab;    }    win_T *const win = find_win_by_nr(&argvars[off], tp); -  const char *varname = (const char *)get_tv_string_chk(&argvars[off + 1]); +  const char *varname = tv_get_string_chk(&argvars[off + 1]);    typval_T *varp = &argvars[off + 2];    if (win != NULL && varname != NULL && varp != NULL) { @@ -14950,8 +14952,8 @@ static void setwinvar(typval_T *argvars, typval_T *rettv, int off)          varname++;          numval = tv_get_number_chk(varp, &error); -        char_u nbuf[NUMBUFLEN]; -        char *const strval = (char *)get_tv_string_buf_chk(varp, nbuf); +        char nbuf[NUMBUFLEN]; +        const char *const strval = tv_get_string_buf_chk(varp, nbuf);          if (!error && strval != NULL) {            set_option_value(varname, numval, strval, OPT_LOCAL);          } @@ -15415,25 +15417,26 @@ static void f_soundfold(typval_T *argvars, typval_T *rettv, FunPtr fptr)   */  static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr)  { -  char_u      *word = (char_u *)""; +  const char *word = "";    hlf_T attr = HLF_COUNT;    size_t len = 0;    tv_list_alloc_ret(rettv);    if (argvars[0].v_type == VAR_UNKNOWN) { -    /* Find the start and length of the badly spelled word. */ -    len = spell_move_to(curwin, FORWARD, TRUE, TRUE, &attr); -    if (len != 0) -      word = get_cursor_pos_ptr(); +    // Find the start and length of the badly spelled word. +    len = spell_move_to(curwin, FORWARD, true, true, &attr); +    if (len != 0) { +      word = (char *)get_cursor_pos_ptr(); +    }    } else if (curwin->w_p_spell && *curbuf->b_s.b_p_spl != NUL) { -    char_u  *str = get_tv_string_chk(&argvars[0]); +    const char *str = tv_get_string_chk(&argvars[0]);      int capcol = -1;      if (str != NULL) { -      /* Check the argument for spelling. */ +      // Check the argument for spelling.        while (*str != NUL) { -        len = spell_check(curwin, str, &attr, &capcol, false); +        len = spell_check(curwin, (char_u *)str, &attr, &capcol, false);          if (attr != HLF_COUNT) {            word = str;            break; @@ -15444,7 +15447,7 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr)    }    assert(len <= INT_MAX); -  tv_list_append_string(rettv->vval.v_list, (const char *)word, len); +  tv_list_append_string(rettv->vval.v_list, word, len);    tv_list_append_string(rettv->vval.v_list,                          (attr == HLF_SPB ? "bad"                           : attr == HLF_SPR ? "rare" @@ -15499,9 +15502,7 @@ static void f_spellsuggest(typval_T *argvars, typval_T *rettv, FunPtr fptr)  static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr)  { -  char_u      *pat = NULL;    regmatch_T regmatch; -  char_u patbuf[NUMBUFLEN];    char_u      *save_cpo;    int match;    colnr_T col = 0; @@ -15513,8 +15514,10 @@ static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr)    p_cpo = (char_u *)"";    const char *str = tv_get_string(&argvars[0]); +  const char *pat = NULL; +  char patbuf[NUMBUFLEN];    if (argvars[1].v_type != VAR_UNKNOWN) { -    pat = get_tv_string_buf_chk(&argvars[1], patbuf); +    pat = tv_get_string_buf_chk(&argvars[1], patbuf);      if (pat == NULL) {        typeerr = true;      } @@ -15522,15 +15525,16 @@ static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr)        keepempty = (bool)tv_get_number_chk(&argvars[2], &typeerr);      }    } -  if (pat == NULL || *pat == NUL) -    pat = (char_u *)"[\\x01- ]\\+"; +  if (pat == NULL || *pat == NUL) { +    pat = "[\\x01- ]\\+"; +  }    tv_list_alloc_ret(rettv);    if (typeerr)      return; -  regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); +  regmatch.regprog = vim_regcomp((char_u *)pat, RE_MAGIC + RE_STRING);    if (regmatch.regprog != NULL) {      regmatch.rm_ic = FALSE;      while (*str != NUL || keepempty) { @@ -15682,7 +15686,7 @@ static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)  {    rettv->vval.v_number = -1; -  char_u *str = get_tv_string_chk(&argvars[0]); +  const char *const str = tv_get_string_chk(&argvars[0]);    if (str == NULL) {      return;    } @@ -15697,11 +15701,11 @@ static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)    while (charidx >= 0 && byteidx < len) {      if (charidx == 0) { -      rettv->vval.v_number = mb_ptr2char(str + byteidx); +      rettv->vval.v_number = mb_ptr2char((const char_u *)str + byteidx);        break;      }      charidx--; -    byteidx += MB_CPTR2LEN(str + byteidx); +    byteidx += MB_CPTR2LEN((const char_u *)str + byteidx);    }  } @@ -15710,24 +15714,22 @@ static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)   */  static void f_stridx(typval_T *argvars, typval_T *rettv, FunPtr fptr)  { -  char_u buf[NUMBUFLEN]; -  char_u      *needle; -  char_u      *haystack; -  char_u      *save_haystack; -  char_u      *pos; -  int start_idx; - -  needle = get_tv_string_chk(&argvars[1]); -  save_haystack = haystack = get_tv_string_buf_chk(&argvars[0], buf);    rettv->vval.v_number = -1; -  if (needle == NULL || haystack == NULL) -    return;             /* type error; errmsg already given */ + +  char buf[NUMBUFLEN]; +  const char *const needle = tv_get_string_chk(&argvars[1]); +  const char *haystack = tv_get_string_buf_chk(&argvars[0], buf); +  const char *const haystack_start = haystack; +  if (needle == NULL || haystack == NULL) { +    return;  // Type error; errmsg already given. +  }    if (argvars[2].v_type != VAR_UNKNOWN) {      bool error = false; -    start_idx = tv_get_number_chk(&argvars[2], &error); -    if (error || start_idx >= (int)STRLEN(haystack)) { +    const ptrdiff_t start_idx = (ptrdiff_t)tv_get_number_chk(&argvars[2], +                                                             &error); +    if (error || start_idx >= (ptrdiff_t)strlen(haystack)) {        return;      }      if (start_idx >= 0) { @@ -15735,9 +15737,10 @@ static void f_stridx(typval_T *argvars, typval_T *rettv, FunPtr fptr)      }    } -  pos = (char_u *)strstr((char *)haystack, (char *)needle); -  if (pos != NULL) -    rettv->vval.v_number = (varnumber_T)(pos - save_haystack); +  const char *pos = strstr(haystack, needle); +  if (pos != NULL) { +    rettv->vval.v_number = (varnumber_T)(pos - haystack_start); +  }  }  /* @@ -15765,7 +15768,7 @@ static void f_strchars(typval_T *argvars, typval_T *rettv, FunPtr fptr)    const char *s = tv_get_string(&argvars[0]);    int skipcc = 0;    varnumber_T len = 0; -  int (*func_mb_ptr2char_adv)(char_u **pp); +  int (*func_mb_ptr2char_adv)(const char_u **pp);    if (argvars[1].v_type != VAR_UNKNOWN) {      skipcc = tv_get_number_chk(&argvars[1], NULL); @@ -15775,7 +15778,7 @@ static void f_strchars(typval_T *argvars, typval_T *rettv, FunPtr fptr)    } else {      func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv;      while (*s != NUL) { -      func_mb_ptr2char_adv((char_u **)&s); +      func_mb_ptr2char_adv((const char_u **)&s);        len++;      }      rettv->vval.v_number = len; @@ -15904,47 +15907,46 @@ static void f_strpart(typval_T *argvars, typval_T *rettv, FunPtr fptr)   */  static void f_strridx(typval_T *argvars, typval_T *rettv, FunPtr fptr)  { -  char_u buf[NUMBUFLEN]; -  char_u      *needle; -  char_u      *haystack; -  char_u      *rest; -  char_u      *lastmatch = NULL; -  int haystack_len, end_idx; - -  needle = get_tv_string_chk(&argvars[1]); -  haystack = get_tv_string_buf_chk(&argvars[0], buf); +  char buf[NUMBUFLEN]; +  const char *const needle = tv_get_string_chk(&argvars[1]); +  const char *const haystack = tv_get_string_buf_chk(&argvars[0], buf);    rettv->vval.v_number = -1; -  if (needle == NULL || haystack == NULL) -    return;             /* type error; errmsg already given */ +  if (needle == NULL || haystack == NULL) { +    return;  // Type error; errmsg already given. +  } -  haystack_len = (int)STRLEN(haystack); +  const size_t haystack_len = STRLEN(haystack); +  ptrdiff_t end_idx;    if (argvars[2].v_type != VAR_UNKNOWN) {      // Third argument: upper limit for index. -    end_idx = tv_get_number_chk(&argvars[2], NULL); +    end_idx = (ptrdiff_t)tv_get_number_chk(&argvars[2], NULL);      if (end_idx < 0) {        return;  // Can never find a match.      }    } else { -    end_idx = haystack_len; +    end_idx = (ptrdiff_t)haystack_len;    } +  const char *lastmatch = NULL;    if (*needle == NUL) { -    /* Empty string matches past the end. */ +    // Empty string matches past the end.      lastmatch = haystack + end_idx;    } else { -    for (rest = haystack; *rest != NUL; ++rest) { -      rest = (char_u *)strstr((char *)rest, (char *)needle); -      if (rest == NULL || rest > haystack + end_idx) +    for (const char *rest = haystack; *rest != NUL; rest++) { +      rest = strstr(rest, needle); +      if (rest == NULL || rest > haystack + end_idx) {          break; +      }        lastmatch = rest;      }    } -  if (lastmatch == NULL) +  if (lastmatch == NULL) {      rettv->vval.v_number = -1; -  else +  } else {      rettv->vval.v_number = (varnumber_T)(lastmatch - haystack); +  }  }  /* @@ -15994,20 +15996,20 @@ static void f_submatch(typval_T *argvars, typval_T *rettv, FunPtr fptr)   */  static void f_substitute(typval_T *argvars, typval_T *rettv, FunPtr fptr)  { -  char_u patbuf[NUMBUFLEN]; -  char_u subbuf[NUMBUFLEN]; -  char_u flagsbuf[NUMBUFLEN]; +  char patbuf[NUMBUFLEN]; +  char subbuf[NUMBUFLEN]; +  char flagsbuf[NUMBUFLEN]; -  char_u      *str = get_tv_string_chk(&argvars[0]); -  char_u      *pat = get_tv_string_buf_chk(&argvars[1], patbuf); -  char_u      *sub = NULL; -  typval_T    *expr = NULL; -  char_u      *flg = get_tv_string_buf_chk(&argvars[3], flagsbuf); +  const char *const str = tv_get_string_chk(&argvars[0]); +  const char *const pat = tv_get_string_buf_chk(&argvars[1], patbuf); +  const char *sub = NULL; +  const char *const flg = tv_get_string_buf_chk(&argvars[3], flagsbuf); +  typval_T *expr = NULL;    if (argvars[2].v_type == VAR_FUNC || argvars[2].v_type == VAR_PARTIAL) {      expr = &argvars[2];    } else { -    sub = get_tv_string_buf_chk(&argvars[2], subbuf); +    sub = tv_get_string_buf_chk(&argvars[2], subbuf);    }    rettv->v_type = VAR_STRING; @@ -16015,7 +16017,8 @@ static void f_substitute(typval_T *argvars, typval_T *rettv, FunPtr fptr)        || flg == NULL) {      rettv->vval.v_string = NULL;    } else { -    rettv->vval.v_string = do_string_sub(str, pat, sub, expr, flg); +    rettv->vval.v_string = do_string_sub((char_u *)str, (char_u *)pat, +                                         (char_u *)sub, expr, (char_u *)flg);    }  } @@ -16333,19 +16336,20 @@ static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv, FunPtr fptr)  static void f_tabpagenr(typval_T *argvars, typval_T *rettv, FunPtr fptr)  {    int nr = 1; -  char_u      *arg;    if (argvars[0].v_type != VAR_UNKNOWN) { -    arg = get_tv_string_chk(&argvars[0]); +    const char *const arg = tv_get_string_chk(&argvars[0]);      nr = 0;      if (arg != NULL) { -      if (STRCMP(arg, "$") == 0) +      if (strcmp(arg, "$") == 0) {          nr = tabpage_index(NULL) - 1; -      else +      } else {          EMSG2(_(e_invexpr2), arg); +      }      } -  } else +  } else {      nr = tabpage_index(curtab); +  }    rettv->vval.v_number = nr;  } @@ -16359,19 +16363,19 @@ static int get_winnr(tabpage_T *tp, typval_T *argvar)    win_T       *twin;    int nr = 1;    win_T       *wp; -  char_u      *arg;    twin = (tp == curtab) ? curwin : tp->tp_curwin;    if (argvar->v_type != VAR_UNKNOWN) { -    arg = get_tv_string_chk(argvar); -    if (arg == NULL) -      nr = 0;                   /* type error; errmsg already given */ -    else if (STRCMP(arg, "$") == 0) +    const char *const arg = tv_get_string_chk(argvar); +    if (arg == NULL) { +      nr = 0;  // Type error; errmsg already given. +    } else if (strcmp(arg, "$") == 0) {        twin = (tp == curtab) ? lastwin : tp->tp_lastwin; -    else if (STRCMP(arg, "#") == 0) { +    } else if (strcmp(arg, "#") == 0) {        twin = (tp == curtab) ? prevwin : tp->tp_prevwin; -      if (twin == NULL) +      if (twin == NULL) {          nr = 0; +      }      } else {        EMSG2(_(e_invexpr2), arg);        nr = 0; @@ -16853,28 +16857,25 @@ static void f_toupper(typval_T *argvars, typval_T *rettv, FunPtr fptr)   */  static void f_tr(typval_T *argvars, typval_T *rettv, FunPtr fptr)  { -  int fromlen; -  int tolen; -  int idx; -  char_u buf[NUMBUFLEN]; -  char_u buf2[NUMBUFLEN]; -  garray_T ga; +  char buf[NUMBUFLEN]; +  char buf2[NUMBUFLEN];    const char *in_str = tv_get_string(&argvars[0]); -  const char_u *fromstr = get_tv_string_buf_chk(&argvars[1], buf); -  const char_u *tostr = get_tv_string_buf_chk(&argvars[2], buf2); +  const char *fromstr = tv_get_string_buf_chk(&argvars[1], buf); +  const char *tostr = tv_get_string_buf_chk(&argvars[2], buf2);    // Default return value: empty string.    rettv->v_type = VAR_STRING;    rettv->vval.v_string = NULL;    if (fromstr == NULL || tostr == NULL) { -    return;  // type error; errmsg already given +    return;  // Type error; errmsg already given.    } +  garray_T ga;    ga_init(&ga, (int)sizeof(char), 80);    if (!has_mbyte) {      // Not multi-byte: fromstr and tostr must be the same length. -    if (STRLEN(fromstr) != STRLEN(tostr)) { +    if (strlen(fromstr) != strlen(tostr)) {        goto error;      }    } @@ -16886,23 +16887,26 @@ static void f_tr(typval_T *argvars, typval_T *rettv, FunPtr fptr)        const char *cpstr = in_str;        const int inlen = (*mb_ptr2len)((const char_u *)in_str);        int cplen = inlen; -      idx = 0; -      for (const char_u *p = fromstr; *p != NUL; p += fromlen) { -        fromlen = (*mb_ptr2len)(p); +      int idx = 0; +      int fromlen; +      for (const char *p = fromstr; *p != NUL; p += fromlen) { +        fromlen = (*mb_ptr2len)((const char_u *)p);          if (fromlen == inlen && STRNCMP(in_str, p, inlen) == 0) { +          int tolen;            for (p = tostr; *p != NUL; p += tolen) { -            tolen = (*mb_ptr2len)(p); +            tolen = (*mb_ptr2len)((const char_u *)p);              if (idx-- == 0) {                cplen = tolen;                cpstr = (char *)p;                break;              }            } -          if (*p == NUL)                /* tostr is shorter than fromstr */ +          if (*p == NUL) {  // tostr is shorter than fromstr.              goto error; +          }            break;          } -        ++idx; +        idx++;        }        if (first && cpstr == in_str) { @@ -16910,8 +16914,9 @@ static void f_tr(typval_T *argvars, typval_T *rettv, FunPtr fptr)          // (multi-byte) characters.  Done only once when a character          // of in_str doesn't appear in fromstr.          first = false; -        for (const char_u *p = tostr; *p != NUL; p += tolen) { -          tolen = (*mb_ptr2len)(p); +        int tolen; +        for (const char *p = tostr; *p != NUL; p += tolen) { +          tolen = (*mb_ptr2len)((const char_u *)p);            idx--;          }          if (idx != 0) { @@ -16926,7 +16931,7 @@ static void f_tr(typval_T *argvars, typval_T *rettv, FunPtr fptr)        in_str += inlen;      } else {        // When not using multi-byte chars we can do it faster. -      char_u *p = vim_strchr(fromstr, *in_str); +      const char *const p = strchr(fromstr, *in_str);        if (p != NULL) {          ga_append(&ga, tostr[p - fromstr]);        } else { @@ -17278,8 +17283,7 @@ static bool write_list(FileDescriptor *const fp, const list_T *const list,  {    int error = 0;    for (const listitem_T *li = list->lv_first; li != NULL; li = li->li_next) { -    const char *const s = (const char *)get_tv_string_chk( -        (typval_T *)&li->li_tv); +    const char *const s = tv_get_string_chk(&li->li_tv);      if (s == NULL) {        return false;      } @@ -17368,17 +17372,16 @@ static char *save_tv_as_string(typval_T *tv, ptrdiff_t *const len, bool endnl)      return NULL;    } -  // For types other than list, let get_tv_string_buf_chk() get the value or +  // For types other than list, let tv_get_string_buf_chk() get the value or    // print an error.    if (tv->v_type != VAR_LIST) { -    char *ret = (char *)get_tv_string_chk(tv); +    const char *ret = tv_get_string_chk(tv);      if (ret && (*len = strlen(ret))) { -      ret = xstrdup(ret); +      return xmemdupz(ret, (size_t)(*len));      } else { -      ret = NULL;        *len = -1; +      return NULL;      } -    return ret;    }    // Pre-calculate the resulting length. @@ -17448,7 +17451,7 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, FunPtr fptr)    bool binary = false;    bool append = false;    if (argvars[2].v_type != VAR_UNKNOWN) { -    const char *const flags = (const char *)get_tv_string_chk(&argvars[2]); +    const char *const flags = tv_get_string_chk(&argvars[2]);      if (flags == NULL) {        return;      } @@ -17460,9 +17463,8 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, FunPtr fptr)      }    } -  const char buf[NUMBUFLEN]; -  const char *const fname = (const char *)get_tv_string_buf_chk(&argvars[1], -                                                                (char_u *)buf); +  char buf[NUMBUFLEN]; +  const char *const fname = tv_get_string_buf_chk(&argvars[1], buf);    if (fname == NULL) {      return;    } @@ -17510,7 +17512,6 @@ pos_T *var2fpos(const typval_T *const tv, const int dollar_lnum,                  int *const ret_fnum)    FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL  { -  char_u              *name;    static pos_T pos;    pos_T               *pp; @@ -17564,7 +17565,7 @@ pos_T *var2fpos(const typval_T *const tv, const int dollar_lnum,      return &pos;    } -  name = get_tv_string_chk(tv); +  const char *const name = tv_get_string_chk(tv);    if (name == NULL) {      return NULL;    } @@ -17578,7 +17579,7 @@ pos_T *var2fpos(const typval_T *const tv, const int dollar_lnum,      return &curwin->w_cursor;    }    if (name[0] == '\'') {  // Mark. -    pp = getmark_buf_fnum(curbuf, name[1], false, ret_fnum); +    pp = getmark_buf_fnum(curbuf, (uint8_t)name[1], false, ret_fnum);      if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0) {        return NULL;      } @@ -18403,58 +18404,11 @@ void set_selfdict(typval_T *rettv, dict_T *selfdict)    }  } -// TODO(ZyX-I): move to eval/typval - -/// Careful: This uses a single, static buffer.  YOU CAN ONLY USE IT ONCE! -char_u *get_tv_string_chk(const typval_T *varp) -  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT -{ -  static char_u mybuf[NUMBUFLEN]; - -  return get_tv_string_buf_chk(varp, mybuf); -} - -char_u *get_tv_string_buf_chk(const typval_T *varp, char_u *buf) -  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT -{ -  switch (varp->v_type) { -  case VAR_NUMBER: -    sprintf((char *)buf, "%" PRId64, (int64_t)varp->vval.v_number); -    return buf; -  case VAR_FUNC: -  case VAR_PARTIAL: -    EMSG(_("E729: using Funcref as a String")); -    break; -  case VAR_LIST: -    EMSG(_("E730: using List as a String")); -    break; -  case VAR_DICT: -    EMSG(_("E731: using Dictionary as a String")); -    break; -  case VAR_FLOAT: -    EMSG(_(e_float_as_string)); -    break; -  case VAR_STRING: -    if (varp->vval.v_string != NULL) -      return varp->vval.v_string; -    return (char_u *)""; -  case VAR_SPECIAL: -    STRCPY(buf, encode_special_var_names[varp->vval.v_special]); -    return buf; -  case VAR_UNKNOWN: -    EMSG(_("E908: using an invalid value as a String")); -    break; -  } -  return NULL; -} - -/* - * Find variable "name" in the list of variables. - * Return a pointer to it if found, NULL if not found. - * Careful: "a:0" variables don't have a name. - * When "htp" is not NULL we are writing to the variable, set "htp" to the - * hashtab_T used. - */ +// Find variable "name" in the list of variables. +// Return a pointer to it if found, NULL if not found. +// Careful: "a:0" variables don't have a name. +// When "htp" is not NULL we are writing to the variable, set "htp" to the +// hashtab_T used.  static dictitem_T *find_var(const char *const name, const size_t name_len,                              hashtab_T **htp, int no_autoload)  { | 
