~ubuntu-branches/debian/sid/neovim/sid

« back to all changes in this revision

Viewing changes to src/nvim/eval.c

  • Committer: Package Import Robot
  • Author(s): James McCoy
  • Date: 2016-04-18 21:42:19 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20160418214219-1e6d4o1fwqarzk46
Tags: 0.1.3-1
* New upstream release.  (Closes: #820562)
* debian/control:
  + Remove unnecessary luarocks Build-Depends
  + Add libkvm-dev Build-Depends for kfreebsd-*
  + Add python(3)-neovim to Recommends.  (Closes: #812737)
  + Declare compiance with policy 3.9.8, no changes needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
160
160
static char *e_emptykey = N_("E713: Cannot use empty key for Dictionary");
161
161
static char *e_listreq = N_("E714: List required");
162
162
static char *e_dictreq = N_("E715: Dictionary required");
 
163
static char *e_strreq = N_("E114: String required");
163
164
static char *e_toomanyarg = N_("E118: Too many arguments for function: %s");
164
165
static char *e_dictkey = N_("E716: Key not present in Dictionary: %s");
165
166
static char *e_funcexts = N_(
378
379
  { VV_NAME("option_type",      VAR_STRING), VV_RO },
379
380
  { VV_NAME("errors",           VAR_LIST), 0 },
380
381
  { VV_NAME("msgpack_types",    VAR_DICT), VV_RO },
 
382
  { VV_NAME("event",            VAR_DICT), VV_RO },
381
383
};
382
384
 
383
385
/* shorthand */
545
547
 
546
548
  set_vim_var_dict(VV_MSGPACK_TYPES, msgpack_types_dict);
547
549
  set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc());
 
550
 
 
551
  dict_T *v_event = dict_alloc();
 
552
  v_event->dv_lock = VAR_FIXED;
 
553
  set_vim_var_dict(VV_EVENT, v_event);
548
554
  set_vim_var_list(VV_ERRORS, list_alloc());
549
555
  set_vim_var_nr(VV_SEARCHFORWARD, 1L);
550
556
  set_vim_var_nr(VV_HLSEARCH, 1L);
1700
1706
        }
1701
1707
        error = TRUE;
1702
1708
      } else {
1703
 
        if (tofree != NULL)
 
1709
        if (tofree != NULL) {
1704
1710
          name = tofree;
1705
 
        if (get_var_tv(name, len, &tv, TRUE, FALSE) == FAIL)
1706
 
          error = TRUE;
1707
 
        else {
1708
 
          /* handle d.key, l[idx], f(expr) */
 
1711
        }
 
1712
        if (get_var_tv(name, len, &tv, NULL, true, false) == FAIL) {
 
1713
          error = true;
 
1714
        } else {
 
1715
          // handle d.key, l[idx], f(expr)
1709
1716
          arg_subsc = arg;
1710
1717
          if (handle_subscript(&arg, &tv, TRUE, TRUE) == FAIL)
1711
1718
            error = TRUE;
2176
2183
        if (len == -1)
2177
2184
          clear_tv(&var1);
2178
2185
        break;
 
2186
      } else if (var_check_ro(lp->ll_di->di_flags, name, false)) {
 
2187
        // existing variable, need to check if it can be changed
 
2188
        return NULL;
2179
2189
      }
2180
 
      /* existing variable, need to check if it can be changed */
2181
 
      else if (var_check_ro(lp->ll_di->di_flags, name))
2182
 
        return NULL;
2183
2190
 
2184
2191
      if (len == -1)
2185
2192
        clear_tv(&var1);
2274
2281
      if (op != NULL && *op != '=') {
2275
2282
        typval_T tv;
2276
2283
 
2277
 
        /* handle +=, -= and .= */
 
2284
        // handle +=, -= and .=
 
2285
        di = NULL;
2278
2286
        if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name),
2279
 
                &tv, TRUE, FALSE) == OK) {
2280
 
          if (tv_op(&tv, rettv, op) == OK)
2281
 
            set_var(lp->ll_name, &tv, FALSE);
 
2287
                       &tv, &di, true, false) == OK) {
 
2288
          if ((di == NULL
 
2289
               || (!var_check_ro(di->di_flags, lp->ll_name, false) &&
 
2290
                   !tv_check_lock(di->di_tv.v_lock, lp->ll_name, false)))
 
2291
              && tv_op(&tv, rettv, op) == OK) {
 
2292
            set_var(lp->ll_name, &tv, false);
 
2293
          }
2282
2294
          clear_tv(&tv);
2283
2295
        }
2284
2296
      } else
2286
2298
      *endp = cc;
2287
2299
    }
2288
2300
  } else if (tv_check_lock(lp->ll_newkey == NULL
2289
 
                 ? lp->ll_tv->v_lock
2290
 
                 : lp->ll_tv->vval.v_dict->dv_lock, lp->ll_name))
2291
 
    ;
2292
 
  else if (lp->ll_range) {
 
2301
                           ? lp->ll_tv->v_lock
 
2302
                           : lp->ll_tv->vval.v_dict->dv_lock,
 
2303
                           lp->ll_name, false)) {
 
2304
  } else if (lp->ll_range) {
2293
2305
    listitem_T *ll_li = lp->ll_li;
2294
2306
    int ll_n1 = lp->ll_n1;
2295
2307
 
2296
2308
    // Check whether any of the list items is locked
2297
 
    for (listitem_T *ri = rettv->vval.v_list->lv_first; ri != NULL && ll_li != NULL; ) {
2298
 
      if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name)) {
 
2309
    for (listitem_T *ri = rettv->vval.v_list->lv_first;
 
2310
         ri != NULL && ll_li != NULL; ) {
 
2311
      if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name, false)) {
2299
2312
        return;
2300
2313
      }
2301
2314
      ri = ri->li_next;
2891
2904
      ret = FAIL;
2892
2905
    *name_end = cc;
2893
2906
  } else if ((lp->ll_list != NULL
2894
 
              && tv_check_lock(lp->ll_list->lv_lock, lp->ll_name))
 
2907
              && tv_check_lock(lp->ll_list->lv_lock, lp->ll_name, false))
2895
2908
             || (lp->ll_dict != NULL
2896
 
                 && tv_check_lock(lp->ll_dict->dv_lock, lp->ll_name))) {
 
2909
                 && tv_check_lock(lp->ll_dict->dv_lock, lp->ll_name, false))) {
2897
2910
    return FAIL;
2898
2911
  } else if (lp->ll_range) {
2899
2912
    listitem_T    *li;
2902
2915
 
2903
2916
    while (ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= ll_n1)) {
2904
2917
      li = ll_li->li_next;
2905
 
      if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name)) {
 
2918
      if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name, false)) {
2906
2919
        return false;
2907
2920
      }
2908
2921
      ll_li = li;
2975
2988
    hi = hash_find(ht, varname);
2976
2989
    if (!HASHITEM_EMPTY(hi)) {
2977
2990
      di = HI2DI(hi);
2978
 
      if (var_check_fixed(di->di_flags, name)
2979
 
          || var_check_ro(di->di_flags, name)
2980
 
          || tv_check_lock(d->dv_lock, name)) {
 
2991
      if (var_check_fixed(di->di_flags, name, false)
 
2992
          || var_check_ro(di->di_flags, name, false)
 
2993
          || tv_check_lock(d->dv_lock, name, false)) {
2981
2994
        return FAIL;
2982
2995
      }
2983
2996
      typval_T oldtv;
3045
3058
      li = li->li_next;
3046
3059
      ++lp->ll_n1;
3047
3060
    }
3048
 
  } else if (lp->ll_list != NULL)
3049
 
    /* (un)lock a List item. */
 
3061
  } else if (lp->ll_list != NULL) {
 
3062
    // (un)lock a List item.
3050
3063
    item_lock(&lp->ll_li->li_tv, deep, lock);
3051
 
  else
3052
 
    /* un(lock) a Dictionary item. */
 
3064
  } else {
 
3065
    // (un)lock a Dictionary item.
3053
3066
    item_lock(&lp->ll_di->di_tv, deep, lock);
 
3067
  }
3054
3068
 
3055
3069
  return ret;
3056
3070
}
3572
3586
      type = TYPE_SEQUAL;
3573
3587
    break;
3574
3588
  case 'i':   if (p[1] == 's') {
3575
 
      if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
 
3589
      if (p[2] == 'n' && p[3] == 'o' && p[4] == 't') {
3576
3590
        len = 5;
3577
 
      if (!vim_isIDc(p[len])) {
 
3591
      }
 
3592
      if (!isalnum(p[len]) && p[len] != '_') {
3578
3593
        type = len == 2 ? TYPE_EQUAL : TYPE_NEQUAL;
3579
3594
        type_is = TRUE;
3580
3595
      }
4001
4016
       * When either side is a float the result is a float.
4002
4017
       */
4003
4018
      if (use_float) {
4004
 
        if (op == '*')
 
4019
        if (op == '*') {
4005
4020
          f1 = f1 * f2;
4006
 
        else if (op == '/') {
4007
 
          /* We rely on the floating point library to handle divide
4008
 
           * by zero to result in "inf" and not a crash. */
4009
 
          f1 = f2 != 0 ? f1 / f2 : INFINITY;
 
4021
        } else if (op == '/') {
 
4022
          // Division by zero triggers error from AddressSanitizer
 
4023
          f1 = (f2 == 0
 
4024
                ? (
 
4025
#ifdef NAN
 
4026
                    f1 == 0
 
4027
                    ? NAN
 
4028
                    :
 
4029
#endif
 
4030
                    (f1 > 0
 
4031
                     ? INFINITY
 
4032
                     : -INFINITY)
 
4033
                )
 
4034
                : f1 / f2);
4010
4035
        } else {
4011
4036
          EMSG(_("E804: Cannot use '%' with Float"));
4012
4037
          return FAIL;
4239
4264
          ret = FAIL;
4240
4265
        }
4241
4266
      } else if (evaluate) {
4242
 
        ret = get_var_tv(s, len, rettv, true, false);
 
4267
        ret = get_var_tv(s, len, rettv, NULL, true, false);
4243
4268
      } else {
4244
4269
        ret = OK;
4245
4270
      }
5998
6023
  ++d->dv_refcount;
5999
6024
}
6000
6025
 
 
6026
/// Clear all the keys of a Dictionary. "d" remains a valid empty Dictionary.
 
6027
///
 
6028
/// @param d The Dictionary to clear
 
6029
void dict_clear(dict_T *d)
 
6030
  FUNC_ATTR_NONNULL_ALL
 
6031
{
 
6032
  hash_lock(&d->dv_hashtab);
 
6033
  assert(d->dv_hashtab.ht_locked > 0);
 
6034
 
 
6035
  size_t todo = d->dv_hashtab.ht_used;
 
6036
  for (hashitem_T *hi = d->dv_hashtab.ht_array; todo > 0; hi++) {
 
6037
    if (!HASHITEM_EMPTY(hi)) {
 
6038
      dictitem_free(HI2DI(hi));
 
6039
      hash_remove(&d->dv_hashtab, hi);
 
6040
      todo--;
 
6041
    }
 
6042
  }
 
6043
 
 
6044
  hash_unlock(&d->dv_hashtab);
 
6045
}
 
6046
 
6001
6047
 
6002
6048
/*
6003
6049
 * Unreference a Dictionary: decrement the reference count and free it when it
6239
6285
  return OK;
6240
6286
}
6241
6287
 
 
6288
/// Set all existing keys in "dict" as read-only.
 
6289
///
 
6290
/// This does not protect against adding new keys to the Dictionary.
 
6291
///
 
6292
/// @param dict The dict whose keys should be frozen
 
6293
void dict_set_keys_readonly(dict_T *dict)
 
6294
  FUNC_ATTR_NONNULL_ALL
 
6295
{
 
6296
  size_t todo = dict->dv_hashtab.ht_used;
 
6297
  for (hashitem_T *hi = dict->dv_hashtab.ht_array; todo > 0 ; hi++) {
 
6298
    if (HASHITEM_EMPTY(hi)) {
 
6299
      continue;
 
6300
    }
 
6301
    todo--;
 
6302
    HI2DI(hi)->di_flags |= DI_FLAGS_RO | DI_FLAGS_FIX;
 
6303
  }
 
6304
}
 
6305
 
6242
6306
/*
6243
6307
 * Get the number of items in a Dictionary.
6244
6308
 */
6839
6903
 
6840
6904
#define CONV_FLOAT(flt) \
6841
6905
    do { \
6842
 
      char numbuf[NUMBUFLEN]; \
6843
 
      vim_snprintf(numbuf, NUMBUFLEN - 1, "%g", (flt)); \
6844
 
      ga_concat(gap, (char_u *) numbuf); \
 
6906
      const float_T flt_ = (flt); \
 
6907
      switch (fpclassify(flt_)) { \
 
6908
        case FP_NAN: { \
 
6909
          ga_concat(gap, (char_u *) "str2float('nan')"); \
 
6910
          break; \
 
6911
        } \
 
6912
        case FP_INFINITE: { \
 
6913
          if (flt_ < 0) { \
 
6914
            ga_append(gap, '-'); \
 
6915
          } \
 
6916
          ga_concat(gap, (char_u *) "str2float('inf')"); \
 
6917
          break; \
 
6918
        } \
 
6919
        default: { \
 
6920
          char numbuf[NUMBUFLEN]; \
 
6921
          vim_snprintf(numbuf, NUMBUFLEN - 1, "%g", flt_); \
 
6922
          ga_concat(gap, (char_u *) numbuf); \
 
6923
        } \
 
6924
      } \
6845
6925
    } while (0)
6846
6926
 
6847
6927
#define CONV_FUNC(fun) \
7262
7342
  { "maparg",            1, 4, f_maparg },
7263
7343
  { "mapcheck",          1, 3, f_mapcheck },
7264
7344
  { "match",             2, 4, f_match },
7265
 
  { "matchadd",          2, 4, f_matchadd },
7266
 
  { "matchaddpos",       2, 4, f_matchaddpos },
 
7345
  { "matchadd",          2, 5, f_matchadd },
 
7346
  { "matchaddpos",       2, 5, f_matchaddpos },
7267
7347
  { "matcharg",          1, 1, f_matcharg },
7268
7348
  { "matchdelete",       1, 1, f_matchdelete },
7269
7349
  { "matchend",          2, 4, f_matchend },
7281
7361
  { "pathshorten",       1, 1, f_pathshorten },
7282
7362
  { "pow",               2, 2, f_pow },
7283
7363
  { "prevnonblank",      1, 1, f_prevnonblank },
7284
 
  { "printf",            2, 19, f_printf },
 
7364
  { "printf",            2, MAX_FUNC_ARGS, f_printf },
7285
7365
  { "pumvisible",        0, 0, f_pumvisible },
7286
7366
  { "py3eval",           1, 1, f_py3eval },
7287
7367
  { "pyeval",            1, 1, f_pyeval },
7295
7375
  { "resolve",           1, 1, f_resolve },
7296
7376
  { "reverse",           1, 1, f_reverse },
7297
7377
  { "round",             1, 1, f_round },
7298
 
  { "rpcnotify",         2, 64, f_rpcnotify },
7299
 
  { "rpcrequest",        2, 64, f_rpcrequest },
 
7378
  { "rpcnotify",         2, MAX_FUNC_ARGS, f_rpcnotify },
 
7379
  { "rpcrequest",        2, MAX_FUNC_ARGS, f_rpcrequest },
7300
7380
  { "rpcstart",          1, 2, f_rpcstart },
7301
7381
  { "rpcstop",           1, 1, f_rpcstop },
7302
7382
  { "screenattr",        2, 2, f_screenattr },
7315
7395
  { "setcharsearch",     1, 1, f_setcharsearch },
7316
7396
  { "setcmdpos",         1, 1, f_setcmdpos },
7317
7397
  { "setline",           2, 2, f_setline },
7318
 
  { "setloclist",        2, 3, f_setloclist },
 
7398
  { "setloclist",        2, 4, f_setloclist },
7319
7399
  { "setmatches",        1, 1, f_setmatches },
7320
7400
  { "setpos",            2, 2, f_setpos },
7321
 
  { "setqflist",         1, 2, f_setqflist },
 
7401
  { "setqflist",         1, 3, f_setqflist },
7322
7402
  { "setreg",            2, 3, f_setreg },
7323
7403
  { "settabvar",         3, 3, f_settabvar },
7324
7404
  { "settabwinvar",      4, 4, f_settabwinvar },
7337
7417
  { "sqrt",              1, 1, f_sqrt },
7338
7418
  { "str2float",         1, 1, f_str2float },
7339
7419
  { "str2nr",            1, 2, f_str2nr },
7340
 
  { "strchars",          1, 1, f_strchars },
 
7420
  { "strchars",          1, 2, f_strchars },
7341
7421
  { "strdisplaywidth",   1, 2, f_strdisplaywidth },
7342
7422
  { "strftime",          1, 2, f_strftime },
7343
7423
  { "stridx",            2, 3, f_stridx },
7855
7935
  rettv->vval.v_number = 1;   /* Default: Failed */
7856
7936
  if (argvars[0].v_type == VAR_LIST) {
7857
7937
    if ((l = argvars[0].vval.v_list) != NULL
7858
 
        && !tv_check_lock(l->lv_lock, (char_u *)_("add() argument"))) {
 
7938
        && !tv_check_lock(l->lv_lock,
 
7939
                          (char_u *)N_("add() argument"), true)) {
7859
7940
      list_append_tv(l, &argvars[1]);
7860
7941
      copy_tv(&argvars[0], rettv);
7861
7942
    }
9130
9211
    name = p;
9131
9212
    len = get_name_len(&p, &tofree, TRUE, FALSE);
9132
9213
    if (len > 0) {
9133
 
      if (tofree != NULL)
 
9214
      if (tofree != NULL) {
9134
9215
        name = tofree;
9135
 
      n = (get_var_tv(name, len, &tv, FALSE, TRUE) == OK);
 
9216
      }
 
9217
      n = (get_var_tv(name, len, &tv, NULL, false, true) == OK);
9136
9218
      if (n) {
9137
9219
        /* handle d.key, l[idx], f(expr) */
9138
9220
        n = (handle_subscript(&p, &tv, TRUE, FALSE) == OK);
9230
9312
  hashitem_T  *hi2;
9231
9313
  int todo;
9232
9314
  bool watched = is_watched(d1);
9233
 
  char *arg_errmsg = N_("extend() argument");
 
9315
  char_u *arg_errmsg = (char_u *)N_("extend() argument");
9234
9316
 
9235
9317
  todo = (int)d2->dv_hashtab.ht_used;
9236
9318
  for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2) {
9264
9346
      } else if (*action == 'f' && HI2DI(hi2) != di1) {
9265
9347
        typval_T oldtv;
9266
9348
 
9267
 
        if (tv_check_lock(di1->di_tv.v_lock, (char_u *)_(arg_errmsg))
9268
 
            || var_check_ro(di1->di_flags, (char_u *)_(arg_errmsg))) {
 
9349
        if (tv_check_lock(di1->di_tv.v_lock, arg_errmsg, true)
 
9350
            || var_check_ro(di1->di_flags, arg_errmsg, true)) {
9269
9351
          break;
9270
9352
        }
9271
9353
 
9291
9373
 */
9292
9374
static void f_extend(typval_T *argvars, typval_T *rettv)
9293
9375
{
9294
 
  char      *arg_errmsg = N_("extend() argument");
 
9376
  char_u *arg_errmsg = (char_u *)N_("extend() argument");
9295
9377
 
9296
9378
  if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST) {
9297
9379
    list_T          *l1, *l2;
9301
9383
 
9302
9384
    l1 = argvars[0].vval.v_list;
9303
9385
    l2 = argvars[1].vval.v_list;
9304
 
    if (l1 != NULL && !tv_check_lock(l1->lv_lock, (char_u *)_(arg_errmsg))
 
9386
    if (l1 != NULL && !tv_check_lock(l1->lv_lock, arg_errmsg, true)
9305
9387
        && l2 != NULL) {
9306
9388
      if (argvars[2].v_type != VAR_UNKNOWN) {
9307
9389
        before = get_tv_number_chk(&argvars[2], &error);
9331
9413
 
9332
9414
    d1 = argvars[0].vval.v_dict;
9333
9415
    d2 = argvars[1].vval.v_dict;
9334
 
    if (d1 != NULL && !tv_check_lock(d1->dv_lock, (char_u *)_(arg_errmsg))
 
9416
    if (d1 != NULL && !tv_check_lock(d1->dv_lock, arg_errmsg, true)
9335
9417
        && d2 != NULL) {
9336
9418
      /* Check the third argument. */
9337
9419
      if (argvars[2].v_type != VAR_UNKNOWN) {
9477
9559
  int rem;
9478
9560
  int todo;
9479
9561
  char_u      *ermsg = (char_u *)(map ? "map()" : "filter()");
9480
 
  char        *arg_errmsg = (map ? N_("map() argument")
9481
 
                             : N_("filter() argument"));
 
9562
  char_u      *arg_errmsg = (char_u *)(map ? N_("map() argument")
 
9563
                                       : N_("filter() argument"));
9482
9564
  int save_did_emsg;
9483
9565
  int idx = 0;
9484
9566
 
9485
9567
  if (argvars[0].v_type == VAR_LIST) {
9486
9568
    if ((l = argvars[0].vval.v_list) == NULL
9487
 
        || (!map && tv_check_lock(l->lv_lock, (char_u *)_(arg_errmsg)))) {
 
9569
        || (!map && tv_check_lock(l->lv_lock, arg_errmsg, true))) {
9488
9570
      return;
9489
9571
    }
9490
9572
  } else if (argvars[0].v_type == VAR_DICT) {
9491
9573
    if ((d = argvars[0].vval.v_dict) == NULL
9492
 
        || (!map && tv_check_lock(d->dv_lock, (char_u *)_(arg_errmsg)))) {
 
9574
        || (!map && tv_check_lock(d->dv_lock, arg_errmsg, true))) {
9493
9575
      return;
9494
9576
    }
9495
9577
  } else {
9523
9605
 
9524
9606
          di = HI2DI(hi);
9525
9607
          if (map
9526
 
              && (tv_check_lock(di->di_tv.v_lock, (char_u *)_(arg_errmsg))
9527
 
                  || var_check_ro(di->di_flags, (char_u *)_(arg_errmsg)))) {
 
9608
              && (tv_check_lock(di->di_tv.v_lock, arg_errmsg, true)
 
9609
                  || var_check_ro(di->di_flags, arg_errmsg, true))) {
9528
9610
            break;
9529
9611
          }
9530
9612
 
9534
9616
          if (r == FAIL || did_emsg)
9535
9617
            break;
9536
9618
          if (!map && rem) {
9537
 
            if (var_check_fixed(di->di_flags, (char_u *)_(arg_errmsg))
9538
 
                || var_check_ro(di->di_flags, (char_u *)_(arg_errmsg))) {
 
9619
            if (var_check_fixed(di->di_flags, arg_errmsg, true)
 
9620
                || var_check_ro(di->di_flags, arg_errmsg, true)) {
9539
9621
              break;
9540
9622
            }
9541
9623
            dictitem_remove(d, di);
9547
9629
      vimvars[VV_KEY].vv_type = VAR_NUMBER;
9548
9630
 
9549
9631
      for (li = l->lv_first; li != NULL; li = nli) {
9550
 
        if (map && tv_check_lock(li->li_tv.v_lock, (char_u *)_(arg_errmsg))) {
 
9632
        if (map && tv_check_lock(li->li_tv.v_lock, arg_errmsg, true)) {
9551
9633
          break;
9552
9634
        }
9553
9635
        nli = li->li_next;
10412
10494
    dict_add_nr_str(dict, "group", 0L, syn_id2name(cur->hlg_id));
10413
10495
    dict_add_nr_str(dict, "priority", (long)cur->priority, NULL);
10414
10496
    dict_add_nr_str(dict, "id", (long)cur->id, NULL);
 
10497
 
 
10498
    if (cur->conceal_char) {
 
10499
      char_u buf[MB_MAXBYTES + 1];
 
10500
 
 
10501
      buf[(*mb_char2bytes)((int)cur->conceal_char, buf)] = NUL;
 
10502
      dict_add_nr_str(dict, "conceal", 0L, (char_u *)&buf);
 
10503
    }
 
10504
 
10415
10505
    list_append_dict(rettv->vval.v_list, dict);
10416
10506
    cur = cur->next;
10417
10507
  }
10534
10624
{
10535
10625
  char_u      *strregname;
10536
10626
  int regname;
10537
 
  char_u buf[NUMBUFLEN + 2];
10538
 
  long reglen = 0;
10539
10627
 
10540
10628
  if (argvars[0].v_type != VAR_UNKNOWN) {
10541
10629
    strregname = get_tv_string_chk(&argvars[0]);
10552
10640
  if (regname == 0)
10553
10641
    regname = '"';
10554
10642
 
10555
 
  buf[0] = NUL;
10556
 
  buf[1] = NUL;
10557
 
  switch (get_reg_type(regname, &reglen)) {
10558
 
  case MLINE: buf[0] = 'V'; break;
10559
 
  case MCHAR: buf[0] = 'v'; break;
10560
 
  case MBLOCK:
10561
 
    buf[0] = Ctrl_V;
10562
 
    sprintf((char *)buf + 1, "%" PRId64, (int64_t)(reglen + 1));
10563
 
    break;
10564
 
  }
 
10643
  colnr_T reglen = 0;
 
10644
  char buf[NUMBUFLEN + 2];
 
10645
  char_u reg_type = get_reg_type(regname, &reglen);
 
10646
  format_reg_type(reg_type, reglen, buf, ARRAY_SIZE(buf));
 
10647
 
10565
10648
  rettv->v_type = VAR_STRING;
10566
 
  rettv->vval.v_string = vim_strsave(buf);
 
10649
  rettv->vval.v_string = (char_u *)xstrdup(buf);
10567
10650
}
10568
10651
 
10569
10652
/*
10583
10666
  varname = get_tv_string_chk(&argvars[1]);
10584
10667
  tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL));
10585
10668
  if (tp != NULL && varname != NULL) {
10586
 
    /* Set tp to be our tabpage, temporarily.  Also set the window to the
10587
 
     * first window in the tabpage, otherwise the window is not valid. */
10588
 
    if (switch_win(&oldcurwin, &oldtabpage, tp->tp_firstwin, tp, TRUE) == OK) {
 
10669
    // Set tp to be our tabpage, temporarily.  Also set the window to the
 
10670
    // first window in the tabpage, otherwise the window is not valid.
 
10671
    win_T *window = tp->tp_firstwin == NULL ? firstwin : tp->tp_firstwin;
 
10672
    if (switch_win(&oldcurwin, &oldtabpage, window, tp, true) == OK) {
10589
10673
      // look up the variable
10590
10674
      // Let gettabvar({nr}, "") return the "t:" dictionary.
10591
10675
      v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't', varname, FALSE);
10678
10762
    int off                    /* 1 for gettabwinvar() */
10679
10763
)
10680
10764
{
10681
 
  win_T       *win, *oldcurwin;
10682
 
  char_u      *varname;
10683
 
  dictitem_T  *v;
10684
 
  tabpage_T   *tp = NULL;
10685
 
  tabpage_T   *oldtabpage = NULL;
 
10765
  win_T *win, *oldcurwin;
 
10766
  char_u *varname;
 
10767
  dictitem_T *v;
 
10768
  tabpage_T *tp = NULL;
 
10769
  tabpage_T *oldtabpage = NULL;
10686
10770
  bool done = false;
10687
10771
 
10688
10772
  if (off == 1)
10697
10781
  rettv->vval.v_string = NULL;
10698
10782
 
10699
10783
  if (win != NULL && varname != NULL) {
10700
 
    /* Set curwin to be our win, temporarily.  Also set the tabpage,
10701
 
     * otherwise the window is not valid. */
10702
 
    if (switch_win(&oldcurwin, &oldtabpage, win, tp, TRUE) == OK) {
10703
 
      if (*varname == '&') {      /* window-local-option */
10704
 
        if (get_option_tv(&varname, rettv, 1) == OK)
 
10784
    // Set curwin to be our win, temporarily.  Also set the tabpage,
 
10785
    // otherwise the window is not valid. Only do this when needed,
 
10786
    // autocommands get blocked.
 
10787
    bool need_switch_win = tp != curtab || win != curwin;
 
10788
    if (!need_switch_win
 
10789
        || switch_win(&oldcurwin, &oldtabpage, win, tp, true) == OK) {
 
10790
      if (*varname == '&') {  // window-local-option
 
10791
        if (get_option_tv(&varname, rettv, 1) == OK) {
10705
10792
          done = true;
 
10793
        }
10706
10794
      } else {
10707
10795
        // Look up the variable.
10708
10796
        // Let getwinvar({nr}, "") return the "w:" dictionary.
10714
10802
      }
10715
10803
    }
10716
10804
 
10717
 
    /* restore previous notion of curwin */
10718
 
    restore_win(oldcurwin, oldtabpage, TRUE);
 
10805
    if (need_switch_win) {
 
10806
      // restore previous notion of curwin
 
10807
      restore_win(oldcurwin, oldtabpage, true);
 
10808
    }
10719
10809
  }
10720
10810
 
10721
10811
  if (!done && argvars[off + 2].v_type != VAR_UNKNOWN)
11442
11532
  list_T      *l;
11443
11533
  int error = FALSE;
11444
11534
 
11445
 
  if (argvars[0].v_type != VAR_LIST)
 
11535
  if (argvars[0].v_type != VAR_LIST) {
11446
11536
    EMSG2(_(e_listarg), "insert()");
11447
 
  else if ((l = argvars[0].vval.v_list) != NULL
11448
 
           && !tv_check_lock(l->lv_lock, (char_u *)_("insert() argument"))) {
11449
 
    if (argvars[2].v_type != VAR_UNKNOWN)
 
11537
  } else if ((l = argvars[0].vval.v_list) != NULL
 
11538
             && !tv_check_lock(l->lv_lock,
 
11539
                               (char_u *)N_("insert() argument"), true)) {
 
11540
    if (argvars[2].v_type != VAR_UNKNOWN) {
11450
11541
      before = get_tv_number_chk(&argvars[2], &error);
11451
 
    if (error)
11452
 
      return;                   /* type error; errmsg already given */
 
11542
    }
 
11543
    if (error) {
 
11544
      // type error; errmsg already given
 
11545
      return;
 
11546
    }
11453
11547
 
11454
11548
    if (before == l->lv_len)
11455
11549
      item = NULL;
12472
12566
  char_u      *pat = get_tv_string_buf_chk(&argvars[1], buf);   /* pattern */
12473
12567
  int prio = 10;                /* default priority */
12474
12568
  int id = -1;
12475
 
  int error = FALSE;
 
12569
  int error = false;
 
12570
  char_u *conceal_char = NULL;
12476
12571
 
12477
12572
  rettv->vval.v_number = -1;
12478
12573
 
12480
12575
    return;
12481
12576
  if (argvars[2].v_type != VAR_UNKNOWN) {
12482
12577
    prio = get_tv_number_chk(&argvars[2], &error);
12483
 
    if (argvars[3].v_type != VAR_UNKNOWN)
 
12578
    if (argvars[3].v_type != VAR_UNKNOWN) {
12484
12579
      id = get_tv_number_chk(&argvars[3], &error);
 
12580
      if (argvars[4].v_type != VAR_UNKNOWN) {
 
12581
        if (argvars[4].v_type != VAR_DICT) {
 
12582
          EMSG(_(e_dictreq));
 
12583
          return;
 
12584
        }
 
12585
        if (dict_find(argvars[4].vval.v_dict,
 
12586
                      (char_u *)"conceal", -1) != NULL) {
 
12587
          conceal_char = get_dict_string(argvars[4].vval.v_dict,
 
12588
                                         (char_u *)"conceal", false);
 
12589
        }
 
12590
      }
 
12591
    }
12485
12592
  }
12486
 
  if (error == TRUE)
 
12593
  if (error == true) {
12487
12594
    return;
 
12595
  }
12488
12596
  if (id >= 1 && id <= 3) {
12489
12597
    EMSGN("E798: ID is reserved for \":match\": %" PRId64, id);
12490
12598
    return;
12491
12599
  }
12492
12600
 
12493
 
  rettv->vval.v_number = match_add(curwin, grp, pat, prio, id, NULL);
 
12601
  rettv->vval.v_number = match_add(curwin, grp, pat, prio, id, NULL,
 
12602
                                   conceal_char);
12494
12603
}
12495
12604
 
12496
12605
static void f_matchaddpos(typval_T *argvars, typval_T *rettv) FUNC_ATTR_NONNULL_ALL
12518
12627
    int error = false;
12519
12628
    int prio = 10;
12520
12629
    int id = -1;
 
12630
    char_u *conceal_char = NULL;
12521
12631
 
12522
12632
    if (argvars[2].v_type != VAR_UNKNOWN) {
12523
 
        prio = get_tv_number_chk(&argvars[2], &error);
12524
 
        if (argvars[3].v_type != VAR_UNKNOWN) {
12525
 
            id = get_tv_number_chk(&argvars[3], &error);
 
12633
      prio = get_tv_number_chk(&argvars[2], &error);
 
12634
      if (argvars[3].v_type != VAR_UNKNOWN) {
 
12635
        id = get_tv_number_chk(&argvars[3], &error);
 
12636
        if (argvars[4].v_type != VAR_UNKNOWN) {
 
12637
          if (argvars[4].v_type != VAR_DICT) {
 
12638
            EMSG(_(e_dictreq));
 
12639
            return;
 
12640
          }
 
12641
          if (dict_find(argvars[4].vval.v_dict,
 
12642
                        (char_u *)"conceal", -1) != NULL) {
 
12643
            conceal_char = get_dict_string(argvars[4].vval.v_dict,
 
12644
                                           (char_u *)"conceal", false);
 
12645
          }
12526
12646
        }
 
12647
      }
12527
12648
    }
12528
12649
    if (error == true) {
12529
12650
        return;
12535
12656
        return;
12536
12657
    }
12537
12658
 
12538
 
    rettv->vval.v_number = match_add(curwin, group, NULL, prio, id, l);
 
12659
  rettv->vval.v_number = match_add(curwin, group, NULL, prio, id, l,
 
12660
                                   conceal_char);
12539
12661
}
12540
12662
 
12541
12663
/*
13903
14025
  char_u      *key;
13904
14026
  dict_T      *d;
13905
14027
  dictitem_T  *di;
13906
 
  char        *arg_errmsg = N_("remove() argument");
 
14028
  char_u      *arg_errmsg = (char_u *)N_("remove() argument");
13907
14029
 
13908
14030
  if (argvars[0].v_type == VAR_DICT) {
13909
 
    if (argvars[2].v_type != VAR_UNKNOWN)
 
14031
    if (argvars[2].v_type != VAR_UNKNOWN) {
13910
14032
      EMSG2(_(e_toomanyarg), "remove()");
13911
 
    else if ((d = argvars[0].vval.v_dict) != NULL
13912
 
             && !tv_check_lock(d->dv_lock, (char_u *)_(arg_errmsg))) {
 
14033
    } else if ((d = argvars[0].vval.v_dict) != NULL
 
14034
               && !tv_check_lock(d->dv_lock, arg_errmsg, true)) {
13913
14035
      key = get_tv_string_chk(&argvars[1]);
13914
14036
      if (key != NULL) {
13915
14037
        di = dict_find(d, key, -1);
13916
14038
        if (di == NULL) {
13917
14039
          EMSG2(_(e_dictkey), key);
13918
 
        } else if (!var_check_fixed(di->di_flags, (char_u *)_(arg_errmsg))
13919
 
                   && !var_check_ro(di->di_flags, (char_u *)_(arg_errmsg))) {
 
14040
        } else if (!var_check_fixed(di->di_flags, arg_errmsg, true)
 
14041
                   && !var_check_ro(di->di_flags, arg_errmsg, true)) {
13920
14042
          *rettv = di->di_tv;
13921
14043
          init_tv(&di->di_tv);
13922
14044
          dictitem_remove(d, di);
13926
14048
        }
13927
14049
      }
13928
14050
    }
13929
 
  } else if (argvars[0].v_type != VAR_LIST)
 
14051
  } else if (argvars[0].v_type != VAR_LIST) {
13930
14052
    EMSG2(_(e_listdictarg), "remove()");
13931
 
  else if ((l = argvars[0].vval.v_list) != NULL
13932
 
           && !tv_check_lock(l->lv_lock, (char_u *)_(arg_errmsg))) {
13933
 
    int error = FALSE;
 
14053
  } else if ((l = argvars[0].vval.v_list) != NULL
 
14054
             && !tv_check_lock(l->lv_lock, arg_errmsg, true)) {
 
14055
    int error = (int)false;
13934
14056
 
13935
14057
    idx = get_tv_number_chk(&argvars[1], &error);
13936
14058
    if (error)
14204
14326
  list_T      *l;
14205
14327
  listitem_T  *li, *ni;
14206
14328
 
14207
 
  if (argvars[0].v_type != VAR_LIST)
 
14329
  if (argvars[0].v_type != VAR_LIST) {
14208
14330
    EMSG2(_(e_listarg), "reverse()");
14209
 
  else if ((l = argvars[0].vval.v_list) != NULL
14210
 
           && !tv_check_lock(l->lv_lock, (char_u *)_("reverse() argument"))) {
 
14331
  } else if ((l = argvars[0].vval.v_list) != NULL
 
14332
             && !tv_check_lock(l->lv_lock,
 
14333
                               (char_u *)N_("reverse() argument"), true)) {
14211
14334
    li = l->lv_last;
14212
14335
    l->lv_first = l->lv_last = NULL;
14213
14336
    l->lv_len = 0;
15156
15279
    appended_lines_mark(lcount, added);
15157
15280
}
15158
15281
 
15159
 
 
15160
 
/*
15161
 
 * Used by "setqflist()" and "setloclist()" functions
15162
 
 */
15163
 
static void set_qf_ll_list(win_T *wp, typval_T *list_arg, typval_T *action_arg, typval_T *rettv)
 
15282
/// Create quickfix/location list from VimL values
 
15283
///
 
15284
/// Used by `setqflist()` and `setloclist()` functions. Accepts invalid
 
15285
/// list_arg, action_arg and title_arg arguments in which case errors out,
 
15286
/// including VAR_UNKNOWN parameters.
 
15287
///
 
15288
/// @param[in,out]  wp  Window to create location list for. May be NULL in
 
15289
///                     which case quickfix list will be created.
 
15290
/// @param[in]  list_arg  Quickfix list contents.
 
15291
/// @param[in]  action_arg  Action to perform: append to an existing list,
 
15292
///                         replace its content or create a new one.
 
15293
/// @param[in]  title_arg  New list title. Defaults to caller function name.
 
15294
/// @param[out]  rettv  Return value: 0 in case of success, -1 otherwise.
 
15295
static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv)
 
15296
  FUNC_ATTR_NONNULL_ARG(2, 3)
15164
15297
{
15165
 
  char_u      *act;
 
15298
  char_u *title = NULL;
15166
15299
  int action = ' ';
15167
 
 
15168
15300
  rettv->vval.v_number = -1;
15169
15301
 
15170
 
  if (list_arg->v_type != VAR_LIST)
 
15302
  typval_T *list_arg = &args[0];
 
15303
  if (list_arg->v_type != VAR_LIST) {
15171
15304
    EMSG(_(e_listreq));
15172
 
  else {
15173
 
    list_T  *l = list_arg->vval.v_list;
15174
 
 
15175
 
    if (action_arg->v_type == VAR_STRING) {
15176
 
      act = get_tv_string_chk(action_arg);
15177
 
      if (act == NULL)
15178
 
        return;                 /* type error; errmsg already given */
15179
 
      if (*act == 'a' || *act == 'r')
15180
 
        action = *act;
15181
 
    }
15182
 
 
15183
 
    if (l != NULL && set_errorlist(wp, l, action,
15184
 
            (char_u *)(wp == NULL ? "setqflist()" : "setloclist()")) == OK)
15185
 
      rettv->vval.v_number = 0;
 
15305
    return;
 
15306
  }
 
15307
 
 
15308
  typval_T *action_arg = &args[1];
 
15309
  if (action_arg->v_type == VAR_UNKNOWN) {
 
15310
    // Option argument was not given.
 
15311
    goto skip_args;
 
15312
  } else if (action_arg->v_type != VAR_STRING) {
 
15313
    EMSG(_(e_strreq));
 
15314
    return;
 
15315
  }
 
15316
  char_u *act = get_tv_string_chk(action_arg);
 
15317
  if (*act == 'a' || *act == 'r') {
 
15318
    action = *act;
 
15319
  }
 
15320
 
 
15321
  typval_T *title_arg = &args[2];
 
15322
  if (title_arg->v_type == VAR_UNKNOWN) {
 
15323
    // Option argument was not given.
 
15324
    goto skip_args;
 
15325
  }
 
15326
  title = get_tv_string_chk(title_arg);
 
15327
  if (!title) {
 
15328
    // Type error. Error already printed by get_tv_string_chk().
 
15329
    return;
 
15330
  }
 
15331
 
 
15332
skip_args:
 
15333
  if (!title) {
 
15334
    title = (char_u*)(wp ? "setloclist()" : "setqflist()");
 
15335
  }
 
15336
 
 
15337
  list_T *l = list_arg->vval.v_list;
 
15338
  if (l && set_errorlist(wp, l, action, title) == OK) {
 
15339
    rettv->vval.v_number = 0;
15186
15340
  }
15187
15341
}
15188
15342
 
15196
15350
  rettv->vval.v_number = -1;
15197
15351
 
15198
15352
  win = find_win_by_nr(&argvars[0], NULL);
15199
 
  if (win != NULL)
15200
 
    set_qf_ll_list(win, &argvars[1], &argvars[2], rettv);
 
15353
  if (win != NULL) {
 
15354
    set_qf_ll_list(win, &argvars[1], rettv);
 
15355
  }
15201
15356
}
15202
15357
 
15203
15358
/*
15243
15398
      int i = 0;
15244
15399
      char_u buf[5];
15245
15400
      dictitem_T *di;
 
15401
 
15246
15402
      d = li->li_tv.vval.v_dict;
15247
 
 
15248
15403
      if (dict_find(d, (char_u *)"pattern", -1) == NULL) {
15249
15404
        if (s == NULL) {
15250
15405
          s = list_alloc();
15269
15424
        }
15270
15425
      }
15271
15426
 
 
15427
      char_u *group = get_dict_string(d, (char_u *)"group", false);
 
15428
      int priority = get_dict_number(d, (char_u *)"priority");
 
15429
      int id = get_dict_number(d, (char_u *)"id");
 
15430
      char_u *conceal = dict_find(d, (char_u *)"conceal", -1) != NULL
 
15431
                                  ? get_dict_string(d, (char_u *)"conceal",
 
15432
                                                    false)
 
15433
                                  : NULL;
15272
15434
      if (i == 0) {
15273
 
        match_add(curwin, get_dict_string(d, (char_u *)"group", false),
 
15435
        match_add(curwin, group,
15274
15436
                  get_dict_string(d, (char_u *)"pattern", false),
15275
 
                  (int)get_dict_number(d, (char_u *)"priority"),
15276
 
                  (int)get_dict_number(d, (char_u *)"id"), NULL);
 
15437
                  priority, id, NULL, conceal);
15277
15438
      } else {
15278
 
        match_add(curwin, get_dict_string(d, (char_u *)"group", false),
15279
 
                  NULL, (int)get_dict_number(d, (char_u *)"priority"),
15280
 
                  (int)get_dict_number(d, (char_u *)"id"), s);
 
15439
        match_add(curwin, group, NULL, priority, id, s, conceal);
15281
15440
        list_unref(s);
15282
15441
        s = NULL;
15283
15442
      }
15329
15488
 */
15330
15489
static void f_setqflist(typval_T *argvars, typval_T *rettv)
15331
15490
{
15332
 
  set_qf_ll_list(NULL, &argvars[0], &argvars[1], rettv);
 
15491
  set_qf_ll_list(NULL, argvars, rettv);
15333
15492
}
15334
15493
 
15335
15494
/*
15503
15662
  varname = get_tv_string_chk(&argvars[off + 1]);
15504
15663
  varp = &argvars[off + 2];
15505
15664
 
15506
 
  if (win != NULL && varname != NULL && varp != NULL
15507
 
      && switch_win(&save_curwin, &save_curtab, win, tp, TRUE) == OK) {
15508
 
    if (*varname == '&') {
15509
 
      long numval;
15510
 
      char_u      *strval;
15511
 
      int error = FALSE;
 
15665
  if (win != NULL && varname != NULL && varp != NULL) {
 
15666
    bool need_switch_win = tp != curtab || win != curwin;
 
15667
    if (!need_switch_win
 
15668
        || switch_win(&save_curwin, &save_curtab, win, tp, true) == OK) {
 
15669
      if (*varname == '&') {
 
15670
        long numval;
 
15671
        char_u *strval;
 
15672
        int error = false;
15512
15673
 
15513
 
      ++varname;
15514
 
      numval = get_tv_number_chk(varp, &error);
15515
 
      strval = get_tv_string_buf_chk(varp, nbuf);
15516
 
      if (!error && strval != NULL)
15517
 
        set_option_value(varname, numval, strval, OPT_LOCAL);
15518
 
    } else {
15519
 
      winvarname = xmalloc(STRLEN(varname) + 3);
15520
 
      STRCPY(winvarname, "w:");
15521
 
      STRCPY(winvarname + 2, varname);
15522
 
      set_var(winvarname, varp, TRUE);
15523
 
      xfree(winvarname);
15524
 
    }
15525
 
    restore_win(save_curwin, save_curtab, TRUE);
 
15674
        ++varname;
 
15675
        numval = get_tv_number_chk(varp, &error);
 
15676
        strval = get_tv_string_buf_chk(varp, nbuf);
 
15677
        if (!error && strval != NULL) {
 
15678
          set_option_value(varname, numval, strval, OPT_LOCAL);
 
15679
        }
 
15680
      } else {
 
15681
        winvarname = xmalloc(STRLEN(varname) + 3);
 
15682
        STRCPY(winvarname, "w:");
 
15683
        STRCPY(winvarname + 2, varname);
 
15684
        set_var(winvarname, varp, true);
 
15685
        xfree(winvarname);
 
15686
      }
 
15687
    }
 
15688
    if (need_switch_win) {
 
15689
      restore_win(save_curwin, save_curtab, true);
 
15690
    }
15526
15691
  }
15527
15692
}
15528
15693
 
15741
15906
    EMSG2(_(e_listarg), sort ? "sort()" : "uniq()");
15742
15907
  } else {
15743
15908
    l = argvars[0].vval.v_list;
15744
 
    if (l == NULL || tv_check_lock(l->lv_lock,
15745
 
        (char_u *)(sort ? _("sort() argument") : _("uniq() argument")))) {
 
15909
    if (l == NULL ||
 
15910
        tv_check_lock(l->lv_lock,
 
15911
                      (char_u *)(sort
 
15912
                                 ? N_("sort() argument")
 
15913
                                 : N_("uniq() argument")),
 
15914
                      true)) {
15746
15915
      return;
15747
15916
    }
15748
15917
    rettv->vval.v_list = l;
16213
16382
static void f_strchars(typval_T *argvars, typval_T *rettv)
16214
16383
{
16215
16384
  char_u              *s = get_tv_string(&argvars[0]);
 
16385
  int skipcc = 0;
16216
16386
  varnumber_T len = 0;
 
16387
  int (*func_mb_ptr2char_adv)(char_u **pp);
16217
16388
 
16218
 
  while (*s != NUL) {
16219
 
    mb_cptr2char_adv(&s);
16220
 
    ++len;
16221
 
  }
16222
 
  rettv->vval.v_number = len;
 
16389
  if (argvars[1].v_type != VAR_UNKNOWN) {
 
16390
    skipcc = get_tv_number_chk(&argvars[1], NULL);
 
16391
  }
 
16392
  if (skipcc < 0 || skipcc > 1) {
 
16393
    EMSG(_(e_invarg));
 
16394
  } else {
 
16395
    func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv;
 
16396
    while (*s != NUL) {
 
16397
      func_mb_ptr2char_adv(&s);
 
16398
      ++len;
 
16399
    }
 
16400
    rettv->vval.v_number = len;
 
16401
  }
16223
16402
}
16224
16403
 
16225
16404
/*
18021
18200
}
18022
18201
 
18023
18202
/// Set Dictionary v: variable to "val".
18024
 
void set_vim_var_dict(int idx, dict_T *val) FUNC_ATTR_NONNULL_ALL
 
18203
void set_vim_var_dict(int idx, dict_T *val)
18025
18204
{
18026
18205
  dict_unref(vimvars[idx].vv_dict);
18027
 
 
18028
 
  // Set readonly
18029
 
  int todo = (int)val->dv_hashtab.ht_used;
18030
 
  for (hashitem_T *hi = val->dv_hashtab.ht_array; todo > 0 ; ++hi) {
18031
 
    if (HASHITEM_EMPTY(hi)) {
18032
 
       continue;
18033
 
    }
18034
 
 
18035
 
    --todo;
18036
 
    HI2DI(hi)->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
18037
 
  }
18038
 
 
18039
18206
  vimvars[idx].vv_dict = val;
18040
 
  ++val->dv_refcount;
 
18207
 
 
18208
  if (val != NULL) {
 
18209
    ++val->dv_refcount;
 
18210
    // Set readonly
 
18211
    dict_set_keys_readonly(val);
 
18212
  }
18041
18213
}
18042
18214
 
18043
18215
/*
18155
18327
static int 
18156
18328
get_var_tv (
18157
18329
    char_u *name,
18158
 
    int len,                        /* length of "name" */
18159
 
    typval_T *rettv,             /* NULL when only checking existence */
18160
 
    int verbose,                    /* may give error message */
18161
 
    int no_autoload                /* do not use script autoloading */
 
18330
    int len,           // length of "name"
 
18331
    typval_T *rettv,   // NULL when only checking existence
 
18332
    dictitem_T **dip,  // non-NULL when typval's dict item is needed
 
18333
    int verbose,       // may give error message
 
18334
    int no_autoload    // do not use script autoloading
18162
18335
)
18163
18336
{
18164
18337
  int ret = OK;
18184
18357
   */
18185
18358
  else {
18186
18359
    v = find_var(name, NULL, no_autoload);
18187
 
    if (v != NULL)
 
18360
    if (v != NULL) {
18188
18361
      tv = &v->di_tv;
 
18362
      if (dip != NULL) {
 
18363
        *dip = v;
 
18364
      }
 
18365
    }
18189
18366
  }
18190
18367
 
18191
18368
  if (tv == NULL) {
18576
18753
  hashitem_T  *hi;
18577
18754
  *d = NULL;
18578
18755
 
 
18756
  if (name[0] == NUL) {
 
18757
    return NULL;
 
18758
  }
18579
18759
  if (name[1] != ':') {
18580
18760
    // name has implicit scope
18581
18761
    if (name[0] == ':' || name[0] == AUTOLOAD_CHAR) {
18625
18805
}
18626
18806
 
18627
18807
// Find the hashtab used for a variable name.
 
18808
// Return NULL if the name is not valid.
18628
18809
// Set "varname" to the start of name without ':'.
18629
18810
static hashtab_T *find_var_ht(uint8_t *name, uint8_t **varname)
18630
18811
{
18848
19029
    return;
18849
19030
 
18850
19031
  if (v != NULL) {
18851
 
    /* existing variable, need to clear the value */
18852
 
    if (var_check_ro(v->di_flags, name)
18853
 
        || tv_check_lock(v->di_tv.v_lock, name))
 
19032
    // existing variable, need to clear the value
 
19033
    if (var_check_ro(v->di_flags, name, false)
 
19034
        || tv_check_lock(v->di_tv.v_lock, name, false)) {
18854
19035
      return;
 
19036
    }
18855
19037
    if (v->di_tv.v_type != tv->v_type
18856
19038
        && !((v->di_tv.v_type == VAR_STRING
18857
19039
              || v->di_tv.v_type == VAR_NUMBER)
18866
19048
      return;
18867
19049
    }
18868
19050
 
18869
 
    /*
18870
 
     * Handle setting internal v: variables separately: we don't change
18871
 
     * the type.
18872
 
     */
 
19051
    // Handle setting internal v: variables separately where needed to
 
19052
    // prevent changing the type.
18873
19053
    if (ht == &vimvarht) {
18874
19054
      if (v->di_tv.v_type == VAR_STRING) {
18875
19055
        xfree(v->di_tv.vval.v_string);
18880
19060
          v->di_tv.vval.v_string = tv->vval.v_string;
18881
19061
          tv->vval.v_string = NULL;
18882
19062
        }
18883
 
      } else if (v->di_tv.v_type != VAR_NUMBER)
18884
 
        EMSG2(_(e_intern2), "set_var()");
18885
 
      else {
 
19063
        return;
 
19064
      } else if (v->di_tv.v_type == VAR_NUMBER) {
18886
19065
        v->di_tv.vval.v_number = get_tv_number(tv);
18887
19066
        if (STRCMP(varname, "searchforward") == 0)
18888
19067
          set_search_direction(v->di_tv.vval.v_number ? '/' : '?');
18890
19069
          no_hlsearch = !v->di_tv.vval.v_number;
18891
19070
          redraw_all_later(SOME_VALID);
18892
19071
        }
 
19072
        return;
 
19073
      } else if (v->di_tv.v_type != tv->v_type) {
 
19074
        EMSG2(_(e_intern2), "set_var()");
18893
19075
      }
18894
 
      return;
18895
19076
    }
18896
19077
 
18897
19078
    if (watched) {
18936
19117
  }
18937
19118
}
18938
19119
 
18939
 
/*
18940
 
 * Return TRUE if di_flags "flags" indicates variable "name" is read-only.
18941
 
 * Also give an error message.
18942
 
 */
18943
 
static int var_check_ro(int flags, char_u *name)
 
19120
// Return true if di_flags "flags" indicates variable "name" is read-only.
 
19121
// Also give an error message.
 
19122
static bool var_check_ro(int flags, char_u *name, bool use_gettext)
18944
19123
{
18945
19124
  if (flags & DI_FLAGS_RO) {
18946
 
    EMSG2(_(e_readonlyvar), name);
18947
 
    return TRUE;
 
19125
    EMSG2(_(e_readonlyvar), use_gettext ? (char_u *)_(name) : name);
 
19126
    return true;
18948
19127
  }
18949
19128
  if ((flags & DI_FLAGS_RO_SBX) && sandbox) {
18950
 
    EMSG2(_(e_readonlysbx), name);
18951
 
    return TRUE;
 
19129
    EMSG2(_(e_readonlysbx), use_gettext ? (char_u *)_(name) : name);
 
19130
    return true;
18952
19131
  }
18953
 
  return FALSE;
 
19132
  return false;
18954
19133
}
18955
19134
 
18956
 
/*
18957
 
 * Return TRUE if di_flags "flags" indicates variable "name" is fixed.
18958
 
 * Also give an error message.
18959
 
 */
18960
 
static int var_check_fixed(int flags, char_u *name)
 
19135
// Return true if di_flags "flags" indicates variable "name" is fixed.
 
19136
// Also give an error message.
 
19137
static bool var_check_fixed(int flags, char_u *name, bool use_gettext)
18961
19138
{
18962
19139
  if (flags & DI_FLAGS_FIX) {
18963
 
    EMSG2(_("E795: Cannot delete variable %s"), name);
18964
 
    return TRUE;
 
19140
    EMSG2(_("E795: Cannot delete variable %s"),
 
19141
          use_gettext ? (char_u *)_(name) : name);
 
19142
    return true;
18965
19143
  }
18966
 
  return FALSE;
 
19144
  return false;
18967
19145
}
18968
19146
 
18969
19147
/*
19011
19189
  return TRUE;
19012
19190
}
19013
19191
 
19014
 
/*
19015
 
 * Return TRUE if typeval "tv" is set to be locked (immutable).
19016
 
 * Also give an error message, using "name".
19017
 
 */
19018
 
static int tv_check_lock(int lock, char_u *name)
 
19192
// Return true if typeval "tv" is set to be locked (immutable).
 
19193
// Also give an error message, using "name" or _("name") when use_gettext is
 
19194
// true.
 
19195
static bool tv_check_lock(int lock, char_u *name, bool use_gettext)
19019
19196
{
19020
19197
  if (lock & VAR_LOCKED) {
19021
19198
    EMSG2(_("E741: Value is locked: %s"),
19022
 
        name == NULL ? (char_u *)_("Unknown") : name);
19023
 
    return TRUE;
 
19199
          name == NULL
 
19200
          ? (char_u *)_("Unknown")
 
19201
          : use_gettext ? (char_u *)_(name)
 
19202
          : name);
 
19203
    return true;
19024
19204
  }
19025
19205
  if (lock & VAR_FIXED) {
19026
19206
    EMSG2(_("E742: Cannot change value of %s"),
19027
 
        name == NULL ? (char_u *)_("Unknown") : name);
19028
 
    return TRUE;
 
19207
          name == NULL
 
19208
          ? (char_u *)_("Unknown")
 
19209
          : use_gettext ? (char_u *)_(name)
 
19210
          : name);
 
19211
    return true;
19029
19212
  }
19030
 
  return FALSE;
 
19213
  return false;
19031
19214
}
19032
19215
 
19033
19216
/*
19620
19803
      break;
19621
19804
    }
19622
19805
  }
19623
 
  ++p;          /* skip the ')' */
 
19806
  if (*p != ')') {
 
19807
    goto erret;
 
19808
  }
 
19809
  ++p;  // skip the ')'
19624
19810
 
19625
19811
  /* find extra arguments "range", "dict" and "abort" */
19626
19812
  for (;; ) {
19844
20030
      goto erret;
19845
20031
    }
19846
20032
    if (fudi.fd_di == NULL) {
19847
 
      /* Can't add a function to a locked dictionary */
19848
 
      if (tv_check_lock(fudi.fd_dict->dv_lock, eap->arg))
 
20033
      if (tv_check_lock(fudi.fd_dict->dv_lock, eap->arg, false)) {
 
20034
        // Can't add a function to a locked dictionary
19849
20035
        goto erret;
 
20036
      }
 
20037
    } else if (tv_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg, false)) {
 
20038
      // Can't change an existing function if it is locked
 
20039
      goto erret;
19850
20040
    }
19851
 
    /* Can't change an existing function if it is locked */
19852
 
    else if (tv_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg))
19853
 
      goto erret;
19854
20041
 
19855
20042
    /* Give the function a sequential number.  Can only be used with a
19856
20043
     * Funcref! */
20828
21015
  save_sourcing_name = sourcing_name;
20829
21016
  save_sourcing_lnum = sourcing_lnum;
20830
21017
  sourcing_lnum = 1;
20831
 
  sourcing_name = xmalloc((save_sourcing_name == NULL ? 0 : STRLEN(save_sourcing_name))
20832
 
                          + STRLEN(fp->uf_name) + 13);
 
21018
  // need space for function name + ("function " + 3) or "[number]"
 
21019
  size_t len = (save_sourcing_name == NULL ? 0 : STRLEN(save_sourcing_name))
 
21020
               + STRLEN(fp->uf_name) + 20;
 
21021
  sourcing_name = xmalloc(len);
20833
21022
  {
20834
21023
    if (save_sourcing_name != NULL
20835
 
        && STRNCMP(save_sourcing_name, "function ", 9) == 0)
20836
 
      sprintf((char *)sourcing_name, "%s..", save_sourcing_name);
20837
 
    else
 
21024
        && STRNCMP(save_sourcing_name, "function ", 9) == 0) {
 
21025
      vim_snprintf((char *)sourcing_name, len, "%s[%zu]..",
 
21026
                   save_sourcing_name, save_sourcing_lnum);
 
21027
    } else {
20838
21028
      STRCPY(sourcing_name, "function ");
 
21029
    }
20839
21030
    cat_func_name(sourcing_name + STRLEN(sourcing_name), fp);
20840
21031
 
20841
21032
    if (p_verbose >= 12) {
21802
21993
  }
21803
21994
 
21804
21995
  if (src[*usedlen] == ':' && src[*usedlen + 1] == 'S') {
 
21996
    // vim_strsave_shellescape() needs a NUL terminated string.
 
21997
    c = (*fnamep)[*fnamelen];
 
21998
    if (c != NUL) {
 
21999
      (*fnamep)[*fnamelen] = NUL;
 
22000
    }
21805
22001
    p = vim_strsave_shellescape(*fnamep, false, false);
 
22002
    if (c != NUL) {
 
22003
      (*fnamep)[*fnamelen] = c;
 
22004
    }
21806
22005
    xfree(*bufp);
21807
22006
    *bufp = *fnamep = p;
21808
22007
    *fnamelen = STRLEN(p);
22101
22300
    char msg[22];
22102
22301
    snprintf(msg, sizeof msg, "\r\n[Process exited %d]", proc->status);
22103
22302
    terminal_close(data->term, msg);
22104
 
    apply_autocmds(EVENT_TERMCLOSE, NULL, NULL, false, curbuf);
22105
22303
  }
22106
22304
 
22107
22305
  if (data->status_ptr) {