diff options
Diffstat (limited to 'data/vim/patches/8.1.0735')
-rw-r--r-- | data/vim/patches/8.1.0735 | 3392 |
1 files changed, 0 insertions, 3392 deletions
diff --git a/data/vim/patches/8.1.0735 b/data/vim/patches/8.1.0735 deleted file mode 100644 index 945f91e9e..000000000 --- a/data/vim/patches/8.1.0735 +++ /dev/null @@ -1,3392 +0,0 @@ -To: vim_dev@googlegroups.com -Subject: Patch 8.1.0735 -Fcc: outbox -From: Bram Moolenaar <Bram@moolenaar.net> -Mime-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit ------------- - -Patch 8.1.0735 -Problem: Cannot handle binary data. -Solution: Add the Blob type. (Yasuhiro Matsumoto, closes #3638) -Files: runtime/doc/eval.txt, runtime/doc/if_perl.txt, - runtime/doc/if_ruby.txt, src/Make_cyg_ming.mak, src/Make_mvc.mak, - src/Makefile, src/blob.c, src/channel.c, src/eval.c, - src/evalfunc.c, src/if_perl.xs, src/if_py_both.h, src/if_python.c, - src/if_python3.c, src/if_ruby.c, src/json.c, src/netbeans.c, - src/proto.h, src/proto/blob.pro, src/proto/channel.pro, - src/structs.h, src/testdir/Make_all.mak, src/vim.h, src/globals.h, - src/testdir/test_blob.vim, src/testdir/test_channel.vim - - -*** ../vim-8.1.0734/runtime/doc/eval.txt 2019-01-12 14:24:22.627597552 +0100 ---- runtime/doc/eval.txt 2019-01-12 22:41:51.485097473 +0100 -*************** -*** 72,77 **** ---- 72,81 ---- - - Channel Used for a channel, see |ch_open()|. *Channel* *Channels* - -+ Blob Binary Large Object. Stores any sequence of bytes. *Blob* -+ Example: 0zFF00ED015DAF -+ 0z is an empty Blob. -+ - The Number and String types are converted automatically, depending on how they - are used. - -*************** -*** 124,130 **** - A List, Dictionary or Float is not a Number or String, thus evaluate to FALSE. - - *E745* *E728* *E703* *E729* *E730* *E731* *E908* *E910* *E913* -! List, Dictionary, Funcref, Job and Channel types are not automatically - converted. - - *E805* *E806* *E808* ---- 128,135 ---- - A List, Dictionary or Float is not a Number or String, thus evaluate to FALSE. - - *E745* *E728* *E703* *E729* *E730* *E731* *E908* *E910* *E913* -! *E974* *E975* *E976* -! List, Dictionary, Funcref, Job, Channel and Blob types are not automatically - converted. - - *E805* *E806* *E808* -*************** -*** 1010,1015 **** ---- 1022,1033 ---- - :let l = mylist[4:4] " List with one item - :let l = mylist[:] " shallow copy of a List - -+ If expr8 is a |Blob| this results in a new |Blob| with the bytes in the -+ indexes expr1a and expr1b, inclusive. Examples: > -+ :let b = 0zDEADBEEF -+ :let bs = b[1:2] " 0zADBE -+ :let bs = b[] " copy ov 0zDEADBEEF -+ - Using expr8[expr1] or expr8[expr1a : expr1b] on a |Funcref| results in an - error. - -*************** -*** 1145,1150 **** ---- 1167,1180 ---- - Note that "\000" and "\x00" force the end of the string. - - -+ blob-literal *blob-literal* *E973* *E977* *E978* -+ ------------ -+ -+ Hexadecimal starting with 0z or 0Z, with an arbitrary number of bytes. -+ The sequence must be an even number of hex characters. Example: > -+ :let b = 0zFF00ED015DAF -+ -+ - literal-string *literal-string* *E115* - --------------- - 'string' string constant *expr-'* -*************** -*** 1898,1903 **** ---- 1930,1937 ---- - v:t_number Value of Number type. Read-only. See: |type()| - *v:t_string* *t_string-variable* - v:t_string Value of String type. Read-only. See: |type()| -+ *v:t_blob* *t_blob-variable* -+ v:t_blob Value of Blob type. Read-only. See: |type()| - - *v:termresponse* *termresponse-variable* - v:termresponse The escape sequence returned by the terminal for the |t_RV| -*************** -*** 2080,2091 **** - ch_open({address} [, {options}]) - Channel open a channel to {address} - ch_read({handle} [, {options}]) String read from {handle} - ch_readraw({handle} [, {options}]) - String read raw from {handle} - ch_sendexpr({handle}, {expr} [, {options}]) - any send {expr} over JSON {handle} -! ch_sendraw({handle}, {string} [, {options}]) -! any send {string} over raw {handle} - ch_setoptions({handle}, {options}) - none set options for {handle} - ch_status({handle} [, {options}]) ---- 2115,2128 ---- - ch_open({address} [, {options}]) - Channel open a channel to {address} - ch_read({handle} [, {options}]) String read from {handle} -+ ch_readblob({handle} [, {options}]) -+ Blob read Blob from {handle} - ch_readraw({handle} [, {options}]) - String read raw from {handle} - ch_sendexpr({handle}, {expr} [, {options}]) - any send {expr} over JSON {handle} -! ch_sendraw({handle}, {expr} [, {options}]) -! any send {expr} over raw {handle} - ch_setoptions({handle}, {options}) - none set options for {handle} - ch_status({handle} [, {options}]) -*************** -*** 2225,2232 **** - hostname() String name of the machine Vim is running on - iconv({expr}, {from}, {to}) String convert encoding of {expr} - indent({lnum}) Number indent of line {lnum} -! index({list}, {expr} [, {start} [, {ic}]]) -! Number index in {list} where {expr} appears - input({prompt} [, {text} [, {completion}]]) - String get input from the user - inputdialog({prompt} [, {text} [, {completion}]]) ---- 2262,2269 ---- - hostname() String name of the machine Vim is running on - iconv({expr}, {from}, {to}) String convert encoding of {expr} - indent({lnum}) Number indent of line {lnum} -! index({object}, {expr} [, {start} [, {ic}]]) -! Number index in {object} where {expr} appears - input({prompt} [, {text} [, {completion}]]) - String get input from the user - inputdialog({prompt} [, {text} [, {completion}]]) -*************** -*** 2235,2241 **** - inputrestore() Number restore typeahead - inputsave() Number save and clear typeahead - inputsecret({prompt} [, {text}]) String like input() but hiding the text -! insert({list}, {item} [, {idx}]) List insert {item} in {list} [before {idx}] - invert({expr}) Number bitwise invert - isdirectory({directory}) Number |TRUE| if {directory} is a directory - islocked({expr}) Number |TRUE| if {expr} is locked ---- 2272,2278 ---- - inputrestore() Number restore typeahead - inputsave() Number save and clear typeahead - inputsecret({prompt} [, {text}]) String like input() but hiding the text -! insert({object}, {item} [, {idx}]) List insert {item} in {object} [before {idx}] - invert({expr}) Number bitwise invert - isdirectory({directory}) Number |TRUE| if {directory} is a directory - islocked({expr}) Number |TRUE| if {expr} is locked -*************** -*** 2325,2331 **** - pyxeval({expr}) any evaluate |python_x| expression - range({expr} [, {max} [, {stride}]]) - List items from {expr} to {max} -! readfile({fname} [, {binary} [, {max}]]) - List get list of lines from file {fname} - reg_executing() String get the executing register name - reg_recording() String get the recording register name ---- 2362,2368 ---- - pyxeval({expr}) any evaluate |python_x| expression - range({expr} [, {max} [, {stride}]]) - List items from {expr} to {max} -! readfile({fname} [, {type} [, {max}]]) - List get list of lines from file {fname} - reg_executing() String get the executing register name - reg_recording() String get the recording register name -*************** -*** 2541,2548 **** - winsaveview() Dict save view of current window - winwidth({nr}) Number width of window {nr} - wordcount() Dict get byte/char/word statistics -! writefile({list}, {fname} [, {flags}]) -! Number write list of lines to file {fname} - xor({expr}, {expr}) Number bitwise XOR - - ---- 2577,2584 ---- - winsaveview() Dict save view of current window - winwidth({nr}) Number width of window {nr} - wordcount() Dict get byte/char/word statistics -! writefile({object}, {fname} [, {flags}]) -! Number write |Blob| or |List| of lines to file - xor({expr}, {expr}) Number bitwise XOR - - -*************** -*** 3185,3190 **** ---- 3222,3232 ---- - See |channel-more|. - {only available when compiled with the |+channel| feature} - -+ ch_readblob({handle} [, {options}]) *ch_readblob()* -+ Like ch_read() but reads binary data and returns a Blob. -+ See |channel-more|. -+ {only available when compiled with the |+channel| feature} -+ - ch_readraw({handle} [, {options}]) *ch_readraw()* - Like ch_read() but for a JS and JSON channel does not decode - the message. For a NL channel it does not block waiting for -*************** -*** 3201,3208 **** - - {only available when compiled with the |+channel| feature} - -! ch_sendraw({handle}, {string} [, {options}]) *ch_sendraw()* -! Send {string} over {handle}. - Works like |ch_sendexpr()|, but does not encode the request or - decode the response. The caller is responsible for the - correct contents. Also does not add a newline for a channel ---- 3243,3250 ---- - - {only available when compiled with the |+channel| feature} - -! ch_sendraw({handle}, {expr} [, {options}]) *ch_sendraw()* -! Send string or Blob {expr} over {handle}. - Works like |ch_sendexpr()|, but does not encode the request or - decode the response. The caller is responsible for the - correct contents. Also does not add a newline for a channel -*************** -*** 5355,5371 **** - When {lnum} is invalid -1 is returned. - - -! index({list}, {expr} [, {start} [, {ic}]]) *index()* -! Return the lowest index in |List| {list} where the item has a -! value equal to {expr}. There is no automatic conversion, so -! the String "4" is different from the Number 4. And the number -! 4 is different from the Float 4.0. The value of 'ignorecase' -! is not used here, case always matters. - If {start} is given then start looking at the item with index - {start} (may be negative for an item relative to the end). - When {ic} is given and it is |TRUE|, ignore case. Otherwise - case must match. -! -1 is returned when {expr} is not found in {list}. - Example: > - :let idx = index(words, "the") - :if index(numbers, 123) >= 0 ---- 5403,5423 ---- - When {lnum} is invalid -1 is returned. - - -! index({object}, {expr} [, {start} [, {ic}]]) *index()* -! If {object} is a |List| return the lowest index where the item -! has a value equal to {expr}. There is no automatic -! conversion, so the String "4" is different from the Number 4. -! And the number 4 is different from the Float 4.0. The value -! of 'ignorecase' is not used here, case always matters. -! -! If {object} is |Blob| return the lowest index where the byte -! value is equal to {expr}. -! - If {start} is given then start looking at the item with index - {start} (may be negative for an item relative to the end). - When {ic} is given and it is |TRUE|, ignore case. Otherwise - case must match. -! -1 is returned when {expr} is not found in {object}. - Example: > - :let idx = index(words, "the") - :if index(numbers, 123) >= 0 -*************** -*** 5471,5483 **** - typed on the command-line in response to the issued prompt. - NOTE: Command-line completion is not supported. - -! insert({list}, {item} [, {idx}]) *insert()* -! Insert {item} at the start of |List| {list}. - If {idx} is specified insert {item} before the item with index - {idx}. If {idx} is zero it goes before the first item, just - like omitting {idx}. A negative {idx} is also possible, see - |list-index|. -1 inserts just before the last item. -! Returns the resulting |List|. Examples: > - :let mylist = insert([2, 3, 5], 1) - :call insert(mylist, 4, -1) - :call insert(mylist, 6, len(mylist)) ---- 5523,5538 ---- - typed on the command-line in response to the issued prompt. - NOTE: Command-line completion is not supported. - -! insert({object}, {item} [, {idx}]) *insert()* -! When {object} is a |List| or a |Blob| insert {item} at the start -! of it. -! - If {idx} is specified insert {item} before the item with index - {idx}. If {idx} is zero it goes before the first item, just - like omitting {idx}. A negative {idx} is also possible, see - |list-index|. -1 inserts just before the last item. -! -! Returns the resulting |List| or |Blob|. Examples: > - :let mylist = insert([2, 3, 5], 1) - :call insert(mylist, 4, -1) - :call insert(mylist, 6, len(mylist)) -*************** -*** 5743,5748 **** ---- 5798,5804 ---- - used recursively: [] - Dict as an object (possibly null); when - used recursively: {} -+ Blob as an array of the individual bytes - v:false "false" - v:true "true" - v:none "null" -*************** -*** 6923,6938 **** - range(2, 0) " error! - < - *readfile()* -! readfile({fname} [, {binary} [, {max}]]) - Read file {fname} and return a |List|, each line of the file - as an item. Lines are broken at NL characters. Macintosh - files separated with CR will result in a single long line - (unless a NL appears somewhere). - All NUL characters are replaced with a NL character. -! When {binary} contains "b" binary mode is used: - - When the last line ends in a NL an extra empty list item is - added. - - No CR characters are removed. - Otherwise: - - CR characters that appear before a NL are removed. - - Whether the last line ends in a NL or not does not matter. ---- 6983,7000 ---- - range(2, 0) " error! - < - *readfile()* -! readfile({fname} [, {type} [, {max}]]) - Read file {fname} and return a |List|, each line of the file - as an item. Lines are broken at NL characters. Macintosh - files separated with CR will result in a single long line - (unless a NL appears somewhere). - All NUL characters are replaced with a NL character. -! When {type} contains "b" binary mode is used: - - When the last line ends in a NL an extra empty list item is - added. - - No CR characters are removed. -+ When {type} contains "B" a |Blob| is returned with the binary -+ data of the file unmodified. - Otherwise: - - CR characters that appear before a NL are removed. - - Whether the last line ends in a NL or not does not matter. -*************** -*** 7108,7113 **** ---- 7170,7185 ---- - Example: > - :echo "last item: " . remove(mylist, -1) - :call remove(mylist, 0, 9) -+ remove({blob}, {idx} [, {end}]) -+ Without {end}: Remove the byte at {idx} from |Blob| {blob} and -+ return the byte. -+ With {end}: Remove bytes from {idx} to {end} (inclusive) and -+ return a |Blob| with these bytes. When {idx} points to the same -+ byte as {end} a |Blob| with one byte is returned. When {end} -+ points to a byte before {idx} this is an error. -+ Example: > -+ :echo "last byte: " . remove(myblob, -1) -+ :call remove(mylist, 0, 9) - remove({dict}, {key}) - Remove the entry from {dict} with key {key}. Example: > - :echo "removed " . remove(dict, "one") -*************** -*** 7148,7156 **** - path name) and also keeps a trailing path separator. - - *reverse()* -! reverse({list}) Reverse the order of items in {list} in-place. Returns -! {list}. -! If you want a list to remain unmodified make a copy first: > - :let revlist = reverse(copy(mylist)) - - round({expr}) *round()* ---- 7220,7230 ---- - path name) and also keeps a trailing path separator. - - *reverse()* -! reverse({object}) -! Reverse the order of items in {object} in-place. -! {object} can be a |List| or a |Blob|. -! Returns {object}. -! If you want an object to remain unmodified make a copy first: > - :let revlist = reverse(copy(mylist)) - - round({expr}) *round()* -*************** -*** 9490,9495 **** ---- 9568,9574 ---- - None 7 |v:t_none| (v:null and v:none) - Job 8 |v:t_job| - Channel 9 |v:t_channel| -+ Blob 10 |v:t_blob| - For backward compatibility, this method can be used: > - :if type(myvar) == type(0) - :if type(myvar) == type("") -*************** -*** 9837,9850 **** - - - *writefile()* -! writefile({list}, {fname} [, {flags}]) -! Write |List| {list} to file {fname}. Each list item is -! separated with a NL. Each list item must be a String or -! Number. - When {flags} contains "b" then binary mode is used: There will - not be a NL after the last list item. An empty item at the - end does cause the last line in the file to end in a NL. - - When {flags} contains "a" then append mode is used, lines are - appended to the file: > - :call writefile(["foo"], "event.log", "a") ---- 9916,9932 ---- - - - *writefile()* -! writefile({object}, {fname} [, {flags}]) -! When {object} is a |List| write it to file {fname}. Each list -! item is separated with a NL. Each list item must be a String -! or Number. - When {flags} contains "b" then binary mode is used: There will - not be a NL after the last list item. An empty item at the - end does cause the last line in the file to end in a NL. - -+ When {object} is a |Blob| write the bytes to file {fname} -+ unmodified. -+ - When {flags} contains "a" then append mode is used, lines are - appended to the file: > - :call writefile(["foo"], "event.log", "a") -*************** -*** 10546,10552 **** - This cannot be used to set a byte in a String. You - can do that like this: > - :let var = var[0:2] . 'X' . var[4:] -! < - *E711* *E719* - :let {var-name}[{idx1}:{idx2}] = {expr1} *E708* *E709* *E710* - Set a sequence of items in a |List| to the result of ---- 10629,10638 ---- - This cannot be used to set a byte in a String. You - can do that like this: > - :let var = var[0:2] . 'X' . var[4:] -! < When {var-name} is a |Blob| then {idx} can be the -! length of the blob, in which case one byte is -! appended. -! - *E711* *E719* - :let {var-name}[{idx1}:{idx2}] = {expr1} *E708* *E709* *E710* - Set a sequence of items in a |List| to the result of -*** ../vim-8.1.0734/runtime/doc/if_perl.txt 2018-05-17 13:41:41.000000000 +0200 ---- runtime/doc/if_perl.txt 2019-01-12 18:52:14.238595885 +0100 -*************** -*** 190,195 **** ---- 191,199 ---- - A |List| is turned into a string by joining the items - and inserting line breaks. - -+ *perl-Blob* -+ VIM::Blob({expr}) Return Blob literal string 0zXXXX from scalar value. -+ - *perl-SetHeight* - Window->SetHeight({height}) - Sets the Window height to {height}, within screen -*** ../vim-8.1.0734/runtime/doc/if_ruby.txt 2018-07-28 17:29:15.757096343 +0200 ---- runtime/doc/if_ruby.txt 2019-01-12 18:52:14.238595885 +0100 -*************** -*** 110,115 **** ---- 110,119 ---- - Vim::message({msg}) - Displays the message {msg}. - -+ *ruby-blob* -+ Vim::blob({arg}) -+ Return Blob literal string from {arg}. -+ - *ruby-set_option* - Vim::set_option({arg}) - Sets a vim option. {arg} can be any argument that the ":set" command -*** ../vim-8.1.0734/src/Make_cyg_ming.mak 2019-01-12 16:10:47.415360504 +0100 ---- src/Make_cyg_ming.mak 2019-01-12 18:52:14.238595885 +0100 -*************** -*** 696,701 **** ---- 696,702 ---- - OBJ = \ - $(OUTDIR)/arabic.o \ - $(OUTDIR)/beval.o \ -+ $(OUTDIR)/blob.o \ - $(OUTDIR)/blowfish.o \ - $(OUTDIR)/buffer.o \ - $(OUTDIR)/charset.o \ -*** ../vim-8.1.0734/src/Make_mvc.mak 2019-01-12 16:10:47.415360504 +0100 ---- src/Make_mvc.mak 2019-01-12 18:52:14.238595885 +0100 -*************** -*** 701,706 **** ---- 701,707 ---- - OBJ = \ - $(OUTDIR)\arabic.obj \ - $(OUTDIR)\beval.obj \ -+ $(OUTDIR)\blob.obj \ - $(OUTDIR)\blowfish.obj \ - $(OUTDIR)\buffer.obj \ - $(OUTDIR)\charset.obj \ -*************** -*** 1346,1351 **** ---- 1347,1354 ---- - - $(OUTDIR)/beval.obj: $(OUTDIR) beval.c $(INCL) - -+ $(OUTDIR)/blob.obj: $(OUTDIR) blob.c $(INCL) -+ - $(OUTDIR)/blowfish.obj: $(OUTDIR) blowfish.c $(INCL) - - $(OUTDIR)/buffer.obj: $(OUTDIR) buffer.c $(INCL) -*************** -*** 1616,1621 **** ---- 1619,1625 ---- - # End Custom Build - proto.h: \ - proto/arabic.pro \ -+ proto/blob.pro \ - proto/blowfish.pro \ - proto/buffer.pro \ - proto/charset.pro \ -*** ../vim-8.1.0734/src/Makefile 2019-01-12 16:10:47.415360504 +0100 ---- src/Makefile 2019-01-12 18:52:14.238595885 +0100 -*************** -*** 1577,1582 **** ---- 1579,1585 ---- - BASIC_SRC = \ - arabic.c \ - beval.c \ -+ blob.c \ - blowfish.c \ - buffer.c \ - charset.c \ -*************** -*** 1693,1698 **** ---- 1696,1702 ---- - objects/arabic.o \ - objects/beval.o \ - objects/buffer.o \ -+ objects/blob.o \ - objects/blowfish.o \ - objects/crypt.o \ - objects/crypt_zip.o \ -*************** -*** 2943,2948 **** ---- 2947,2955 ---- - objects/arabic.o: arabic.c - $(CCC) -o $@ arabic.c - -+ objects/blob.o: blob.c -+ $(CCC) -o $@ blob.c -+ - objects/blowfish.o: blowfish.c - $(CCC) -o $@ blowfish.c - -*************** -*** 3395,3400 **** ---- 3402,3411 ---- - auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ - proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ - proto.h globals.h farsi.h arabic.h -+ objects/blob.o: blob.c vim.h protodef.h auto/config.h feature.h os_unix.h \ -+ auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ -+ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ -+ proto.h globals.h farsi.h arabic.h - objects/blowfish.o: blowfish.c vim.h protodef.h auto/config.h feature.h os_unix.h \ - auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ - proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ -*** ../vim-8.1.0734/src/blob.c 2019-01-12 22:40:58.041219177 +0100 ---- src/blob.c 2019-01-12 20:30:51.295186522 +0100 -*************** -*** 0 **** ---- 1,167 ---- -+ /* vi:set ts=8 sts=4 sw=4 noet: -+ * -+ * VIM - Vi IMproved by Bram Moolenaar -+ * -+ * Do ":help uganda" in Vim to read copying and usage conditions. -+ * Do ":help credits" in Vim to see a list of people who contributed. -+ * See README.txt for an overview of the Vim source code. -+ */ -+ -+ /* -+ * blob.c: Blob support by Yasuhiro Matsumoto -+ */ -+ -+ #include "vim.h" -+ -+ #if defined(FEAT_EVAL) || defined(PROTO) -+ -+ /* -+ * Allocate an empty blob. -+ * Caller should take care of the reference count. -+ */ -+ blob_T * -+ blob_alloc(void) -+ { -+ blob_T *blob = (blob_T *)alloc_clear(sizeof(blob_T)); -+ -+ if (blob != NULL) -+ ga_init2(&blob->bv_ga, 1, 100); -+ return blob; -+ } -+ -+ /* -+ * Allocate an empty blob for a return value, with reference count set. -+ * Returns OK or FAIL. -+ */ -+ int -+ rettv_blob_alloc(typval_T *rettv) -+ { -+ blob_T *b = blob_alloc(); -+ -+ if (b == NULL) -+ return FAIL; -+ -+ rettv_blob_set(rettv, b); -+ return OK; -+ } -+ -+ /* -+ * Set a blob as the return value. -+ */ -+ void -+ rettv_blob_set(typval_T *rettv, blob_T *b) -+ { -+ rettv->v_type = VAR_BLOB; -+ rettv->vval.v_blob = b; -+ if (b != NULL) -+ ++b->bv_refcount; -+ } -+ -+ void -+ blob_free(blob_T *b) -+ { -+ ga_clear(&b->bv_ga); -+ vim_free(b); -+ } -+ -+ /* -+ * Unreference a blob: decrement the reference count and free it when it -+ * becomes zero. -+ */ -+ void -+ blob_unref(blob_T *b) -+ { -+ if (b != NULL && --b->bv_refcount <= 0) -+ blob_free(b); -+ } -+ -+ /* -+ * Get the length of data. -+ */ -+ long -+ blob_len(blob_T *b) -+ { -+ if (b == NULL) -+ return 0L; -+ return b->bv_ga.ga_len; -+ } -+ -+ /* -+ * Get byte "idx" in blob "b". -+ * Caller must check that "idx" is valid. -+ */ -+ char_u -+ blob_get(blob_T *b, int idx) -+ { -+ return ((char_u*)b->bv_ga.ga_data)[idx]; -+ } -+ -+ /* -+ * Store one byte "c" in blob "b" at "idx". -+ * Caller must make sure that "idx" is valid. -+ */ -+ void -+ blob_set(blob_T *b, int idx, char_u c) -+ { -+ ((char_u*)b->bv_ga.ga_data)[idx] = c; -+ } -+ -+ /* -+ * Return TRUE when two blobs have exactly the same values. -+ */ -+ int -+ blob_equal( -+ blob_T *b1, -+ blob_T *b2) -+ { -+ int i; -+ -+ if (b1 == NULL || b2 == NULL) -+ return FALSE; -+ if (b1 == b2) -+ return TRUE; -+ if (blob_len(b1) != blob_len(b2)) -+ return FALSE; -+ -+ for (i = 0; i < b1->bv_ga.ga_len; i++) -+ if (blob_get(b1, i) != blob_get(b2, i)) return FALSE; -+ return TRUE; -+ } -+ -+ /* -+ * Read "blob" from file "fd". -+ * Return OK or FAIL. -+ */ -+ int -+ read_blob(FILE *fd, blob_T *blob) -+ { -+ struct stat st; -+ -+ if (fstat(fileno(fd), &st) < 0) -+ return FAIL; -+ if (ga_grow(&blob->bv_ga, st.st_size) == FAIL) -+ return FAIL; -+ blob->bv_ga.ga_len = st.st_size; -+ if (fread(blob->bv_ga.ga_data, 1, blob->bv_ga.ga_len, fd) -+ < (size_t)blob->bv_ga.ga_len) -+ return FAIL; -+ return OK; -+ } -+ -+ /* -+ * Write "blob" to file "fd". -+ * Return OK or FAIL. -+ */ -+ int -+ write_blob(FILE *fd, blob_T *blob) -+ { -+ if (fwrite(blob->bv_ga.ga_data, 1, blob->bv_ga.ga_len, fd) -+ < (size_t)blob->bv_ga.ga_len) -+ { -+ EMSG(_(e_write)); -+ return FAIL; -+ } -+ return OK; -+ } -+ -+ #endif /* defined(FEAT_EVAL) */ -*** ../vim-8.1.0734/src/channel.c 2019-01-05 00:02:52.045705776 +0100 ---- src/channel.c 2019-01-12 20:58:35.124077325 +0100 -*************** -*** 1665,1671 **** - * Returns NULL if there is nothing. - */ - char_u * -! channel_get(channel_T *channel, ch_part_T part) - { - readq_T *head = &channel->ch_part[part].ch_head; - readq_T *node = head->rq_next; ---- 1665,1671 ---- - * Returns NULL if there is nothing. - */ - char_u * -! channel_get(channel_T *channel, ch_part_T part, int *outlen) - { - readq_T *head = &channel->ch_part[part].ch_head; - readq_T *node = head->rq_next; -*************** -*** 1673,1678 **** ---- 1673,1680 ---- - - if (node == NULL) - return NULL; -+ if (outlen != NULL) -+ *outlen += node->rq_buflen; - /* dispose of the node but keep the buffer */ - p = node->rq_buffer; - head->rq_next = node->rq_next; -*************** -*** 1689,1695 **** - * Replaces NUL bytes with NL. - */ - static char_u * -! channel_get_all(channel_T *channel, ch_part_T part) - { - readq_T *head = &channel->ch_part[part].ch_head; - readq_T *node = head->rq_next; ---- 1691,1697 ---- - * Replaces NUL bytes with NL. - */ - static char_u * -! channel_get_all(channel_T *channel, ch_part_T part, int *outlen) - { - readq_T *head = &channel->ch_part[part].ch_head; - readq_T *node = head->rq_next; -*************** -*** 1699,1705 **** - - /* If there is only one buffer just get that one. */ - if (head->rq_next == NULL || head->rq_next->rq_next == NULL) -! return channel_get(channel, part); - - /* Concatenate everything into one buffer. */ - for (node = head->rq_next; node != NULL; node = node->rq_next) ---- 1701,1707 ---- - - /* If there is only one buffer just get that one. */ - if (head->rq_next == NULL || head->rq_next->rq_next == NULL) -! return channel_get(channel, part, outlen); - - /* Concatenate everything into one buffer. */ - for (node = head->rq_next; node != NULL; node = node->rq_next) -*************** -*** 1718,1727 **** - /* Free all buffers */ - do - { -! p = channel_get(channel, part); - vim_free(p); - } while (p != NULL); - - /* turn all NUL into NL */ - while (len > 0) - { ---- 1720,1735 ---- - /* Free all buffers */ - do - { -! p = channel_get(channel, part, NULL); - vim_free(p); - } while (p != NULL); - -+ if (outlen != NULL) -+ { -+ *outlen += len; -+ return res; -+ } -+ - /* turn all NUL into NL */ - while (len > 0) - { -*************** -*** 1893,1899 **** - { - channel_T *channel = (channel_T *)reader->js_cookie; - ch_part_T part = reader->js_cookie_arg; -! char_u *next = channel_get(channel, part); - int keeplen; - int addlen; - char_u *p; ---- 1901,1907 ---- - { - channel_T *channel = (channel_T *)reader->js_cookie; - ch_part_T part = reader->js_cookie_arg; -! char_u *next = channel_get(channel, part, NULL); - int keeplen; - int addlen; - char_u *p; -*************** -*** 1942,1948 **** - if (channel_peek(channel, part) == NULL) - return FALSE; - -! reader.js_buf = channel_get(channel, part); - reader.js_used = 0; - reader.js_fill = channel_fill; - reader.js_cookie = channel; ---- 1950,1956 ---- - if (channel_peek(channel, part) == NULL) - return FALSE; - -! reader.js_buf = channel_get(channel, part, NULL); - reader.js_used = 0; - reader.js_fill = channel_fill; - reader.js_cookie = channel; -*************** -*** 2475,2481 **** - { - char_u *msg; - -! while ((msg = channel_get(channel, part)) != NULL) - { - ch_log(channel, "Dropping message '%s'", (char *)msg); - vim_free(msg); ---- 2483,2489 ---- - { - char_u *msg; - -! while ((msg = channel_get(channel, part, NULL)) != NULL) - { - ch_log(channel, "Dropping message '%s'", (char *)msg); - vim_free(msg); -*************** -*** 2639,2645 **** - if (nl + 1 == buf + node->rq_buflen) - { - /* get the whole buffer, drop the NL */ -! msg = channel_get(channel, part); - *nl = NUL; - } - else ---- 2647,2653 ---- - if (nl + 1 == buf + node->rq_buflen) - { - /* get the whole buffer, drop the NL */ -! msg = channel_get(channel, part, NULL); - *nl = NUL; - } - else -*************** -*** 2655,2661 **** - /* For a raw channel we don't know where the message ends, just - * get everything we have. - * Convert NUL to NL, the internal representation. */ -! msg = channel_get_all(channel, part); - } - - if (msg == NULL) ---- 2663,2669 ---- - /* For a raw channel we don't know where the message ends, just - * get everything we have. - * Convert NUL to NL, the internal representation. */ -! msg = channel_get_all(channel, part, NULL); - } - - if (msg == NULL) -*************** -*** 3007,3013 **** - cbq_T *cb_head = &ch_part->ch_cb_head; - - while (channel_peek(channel, part) != NULL) -! vim_free(channel_get(channel, part)); - - while (cb_head->cq_next != NULL) - { ---- 3015,3021 ---- - cbq_T *cb_head = &ch_part->ch_cb_head; - - while (channel_peek(channel, part) != NULL) -! vim_free(channel_get(channel, part, NULL)); - - while (cb_head->cq_next != NULL) - { -*************** -*** 3381,3387 **** - * Returns NULL in case of error or timeout. - */ - static char_u * -! channel_read_block(channel_T *channel, ch_part_T part, int timeout, int raw) - { - char_u *buf; - char_u *msg; ---- 3389,3396 ---- - * Returns NULL in case of error or timeout. - */ - static char_u * -! channel_read_block( -! channel_T *channel, ch_part_T part, int timeout, int raw, int *outlen) - { - char_u *buf; - char_u *msg; -*************** -*** 3422,3430 **** - } - - /* We have a complete message now. */ -! if (mode == MODE_RAW) - { -! msg = channel_get_all(channel, part); - } - else - { ---- 3431,3439 ---- - } - - /* We have a complete message now. */ -! if (mode == MODE_RAW || outlen != NULL) - { -! msg = channel_get_all(channel, part, outlen); - } - else - { -*************** -*** 3441,3452 **** - if (nl == NULL) - { - /* must be a closed channel with missing NL */ -! msg = channel_get(channel, part); - } - else if (nl + 1 == buf + node->rq_buflen) - { - /* get the whole buffer */ -! msg = channel_get(channel, part); - *nl = NUL; - } - else ---- 3450,3461 ---- - if (nl == NULL) - { - /* must be a closed channel with missing NL */ -! msg = channel_get(channel, part, NULL); - } - else if (nl + 1 == buf + node->rq_buflen) - { - /* get the whole buffer */ -! msg = channel_get(channel, part, NULL); - *nl = NUL; - } - else -*************** -*** 3554,3560 **** - * Common for ch_read() and ch_readraw(). - */ - void -! common_channel_read(typval_T *argvars, typval_T *rettv, int raw) - { - channel_T *channel; - ch_part_T part = PART_COUNT; ---- 3563,3569 ---- - * Common for ch_read() and ch_readraw(). - */ - void -! common_channel_read(typval_T *argvars, typval_T *rettv, int raw, int blob) - { - channel_T *channel; - ch_part_T part = PART_COUNT; -*************** -*** 3585,3593 **** - if (opt.jo_set & JO_TIMEOUT) - timeout = opt.jo_timeout; - -! if (raw || mode == MODE_RAW || mode == MODE_NL) - rettv->vval.v_string = channel_read_block(channel, part, -! timeout, raw); - else - { - if (opt.jo_set & JO_ID) ---- 3594,3625 ---- - if (opt.jo_set & JO_TIMEOUT) - timeout = opt.jo_timeout; - -! if (blob) -! { -! int outlen = 0; -! char_u *p = channel_read_block(channel, part, -! timeout, TRUE, &outlen); -! if (p != NULL) -! { -! blob_T *b = blob_alloc(); -! -! if (b != NULL) -! { -! b->bv_ga.ga_len = outlen; -! if (ga_grow(&b->bv_ga, outlen) == FAIL) -! blob_free(b); -! else -! { -! memcpy(b->bv_ga.ga_data, p, outlen); -! rettv_blob_set(rettv, b); -! } -! } -! vim_free(p); -! } -! } -! else if (raw || mode == MODE_RAW || mode == MODE_NL) - rettv->vval.v_string = channel_read_block(channel, part, -! timeout, raw, NULL); - else - { - if (opt.jo_set & JO_ID) -*************** -*** 3905,3910 **** ---- 3937,3943 ---- - send_common( - typval_T *argvars, - char_u *text, -+ int len, - int id, - int eval, - jobopt_T *opt, -*************** -*** 3938,3944 **** - opt->jo_callback, opt->jo_partial, id); - } - -! if (channel_send(channel, part_send, text, (int)STRLEN(text), fun) == OK - && opt->jo_callback == NULL) - return channel; - return NULL; ---- 3971,3977 ---- - opt->jo_callback, opt->jo_partial, id); - } - -! if (channel_send(channel, part_send, text, len, fun) == OK - && opt->jo_callback == NULL) - return channel; - return NULL; -*************** -*** 3982,3988 **** - if (text == NULL) - return; - -! channel = send_common(argvars, text, id, eval, &opt, - eval ? "ch_evalexpr" : "ch_sendexpr", &part_read); - vim_free(text); - if (channel != NULL && eval) ---- 4015,4021 ---- - if (text == NULL) - return; - -! channel = send_common(argvars, text, (int)STRLEN(text), id, eval, &opt, - eval ? "ch_evalexpr" : "ch_sendexpr", &part_read); - vim_free(text); - if (channel != NULL && eval) -*************** -*** 4014,4019 **** ---- 4047,4053 ---- - { - char_u buf[NUMBUFLEN]; - char_u *text; -+ int len; - channel_T *channel; - ch_part_T part_read; - jobopt_T opt; -*************** -*** 4023,4030 **** - rettv->v_type = VAR_STRING; - rettv->vval.v_string = NULL; - -! text = tv_get_string_buf(&argvars[1], buf); -! channel = send_common(argvars, text, 0, eval, &opt, - eval ? "ch_evalraw" : "ch_sendraw", &part_read); - if (channel != NULL && eval) - { ---- 4057,4073 ---- - rettv->v_type = VAR_STRING; - rettv->vval.v_string = NULL; - -! if (argvars[1].v_type == VAR_BLOB) -! { -! text = argvars[1].vval.v_blob->bv_ga.ga_data; -! len = argvars[1].vval.v_blob->bv_ga.ga_len; -! } -! else -! { -! text = tv_get_string_buf(&argvars[1], buf); -! len = STRLEN(text); -! } -! channel = send_common(argvars, text, len, 0, eval, &opt, - eval ? "ch_evalraw" : "ch_sendraw", &part_read); - if (channel != NULL && eval) - { -*************** -*** 4033,4039 **** - else - timeout = channel_get_timeout(channel, part_read); - rettv->vval.v_string = channel_read_block(channel, part_read, -! timeout, TRUE); - } - free_job_options(&opt); - } ---- 4076,4082 ---- - else - timeout = channel_get_timeout(channel, part_read); - rettv->vval.v_string = channel_read_block(channel, part_read, -! timeout, TRUE, NULL); - } - free_job_options(&opt); - } -*** ../vim-8.1.0734/src/eval.c 2018-12-22 13:27:59.115503998 +0100 ---- src/eval.c 2019-01-12 22:02:53.262933357 +0100 -*************** -*** 78,83 **** ---- 78,85 ---- - int fi_varcount; /* nr of variables in the list */ - listwatch_T fi_lw; /* keep an eye on the item used. */ - list_T *fi_list; /* list being used */ -+ int fi_bi; /* index of blob */ -+ blob_T *fi_blob; /* blob being used */ - } forinfo_T; - - -*************** -*** 187,192 **** ---- 189,195 ---- - {VV_NAME("t_none", VAR_NUMBER), VV_RO}, - {VV_NAME("t_job", VAR_NUMBER), VV_RO}, - {VV_NAME("t_channel", VAR_NUMBER), VV_RO}, -+ {VV_NAME("t_blob", VAR_NUMBER), VV_RO}, - {VV_NAME("termrfgresp", VAR_STRING), VV_RO}, - {VV_NAME("termrbgresp", VAR_STRING), VV_RO}, - {VV_NAME("termu7resp", VAR_STRING), VV_RO}, -*************** -*** 202,207 **** ---- 205,211 ---- - #define vv_str vv_di.di_tv.vval.v_string - #define vv_list vv_di.di_tv.vval.v_list - #define vv_dict vv_di.di_tv.vval.v_dict -+ #define vv_blob vv_di.di_tv.vval.v_blob - #define vv_tv vv_di.di_tv - - static dictitem_T vimvars_var; /* variable used for v: */ -*************** -*** 338,343 **** ---- 342,348 ---- - set_vim_var_nr(VV_TYPE_NONE, VAR_TYPE_NONE); - set_vim_var_nr(VV_TYPE_JOB, VAR_TYPE_JOB); - set_vim_var_nr(VV_TYPE_CHANNEL, VAR_TYPE_CHANNEL); -+ set_vim_var_nr(VV_TYPE_BLOB, VAR_TYPE_BLOB); - - set_reg_var(0); /* default for v:register is not 0 but '"' */ - -*************** -*** 1918,1927 **** - { - if (!(lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list != NULL) - && !(lp->ll_tv->v_type == VAR_DICT -! && lp->ll_tv->vval.v_dict != NULL)) - { - if (!quiet) -! EMSG(_("E689: Can only index a List or Dictionary")); - return NULL; - } - if (lp->ll_range) ---- 1923,1934 ---- - { - if (!(lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list != NULL) - && !(lp->ll_tv->v_type == VAR_DICT -! && lp->ll_tv->vval.v_dict != NULL) -! && !(lp->ll_tv->v_type == VAR_BLOB -! && lp->ll_tv->vval.v_blob != NULL)) - { - if (!quiet) -! EMSG(_("E689: Can only index a List, Dictionary or Blob")); - return NULL; - } - if (lp->ll_range) -*************** -*** 1974,1984 **** - clear_tv(&var1); - return NULL; - } -! if (rettv != NULL && (rettv->v_type != VAR_LIST -! || rettv->vval.v_list == NULL)) - { - if (!quiet) -! EMSG(_("E709: [:] requires a List value")); - clear_tv(&var1); - return NULL; - } ---- 1981,1994 ---- - clear_tv(&var1); - return NULL; - } -! if (rettv != NULL -! && !(rettv->v_type == VAR_LIST -! || rettv->vval.v_list != NULL) -! && !(rettv->v_type == VAR_BLOB -! || rettv->vval.v_blob != NULL)) - { - if (!quiet) -! EMSG(_("E709: [:] requires a List or Blob value")); - clear_tv(&var1); - return NULL; - } -*************** -*** 2097,2102 **** ---- 2107,2139 ---- - clear_tv(&var1); - lp->ll_tv = &lp->ll_di->di_tv; - } -+ else if (lp->ll_tv->v_type == VAR_BLOB) -+ { -+ /* -+ * Get the number and item for the only or first index of the List. -+ */ -+ if (empty1) -+ lp->ll_n1 = 0; -+ else -+ // is number or string -+ lp->ll_n1 = (long)tv_get_number(&var1); -+ clear_tv(&var1); -+ -+ if (lp->ll_n1 < 0 -+ || lp->ll_n1 > blob_len(lp->ll_tv->vval.v_blob)) -+ { -+ if (!quiet) -+ EMSGN(_(e_listidx), lp->ll_n1); -+ return NULL; -+ } -+ if (lp->ll_range && !lp->ll_empty2) -+ { -+ lp->ll_n2 = (long)tv_get_number(&var2); -+ clear_tv(&var2); -+ } -+ lp->ll_blob = lp->ll_tv->vval.v_blob; -+ lp->ll_tv = NULL; -+ } - else - { - /* -*************** -*** 2201,2207 **** - { - cc = *endp; - *endp = NUL; -! if (op != NULL && *op != '=') - { - typval_T tv; - ---- 2238,2289 ---- - { - cc = *endp; - *endp = NUL; -! if (lp->ll_blob != NULL) -! { -! int error = FALSE, val; -! if (op != NULL && *op != '=') -! { -! EMSG2(_(e_letwrong), op); -! return; -! } -! -! if (lp->ll_range && rettv->v_type == VAR_BLOB) -! { -! int i; -! -! if (blob_len(rettv->vval.v_blob) != blob_len(lp->ll_blob)) -! { -! EMSG(_("E972: Blob value has more items than target")); -! return; -! } -! -! for (i = lp->ll_n1; i <= lp->ll_n2; i++) -! blob_set(lp->ll_blob, i, -! blob_get(rettv->vval.v_blob, i)); -! } -! else -! { -! val = (int)tv_get_number_chk(rettv, &error); -! if (!error) -! { -! garray_T *gap = &lp->ll_blob->bv_ga; -! -! // Allow for appending a byte. Setting a byte beyond -! // the end is an error otherwise. -! if (lp->ll_n1 < gap->ga_len -! || (lp->ll_n1 == gap->ga_len -! && ga_grow(&lp->ll_blob->bv_ga, 1) == OK)) -! { -! blob_set(lp->ll_blob, lp->ll_n1, val); -! if (lp->ll_n1 == gap->ga_len) -! ++gap->ga_len; -! } -! else -! EMSG(_(e_invrange)); -! } -! } -! } -! else if (op != NULL && *op != '=') - { - typval_T tv; - -*************** -*** 2352,2357 **** ---- 2434,2453 ---- - case VAR_CHANNEL: - break; - -+ case VAR_BLOB: -+ if (*op != '+' || tv2->v_type != VAR_BLOB) -+ break; -+ // BLOB += BLOB -+ if (tv1->vval.v_blob != NULL && tv2->vval.v_blob != NULL) -+ { -+ blob_T *b1 = tv1->vval.v_blob; -+ blob_T *b2 = tv2->vval.v_blob; -+ int i, len = blob_len(b2); -+ for (i = 0; i < len; i++) -+ ga_append(&b1->bv_ga, blob_get(b2, i)); -+ } -+ return OK; -+ - case VAR_LIST: - if (*op != '+' || tv2->v_type != VAR_LIST) - break; -*************** -*** 2451,2456 **** ---- 2547,2553 ---- - char_u *expr; - typval_T tv; - list_T *l; -+ blob_T *b; - - *errp = TRUE; /* default: there is an error */ - -*************** -*** 2476,2499 **** - *errp = FALSE; - if (!skip) - { -! l = tv.vval.v_list; -! if (tv.v_type != VAR_LIST) - { -! EMSG(_(e_listreq)); -! clear_tv(&tv); - } -! else if (l == NULL) - { -! /* a null list is like an empty list: do nothing */ -! clear_tv(&tv); - } - else - { -! /* No need to increment the refcount, it's already set for the -! * list being used in "tv". */ -! fi->fi_list = l; -! list_add_watch(l, &fi->fi_lw); -! fi->fi_lw.lw_item = l->lv_first; - } - } - } ---- 2573,2610 ---- - *errp = FALSE; - if (!skip) - { -! if (tv.v_type == VAR_LIST) - { -! l = tv.vval.v_list; -! if (l == NULL) -! { -! // a null list is like an empty list: do nothing -! clear_tv(&tv); -! } -! else -! { -! // No need to increment the refcount, it's already set for -! // the list being used in "tv". -! fi->fi_list = l; -! list_add_watch(l, &fi->fi_lw); -! fi->fi_lw.lw_item = l->lv_first; -! } - } -! else if (tv.v_type == VAR_BLOB) - { -! b = tv.vval.v_blob; -! if (b == NULL) -! clear_tv(&tv); -! else -! { -! fi->fi_blob = b; -! fi->fi_bi = 0; -! } - } - else - { -! EMSG(_(e_listreq)); -! clear_tv(&tv); - } - } - } -*************** -*** 2516,2521 **** ---- 2627,2646 ---- - int result; - listitem_T *item; - -+ if (fi->fi_blob != NULL) -+ { -+ typval_T tv; -+ -+ if (fi->fi_bi >= blob_len(fi->fi_blob)) -+ return FALSE; -+ tv.v_type = VAR_NUMBER; -+ tv.v_lock = VAR_FIXED; -+ tv.vval.v_number = blob_get(fi->fi_blob, fi->fi_bi); -+ ++fi->fi_bi; -+ return ex_let_vars(arg, &tv, TRUE, -+ fi->fi_semicolon, fi->fi_varcount, NULL) == OK; -+ } -+ - item = fi->fi_lw.lw_item; - if (item == NULL) - result = FALSE; -*************** -*** 2955,2960 **** ---- 3080,3086 ---- - list_T *l; - listitem_T *li; - dict_T *d; -+ blob_T *b; - hashitem_T *hi; - int todo; - -*************** -*** 2986,2991 **** ---- 3112,3126 ---- - case VAR_CHANNEL: - break; - -+ case VAR_BLOB: -+ if ((b = tv->vval.v_blob) != NULL) -+ { -+ if (lock) -+ b->bv_lock |= VAR_LOCKED; -+ else -+ b->bv_lock &= ~VAR_LOCKED; -+ } -+ break; - case VAR_LIST: - if ((l = tv->vval.v_list) != NULL) - { -*************** -*** 3609,3615 **** - if (op != '+' && op != '-' && op != '.') - break; - -! if ((op != '+' || rettv->v_type != VAR_LIST) - #ifdef FEAT_FLOAT - && (op == '.' || rettv->v_type != VAR_FLOAT) - #endif ---- 3744,3751 ---- - if (op != '+' && op != '-' && op != '.') - break; - -! if ((op != '+' || (rettv->v_type != VAR_LIST -! && rettv->v_type != VAR_BLOB)) - #ifdef FEAT_FLOAT - && (op == '.' || rettv->v_type != VAR_FLOAT) - #endif -*************** -*** 3659,3664 **** ---- 3795,3819 ---- - rettv->v_type = VAR_STRING; - rettv->vval.v_string = p; - } -+ else if (op == '+' && rettv->v_type == VAR_BLOB -+ && var2.v_type == VAR_BLOB) -+ { -+ blob_T *b1 = rettv->vval.v_blob; -+ blob_T *b2 = var2.vval.v_blob; -+ blob_T *b = blob_alloc(); -+ int i; -+ -+ if (b != NULL) -+ { -+ for (i = 0; i < blob_len(b1); i++) -+ ga_append(&b->bv_ga, blob_get(b1, i)); -+ for (i = 0; i < blob_len(b2); i++) -+ ga_append(&b->bv_ga, blob_get(b2, i)); -+ -+ clear_tv(rettv); -+ rettv_blob_set(rettv, b); -+ } -+ } - else if (op == '+' && rettv->v_type == VAR_LIST - && var2.v_type == VAR_LIST) - { -*************** -*** 3921,3926 **** ---- 4076,4082 ---- - /* - * Handle sixth level expression: - * number number constant -+ * 0zFFFFFFFF Blob constant - * "string" string constant - * 'string' literal string constant - * &option-name option value -*************** -*** 4027,4033 **** ---- 4183,4220 ---- - } - else - #endif -+ if (**arg == '0' && ((*arg)[1] == 'z' || (*arg)[1] == 'Z')) - { -+ char_u *bp; -+ blob_T *blob; -+ -+ // Blob constant: 0z0123456789abcdef -+ if (evaluate) -+ blob = blob_alloc(); -+ for (bp = *arg + 2; vim_isxdigit(bp[0]); bp += 2) -+ { -+ if (!vim_isxdigit(bp[1])) -+ { -+ EMSG(_("E973: Blob literal should have an even number of hex characters'")); -+ vim_free(blob); -+ ret = FAIL; -+ break; -+ } -+ if (blob != NULL) -+ ga_append(&blob->bv_ga, -+ (hex2nr(*bp) << 4) + hex2nr(*(bp+1))); -+ } -+ if (blob != NULL) -+ { -+ ++blob->bv_refcount; -+ rettv->v_type = VAR_BLOB; -+ rettv->vval.v_blob = blob; -+ } -+ *arg = bp; -+ } -+ else -+ { -+ // decimal, hex or octal number - vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0); - *arg += len; - if (evaluate) -*************** -*** 4263,4268 **** ---- 4450,4456 ---- - { - int empty1 = FALSE, empty2 = FALSE; - typval_T var1, var2; -+ long i; - long n1, n2 = 0; - long len = -1; - int range = FALSE; -*************** -*** 4297,4302 **** ---- 4485,4491 ---- - case VAR_NUMBER: - case VAR_LIST: - case VAR_DICT: -+ case VAR_BLOB: - break; - } - -*************** -*** 4439,4444 **** ---- 4628,4694 ---- - rettv->vval.v_string = s; - break; - -+ case VAR_BLOB: -+ len = blob_len(rettv->vval.v_blob); -+ if (range) -+ { -+ // The resulting variable is a substring. If the indexes -+ // are out of range the result is empty. -+ if (n1 < 0) -+ { -+ n1 = len + n1; -+ if (n1 < 0) -+ n1 = 0; -+ } -+ if (n2 < 0) -+ n2 = len + n2; -+ else if (n2 >= len) -+ n2 = len - 1; -+ if (n1 >= len || n2 < 0 || n1 > n2) -+ { -+ clear_tv(rettv); -+ rettv->v_type = VAR_BLOB; -+ rettv->vval.v_blob = NULL; -+ } -+ else -+ { -+ blob_T *blob = blob_alloc(); -+ -+ if (blob != NULL) -+ { -+ if (ga_grow(&blob->bv_ga, n2 - n1 + 1) == FAIL) -+ { -+ blob_free(blob); -+ return FAIL; -+ } -+ blob->bv_ga.ga_len = n2 - n1 + 1; -+ for (i = n1; i <= n2; i++) -+ blob_set(blob, i - n1, -+ blob_get(rettv->vval.v_blob, i)); -+ -+ clear_tv(rettv); -+ rettv_blob_set(rettv, blob); -+ } -+ } -+ } -+ else -+ { -+ // The resulting variable is a string of a single -+ // character. If the index is too big or negative the -+ // result is empty. -+ if (n1 < len && n1 >= 0) -+ { -+ int v = (int)blob_get(rettv->vval.v_blob, n1); -+ -+ clear_tv(rettv); -+ rettv->v_type = VAR_NUMBER; -+ rettv->vval.v_number = v; -+ } -+ else -+ EMSGN(_(e_blobidx), n1); -+ } -+ break; -+ - case VAR_LIST: - len = list_len(rettv->vval.v_list); - if (n1 < 0) -*************** -*** 4970,4975 **** ---- 5220,5228 ---- - --recursive_cnt; - return r; - -+ case VAR_BLOB: -+ return blob_equal(tv1->vval.v_blob, tv2->vval.v_blob); -+ - case VAR_NUMBER: - return tv1->vval.v_number == tv2->vval.v_number; - -*************** -*** 5602,5607 **** ---- 5855,5890 ---- - break; - } - -+ case VAR_BLOB: -+ if (tv->vval.v_blob == NULL) -+ { -+ *tofree = NULL; -+ r = (char_u *)"[]"; -+ } -+ else -+ { -+ blob_T *b; -+ int i; -+ garray_T ga; -+ -+ // Store bytes in the growarray. -+ ga_init2(&ga, 1, 4000); -+ b = tv->vval.v_blob; -+ ga_append(&ga, '['); -+ for (i = 0; i < blob_len(b); i++) -+ { -+ if (i > 0) -+ ga_concat(&ga, (char_u *)","); -+ vim_snprintf((char *)numbuf, NUMBUFLEN, "0x%02X", -+ (int)blob_get(b, i)); -+ ga_concat(&ga, numbuf); -+ } -+ ga_append(&ga, ']'); -+ *tofree = ga.ga_data; -+ r = *tofree; -+ } -+ break; -+ - case VAR_LIST: - if (tv->vval.v_list == NULL) - { -*************** -*** 6841,6846 **** ---- 7124,7132 ---- - case VAR_PARTIAL: - partial_unref(varp->vval.v_partial); - break; -+ case VAR_BLOB: -+ blob_unref(varp->vval.v_blob); -+ break; - case VAR_LIST: - list_unref(varp->vval.v_list); - break; -*************** -*** 6887,6892 **** ---- 7173,7182 ---- - partial_unref(varp->vval.v_partial); - varp->vval.v_partial = NULL; - break; -+ case VAR_BLOB: -+ blob_unref(varp->vval.v_blob); -+ varp->vval.v_blob = NULL; -+ break; - case VAR_LIST: - list_unref(varp->vval.v_list); - varp->vval.v_list = NULL; -*************** -*** 6990,6995 **** ---- 7280,7288 ---- - EMSG(_("E913: Using a Channel as a Number")); - break; - #endif -+ case VAR_BLOB: -+ EMSG(_("E974: Using a Blob as a Number")); -+ break; - case VAR_UNKNOWN: - internal_error("tv_get_number(UNKNOWN)"); - break; -*************** -*** 7037,7042 **** ---- 7330,7338 ---- - EMSG(_("E914: Using a Channel as a Float")); - break; - # endif -+ case VAR_BLOB: -+ EMSG(_("E975: Using a Blob as a Float")); -+ break; - case VAR_UNKNOWN: - internal_error("tv_get_float(UNKNOWN)"); - break; -*************** -*** 7113,7118 **** ---- 7409,7417 ---- - case VAR_SPECIAL: - STRCPY(buf, get_var_special_name(varp->vval.v_number)); - return buf; -+ case VAR_BLOB: -+ EMSG(_("E976: using Blob as a String")); -+ break; - case VAR_JOB: - #ifdef FEAT_JOB_CHANNEL - { -*************** -*** 7805,7810 **** ---- 8104,8118 ---- - ++to->vval.v_partial->pt_refcount; - } - break; -+ case VAR_BLOB: -+ if (from->vval.v_blob == NULL) -+ to->vval.v_blob = NULL; -+ else -+ { -+ to->vval.v_blob = from->vval.v_blob; -+ ++to->vval.v_blob->bv_refcount; -+ } -+ break; - case VAR_LIST: - if (from->vval.v_list == NULL) - to->vval.v_list = NULL; -*************** -*** 7863,7868 **** ---- 8171,8177 ---- - case VAR_SPECIAL: - case VAR_JOB: - case VAR_CHANNEL: -+ case VAR_BLOB: - copy_tv(from, to); - break; - case VAR_LIST: -*************** -*** 8601,8606 **** ---- 8910,8916 ---- - #endif - case 'D': type = VAR_DICT; break; - case 'L': type = VAR_LIST; break; -+ case 'B': type = VAR_BLOB; break; - case 'X': type = VAR_SPECIAL; break; - } - -*************** -*** 8608,8614 **** - if (tab != NULL) - { - tv.v_type = type; -! if (type == VAR_STRING || type == VAR_DICT || type == VAR_LIST) - tv.vval.v_string = viminfo_readstring(virp, - (int)(tab - virp->vir_line + 1), TRUE); - #ifdef FEAT_FLOAT ---- 8918,8925 ---- - if (tab != NULL) - { - tv.v_type = type; -! if (type == VAR_STRING || type == VAR_DICT || -! type == VAR_LIST || type == VAR_BLOB) - tv.vval.v_string = viminfo_readstring(virp, - (int)(tab - virp->vir_line + 1), TRUE); - #ifdef FEAT_FLOAT -*************** -*** 8617,8623 **** - #endif - else - tv.vval.v_number = atol((char *)tab + 1); -! if (type == VAR_DICT || type == VAR_LIST) - { - typval_T *etv = eval_expr(tv.vval.v_string, NULL); - ---- 8928,8934 ---- - #endif - else - tv.vval.v_number = atol((char *)tab + 1); -! if (type == VAR_DICT || type == VAR_LIST || type == VAR_BLOB) - { - typval_T *etv = eval_expr(tv.vval.v_string, NULL); - -*************** -*** 8640,8646 **** - - if (tv.v_type == VAR_STRING) - vim_free(tv.vval.v_string); -! else if (tv.v_type == VAR_DICT || tv.v_type == VAR_LIST) - clear_tv(&tv); - } - } ---- 8951,8958 ---- - - if (tv.v_type == VAR_STRING) - vim_free(tv.vval.v_string); -! else if (tv.v_type == VAR_DICT || tv.v_type == VAR_LIST || -! tv.v_type == VAR_BLOB) - clear_tv(&tv); - } - } -*************** -*** 8684,8689 **** ---- 8996,9002 ---- - case VAR_FLOAT: s = "FLO"; break; - case VAR_DICT: s = "DIC"; break; - case VAR_LIST: s = "LIS"; break; -+ case VAR_BLOB: s = "BLO"; break; - case VAR_SPECIAL: s = "XPL"; break; - - case VAR_UNKNOWN: -*************** -*** 9250,9255 **** ---- 9563,9595 ---- - * it means TRUE. */ - n1 = (type == TYPE_NEQUAL); - } -+ else if (typ1->v_type == VAR_BLOB || typ2->v_type == VAR_BLOB) -+ { -+ if (type_is) -+ { -+ n1 = (typ1->v_type == typ2->v_type -+ && typ1->vval.v_blob == typ2->vval.v_blob); -+ if (type == TYPE_NEQUAL) -+ n1 = !n1; -+ } -+ else if (typ1->v_type != typ2->v_type -+ || (type != TYPE_EQUAL && type != TYPE_NEQUAL)) -+ { -+ if (typ1->v_type != typ2->v_type) -+ EMSG(_("E977: Can only compare Blob with Blob")); -+ else -+ EMSG(_(e_invalblob)); -+ clear_tv(typ1); -+ return FAIL; -+ } -+ else -+ { -+ // Compare two Blobs for being equal or unequal. -+ n1 = blob_equal(typ1->vval.v_blob, typ2->vval.v_blob); -+ if (type == TYPE_NEQUAL) -+ n1 = !n1; -+ } -+ } - else if (typ1->v_type == VAR_LIST || typ2->v_type == VAR_LIST) - { - if (type_is) -*************** -*** 10278,10283 **** ---- 10618,10624 ---- - dict_T *d = NULL; - typval_T save_val; - typval_T save_key; -+ blob_T *b = NULL; - int rem; - int todo; - char_u *ermsg = (char_u *)(map ? "map()" : "filter()"); -*************** -*** 10286,10292 **** - int save_did_emsg; - int idx = 0; - -! if (argvars[0].v_type == VAR_LIST) - { - if ((l = argvars[0].vval.v_list) == NULL - || (!map && tv_check_lock(l->lv_lock, arg_errmsg, TRUE))) ---- 10627,10638 ---- - int save_did_emsg; - int idx = 0; - -! if (argvars[0].v_type == VAR_BLOB) -! { -! if ((b = argvars[0].vval.v_blob) == NULL) -! return; -! } -! else if (argvars[0].v_type == VAR_LIST) - { - if ((l = argvars[0].vval.v_list) == NULL - || (!map && tv_check_lock(l->lv_lock, arg_errmsg, TRUE))) -*************** -*** 10353,10358 **** ---- 10699,10735 ---- - } - hash_unlock(ht); - } -+ else if (argvars[0].v_type == VAR_BLOB) -+ { -+ int i; -+ typval_T tv; -+ -+ vimvars[VV_KEY].vv_type = VAR_NUMBER; -+ for (i = 0; i < b->bv_ga.ga_len; i++) -+ { -+ tv.v_type = VAR_NUMBER; -+ tv.vval.v_number = blob_get(b, i); -+ vimvars[VV_KEY].vv_nr = idx; -+ if (filter_map_one(&tv, expr, map, &rem) == FAIL || did_emsg) -+ break; -+ if (tv.v_type != VAR_NUMBER) -+ { -+ EMSG(_(e_invalblob)); -+ return; -+ } -+ tv.v_type = VAR_NUMBER; -+ blob_set(b, i, tv.vval.v_number); -+ if (!map && rem) -+ { -+ char_u *p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data; -+ -+ mch_memmove(p + idx, p + i + 1, -+ (size_t)b->bv_ga.ga_len - i - 1); -+ --b->bv_ga.ga_len; -+ --i; -+ } -+ } -+ } - else - { - vimvars[VV_KEY].vv_type = VAR_NUMBER; -*** ../vim-8.1.0734/src/evalfunc.c 2019-01-12 13:50:27.712026891 +0100 ---- src/evalfunc.c 2019-01-12 22:21:55.631440482 +0100 -*************** -*** 96,101 **** ---- 96,102 ---- - static void f_ch_logfile(typval_T *argvars, typval_T *rettv); - static void f_ch_open(typval_T *argvars, typval_T *rettv); - static void f_ch_read(typval_T *argvars, typval_T *rettv); -+ static void f_ch_readblob(typval_T *argvars, typval_T *rettv); - static void f_ch_readraw(typval_T *argvars, typval_T *rettv); - static void f_ch_sendexpr(typval_T *argvars, typval_T *rettv); - static void f_ch_sendraw(typval_T *argvars, typval_T *rettv); -*************** -*** 570,575 **** ---- 571,577 ---- - {"ch_logfile", 1, 2, f_ch_logfile}, - {"ch_open", 1, 2, f_ch_open}, - {"ch_read", 1, 2, f_ch_read}, -+ {"ch_readblob", 1, 2, f_ch_readblob}, - {"ch_readraw", 1, 2, f_ch_readraw}, - {"ch_sendexpr", 2, 3, f_ch_sendexpr}, - {"ch_sendraw", 2, 3, f_ch_sendraw}, -*************** -*** 1237,1242 **** ---- 1239,1245 ---- - f_add(typval_T *argvars, typval_T *rettv) - { - list_T *l; -+ blob_T *b; - - rettv->vval.v_number = 1; /* Default: Failed */ - if (argvars[0].v_type == VAR_LIST) -*************** -*** 1247,1252 **** ---- 1250,1265 ---- - && list_append_tv(l, &argvars[1]) == OK) - copy_tv(&argvars[0], rettv); - } -+ else if (argvars[0].v_type == VAR_BLOB) -+ { -+ if ((b = argvars[0].vval.v_blob) != NULL -+ && !tv_check_lock(b->bv_lock, -+ (char_u *)N_("add() argument"), TRUE)) -+ { -+ ga_append(&b->bv_ga, (char_u)tv_get_number(&argvars[1])); -+ copy_tv(&argvars[0], rettv); -+ } -+ } - else - EMSG(_(e_listreq)); - } -*************** -*** 2309,2315 **** - static void - f_ch_read(typval_T *argvars, typval_T *rettv) - { -! common_channel_read(argvars, rettv, FALSE); - } - - /* ---- 2322,2337 ---- - static void - f_ch_read(typval_T *argvars, typval_T *rettv) - { -! common_channel_read(argvars, rettv, FALSE, FALSE); -! } -! -! /* -! * "ch_readblob()" function -! */ -! static void -! f_ch_readblob(typval_T *argvars, typval_T *rettv) -! { -! common_channel_read(argvars, rettv, TRUE, TRUE); - } - - /* -*************** -*** 2318,2324 **** - static void - f_ch_readraw(typval_T *argvars, typval_T *rettv) - { -! common_channel_read(argvars, rettv, TRUE); - } - - /* ---- 2340,2346 ---- - static void - f_ch_readraw(typval_T *argvars, typval_T *rettv) - { -! common_channel_read(argvars, rettv, TRUE, FALSE); - } - - /* -*************** -*** 3170,3175 **** ---- 3192,3203 ---- - n = argvars[0].vval.v_number != VVAL_TRUE; - break; - -+ case VAR_BLOB: -+ n = argvars[0].vval.v_blob == NULL -+ || argvars[0].vval.v_blob->bv_ga.ga_data == NULL -+ || argvars[0].vval.v_blob->bv_ga.ga_len == 0; -+ break; -+ - case VAR_JOB: - #ifdef FEAT_JOB_CHANNEL - n = argvars[0].vval.v_job == NULL -*************** -*** 4365,4371 **** - dict_T *d; - typval_T *tv = NULL; - -! if (argvars[0].v_type == VAR_LIST) - { - if ((l = argvars[0].vval.v_list) != NULL) - { ---- 4393,4413 ---- - dict_T *d; - typval_T *tv = NULL; - -! if (argvars[0].v_type == VAR_BLOB) -! { -! int error = FALSE; -! int idx = tv_get_number_chk(&argvars[1], &error); -! -! if (!error) -! { -! rettv->v_type = VAR_NUMBER; -! if (idx >= blob_len(argvars[0].vval.v_blob)) -! EMSGN(_(e_blobidx), idx); -! else -! rettv->vval.v_number = blob_get(argvars[0].vval.v_blob, idx); -! } -! } -! else if (argvars[0].v_type == VAR_LIST) - { - if ((l = argvars[0].vval.v_list) != NULL) - { -*************** -*** 6965,6987 **** - { - list_T *l; - listitem_T *item; - long idx = 0; - int ic = FALSE; - - rettv->vval.v_number = -1; -! if (argvars[0].v_type != VAR_LIST) - { - EMSG(_(e_listreq)); - return; - } - l = argvars[0].vval.v_list; - if (l != NULL) - { - item = l->lv_first; - if (argvars[2].v_type != VAR_UNKNOWN) - { -- int error = FALSE; -- - /* Start at specified item. Use the cached index that list_find() - * sets, so that a negative number also works. */ - item = list_find(l, (long)tv_get_number_chk(&argvars[2], &error)); ---- 7007,7056 ---- - { - list_T *l; - listitem_T *item; -+ blob_T *b; - long idx = 0; - int ic = FALSE; -+ int error = FALSE; - - rettv->vval.v_number = -1; -! if (argvars[0].v_type == VAR_BLOB) -! { -! typval_T tv; -! int start = 0; -! -! if (argvars[2].v_type != VAR_UNKNOWN) -! { -! start = tv_get_number_chk(&argvars[2], &error); -! if (error) -! return; -! } -! b = argvars[0].vval.v_blob; -! if (b == NULL) -! return; -! for (idx = start; idx < blob_len(b); ++idx) -! { -! tv.v_type = VAR_NUMBER; -! tv.vval.v_number = blob_get(b, idx); -! if (tv_equal(&tv, &argvars[1], ic, FALSE)) -! { -! rettv->vval.v_number = idx; -! return; -! } -! } -! return; -! } -! else if (argvars[0].v_type != VAR_LIST) - { - EMSG(_(e_listreq)); - return; - } -+ - l = argvars[0].vval.v_list; - if (l != NULL) - { - item = l->lv_first; - if (argvars[2].v_type != VAR_UNKNOWN) - { - /* Start at specified item. Use the cached index that list_find() - * sets, so that a negative number also works. */ - item = list_find(l, (long)tv_get_number_chk(&argvars[2], &error)); -*************** -*** 7160,7169 **** - list_T *l; - int error = FALSE; - -! if (argvars[0].v_type != VAR_LIST) - EMSG2(_(e_listarg), "insert()"); -! else if ((l = argvars[0].vval.v_list) != NULL -! && !tv_check_lock(l->lv_lock, (char_u *)N_("insert() argument"), TRUE)) - { - if (argvars[2].v_type != VAR_UNKNOWN) - before = (long)tv_get_number_chk(&argvars[2], &error); ---- 7229,7273 ---- - list_T *l; - int error = FALSE; - -! if (argvars[0].v_type == VAR_BLOB) -! { -! int val, len; -! char_u *p; -! -! len = blob_len(argvars[0].vval.v_blob); -! if (argvars[2].v_type != VAR_UNKNOWN) -! { -! before = (long)tv_get_number_chk(&argvars[2], &error); -! if (error) -! return; // type error; errmsg already given -! if (before < 0 || before > len) -! { -! EMSG2(_(e_invarg2), tv_get_string(&argvars[2])); -! return; -! } -! } -! val = tv_get_number_chk(&argvars[1], &error); -! if (error) -! return; -! if (val < 0 || val > 255) -! { -! EMSG2(_(e_invarg2), tv_get_string(&argvars[1])); -! return; -! } -! -! if (ga_grow(&argvars[0].vval.v_blob->bv_ga, 1) == FAIL) -! return; -! p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data; -! mch_memmove(p + before + 1, p + before, (size_t)len - before); -! *(p + before) = val; -! ++argvars[0].vval.v_blob->bv_ga.ga_len; -! -! copy_tv(&argvars[0], rettv); -! } -! else if (argvars[0].v_type != VAR_LIST) - EMSG2(_(e_listarg), "insert()"); -! else if ((l = argvars[0].vval.v_list) != NULL && !tv_check_lock(l->lv_lock, -! (char_u *)N_("insert() argument"), TRUE)) - { - if (argvars[2].v_type != VAR_UNKNOWN) - before = (long)tv_get_number_chk(&argvars[2], &error); -*************** -*** 7527,7532 **** ---- 7631,7639 ---- - rettv->vval.v_number = (varnumber_T)STRLEN( - tv_get_string(&argvars[0])); - break; -+ case VAR_BLOB: -+ rettv->vval.v_number = blob_len(argvars[0].vval.v_blob); -+ break; - case VAR_LIST: - rettv->vval.v_number = list_len(argvars[0].vval.v_list); - break; -*************** -*** 8926,8931 **** ---- 9033,9039 ---- - f_readfile(typval_T *argvars, typval_T *rettv) - { - int binary = FALSE; -+ int blob = FALSE; - int failed = FALSE; - char_u *fname; - FILE *fd; -*************** -*** 8944,8955 **** - { - if (STRCMP(tv_get_string(&argvars[1]), "b") == 0) - binary = TRUE; - if (argvars[2].v_type != VAR_UNKNOWN) - maxline = (long)tv_get_number(&argvars[2]); - } - -! if (rettv_list_alloc(rettv) == FAIL) -! return; - - /* Always open the file in binary mode, library functions have a mind of - * their own about CR-LF conversion. */ ---- 9052,9074 ---- - { - if (STRCMP(tv_get_string(&argvars[1]), "b") == 0) - binary = TRUE; -+ if (STRCMP(tv_get_string(&argvars[1]), "B") == 0) -+ blob = TRUE; -+ - if (argvars[2].v_type != VAR_UNKNOWN) - maxline = (long)tv_get_number(&argvars[2]); - } - -! if (blob) -! { -! if (rettv_blob_alloc(rettv) == FAIL) -! return; -! } -! else -! { -! if (rettv_list_alloc(rettv) == FAIL) -! return; -! } - - /* Always open the file in binary mode, library functions have a mind of - * their own about CR-LF conversion. */ -*************** -*** 8960,8965 **** ---- 9079,9095 ---- - return; - } - -+ if (blob) -+ { -+ if (read_blob(fd, rettv->vval.v_blob) == FAIL) -+ { -+ EMSG("cannot read file"); -+ blob_free(rettv->vval.v_blob); -+ } -+ fclose(fd); -+ return; -+ } -+ - while (cnt < maxline || maxline < 0) - { - readlen = (int)fread(buf, 1, io_size, fd); -*************** -*** 9555,9560 **** ---- 9685,9691 ---- - dict_T *d; - dictitem_T *di; - char_u *arg_errmsg = (char_u *)N_("remove() argument"); -+ int error = FALSE; - - if (argvars[0].v_type == VAR_DICT) - { -*************** -*** 9579,9594 **** - } - } - } - else if (argvars[0].v_type != VAR_LIST) - EMSG2(_(e_listdictarg), "remove()"); - else if ((l = argvars[0].vval.v_list) != NULL -! && !tv_check_lock(l->lv_lock, arg_errmsg, TRUE)) - { -- int error = FALSE; -- - idx = (long)tv_get_number_chk(&argvars[1], &error); - if (error) -! ; /* type error: do nothing, errmsg already given */ - else if ((item = list_find(l, idx)) == NULL) - EMSGN(_(e_listidx), idx); - else ---- 9710,9785 ---- - } - } - } -+ else if (argvars[0].v_type == VAR_BLOB) -+ { -+ idx = (long)tv_get_number_chk(&argvars[1], &error); -+ if (!error) -+ { -+ blob_T *b = argvars[0].vval.v_blob; -+ int len = blob_len(b); -+ char_u *p; -+ -+ if (idx < 0) -+ // count from the end -+ idx = len + idx; -+ if (idx < 0 || idx >= len) -+ { -+ EMSGN(_(e_blobidx), idx); -+ return; -+ } -+ if (argvars[2].v_type == VAR_UNKNOWN) -+ { -+ // Remove one item, return its value. -+ p = (char_u *)b->bv_ga.ga_data; -+ rettv->vval.v_number = (varnumber_T) *(p + idx); -+ mch_memmove(p + idx, p + idx + 1, (size_t)len - idx - 1); -+ --b->bv_ga.ga_len; -+ } -+ else -+ { -+ blob_T *blob; -+ -+ // Remove range of items, return list with values. -+ end = (long)tv_get_number_chk(&argvars[2], &error); -+ if (error) -+ return; -+ if (end < 0) -+ // count from the end -+ end = len + end; -+ if (end >= len || idx > end) -+ { -+ EMSGN(_(e_blobidx), end); -+ return; -+ } -+ blob = blob_alloc(); -+ if (blob == NULL) -+ return; -+ blob->bv_ga.ga_len = end - idx + 1; -+ if (ga_grow(&blob->bv_ga, end - idx + 1) == FAIL) -+ { -+ vim_free(blob); -+ return; -+ } -+ p = (char_u *)b->bv_ga.ga_data; -+ mch_memmove((char_u *)blob->bv_ga.ga_data, p + idx, -+ (size_t)(end - idx + 1)); -+ ++blob->bv_refcount; -+ rettv->v_type = VAR_BLOB; -+ rettv->vval.v_blob = blob; -+ -+ mch_memmove(p + idx, p + end + 1, (size_t)(len - end)); -+ b->bv_ga.ga_len -= end - idx + 1; -+ } -+ } -+ } - else if (argvars[0].v_type != VAR_LIST) - EMSG2(_(e_listdictarg), "remove()"); - else if ((l = argvars[0].vval.v_list) != NULL -! && !tv_check_lock(l->lv_lock, arg_errmsg, TRUE)) - { - idx = (long)tv_get_number_chk(&argvars[1], &error); - if (error) -! ; // type error: do nothing, errmsg already given - else if ((item = list_find(l, idx)) == NULL) - EMSGN(_(e_listidx), idx); - else -*************** -*** 9602,9611 **** - } - else - { -! /* Remove range of items, return list with values. */ - end = (long)tv_get_number_chk(&argvars[2], &error); - if (error) -! ; /* type error: do nothing */ - else if ((item2 = list_find(l, end)) == NULL) - EMSGN(_(e_listidx), end); - else ---- 9793,9802 ---- - } - else - { -! // Remove range of items, return list with values. - end = (long)tv_get_number_chk(&argvars[2], &error); - if (error) -! ; // type error: do nothing - else if ((item2 = list_find(l, end)) == NULL) - EMSGN(_(e_listidx), end); - else -*************** -*** 9912,9917 **** ---- 10103,10124 ---- - list_T *l; - listitem_T *li, *ni; - -+ if (argvars[0].v_type == VAR_BLOB) -+ { -+ blob_T *b = argvars[0].vval.v_blob; -+ int i, len = blob_len(b); -+ -+ for (i = 0; i < len / 2; i++) -+ { -+ int tmp = blob_get(b, i); -+ -+ blob_set(b, i, blob_get(b, len - i - 1)); -+ blob_set(b, len - i - 1, tmp); -+ } -+ rettv_blob_set(rettv, b); -+ return; -+ } -+ - if (argvars[0].v_type != VAR_LIST) - EMSG2(_(e_listarg), "reverse()"); - else if ((l = argvars[0].vval.v_list) != NULL -*************** -*** 14198,14203 **** ---- 14405,14411 ---- - break; - case VAR_JOB: n = VAR_TYPE_JOB; break; - case VAR_CHANNEL: n = VAR_TYPE_CHANNEL; break; -+ case VAR_BLOB: n = VAR_TYPE_BLOB; break; - case VAR_UNKNOWN: - internal_error("f_type(UNKNOWN)"); - n = -1; -*************** -*** 14556,14578 **** - FILE *fd; - int ret = 0; - listitem_T *li; -! list_T *list; - - rettv->vval.v_number = -1; - if (check_restricted() || check_secure()) - return; - -! if (argvars[0].v_type != VAR_LIST) - { -! EMSG2(_(e_listarg), "writefile()"); -! return; - } -! list = argvars[0].vval.v_list; -! if (list == NULL) -! return; -! for (li = list->lv_first; li != NULL; li = li->li_next) -! if (tv_get_string_chk(&li->li_tv) == NULL) - return; - - if (argvars[2].v_type != VAR_UNKNOWN) - { ---- 14764,14796 ---- - FILE *fd; - int ret = 0; - listitem_T *li; -! list_T *list = NULL; -! blob_T *blob = NULL; - - rettv->vval.v_number = -1; - if (check_restricted() || check_secure()) - return; - -! if (argvars[0].v_type == VAR_LIST) - { -! list = argvars[0].vval.v_list; -! if (list == NULL) -! return; -! for (li = list->lv_first; li != NULL; li = li->li_next) -! if (tv_get_string_chk(&li->li_tv) == NULL) -! return; - } -! else if (argvars[0].v_type == VAR_BLOB) -! { -! blob = argvars[0].vval.v_blob; -! if (blob == NULL) - return; -+ } -+ else -+ { -+ EMSG2(_(e_invarg2), "writefile()"); -+ return; -+ } - - if (argvars[2].v_type != VAR_UNKNOWN) - { -*************** -*** 14604,14609 **** ---- 14822,14839 ---- - EMSG2(_(e_notcreate), *fname == NUL ? (char_u *)_("<empty>") : fname); - ret = -1; - } -+ else if (blob) -+ { -+ if (write_blob(fd, blob) == FAIL) -+ ret = -1; -+ #ifdef HAVE_FSYNC -+ else if (do_fsync) -+ // Ignore the error, the user wouldn't know what to do about it. -+ // May happen for a device. -+ vim_ignored = fsync(fileno(fd)); -+ #endif -+ fclose(fd); -+ } - else - { - if (write_list(fd, list, binary) == FAIL) -*** ../vim-8.1.0734/src/if_perl.xs 2018-09-21 14:01:23.148405740 +0200 ---- src/if_perl.xs 2019-01-12 18:52:14.242595860 +0100 -*************** -*** 236,241 **** ---- 236,242 ---- - # else - # define Perl_sv_2pv dll_Perl_sv_2pv - # endif -+ # define Perl_sv_2pvbyte dll_Perl_sv_2pvbyte - # define Perl_sv_bless dll_Perl_sv_bless - # if (PERL_REVISION == 5) && (PERL_VERSION >= 8) - # define Perl_sv_catpvn_flags dll_Perl_sv_catpvn_flags -*************** -*** 388,393 **** ---- 389,395 ---- - # else - static char* (*Perl_sv_2pv)(pTHX_ SV*, STRLEN*); - # endif -+ static char* (*Perl_sv_2pvbyte)(pTHX_ SV*, STRLEN*); - static SV* (*Perl_sv_bless)(pTHX_ SV*, HV*); - # if (PERL_REVISION == 5) && (PERL_VERSION >= 8) - static void (*Perl_sv_catpvn_flags)(pTHX_ SV* , const char*, STRLEN, I32); -*************** -*** 543,548 **** ---- 545,551 ---- - # else - {"Perl_sv_2pv", (PERL_PROC*)&Perl_sv_2pv}, - # endif -+ {"Perl_sv_2pvbyte", (PERL_PROC*)&Perl_sv_2pvbyte}, - # ifdef PERL589_OR_LATER - {"Perl_sv_2iv_flags", (PERL_PROC*)&Perl_sv_2iv_flags}, - {"Perl_newXS_flags", (PERL_PROC*)&Perl_newXS_flags}, -*************** -*** 1556,1561 **** ---- 1559,1585 ---- - vim_free(value); - } - -+ SV* -+ Blob(SV* sv) -+ PREINIT: -+ STRLEN len; -+ char *s; -+ int i; -+ char buf[3]; -+ SV* newsv; -+ -+ CODE: -+ s = SvPVbyte(sv, len); -+ newsv = newSVpv("0z", 2); -+ for (i = 0; i < len; i++) -+ { -+ sprintf(buf, "%02X", s[i]); -+ sv_catpvn(newsv, buf, 2); -+ } -+ RETVAL = newsv; -+ OUTPUT: -+ RETVAL -+ - void - Buffers(...) - -*** ../vim-8.1.0734/src/if_py_both.h 2018-12-23 13:36:36.671194499 +0100 ---- src/if_py_both.h 2019-01-12 18:52:14.242595860 +0100 -*************** -*** 867,872 **** ---- 867,876 ---- - } - return ret; - } -+ else if (our_tv->v_type == VAR_BLOB) -+ ret = PyBytes_FromStringAndSize( -+ (char*) our_tv->vval.v_blob->bv_ga.ga_data, -+ (Py_ssize_t) our_tv->vval.v_blob->bv_ga.ga_len); - else - { - Py_INCREF(Py_None); -*************** -*** 6394,6399 **** ---- 6398,6407 ---- - tv->vval.v_partial->pt_argc, argv, - tv->vval.v_partial->pt_dict, - tv->vval.v_partial->pt_auto); -+ case VAR_BLOB: -+ return PyBytes_FromStringAndSize( -+ (char*) tv->vval.v_blob->bv_ga.ga_data, -+ (Py_ssize_t) tv->vval.v_blob->bv_ga.ga_len); - case VAR_UNKNOWN: - case VAR_CHANNEL: - case VAR_JOB: -*** ../vim-8.1.0734/src/if_python.c 2018-03-29 18:08:42.000000000 +0200 ---- src/if_python.c 2019-01-12 18:52:14.242595860 +0100 -*************** -*** 1575,1580 **** ---- 1575,1581 ---- - case VAR_SPECIAL: - case VAR_JOB: - case VAR_CHANNEL: -+ case VAR_BLOB: - break; - } - } -*** ../vim-8.1.0734/src/if_python3.c 2018-09-30 21:43:17.195693290 +0200 ---- src/if_python3.c 2019-01-12 18:52:14.242595860 +0100 -*************** -*** 232,237 **** ---- 232,239 ---- - # endif - # undef PyBytes_FromString - # define PyBytes_FromString py3_PyBytes_FromString -+ # undef PyBytes_FromStringAndSize -+ # define PyBytes_FromStringAndSize py3_PyBytes_FromStringAndSize - # define PyFloat_FromDouble py3_PyFloat_FromDouble - # define PyFloat_AsDouble py3_PyFloat_AsDouble - # define PyObject_GenericGetAttr py3_PyObject_GenericGetAttr -*************** -*** 394,399 **** ---- 396,402 ---- - static char* (*py3_PyBytes_AsString)(PyObject *bytes); - static int (*py3_PyBytes_AsStringAndSize)(PyObject *bytes, char **buffer, Py_ssize_t *length); - static PyObject* (*py3_PyBytes_FromString)(char *str); -+ static PyObject* (*py3_PyBytes_FromStringAndSize)(char *str, Py_ssize_t length); - static PyObject* (*py3_PyFloat_FromDouble)(double num); - static double (*py3_PyFloat_AsDouble)(PyObject *); - static PyObject* (*py3_PyObject_GenericGetAttr)(PyObject *obj, PyObject *name); -*************** -*** 559,564 **** ---- 562,568 ---- - {"PyBytes_AsString", (PYTHON_PROC*)&py3_PyBytes_AsString}, - {"PyBytes_AsStringAndSize", (PYTHON_PROC*)&py3_PyBytes_AsStringAndSize}, - {"PyBytes_FromString", (PYTHON_PROC*)&py3_PyBytes_FromString}, -+ {"PyBytes_FromStringAndSize", (PYTHON_PROC*)&py3_PyBytes_FromStringAndSize}, - {"PyFloat_FromDouble", (PYTHON_PROC*)&py3_PyFloat_FromDouble}, - {"PyFloat_AsDouble", (PYTHON_PROC*)&py3_PyFloat_AsDouble}, - {"PyObject_GenericGetAttr", (PYTHON_PROC*)&py3_PyObject_GenericGetAttr}, -*************** -*** 1680,1685 **** ---- 1684,1690 ---- - case VAR_SPECIAL: - case VAR_JOB: - case VAR_CHANNEL: -+ case VAR_BLOB: - break; - } - } -*** ../vim-8.1.0734/src/if_ruby.c 2019-01-08 20:29:29.339909743 +0100 ---- src/if_ruby.c 2019-01-12 18:52:14.242595860 +0100 -*************** -*** 51,56 **** ---- 51,57 ---- - # define rb_cFloat (*dll_rb_cFloat) - # endif - # define rb_cNilClass (*dll_rb_cNilClass) -+ # define rb_cString (*dll_rb_cString) - # define rb_cSymbol (*dll_rb_cSymbol) - # define rb_cTrueClass (*dll_rb_cTrueClass) - # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 -*************** -*** 219,224 **** ---- 220,226 ---- - */ - # define rb_assoc_new dll_rb_assoc_new - # define rb_cObject (*dll_rb_cObject) -+ # define rb_class_new_instance dll_rb_class_new_instance - # define rb_check_type dll_rb_check_type - # ifdef USE_TYPEDDATA - # define rb_check_typeddata dll_rb_check_typeddata -*************** -*** 365,372 **** ---- 367,376 ---- - # endif - VALUE *dll_rb_cNilClass; - static VALUE *dll_rb_cObject; -+ VALUE *dll_rb_cString; - VALUE *dll_rb_cSymbol; - VALUE *dll_rb_cTrueClass; -+ static VALUE (*dll_rb_class_new_instance) (int,VALUE*,VALUE); - static void (*dll_rb_check_type) (VALUE,int); - # ifdef USE_TYPEDDATA - static void *(*dll_rb_check_typeddata) (VALUE,const rb_data_type_t *); -*************** -*** 579,586 **** ---- 583,592 ---- - # endif - {"rb_cNilClass", (RUBY_PROC*)&dll_rb_cNilClass}, - {"rb_cObject", (RUBY_PROC*)&dll_rb_cObject}, -+ {"rb_cString", (RUBY_PROC*)&dll_rb_cString}, - {"rb_cSymbol", (RUBY_PROC*)&dll_rb_cSymbol}, - {"rb_cTrueClass", (RUBY_PROC*)&dll_rb_cTrueClass}, -+ {"rb_class_new_instance", (RUBY_PROC*)&dll_rb_class_new_instance}, - {"rb_check_type", (RUBY_PROC*)&dll_rb_check_type}, - # ifdef USE_TYPEDDATA - {"rb_check_typeddata", (RUBY_PROC*)&dll_rb_check_typeddata}, -*************** -*** 1164,1170 **** - result = Qtrue; - else if (tv->vval.v_number == VVAL_FALSE) - result = Qfalse; -! } /* else return Qnil; */ - - return result; - } ---- 1170,1182 ---- - result = Qtrue; - else if (tv->vval.v_number == VVAL_FALSE) - result = Qfalse; -! } -! else if (tv->v_type == VAR_BLOB) -! { -! result = rb_str_new(tv->vval.v_blob->bv_ga.ga_data, -! tv->vval.v_blob->bv_ga.ga_len); -! } -! /* else return Qnil; */ - - return result; - } -*************** -*** 1242,1247 **** ---- 1254,1272 ---- - return buf; - } - -+ static VALUE vim_blob(VALUE self UNUSED, VALUE str) -+ { -+ VALUE result = rb_str_new("0z", 2); -+ char buf[4]; -+ int i; -+ for (i = 0; i < RSTRING_LEN(str); i++) -+ { -+ sprintf(buf, "%02X", RSTRING_PTR(str)[i]); -+ rb_str_concat(result, rb_str_new_cstr(buf)); -+ } -+ return result; -+ } -+ - static VALUE buffer_s_current(void) - { - return buffer_new(curbuf); -*************** -*** 1662,1667 **** ---- 1687,1693 ---- - rb_define_module_function(mVIM, "set_option", vim_set_option, 1); - rb_define_module_function(mVIM, "command", vim_command, 1); - rb_define_module_function(mVIM, "evaluate", vim_evaluate, 1); -+ rb_define_module_function(mVIM, "blob", vim_blob, 1); - - eDeletedBufferError = rb_define_class_under(mVIM, "DeletedBufferError", - rb_eStandardError); -*** ../vim-8.1.0734/src/json.c 2019-01-12 14:24:22.627597552 +0100 ---- src/json.c 2019-01-12 18:52:14.242595860 +0100 -*************** -*** 195,202 **** ---- 195,204 ---- - { - char_u numbuf[NUMBUFLEN]; - char_u *res; -+ blob_T *b; - list_T *l; - dict_T *d; -+ int i; - - switch (val->v_type) - { -*************** -*** 233,238 **** ---- 235,259 ---- - EMSG(_(e_invarg)); - return FAIL; - -+ case VAR_BLOB: -+ b = val->vval.v_blob; -+ if (b == NULL || b->bv_ga.ga_len == 0) -+ ga_concat(gap, (char_u *)"[]"); -+ else -+ { -+ ga_append(gap, '['); -+ for (i = 0; i < b->bv_ga.ga_len; i++) -+ { -+ if (i > 0) -+ ga_concat(gap, (char_u *)","); -+ vim_snprintf((char *)numbuf, NUMBUFLEN, "%d", -+ (int)blob_get(b, i)); -+ ga_concat(gap, numbuf); -+ } -+ ga_append(gap, ']'); -+ } -+ break; -+ - case VAR_LIST: - l = val->vval.v_list; - if (l == NULL) -*** ../vim-8.1.0734/src/netbeans.c 2018-12-29 18:53:07.843607433 +0100 ---- src/netbeans.c 2019-01-12 18:52:14.242595860 +0100 -*************** -*** 404,410 **** - if (*p == NUL) - { - own_node = TRUE; -! buffer = channel_get(nb_channel, PART_SOCK); - /* "node" is now invalid! */ - } - else ---- 404,410 ---- - if (*p == NUL) - { - own_node = TRUE; -! buffer = channel_get(nb_channel, PART_SOCK, NULL); - /* "node" is now invalid! */ - } - else -*** ../vim-8.1.0734/src/proto.h 2019-01-01 13:20:05.940711222 +0100 ---- src/proto.h 2019-01-12 18:52:14.242595860 +0100 -*************** -*** 88,93 **** ---- 88,94 ---- - # include "hashtab.pro" - # include "json.pro" - # include "list.pro" -+ # include "blob.pro" - # include "main.pro" - # include "mark.pro" - # include "memfile.pro" -*** ../vim-8.1.0734/src/proto/blob.pro 2019-01-12 22:40:58.105219042 +0100 ---- src/proto/blob.pro 2019-01-12 20:31:31.262919660 +0100 -*************** -*** 0 **** ---- 1,13 ---- -+ /* blob.c */ -+ blob_T *blob_alloc(void); -+ int rettv_blob_alloc(typval_T *rettv); -+ void rettv_blob_set(typval_T *rettv, blob_T *b); -+ void blob_free(blob_T *b); -+ void blob_unref(blob_T *b); -+ long blob_len(blob_T *b); -+ char_u blob_get(blob_T *b, int idx); -+ void blob_set(blob_T *b, int idx, char_u c); -+ int blob_equal(blob_T *b1, blob_T *b2); -+ int read_blob(FILE *fd, blob_T *blob); -+ int write_blob(FILE *fd, blob_T *blob); -+ /* vim: set ft=c : */ -*** ../vim-8.1.0734/src/proto/channel.pro 2018-12-14 21:31:58.008319718 +0100 ---- src/proto/channel.pro 2019-01-12 18:52:14.242595860 +0100 -*************** -*** 18,24 **** - void channel_write_new_lines(buf_T *buf); - readq_T *channel_peek(channel_T *channel, ch_part_T part); - char_u *channel_first_nl(readq_T *node); -! char_u *channel_get(channel_T *channel, ch_part_T part); - void channel_consume(channel_T *channel, ch_part_T part, int len); - int channel_collapse(channel_T *channel, ch_part_T part, int want_nl); - int channel_can_write_to(channel_T *channel); ---- 18,24 ---- - void channel_write_new_lines(buf_T *buf); - readq_T *channel_peek(channel_T *channel, ch_part_T part); - char_u *channel_first_nl(readq_T *node); -! char_u *channel_get(channel_T *channel, ch_part_T part, int *outlen); - void channel_consume(channel_T *channel, ch_part_T part, int len); - int channel_collapse(channel_T *channel, ch_part_T part, int want_nl); - int channel_can_write_to(channel_T *channel); -*************** -*** 30,36 **** - void channel_close_in(channel_T *channel); - void channel_clear(channel_T *channel); - void channel_free_all(void); -! void common_channel_read(typval_T *argvars, typval_T *rettv, int raw); - channel_T *channel_fd2channel(sock_T fd, ch_part_T *partp); - void channel_handle_events(int only_keep_open); - int channel_any_keep_open(void); ---- 30,36 ---- - void channel_close_in(channel_T *channel); - void channel_clear(channel_T *channel); - void channel_free_all(void); -! void common_channel_read(typval_T *argvars, typval_T *rettv, int raw, int blob); - channel_T *channel_fd2channel(sock_T fd, ch_part_T *partp); - void channel_handle_events(int only_keep_open); - int channel_any_keep_open(void); -*** ../vim-8.1.0734/src/structs.h 2019-01-04 15:09:52.918373097 +0100 ---- src/structs.h 2019-01-12 18:56:15.668991755 +0100 -*************** -*** 1251,1256 **** ---- 1251,1257 ---- - typedef struct listvar_S list_T; - typedef struct dictvar_S dict_T; - typedef struct partial_S partial_T; -+ typedef struct blobvar_S blob_T; - - typedef struct jobvar_S job_T; - typedef struct readq_S readq_T; -*************** -*** 1272,1277 **** ---- 1273,1279 ---- - VAR_SPECIAL, // "v_number" is used - VAR_JOB, // "v_job" is used - VAR_CHANNEL, // "v_channel" is used -+ VAR_BLOB, // "v_blob" is used - } vartype_T; - - /* -*************** -*** 1295,1300 **** ---- 1297,1303 ---- - job_T *v_job; /* job value (can be NULL!) */ - channel_T *v_channel; /* channel value (can be NULL!) */ - #endif -+ blob_T *v_blob; /* blob value (can be NULL!) */ - } vval; - } typval_T; - -*************** -*** 1401,1406 **** ---- 1404,1419 ---- - dict_T *dv_used_prev; /* previous dict in used dicts list */ - }; - -+ /* -+ * Structure to hold info about a blob. -+ */ -+ struct blobvar_S -+ { -+ garray_T bv_ga; // growarray with the data -+ int bv_refcount; // reference count -+ char bv_lock; // zero, VAR_LOCKED, VAR_FIXED -+ }; -+ - #if defined(FEAT_EVAL) || defined(PROTO) - typedef struct funccall_S funccall_T; - -*************** -*** 3526,3531 **** ---- 3539,3545 ---- - dict_T *ll_dict; /* The Dictionary or NULL */ - dictitem_T *ll_di; /* The dictitem or NULL */ - char_u *ll_newkey; /* New key for Dict in alloc. mem or NULL. */ -+ blob_T *ll_blob; /* The Blob or NULL */ - } lval_T; - - /* Structure used to save the current state. Used when executing Normal mode -*** ../vim-8.1.0734/src/testdir/Make_all.mak 2019-01-12 13:25:42.633479785 +0100 ---- src/testdir/Make_all.mak 2019-01-12 18:54:17.729776157 +0100 -*************** -*** 73,78 **** ---- 73,79 ---- - test_backspace_opt \ - test_backup \ - test_behave \ -+ test_blob \ - test_blockedit \ - test_breakindent \ - test_bufline \ -*************** -*** 283,288 **** ---- 284,290 ---- - test_autocmd.res \ - test_autoload.res \ - test_backspace_opt.res \ -+ test_blob.res \ - test_blockedit.res \ - test_breakindent.res \ - test_bufwintabinfo.res \ -*** ../vim-8.1.0734/src/vim.h 2019-01-12 13:25:42.633479785 +0100 ---- src/vim.h 2019-01-12 18:52:14.242595860 +0100 -*************** -*** 1994,2006 **** - #define VV_TYPE_NONE 78 - #define VV_TYPE_JOB 79 - #define VV_TYPE_CHANNEL 80 -! #define VV_TERMRFGRESP 81 -! #define VV_TERMRBGRESP 82 -! #define VV_TERMU7RESP 83 -! #define VV_TERMSTYLERESP 84 -! #define VV_TERMBLINKRESP 85 -! #define VV_EVENT 86 -! #define VV_LEN 87 /* number of v: vars */ - - /* used for v_number in VAR_SPECIAL */ - #define VVAL_FALSE 0L ---- 1994,2007 ---- - #define VV_TYPE_NONE 78 - #define VV_TYPE_JOB 79 - #define VV_TYPE_CHANNEL 80 -! #define VV_TYPE_BLOB 81 -! #define VV_TERMRFGRESP 82 -! #define VV_TERMRBGRESP 83 -! #define VV_TERMU7RESP 84 -! #define VV_TERMSTYLERESP 85 -! #define VV_TERMBLINKRESP 86 -! #define VV_EVENT 87 -! #define VV_LEN 88 /* number of v: vars */ - - /* used for v_number in VAR_SPECIAL */ - #define VVAL_FALSE 0L -*************** -*** 2019,2024 **** ---- 2020,2026 ---- - #define VAR_TYPE_NONE 7 - #define VAR_TYPE_JOB 8 - #define VAR_TYPE_CHANNEL 9 -+ #define VAR_TYPE_BLOB 10 - - #ifdef FEAT_CLIPBOARD - -*** ../vim-8.1.0734/src/globals.h 2019-01-06 13:10:46.324499127 +0100 ---- src/globals.h 2019-01-12 19:44:10.389888679 +0100 -*************** -*** 1524,1529 **** ---- 1524,1531 ---- - EXTERN char_u e_emptykey[] INIT(= N_("E713: Cannot use empty key for Dictionary")); - EXTERN char_u e_dictreq[] INIT(= N_("E715: Dictionary required")); - EXTERN char_u e_listidx[] INIT(= N_("E684: list index out of range: %ld")); -+ EXTERN char_u e_blobidx[] INIT(= N_("E979: Blob index out of range: %ld")); -+ EXTERN char_u e_invalblob[] INIT(= N_("E978: Invalid operation for Blob")); - EXTERN char_u e_toomanyarg[] INIT(= N_("E118: Too many arguments for function: %s")); - EXTERN char_u e_dictkey[] INIT(= N_("E716: Key not present in Dictionary: %s")); - EXTERN char_u e_listreq[] INIT(= N_("E714: List required")); -*** ../vim-8.1.0734/src/testdir/test_blob.vim 2019-01-12 22:40:58.129218991 +0100 ---- src/testdir/test_blob.vim 2019-01-12 22:24:32.278412344 +0100 -*************** -*** 0 **** ---- 1,179 ---- -+ " Tests for the Blob types -+ -+ func TearDown() -+ " Run garbage collection after every test -+ call test_garbagecollect_now() -+ endfunc -+ -+ " Tests for Blob type -+ -+ " Blob creation from constant -+ func Test_blob_create() -+ let b = 0zDEADBEEF -+ call assert_equal(v:t_blob, type(b)) -+ call assert_equal(4, len(b)) -+ call assert_equal(0xDE, b[0]) -+ call assert_equal(0xAD, b[1]) -+ call assert_equal(0xBE, b[2]) -+ call assert_equal(0xEF, b[3]) -+ call assert_fails('let x = b[4]') -+ -+ call assert_equal(0xDE, get(b, 0)) -+ call assert_equal(0xEF, get(b, 3)) -+ call assert_fails('let x = get(b, 4)') -+ endfunc -+ -+ " assignment to a blob -+ func Test_blob_assign() -+ let b = 0zDEADBEEF -+ let b2 = b[1:2] -+ call assert_equal(0zADBE, b2) -+ -+ let bcopy = b[:] -+ call assert_equal(b, bcopy) -+ call assert_false(b is bcopy) -+ endfunc -+ -+ func Test_blob_to_string() -+ let b = 0zDEADBEEF -+ call assert_equal('[0xDE,0xAD,0xBE,0xEF]', string(b)) -+ call remove(b, 0, 3) -+ call assert_equal('[]', string(b)) -+ endfunc -+ -+ func Test_blob_compare() -+ let b1 = 0z0011 -+ let b2 = 0z1100 -+ call assert_false(b1 == b2) -+ call assert_true(b1 != b2) -+ call assert_true(b1 == 0z0011) -+ -+ call assert_false(b1 is b2) -+ let b2 = b1 -+ call assert_true(b1 is b2) -+ -+ call assert_fails('let x = b1 > b2') -+ call assert_fails('let x = b1 < b2') -+ call assert_fails('let x = b1 - b2') -+ call assert_fails('let x = b1 / b2') -+ call assert_fails('let x = b1 * b2') -+ endfunc -+ -+ " test for range assign -+ func Test_blob_range_assign() -+ let b = 0z00 -+ let b[1] = 0x11 -+ let b[2] = 0x22 -+ call assert_equal(0z001122, b) -+ call assert_fails('let b[4] = 0x33') -+ endfunc -+ -+ func Test_blob_for_loop() -+ let blob = 0z00010203 -+ let i = 0 -+ for byte in blob -+ call assert_equal(i, byte) -+ let i += 1 -+ endfor -+ -+ let blob = 0z00 -+ call remove(blob, 0) -+ call assert_equal(0, len(blob)) -+ for byte in blob -+ call assert_error('loop over empty blob') -+ endfor -+ endfunc -+ -+ func Test_blob_concatenate() -+ let b = 0z0011 -+ let b += 0z2233 -+ call assert_equal(0z00112233, b) -+ -+ call assert_fails('let b += "a"') -+ call assert_fails('let b += 88') -+ -+ let b = 0zDEAD + 0zBEEF -+ call assert_equal(0zDEADBEEF, b) -+ endfunc -+ -+ " Test removing items in blob -+ func Test_blob_func_remove() -+ " Test removing 1 element -+ let b = 0zDEADBEEF -+ call assert_equal(0xDE, remove(b, 0)) -+ call assert_equal(0zADBEEF, b) -+ -+ let b = 0zDEADBEEF -+ call assert_equal(0xEF, remove(b, -1)) -+ call assert_equal(0zDEADBE, b) -+ -+ let b = 0zDEADBEEF -+ call assert_equal(0xAD, remove(b, 1)) -+ call assert_equal(0zDEBEEF, b) -+ -+ " Test removing range of element(s) -+ let b = 0zDEADBEEF -+ call assert_equal(0zBE, remove(b, 2, 2)) -+ call assert_equal(0zDEADEF, b) -+ -+ let b = 0zDEADBEEF -+ call assert_equal(0zADBE, remove(b, 1, 2)) -+ call assert_equal(0zDEEF, b) -+ -+ " Test invalid cases -+ let b = 0zDEADBEEF -+ call assert_fails("call remove(b, 5)", 'E979:') -+ call assert_fails("call remove(b, 1, 5)", 'E979:') -+ call assert_fails("call remove(b, 3, 2)", 'E979:') -+ call assert_fails("call remove(1, 0)", 'E712:') -+ call assert_fails("call remove(b, b)", 'E974:') -+ endfunc -+ -+ func Test_blob_read_write() -+ let b = 0zDEADBEEF -+ call writefile(b, 'Xblob') -+ let br = readfile('Xblob', 'B') -+ call assert_equal(b, br) -+ call delete('Xblob') -+ endfunc -+ -+ " filter() item in blob -+ func Test_blob_filter() -+ let b = 0zDEADBEEF -+ call filter(b, 'v:val != 0xEF') -+ call assert_equal(0zDEADBE, b) -+ endfunc -+ -+ " map() item in blob -+ func Test_blob_map() -+ let b = 0zDEADBEEF -+ call map(b, 'v:val + 1') -+ call assert_equal(0zDFAEBFF0, b) -+ endfunc -+ -+ func Test_blob_index() -+ call assert_equal(2, index(0zDEADBEEF, 0xBE)) -+ call assert_equal(-1, index(0zDEADBEEF, 0)) -+ endfunc -+ -+ func Test_blob_insert() -+ let b = 0zDEADBEEF -+ call insert(b, 0x33) -+ call assert_equal(0z33DEADBEEF, b) -+ -+ let b = 0zDEADBEEF -+ call insert(b, 0x33, 2) -+ call assert_equal(0zDEAD33BEEF, b) -+ endfunc -+ -+ func Test_blob_reverse() -+ call assert_equal(0zEFBEADDE, reverse(0zDEADBEEF)) -+ call assert_equal(0zBEADDE, reverse(0zDEADBE)) -+ call assert_equal(0zADDE, reverse(0zDEAD)) -+ call assert_equal(0zDE, reverse(0zDE)) -+ endfunc -+ -+ func Test_blob_json_encode() -+ call assert_equal('[222,173,190,239]', json_encode(0zDEADBEEF)) -+ call assert_equal('[]', json_encode(0z)) -+ endfunc -*** ../vim-8.1.0734/src/testdir/test_channel.vim 2019-01-09 22:24:46.568161097 +0100 ---- src/testdir/test_channel.vim 2019-01-12 21:27:24.348531499 +0100 -*************** -*** 516,521 **** ---- 516,566 ---- - call assert_equal(1, found) - endfunc - -+ func Test_raw_pipe_blob() -+ if !has('job') -+ return -+ endif -+ call ch_log('Test_raw_pipe_blob()') -+ " Add a dummy close callback to avoid that messages are dropped when calling -+ " ch_canread(). -+ " Also test the non-blocking option. -+ let job = job_start(s:python . " test_channel_pipe.py", -+ \ {'mode': 'raw', 'drop': 'never', 'noblock': 1}) -+ call assert_equal(v:t_job, type(job)) -+ call assert_equal("run", job_status(job)) -+ -+ call assert_equal("open", ch_status(job)) -+ call assert_equal("open", ch_status(job), {"part": "out"}) -+ -+ try -+ " Create a blob with the echo command and write it. -+ let blob = 0z00 -+ let cmd = "echo something\n" -+ for i in range(0, len(cmd) - 1) -+ let blob[i] = char2nr(cmd[i]) -+ endfor -+ call assert_equal(len(cmd), len(blob)) -+ call ch_sendraw(job, blob) -+ -+ " Read a blob with the reply. -+ let msg = ch_readblob(job) -+ let expected = 'something' -+ for i in range(0, len(expected) - 1) -+ call assert_equal(char2nr(expected[i]), msg[i]) -+ endfor -+ -+ let reply = ch_evalraw(job, "quit\n", {'timeout': 100}) -+ call assert_equal("Goodbye!\n", substitute(reply, "\r", "", 'g')) -+ finally -+ call job_stop(job) -+ endtry -+ -+ let g:Ch_job = job -+ call WaitForAssert({-> assert_equal("dead", job_status(g:Ch_job))}) -+ let info = job_info(job) -+ call assert_equal("dead", info.status) -+ endfunc -+ - func Test_nl_pipe() - if !has('job') - return -*** ../vim-8.1.0734/src/version.c 2019-01-12 16:29:26.327986331 +0100 ---- src/version.c 2019-01-12 18:48:53.379924473 +0100 -*************** -*** 797,798 **** ---- 797,800 ---- - { /* Add new patch number below this line */ -+ /**/ -+ 735, - /**/ - --- -hundred-and-one symptoms of being an internet addict: -180. You maintain more than six e-mail addresses. - - /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ -/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ -\\\ an exciting new programming language -- http://www.Zimbu.org /// - \\\ help me help AIDS victims -- http://ICCF-Holland.org /// |