comparison src/evalfunc.c @ 15454:1d2b5c016f17 v8.1.0735

patch 8.1.0735: cannot handle binary data commit https://github.com/vim/vim/commit/6e5ea8d2a995b32bbc5972edc4f827b959f2702f Author: Bram Moolenaar <Bram@vim.org> Date: Sat Jan 12 22:47:31 2019 +0100 patch 8.1.0735: cannot handle binary data Problem: Cannot handle binary data. Solution: Add the Blob type. (Yasuhiro Matsumoto, closes https://github.com/vim/vim/issues/3638)
author Bram Moolenaar <Bram@vim.org>
date Sat, 12 Jan 2019 23:00:06 +0100
parents b6224857db6f
children f01eb1aed348
comparison
equal deleted inserted replaced
15453:cdee6e827112 15454:1d2b5c016f17
94 static void f_ch_info(typval_T *argvars, typval_T *rettv); 94 static void f_ch_info(typval_T *argvars, typval_T *rettv);
95 static void f_ch_log(typval_T *argvars, typval_T *rettv); 95 static void f_ch_log(typval_T *argvars, typval_T *rettv);
96 static void f_ch_logfile(typval_T *argvars, typval_T *rettv); 96 static void f_ch_logfile(typval_T *argvars, typval_T *rettv);
97 static void f_ch_open(typval_T *argvars, typval_T *rettv); 97 static void f_ch_open(typval_T *argvars, typval_T *rettv);
98 static void f_ch_read(typval_T *argvars, typval_T *rettv); 98 static void f_ch_read(typval_T *argvars, typval_T *rettv);
99 static void f_ch_readblob(typval_T *argvars, typval_T *rettv);
99 static void f_ch_readraw(typval_T *argvars, typval_T *rettv); 100 static void f_ch_readraw(typval_T *argvars, typval_T *rettv);
100 static void f_ch_sendexpr(typval_T *argvars, typval_T *rettv); 101 static void f_ch_sendexpr(typval_T *argvars, typval_T *rettv);
101 static void f_ch_sendraw(typval_T *argvars, typval_T *rettv); 102 static void f_ch_sendraw(typval_T *argvars, typval_T *rettv);
102 static void f_ch_setoptions(typval_T *argvars, typval_T *rettv); 103 static void f_ch_setoptions(typval_T *argvars, typval_T *rettv);
103 static void f_ch_status(typval_T *argvars, typval_T *rettv); 104 static void f_ch_status(typval_T *argvars, typval_T *rettv);
568 {"ch_info", 1, 1, f_ch_info}, 569 {"ch_info", 1, 1, f_ch_info},
569 {"ch_log", 1, 2, f_ch_log}, 570 {"ch_log", 1, 2, f_ch_log},
570 {"ch_logfile", 1, 2, f_ch_logfile}, 571 {"ch_logfile", 1, 2, f_ch_logfile},
571 {"ch_open", 1, 2, f_ch_open}, 572 {"ch_open", 1, 2, f_ch_open},
572 {"ch_read", 1, 2, f_ch_read}, 573 {"ch_read", 1, 2, f_ch_read},
574 {"ch_readblob", 1, 2, f_ch_readblob},
573 {"ch_readraw", 1, 2, f_ch_readraw}, 575 {"ch_readraw", 1, 2, f_ch_readraw},
574 {"ch_sendexpr", 2, 3, f_ch_sendexpr}, 576 {"ch_sendexpr", 2, 3, f_ch_sendexpr},
575 {"ch_sendraw", 2, 3, f_ch_sendraw}, 577 {"ch_sendraw", 2, 3, f_ch_sendraw},
576 {"ch_setoptions", 2, 2, f_ch_setoptions}, 578 {"ch_setoptions", 2, 2, f_ch_setoptions},
577 {"ch_status", 1, 2, f_ch_status}, 579 {"ch_status", 1, 2, f_ch_status},
1235 */ 1237 */
1236 static void 1238 static void
1237 f_add(typval_T *argvars, typval_T *rettv) 1239 f_add(typval_T *argvars, typval_T *rettv)
1238 { 1240 {
1239 list_T *l; 1241 list_T *l;
1242 blob_T *b;
1240 1243
1241 rettv->vval.v_number = 1; /* Default: Failed */ 1244 rettv->vval.v_number = 1; /* Default: Failed */
1242 if (argvars[0].v_type == VAR_LIST) 1245 if (argvars[0].v_type == VAR_LIST)
1243 { 1246 {
1244 if ((l = argvars[0].vval.v_list) != NULL 1247 if ((l = argvars[0].vval.v_list) != NULL
1245 && !tv_check_lock(l->lv_lock, 1248 && !tv_check_lock(l->lv_lock,
1246 (char_u *)N_("add() argument"), TRUE) 1249 (char_u *)N_("add() argument"), TRUE)
1247 && list_append_tv(l, &argvars[1]) == OK) 1250 && list_append_tv(l, &argvars[1]) == OK)
1248 copy_tv(&argvars[0], rettv); 1251 copy_tv(&argvars[0], rettv);
1252 }
1253 else if (argvars[0].v_type == VAR_BLOB)
1254 {
1255 if ((b = argvars[0].vval.v_blob) != NULL
1256 && !tv_check_lock(b->bv_lock,
1257 (char_u *)N_("add() argument"), TRUE))
1258 {
1259 ga_append(&b->bv_ga, (char_u)tv_get_number(&argvars[1]));
1260 copy_tv(&argvars[0], rettv);
1261 }
1249 } 1262 }
1250 else 1263 else
1251 EMSG(_(e_listreq)); 1264 EMSG(_(e_listreq));
1252 } 1265 }
1253 1266
2307 * "ch_read()" function 2320 * "ch_read()" function
2308 */ 2321 */
2309 static void 2322 static void
2310 f_ch_read(typval_T *argvars, typval_T *rettv) 2323 f_ch_read(typval_T *argvars, typval_T *rettv)
2311 { 2324 {
2312 common_channel_read(argvars, rettv, FALSE); 2325 common_channel_read(argvars, rettv, FALSE, FALSE);
2326 }
2327
2328 /*
2329 * "ch_readblob()" function
2330 */
2331 static void
2332 f_ch_readblob(typval_T *argvars, typval_T *rettv)
2333 {
2334 common_channel_read(argvars, rettv, TRUE, TRUE);
2313 } 2335 }
2314 2336
2315 /* 2337 /*
2316 * "ch_readraw()" function 2338 * "ch_readraw()" function
2317 */ 2339 */
2318 static void 2340 static void
2319 f_ch_readraw(typval_T *argvars, typval_T *rettv) 2341 f_ch_readraw(typval_T *argvars, typval_T *rettv)
2320 { 2342 {
2321 common_channel_read(argvars, rettv, TRUE); 2343 common_channel_read(argvars, rettv, TRUE, FALSE);
2322 } 2344 }
2323 2345
2324 /* 2346 /*
2325 * "ch_evalexpr()" function 2347 * "ch_evalexpr()" function
2326 */ 2348 */
3166 n = argvars[0].vval.v_dict == NULL 3188 n = argvars[0].vval.v_dict == NULL
3167 || argvars[0].vval.v_dict->dv_hashtab.ht_used == 0; 3189 || argvars[0].vval.v_dict->dv_hashtab.ht_used == 0;
3168 break; 3190 break;
3169 case VAR_SPECIAL: 3191 case VAR_SPECIAL:
3170 n = argvars[0].vval.v_number != VVAL_TRUE; 3192 n = argvars[0].vval.v_number != VVAL_TRUE;
3193 break;
3194
3195 case VAR_BLOB:
3196 n = argvars[0].vval.v_blob == NULL
3197 || argvars[0].vval.v_blob->bv_ga.ga_data == NULL
3198 || argvars[0].vval.v_blob->bv_ga.ga_len == 0;
3171 break; 3199 break;
3172 3200
3173 case VAR_JOB: 3201 case VAR_JOB:
3174 #ifdef FEAT_JOB_CHANNEL 3202 #ifdef FEAT_JOB_CHANNEL
3175 n = argvars[0].vval.v_job == NULL 3203 n = argvars[0].vval.v_job == NULL
4363 list_T *l; 4391 list_T *l;
4364 dictitem_T *di; 4392 dictitem_T *di;
4365 dict_T *d; 4393 dict_T *d;
4366 typval_T *tv = NULL; 4394 typval_T *tv = NULL;
4367 4395
4368 if (argvars[0].v_type == VAR_LIST) 4396 if (argvars[0].v_type == VAR_BLOB)
4397 {
4398 int error = FALSE;
4399 int idx = tv_get_number_chk(&argvars[1], &error);
4400
4401 if (!error)
4402 {
4403 rettv->v_type = VAR_NUMBER;
4404 if (idx >= blob_len(argvars[0].vval.v_blob))
4405 EMSGN(_(e_blobidx), idx);
4406 else
4407 rettv->vval.v_number = blob_get(argvars[0].vval.v_blob, idx);
4408 }
4409 }
4410 else if (argvars[0].v_type == VAR_LIST)
4369 { 4411 {
4370 if ((l = argvars[0].vval.v_list) != NULL) 4412 if ((l = argvars[0].vval.v_list) != NULL)
4371 { 4413 {
4372 int error = FALSE; 4414 int error = FALSE;
4373 4415
6963 static void 7005 static void
6964 f_index(typval_T *argvars, typval_T *rettv) 7006 f_index(typval_T *argvars, typval_T *rettv)
6965 { 7007 {
6966 list_T *l; 7008 list_T *l;
6967 listitem_T *item; 7009 listitem_T *item;
7010 blob_T *b;
6968 long idx = 0; 7011 long idx = 0;
6969 int ic = FALSE; 7012 int ic = FALSE;
7013 int error = FALSE;
6970 7014
6971 rettv->vval.v_number = -1; 7015 rettv->vval.v_number = -1;
6972 if (argvars[0].v_type != VAR_LIST) 7016 if (argvars[0].v_type == VAR_BLOB)
7017 {
7018 typval_T tv;
7019 int start = 0;
7020
7021 if (argvars[2].v_type != VAR_UNKNOWN)
7022 {
7023 start = tv_get_number_chk(&argvars[2], &error);
7024 if (error)
7025 return;
7026 }
7027 b = argvars[0].vval.v_blob;
7028 if (b == NULL)
7029 return;
7030 for (idx = start; idx < blob_len(b); ++idx)
7031 {
7032 tv.v_type = VAR_NUMBER;
7033 tv.vval.v_number = blob_get(b, idx);
7034 if (tv_equal(&tv, &argvars[1], ic, FALSE))
7035 {
7036 rettv->vval.v_number = idx;
7037 return;
7038 }
7039 }
7040 return;
7041 }
7042 else if (argvars[0].v_type != VAR_LIST)
6973 { 7043 {
6974 EMSG(_(e_listreq)); 7044 EMSG(_(e_listreq));
6975 return; 7045 return;
6976 } 7046 }
7047
6977 l = argvars[0].vval.v_list; 7048 l = argvars[0].vval.v_list;
6978 if (l != NULL) 7049 if (l != NULL)
6979 { 7050 {
6980 item = l->lv_first; 7051 item = l->lv_first;
6981 if (argvars[2].v_type != VAR_UNKNOWN) 7052 if (argvars[2].v_type != VAR_UNKNOWN)
6982 { 7053 {
6983 int error = FALSE;
6984
6985 /* Start at specified item. Use the cached index that list_find() 7054 /* Start at specified item. Use the cached index that list_find()
6986 * sets, so that a negative number also works. */ 7055 * sets, so that a negative number also works. */
6987 item = list_find(l, (long)tv_get_number_chk(&argvars[2], &error)); 7056 item = list_find(l, (long)tv_get_number_chk(&argvars[2], &error));
6988 idx = l->lv_idx; 7057 idx = l->lv_idx;
6989 if (argvars[3].v_type != VAR_UNKNOWN) 7058 if (argvars[3].v_type != VAR_UNKNOWN)
7158 long before = 0; 7227 long before = 0;
7159 listitem_T *item; 7228 listitem_T *item;
7160 list_T *l; 7229 list_T *l;
7161 int error = FALSE; 7230 int error = FALSE;
7162 7231
7163 if (argvars[0].v_type != VAR_LIST) 7232 if (argvars[0].v_type == VAR_BLOB)
7233 {
7234 int val, len;
7235 char_u *p;
7236
7237 len = blob_len(argvars[0].vval.v_blob);
7238 if (argvars[2].v_type != VAR_UNKNOWN)
7239 {
7240 before = (long)tv_get_number_chk(&argvars[2], &error);
7241 if (error)
7242 return; // type error; errmsg already given
7243 if (before < 0 || before > len)
7244 {
7245 EMSG2(_(e_invarg2), tv_get_string(&argvars[2]));
7246 return;
7247 }
7248 }
7249 val = tv_get_number_chk(&argvars[1], &error);
7250 if (error)
7251 return;
7252 if (val < 0 || val > 255)
7253 {
7254 EMSG2(_(e_invarg2), tv_get_string(&argvars[1]));
7255 return;
7256 }
7257
7258 if (ga_grow(&argvars[0].vval.v_blob->bv_ga, 1) == FAIL)
7259 return;
7260 p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data;
7261 mch_memmove(p + before + 1, p + before, (size_t)len - before);
7262 *(p + before) = val;
7263 ++argvars[0].vval.v_blob->bv_ga.ga_len;
7264
7265 copy_tv(&argvars[0], rettv);
7266 }
7267 else if (argvars[0].v_type != VAR_LIST)
7164 EMSG2(_(e_listarg), "insert()"); 7268 EMSG2(_(e_listarg), "insert()");
7165 else if ((l = argvars[0].vval.v_list) != NULL 7269 else if ((l = argvars[0].vval.v_list) != NULL && !tv_check_lock(l->lv_lock,
7166 && !tv_check_lock(l->lv_lock, (char_u *)N_("insert() argument"), TRUE)) 7270 (char_u *)N_("insert() argument"), TRUE))
7167 { 7271 {
7168 if (argvars[2].v_type != VAR_UNKNOWN) 7272 if (argvars[2].v_type != VAR_UNKNOWN)
7169 before = (long)tv_get_number_chk(&argvars[2], &error); 7273 before = (long)tv_get_number_chk(&argvars[2], &error);
7170 if (error) 7274 if (error)
7171 return; /* type error; errmsg already given */ 7275 return; /* type error; errmsg already given */
7524 { 7628 {
7525 case VAR_STRING: 7629 case VAR_STRING:
7526 case VAR_NUMBER: 7630 case VAR_NUMBER:
7527 rettv->vval.v_number = (varnumber_T)STRLEN( 7631 rettv->vval.v_number = (varnumber_T)STRLEN(
7528 tv_get_string(&argvars[0])); 7632 tv_get_string(&argvars[0]));
7633 break;
7634 case VAR_BLOB:
7635 rettv->vval.v_number = blob_len(argvars[0].vval.v_blob);
7529 break; 7636 break;
7530 case VAR_LIST: 7637 case VAR_LIST:
7531 rettv->vval.v_number = list_len(argvars[0].vval.v_list); 7638 rettv->vval.v_number = list_len(argvars[0].vval.v_list);
7532 break; 7639 break;
7533 case VAR_DICT: 7640 case VAR_DICT:
8924 */ 9031 */
8925 static void 9032 static void
8926 f_readfile(typval_T *argvars, typval_T *rettv) 9033 f_readfile(typval_T *argvars, typval_T *rettv)
8927 { 9034 {
8928 int binary = FALSE; 9035 int binary = FALSE;
9036 int blob = FALSE;
8929 int failed = FALSE; 9037 int failed = FALSE;
8930 char_u *fname; 9038 char_u *fname;
8931 FILE *fd; 9039 FILE *fd;
8932 char_u buf[(IOSIZE/256)*256]; /* rounded to avoid odd + 1 */ 9040 char_u buf[(IOSIZE/256)*256]; /* rounded to avoid odd + 1 */
8933 int io_size = sizeof(buf); 9041 int io_size = sizeof(buf);
8942 9050
8943 if (argvars[1].v_type != VAR_UNKNOWN) 9051 if (argvars[1].v_type != VAR_UNKNOWN)
8944 { 9052 {
8945 if (STRCMP(tv_get_string(&argvars[1]), "b") == 0) 9053 if (STRCMP(tv_get_string(&argvars[1]), "b") == 0)
8946 binary = TRUE; 9054 binary = TRUE;
9055 if (STRCMP(tv_get_string(&argvars[1]), "B") == 0)
9056 blob = TRUE;
9057
8947 if (argvars[2].v_type != VAR_UNKNOWN) 9058 if (argvars[2].v_type != VAR_UNKNOWN)
8948 maxline = (long)tv_get_number(&argvars[2]); 9059 maxline = (long)tv_get_number(&argvars[2]);
8949 } 9060 }
8950 9061
8951 if (rettv_list_alloc(rettv) == FAIL) 9062 if (blob)
8952 return; 9063 {
9064 if (rettv_blob_alloc(rettv) == FAIL)
9065 return;
9066 }
9067 else
9068 {
9069 if (rettv_list_alloc(rettv) == FAIL)
9070 return;
9071 }
8953 9072
8954 /* Always open the file in binary mode, library functions have a mind of 9073 /* Always open the file in binary mode, library functions have a mind of
8955 * their own about CR-LF conversion. */ 9074 * their own about CR-LF conversion. */
8956 fname = tv_get_string(&argvars[0]); 9075 fname = tv_get_string(&argvars[0]);
8957 if (*fname == NUL || (fd = mch_fopen((char *)fname, READBIN)) == NULL) 9076 if (*fname == NUL || (fd = mch_fopen((char *)fname, READBIN)) == NULL)
8958 { 9077 {
8959 EMSG2(_(e_notopen), *fname == NUL ? (char_u *)_("<empty>") : fname); 9078 EMSG2(_(e_notopen), *fname == NUL ? (char_u *)_("<empty>") : fname);
9079 return;
9080 }
9081
9082 if (blob)
9083 {
9084 if (read_blob(fd, rettv->vval.v_blob) == FAIL)
9085 {
9086 EMSG("cannot read file");
9087 blob_free(rettv->vval.v_blob);
9088 }
9089 fclose(fd);
8960 return; 9090 return;
8961 } 9091 }
8962 9092
8963 while (cnt < maxline || maxline < 0) 9093 while (cnt < maxline || maxline < 0)
8964 { 9094 {
9553 long end; 9683 long end;
9554 char_u *key; 9684 char_u *key;
9555 dict_T *d; 9685 dict_T *d;
9556 dictitem_T *di; 9686 dictitem_T *di;
9557 char_u *arg_errmsg = (char_u *)N_("remove() argument"); 9687 char_u *arg_errmsg = (char_u *)N_("remove() argument");
9688 int error = FALSE;
9558 9689
9559 if (argvars[0].v_type == VAR_DICT) 9690 if (argvars[0].v_type == VAR_DICT)
9560 { 9691 {
9561 if (argvars[2].v_type != VAR_UNKNOWN) 9692 if (argvars[2].v_type != VAR_UNKNOWN)
9562 EMSG2(_(e_toomanyarg), "remove()"); 9693 EMSG2(_(e_toomanyarg), "remove()");
9577 dictitem_remove(d, di); 9708 dictitem_remove(d, di);
9578 } 9709 }
9579 } 9710 }
9580 } 9711 }
9581 } 9712 }
9713 else if (argvars[0].v_type == VAR_BLOB)
9714 {
9715 idx = (long)tv_get_number_chk(&argvars[1], &error);
9716 if (!error)
9717 {
9718 blob_T *b = argvars[0].vval.v_blob;
9719 int len = blob_len(b);
9720 char_u *p;
9721
9722 if (idx < 0)
9723 // count from the end
9724 idx = len + idx;
9725 if (idx < 0 || idx >= len)
9726 {
9727 EMSGN(_(e_blobidx), idx);
9728 return;
9729 }
9730 if (argvars[2].v_type == VAR_UNKNOWN)
9731 {
9732 // Remove one item, return its value.
9733 p = (char_u *)b->bv_ga.ga_data;
9734 rettv->vval.v_number = (varnumber_T) *(p + idx);
9735 mch_memmove(p + idx, p + idx + 1, (size_t)len - idx - 1);
9736 --b->bv_ga.ga_len;
9737 }
9738 else
9739 {
9740 blob_T *blob;
9741
9742 // Remove range of items, return list with values.
9743 end = (long)tv_get_number_chk(&argvars[2], &error);
9744 if (error)
9745 return;
9746 if (end < 0)
9747 // count from the end
9748 end = len + end;
9749 if (end >= len || idx > end)
9750 {
9751 EMSGN(_(e_blobidx), end);
9752 return;
9753 }
9754 blob = blob_alloc();
9755 if (blob == NULL)
9756 return;
9757 blob->bv_ga.ga_len = end - idx + 1;
9758 if (ga_grow(&blob->bv_ga, end - idx + 1) == FAIL)
9759 {
9760 vim_free(blob);
9761 return;
9762 }
9763 p = (char_u *)b->bv_ga.ga_data;
9764 mch_memmove((char_u *)blob->bv_ga.ga_data, p + idx,
9765 (size_t)(end - idx + 1));
9766 ++blob->bv_refcount;
9767 rettv->v_type = VAR_BLOB;
9768 rettv->vval.v_blob = blob;
9769
9770 mch_memmove(p + idx, p + end + 1, (size_t)(len - end));
9771 b->bv_ga.ga_len -= end - idx + 1;
9772 }
9773 }
9774 }
9582 else if (argvars[0].v_type != VAR_LIST) 9775 else if (argvars[0].v_type != VAR_LIST)
9583 EMSG2(_(e_listdictarg), "remove()"); 9776 EMSG2(_(e_listdictarg), "remove()");
9584 else if ((l = argvars[0].vval.v_list) != NULL 9777 else if ((l = argvars[0].vval.v_list) != NULL
9585 && !tv_check_lock(l->lv_lock, arg_errmsg, TRUE)) 9778 && !tv_check_lock(l->lv_lock, arg_errmsg, TRUE))
9586 { 9779 {
9587 int error = FALSE;
9588
9589 idx = (long)tv_get_number_chk(&argvars[1], &error); 9780 idx = (long)tv_get_number_chk(&argvars[1], &error);
9590 if (error) 9781 if (error)
9591 ; /* type error: do nothing, errmsg already given */ 9782 ; // type error: do nothing, errmsg already given
9592 else if ((item = list_find(l, idx)) == NULL) 9783 else if ((item = list_find(l, idx)) == NULL)
9593 EMSGN(_(e_listidx), idx); 9784 EMSGN(_(e_listidx), idx);
9594 else 9785 else
9595 { 9786 {
9596 if (argvars[2].v_type == VAR_UNKNOWN) 9787 if (argvars[2].v_type == VAR_UNKNOWN)
9600 *rettv = item->li_tv; 9791 *rettv = item->li_tv;
9601 vim_free(item); 9792 vim_free(item);
9602 } 9793 }
9603 else 9794 else
9604 { 9795 {
9605 /* Remove range of items, return list with values. */ 9796 // Remove range of items, return list with values.
9606 end = (long)tv_get_number_chk(&argvars[2], &error); 9797 end = (long)tv_get_number_chk(&argvars[2], &error);
9607 if (error) 9798 if (error)
9608 ; /* type error: do nothing */ 9799 ; // type error: do nothing
9609 else if ((item2 = list_find(l, end)) == NULL) 9800 else if ((item2 = list_find(l, end)) == NULL)
9610 EMSGN(_(e_listidx), end); 9801 EMSGN(_(e_listidx), end);
9611 else 9802 else
9612 { 9803 {
9613 int cnt = 0; 9804 int cnt = 0;
9909 static void 10100 static void
9910 f_reverse(typval_T *argvars, typval_T *rettv) 10101 f_reverse(typval_T *argvars, typval_T *rettv)
9911 { 10102 {
9912 list_T *l; 10103 list_T *l;
9913 listitem_T *li, *ni; 10104 listitem_T *li, *ni;
10105
10106 if (argvars[0].v_type == VAR_BLOB)
10107 {
10108 blob_T *b = argvars[0].vval.v_blob;
10109 int i, len = blob_len(b);
10110
10111 for (i = 0; i < len / 2; i++)
10112 {
10113 int tmp = blob_get(b, i);
10114
10115 blob_set(b, i, blob_get(b, len - i - 1));
10116 blob_set(b, len - i - 1, tmp);
10117 }
10118 rettv_blob_set(rettv, b);
10119 return;
10120 }
9914 10121
9915 if (argvars[0].v_type != VAR_LIST) 10122 if (argvars[0].v_type != VAR_LIST)
9916 EMSG2(_(e_listarg), "reverse()"); 10123 EMSG2(_(e_listarg), "reverse()");
9917 else if ((l = argvars[0].vval.v_list) != NULL 10124 else if ((l = argvars[0].vval.v_list) != NULL
9918 && !tv_check_lock(l->lv_lock, 10125 && !tv_check_lock(l->lv_lock,
14196 else 14403 else
14197 n = VAR_TYPE_NONE; 14404 n = VAR_TYPE_NONE;
14198 break; 14405 break;
14199 case VAR_JOB: n = VAR_TYPE_JOB; break; 14406 case VAR_JOB: n = VAR_TYPE_JOB; break;
14200 case VAR_CHANNEL: n = VAR_TYPE_CHANNEL; break; 14407 case VAR_CHANNEL: n = VAR_TYPE_CHANNEL; break;
14408 case VAR_BLOB: n = VAR_TYPE_BLOB; break;
14201 case VAR_UNKNOWN: 14409 case VAR_UNKNOWN:
14202 internal_error("f_type(UNKNOWN)"); 14410 internal_error("f_type(UNKNOWN)");
14203 n = -1; 14411 n = -1;
14204 break; 14412 break;
14205 } 14413 }
14554 #endif 14762 #endif
14555 char_u *fname; 14763 char_u *fname;
14556 FILE *fd; 14764 FILE *fd;
14557 int ret = 0; 14765 int ret = 0;
14558 listitem_T *li; 14766 listitem_T *li;
14559 list_T *list; 14767 list_T *list = NULL;
14768 blob_T *blob = NULL;
14560 14769
14561 rettv->vval.v_number = -1; 14770 rettv->vval.v_number = -1;
14562 if (check_restricted() || check_secure()) 14771 if (check_restricted() || check_secure())
14563 return; 14772 return;
14564 14773
14565 if (argvars[0].v_type != VAR_LIST) 14774 if (argvars[0].v_type == VAR_LIST)
14566 { 14775 {
14567 EMSG2(_(e_listarg), "writefile()"); 14776 list = argvars[0].vval.v_list;
14777 if (list == NULL)
14778 return;
14779 for (li = list->lv_first; li != NULL; li = li->li_next)
14780 if (tv_get_string_chk(&li->li_tv) == NULL)
14781 return;
14782 }
14783 else if (argvars[0].v_type == VAR_BLOB)
14784 {
14785 blob = argvars[0].vval.v_blob;
14786 if (blob == NULL)
14787 return;
14788 }
14789 else
14790 {
14791 EMSG2(_(e_invarg2), "writefile()");
14568 return; 14792 return;
14569 } 14793 }
14570 list = argvars[0].vval.v_list;
14571 if (list == NULL)
14572 return;
14573 for (li = list->lv_first; li != NULL; li = li->li_next)
14574 if (tv_get_string_chk(&li->li_tv) == NULL)
14575 return;
14576 14794
14577 if (argvars[2].v_type != VAR_UNKNOWN) 14795 if (argvars[2].v_type != VAR_UNKNOWN)
14578 { 14796 {
14579 char_u *arg2 = tv_get_string_chk(&argvars[2]); 14797 char_u *arg2 = tv_get_string_chk(&argvars[2]);
14580 14798
14602 append ? APPENDBIN : WRITEBIN)) == NULL) 14820 append ? APPENDBIN : WRITEBIN)) == NULL)
14603 { 14821 {
14604 EMSG2(_(e_notcreate), *fname == NUL ? (char_u *)_("<empty>") : fname); 14822 EMSG2(_(e_notcreate), *fname == NUL ? (char_u *)_("<empty>") : fname);
14605 ret = -1; 14823 ret = -1;
14606 } 14824 }
14825 else if (blob)
14826 {
14827 if (write_blob(fd, blob) == FAIL)
14828 ret = -1;
14829 #ifdef HAVE_FSYNC
14830 else if (do_fsync)
14831 // Ignore the error, the user wouldn't know what to do about it.
14832 // May happen for a device.
14833 vim_ignored = fsync(fileno(fd));
14834 #endif
14835 fclose(fd);
14836 }
14607 else 14837 else
14608 { 14838 {
14609 if (write_list(fd, list, binary) == FAIL) 14839 if (write_list(fd, list, binary) == FAIL)
14610 ret = -1; 14840 ret = -1;
14611 #ifdef HAVE_FSYNC 14841 #ifdef HAVE_FSYNC