Mercurial > vim
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 |