summaryrefslogtreecommitdiff
path: root/data/vim/patches/8.1.0735
diff options
context:
space:
mode:
Diffstat (limited to 'data/vim/patches/8.1.0735')
-rw-r--r--data/vim/patches/8.1.07353392
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 ///