diff options
author | Sam Bingner <sam@bingner.com> | 2018-12-13 15:11:52 -1000 |
---|---|---|
committer | Sam Bingner <sam@bingner.com> | 2018-12-13 15:11:52 -1000 |
commit | 957aa75d05c00731d7112bed7b68ce4568667d0c (patch) | |
tree | 0445216818495a7864eaa3acde1a1570d34b958d /data/vim/patches/8.1.0360 | |
parent | c54a909c8b5a8519130803cf55f68603c0ad3682 (diff) |
Update vim
Diffstat (limited to 'data/vim/patches/8.1.0360')
-rw-r--r-- | data/vim/patches/8.1.0360 | 6803 |
1 files changed, 6803 insertions, 0 deletions
diff --git a/data/vim/patches/8.1.0360 b/data/vim/patches/8.1.0360 new file mode 100644 index 000000000..df0fd10d6 --- /dev/null +++ b/data/vim/patches/8.1.0360 @@ -0,0 +1,6803 @@ +To: vim_dev@googlegroups.com +Subject: Patch 8.1.0360 +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.0360 +Problem: Using an external diff program is slow and inflexible. +Solution: Include the xdiff library. (Christian Brabandt, closes #2732) + Use it by default. +Files: Filelist, runtime/doc/diff.txt, runtime/doc/options.txt, + src/Make_cyg_ming.mak, src/Make_mvc.mak, src/Makefile, src/diff.c, + src/structs.h, src/testdir/dumps/Test_diff_01.dump, + src/testdir/dumps/Test_diff_02.dump, + src/testdir/dumps/Test_diff_03.dump, + src/testdir/dumps/Test_diff_04.dump, + src/testdir/dumps/Test_diff_05.dump, + src/testdir/dumps/Test_diff_06.dump, + src/testdir/dumps/Test_diff_07.dump, + src/testdir/dumps/Test_diff_08.dump, + src/testdir/dumps/Test_diff_09.dump, + src/testdir/dumps/Test_diff_10.dump, + src/testdir/dumps/Test_diff_11.dump, + src/testdir/dumps/Test_diff_12.dump, + src/testdir/dumps/Test_diff_13.dump, + src/testdir/dumps/Test_diff_14.dump, + src/testdir/dumps/Test_diff_15.dump, + src/testdir/dumps/Test_diff_16.dump, + src/testdir/test_diffmode.vim, src/xdiff/COPYING, + src/xdiff/xdiff.h, src/xdiff/xdiffi.c, src/xdiff/xdiffi.h, + src/xdiff/xemit.c, src/xdiff/xemit.h, src/xdiff/xhistogram.c, + src/xdiff/xinclude.h, src/xdiff/xmacros.h, src/xdiff/xpatience.c, + src/xdiff/xprepare.c, src/xdiff/xprepare.h, src/xdiff/xtypes.h, + src/xdiff/xutils.c, src/xdiff/xutils.h, src/xdiff/README.txt + + +*** ../vim-8.1.0359/Filelist 2018-09-02 15:26:53.829022193 +0200 +--- Filelist 2018-09-10 17:23:29.323602967 +0200 +*************** +*** 273,278 **** +--- 273,292 ---- + src/libvterm/t/92lp1640917.test \ + src/libvterm/t/harness.c \ + src/libvterm/t/run-test.pl \ ++ src/xdiff/xdiff.h \ ++ src/xdiff/xdiffi.c \ ++ src/xdiff/xdiffi.h \ ++ src/xdiff/xemit.c \ ++ src/xdiff/xemit.h \ ++ src/xdiff/xhistogram.c \ ++ src/xdiff/xinclude.h \ ++ src/xdiff/xmacros.h \ ++ src/xdiff/xpatience.c \ ++ src/xdiff/xprepare.c \ ++ src/xdiff/xprepare.h \ ++ src/xdiff/xtypes.h \ ++ src/xdiff/xutils.c \ ++ src/xdiff/xutils.h \ + + + # source files for Unix only +*** ../vim-8.1.0359/runtime/doc/diff.txt 2018-05-17 13:40:51.000000000 +0200 +--- runtime/doc/diff.txt 2018-09-10 17:24:29.783082384 +0200 +*************** +*** 39,45 **** + then append the file name of the first argument to the directory name to find + the file. + +! This only works when a standard "diff" command is available. See 'diffexpr'. + + Diffs are local to the current tab page |tab-page|. You can't see diffs with + a window in another tab page. This does make it possible to have several +--- 39,47 ---- + then append the file name of the first argument to the directory name to find + the file. + +! By default an internal diff library will be used. When 'diffopt' or +! 'diffexpr' has been set an external "diff" command will be used. This only +! works when such a diff program is available. + + Diffs are local to the current tab page |tab-page|. You can't see diffs with + a window in another tab page. This does make it possible to have several +*************** +*** 344,351 **** + + The ">" is replaced with the value of 'shellredir'. + +! The output of "diff" must be a normal "ed" style diff. Do NOT use a context +! diff. This example explains the format that Vim expects: > + + 1a2 + > bbb +--- 346,354 ---- + + The ">" is replaced with the value of 'shellredir'. + +! The output of "diff" must be a normal "ed" style diff or a unified diff. Do +! NOT use a context diff. This example explains the format that Vim expects for +! the "ed" style diff: > + + 1a2 + > bbb +*************** +*** 384,395 **** +--- 387,402 ---- + endif + silent execute "!diff -a --binary " . opt . v:fname_in . " " . v:fname_new . + \ " > " . v:fname_out ++ redraw! + endfunction + + The "-a" argument is used to force comparing the files as text, comparing as + binaries isn't useful. The "--binary" argument makes the files read in binary + mode, so that a CTRL-Z doesn't end the text on DOS. + ++ The `redraw!` command may not be needed, depending on whether executing a ++ shell command shows something on the display or not. ++ + *E810* *E97* + Vim will do a test if the diff output looks alright. If it doesn't, you will + get an error message. Possible causes: +*************** +*** 441,444 **** + directory are accidentally patched. Vim will also delete files starting with + v:fname_in and ending in ".rej" and ".orig". + +! vim:tw=78:ts=8:ft=help:norl: +--- 448,451 ---- + directory are accidentally patched. Vim will also delete files starting with + v:fname_in and ending in ".rej" and ".orig". + +! vim:tw=78:ts=8:noet:ft=help:norl: +*** ../vim-8.1.0359/runtime/doc/options.txt 2018-08-07 21:39:09.243060141 +0200 +--- runtime/doc/options.txt 2018-09-10 17:25:45.414250299 +0200 +*************** +*** 2605,2612 **** + {not in Vi} + {not available when compiled without the |+diff| + feature} +! Expression which is evaluated to obtain an ed-style diff file from two +! versions of a file. See |diff-diffexpr|. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + +--- 2609,2616 ---- + {not in Vi} + {not available when compiled without the |+diff| + feature} +! Expression which is evaluated to obtain a diff file (either ed-style +! or unified-style) from two versions of a file. See |diff-diffexpr|. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + +*************** +*** 2653,2663 **** + foldcolumn:{n} Set the 'foldcolumn' option to {n} when + starting diff mode. Without this 2 is used. + +! Examples: > + +! :set diffopt=filler,context:4 + :set diffopt= +! :set diffopt=filler,foldcolumn:3 + < + *'digraph'* *'dg'* *'nodigraph'* *'nodg'* + 'digraph' 'dg' boolean (default off) +--- 2657,2687 ---- + foldcolumn:{n} Set the 'foldcolumn' option to {n} when + starting diff mode. Without this 2 is used. + +! internal Use the internal diff library. This is +! ignored when 'diffexpr' is set. *E960* +! When running out of memory when writing a +! buffer this item will be ignored for diffs +! involving that buffer. Set the 'verbose' +! option to see when this happens. +! +! indent-heuristic +! Use the indent heuristic for the internal +! diff library. +! +! algorithm:{text} Use the specified diff algorithm with the +! internal diff engine. Currently supported +! algorithms are: +! myers the default algorithm +! minimal spend extra time to generate the +! smallest possible diff +! patience patience diff algorithm +! histogram histogram diff algorithm + +! Examples: > +! :set diffopt=internal,filler,context:4 + :set diffopt= +! :set diffopt=internal,filler,foldcolumn:3 +! :set diffopt-=internal " do NOT use the internal diff parser + < + *'digraph'* *'dg'* *'nodigraph'* *'nodg'* + 'digraph' 'dg' boolean (default off) +*** ../vim-8.1.0359/src/Make_cyg_ming.mak 2018-06-30 16:25:00.551755794 +0200 +--- src/Make_cyg_ming.mak 2018-09-10 17:29:26.599063750 +0200 +*************** +*** 166,171 **** +--- 166,190 ---- + ifndef CROSS_COMPILE + CROSS_COMPILE = + endif ++ ++ # About the "sh.exe" condition, as explained by Ken Takata: ++ # ++ # If the makefile is executed with mingw32-make and sh.exe is not found in ++ # $PATH, then $SHELL is set to "sh.exe" (without any path). In this case, ++ # unix-like commands might not work and a dos-style path is needed. ++ # ++ # If the makefile is executed with mingw32-make and sh.exe IS found in $PATH, ++ # then $SHELL is set with the actual path of sh.exe (e.g. ++ # "C:/msys64/usr/bin/sh.exe"). In this case, unix-like commands can be used. ++ # ++ # If it is executed by the "make" command from cmd.exe, $SHELL is set to ++ # "/bin/sh". If the "make" command is in the $PATH, other unix-like commands ++ # might also work. ++ # ++ # If it is executed by the "make" command from a unix-like shell, ++ # $SHELL is set with the unix-style path (e.g. "/bin/bash"). ++ # In this case, unix-like commands can be used. ++ # + ifneq (sh.exe, $(SHELL)) + DEL = rm + MKDIR = mkdir -p +*************** +*** 810,815 **** +--- 829,851 ---- + $(OUTDIR)/term_vterm.o + endif + ++ # Include xdiff ++ OBJ += $(OUTDIR)/xdiffi.o \ ++ $(OUTDIR)/xemit.o \ ++ $(OUTDIR)/xprepare.o \ ++ $(OUTDIR)/xutils.o \ ++ $(OUTDIR)/xhistogram.o \ ++ $(OUTDIR)/xpatience.o ++ ++ XDIFF_DEPS = \ ++ xdiff/xdiff.h \ ++ xdiff/xdiffi.h \ ++ xdiff/xemit.h \ ++ xdiff/xinclude.h \ ++ xdiff/xmacros.h \ ++ xdiff/xprepare.h \ ++ xdiff/xtypes.h \ ++ xdiff/xutils.h + + ifdef MZSCHEME + MZSCHEME_SUFFIX = Z +*************** +*** 1055,1060 **** +--- 1091,1113 ---- + $(OUTDIR)/term_vterm.o: libvterm/src/vterm.c $(TERM_DEPS) + $(CCCTERM) libvterm/src/vterm.c -o $@ + ++ $(OUTDIR)/xdiffi.o: xdiff/xdiffi.c $(XDIFF_DEPS) ++ $(CC) -c $(CFLAGS) xdiff/xdiffi.c -o $(OUTDIR)/xdiffi.o ++ ++ $(OUTDIR)/xemit.o: xdiff/xemit.c $(XDIFF_DEPS) ++ $(CC) -c $(CFLAGS) xdiff/xemit.c -o $(OUTDIR)/xemit.o ++ ++ $(OUTDIR)/xprepare.o: xdiff/xprepare.c $(XDIFF_DEPS) ++ $(CC) -c $(CFLAGS) xdiff/xprepare.c -o $(OUTDIR)/xprepare.o ++ ++ $(OUTDIR)/xutils.o: xdiff/xutils.c $(XDIFF_DEPS) ++ $(CC) -c $(CFLAGS) xdiff/xutils.c -o $(OUTDIR)/xutils.o ++ ++ $(OUTDIR)/xhistogram.o: xdiff/xhistogram.c $(XDIFF_DEPS) ++ $(CC) -c $(CFLAGS) xdiff/xhistogram.c -o $(OUTDIR)/xhistogram.o ++ ++ $(OUTDIR)/xpatience.o: xdiff/xpatience.c $(XDIFF_DEPS) ++ $(CC) -c $(CFLAGS) xdiff/xpatience.c -o $(OUTDIR)/xpatience.o + + pathdef.c: $(INCL) + ifneq (sh.exe, $(SHELL)) +*** ../vim-8.1.0359/src/Make_mvc.mak 2018-07-04 23:05:19.221931527 +0200 +--- src/Make_mvc.mak 2018-09-10 17:32:03.885044447 +0200 +*************** +*** 813,818 **** +--- 813,836 ---- + !endif + SUBSYSTEM_TOOLS = console + ++ XDIFF_OBJ = $(OBJDIR)/xdiffi.obj \ ++ $(OBJDIR)/xemit.obj \ ++ $(OBJDIR)/xprepare.obj \ ++ $(OBJDIR)/xutils.obj \ ++ $(OBJDIR)/xhistogram.obj \ ++ $(OBJDIR)/xpatience.obj ++ ++ XDIFF_DEPS = \ ++ xdiff/xdiff.h \ ++ xdiff/xdiffi.h \ ++ xdiff/xemit.h \ ++ xdiff/xinclude.h \ ++ xdiff/xmacros.h \ ++ xdiff/xprepare.h \ ++ xdiff/xtypes.h \ ++ xdiff/xutils.h ++ ++ + !if "$(SUBSYSTEM_VER)" != "" + SUBSYSTEM = $(SUBSYSTEM),$(SUBSYSTEM_VER) + SUBSYSTEM_TOOLS = $(SUBSYSTEM_TOOLS),$(SUBSYSTEM_VER) +*************** +*** 1204,1215 **** + tee/tee.exe \ + GvimExt/gvimext.dll + +! $(VIM).exe: $(OUTDIR) $(OBJ) $(GUI_OBJ) $(CUI_OBJ) $(OLE_OBJ) $(OLE_IDL) $(MZSCHEME_OBJ) \ + $(LUA_OBJ) $(PERL_OBJ) $(PYTHON_OBJ) $(PYTHON3_OBJ) $(RUBY_OBJ) $(TCL_OBJ) \ + $(CSCOPE_OBJ) $(TERM_OBJ) $(NETBEANS_OBJ) $(CHANNEL_OBJ) $(XPM_OBJ) \ + version.c version.h + $(CC) $(CFLAGS_OUTDIR) version.c +! $(link) $(LINKARGS1) -out:$(VIM).exe $(OBJ) $(GUI_OBJ) $(CUI_OBJ) $(OLE_OBJ) \ + $(LUA_OBJ) $(MZSCHEME_OBJ) $(PERL_OBJ) $(PYTHON_OBJ) $(PYTHON3_OBJ) $(RUBY_OBJ) \ + $(TCL_OBJ) $(CSCOPE_OBJ) $(TERM_OBJ) $(NETBEANS_OBJ) $(CHANNEL_OBJ) \ + $(XPM_OBJ) $(OUTDIR)\version.obj $(LINKARGS2) +--- 1222,1233 ---- + tee/tee.exe \ + GvimExt/gvimext.dll + +! $(VIM).exe: $(OUTDIR) $(OBJ) $(XDIFF_OBJ) $(GUI_OBJ) $(CUI_OBJ) $(OLE_OBJ) $(OLE_IDL) $(MZSCHEME_OBJ) \ + $(LUA_OBJ) $(PERL_OBJ) $(PYTHON_OBJ) $(PYTHON3_OBJ) $(RUBY_OBJ) $(TCL_OBJ) \ + $(CSCOPE_OBJ) $(TERM_OBJ) $(NETBEANS_OBJ) $(CHANNEL_OBJ) $(XPM_OBJ) \ + version.c version.h + $(CC) $(CFLAGS_OUTDIR) version.c +! $(link) $(LINKARGS1) -out:$(VIM).exe $(OBJ) $(XDIFF_OBJ) $(GUI_OBJ) $(CUI_OBJ) $(OLE_OBJ) \ + $(LUA_OBJ) $(MZSCHEME_OBJ) $(PERL_OBJ) $(PYTHON_OBJ) $(PYTHON3_OBJ) $(RUBY_OBJ) \ + $(TCL_OBJ) $(CSCOPE_OBJ) $(TERM_OBJ) $(NETBEANS_OBJ) $(CHANNEL_OBJ) \ + $(XPM_OBJ) $(OUTDIR)\version.obj $(LINKARGS2) +*************** +*** 1304,1309 **** +--- 1322,1328 ---- + $(MAKE) /NOLOGO -f Make_dos.mak nolog + $(MAKE) /NOLOGO -f Make_dos.mak $@.res + $(MAKE) /NOLOGO -f Make_dos.mak report ++ cat messages + cd .. + + ########################################################################### +*************** +*** 1344,1349 **** +--- 1363,1386 ---- + + $(OUTDIR)/diff.obj: $(OUTDIR) diff.c $(INCL) + ++ $(OUTDIR)/xdiffi.obj: $(OUTDIR) xdiff/xdiffi.c $(XDIFF_DEPS) ++ $(CC) $(CFLAGS_OUTDIR) xdiff/xdiffi.c ++ ++ $(OUTDIR)/xemit.obj: $(OUTDIR) xdiff/xemit.c $(XDIFF_DEPS) ++ $(CC) $(CFLAGS_OUTDIR) xdiff/xemit.c ++ ++ $(OUTDIR)/xprepare.obj: $(OUTDIR) xdiff/xprepare.c $(XDIFF_DEPS) ++ $(CC) $(CFLAGS_OUTDIR) xdiff/xprepare.c ++ ++ $(OUTDIR)/xutils.obj: $(OUTDIR) xdiff/xutils.c $(XDIFF_DEPS) ++ $(CC) $(CFLAGS_OUTDIR) xdiff/xutils.c ++ ++ $(OUTDIR)/xhistogram.obj: $(OUTDIR) xdiff/xhistogram.c $(XDIFF_DEPS) ++ $(CC) $(CFLAGS_OUTDIR) xdiff/xhistogram.c ++ ++ $(OUTDIR)/xpatience.obj: $(OUTDIR) xdiff/xpatience.c $(XDIFF_DEPS) ++ $(CC) $(CFLAGS_OUTDIR) xdiff/xpatience.c ++ + $(OUTDIR)/digraph.obj: $(OUTDIR) digraph.c $(INCL) + + $(OUTDIR)/edit.obj: $(OUTDIR) edit.c $(INCL) +*** ../vim-8.1.0359/src/Makefile 2018-07-07 22:26:49.306702821 +0200 +--- src/Makefile 2018-09-10 17:32:57.212394678 +0200 +*************** +*** 1400,1405 **** +--- 1400,1431 ---- + + TERM_SRC = libvterm/src/*.c + ++ XDIFF_SRC = \ ++ xdiff/xdiffi.c \ ++ xdiff/xemit.c \ ++ xdiff/xprepare.c \ ++ xdiff/xutils.c \ ++ xdiff/xhistogram.c \ ++ xdiff/xpatience.c \ ++ ++ XDIFF_OBJS = \ ++ objects/xdiffi.o \ ++ objects/xemit.o \ ++ objects/xprepare.o \ ++ objects/xutils.o \ ++ objects/xhistogram.o \ ++ objects/xpatience.o \ ++ ++ XDIFF_INCL = \ ++ xdiff/xdiff.h \ ++ xdiff/xdiffi.h \ ++ xdiff/xemit.h \ ++ xdiff/xinclude.h \ ++ xdiff/xmacros.h \ ++ xdiff/xprepare.h \ ++ xdiff/xtypes.h \ ++ xdiff/xutils.h \ ++ + ### Command to create dependencies based on #include "..." + ### prototype headers are ignored due to -DPROTO, system + ### headers #include <...> are ignored if we use the -MM option, as +*************** +*** 1611,1616 **** +--- 1637,1643 ---- + SRC = $(BASIC_SRC) \ + $(GUI_SRC) \ + $(TERM_SRC) \ ++ $(XDIFF_SRC) \ + $(HANGULIN_SRC) \ + $(LUA_SRC) \ + $(MZSCHEME_SRC) \ +*************** +*** 1728,1733 **** +--- 1755,1761 ---- + $(WORKSHOP_OBJ) \ + $(NETBEANS_OBJ) \ + $(CHANNEL_OBJ) \ ++ $(XDIFF_OBJS) \ + $(WSDEBUG_OBJ) + + # The files included by tests are not in OBJ_COMMON. +*************** +*** 2731,2737 **** + + shadow: runtime pixmaps + $(MKDIR_P) $(SHADOWDIR) +! cd $(SHADOWDIR); ln -s ../*.[chm] ../*.in ../*.sh ../*.xs ../*.xbm ../gui_gtk_res.xml ../toolcheck ../proto ../libvterm ../vimtutor ../gvimtutor ../install-sh ../Make_all.mak . + mkdir $(SHADOWDIR)/auto + cd $(SHADOWDIR)/auto; ln -s ../../auto/configure . + $(MKDIR_P) $(SHADOWDIR)/po +--- 2759,2765 ---- + + shadow: runtime pixmaps + $(MKDIR_P) $(SHADOWDIR) +! cd $(SHADOWDIR); ln -s ../*.[chm] ../*.in ../*.sh ../*.xs ../*.xbm ../gui_gtk_res.xml ../toolcheck ../proto ../xdiff ../libvterm ../vimtutor ../gvimtutor ../install-sh ../Make_all.mak . + mkdir $(SHADOWDIR)/auto + cd $(SHADOWDIR)/auto; ln -s ../../auto/configure . + $(MKDIR_P) $(SHADOWDIR)/po +*************** +*** 2915,2921 **** + objects/dict.o: dict.c + $(CCC) -o $@ dict.c + +! objects/diff.o: diff.c + $(CCC) -o $@ diff.c + + objects/digraph.o: digraph.c +--- 2943,2949 ---- + objects/dict.o: dict.c + $(CCC) -o $@ dict.c + +! objects/diff.o: diff.c $(XDIFF_INCL) + $(CCC) -o $@ diff.c + + objects/digraph.o: digraph.c +*************** +*** 3229,3234 **** +--- 3257,3283 ---- + objects/term_vterm.o: libvterm/src/vterm.c $(TERM_DEPS) + $(CCCTERM) -o $@ libvterm/src/vterm.c + ++ CCCDIFF = $(CCC_NF) $(ALL_CFLAGS) ++ ++ objects/xdiffi.o: xdiff/xdiffi.c $(XDIFF_INCL) ++ $(CCCDIFF) -o $@ xdiff/xdiffi.c ++ ++ objects/xprepare.o: xdiff/xprepare.c $(XDIFF_INCL) ++ $(CCCDIFF) -o $@ xdiff/xprepare.c ++ ++ objects/xutils.o: xdiff/xutils.c $(XDIFF_INCL) ++ $(CCCDIFF) -o $@ xdiff/xutils.c ++ ++ objects/xemit.o: xdiff/xemit.c $(XDIFF_INCL) ++ $(CCCDIFF) -o $@ xdiff/xemit.c ++ ++ objects/xhistogram.o: xdiff/xhistogram.c $(XDIFF_INCL) ++ $(CCCDIFF) -o $@ xdiff/xhistogram.c ++ ++ objects/xpatience.o: xdiff/xpatience.c $(XDIFF_INCL) ++ $(CCCDIFF) -o $@ xdiff/xpatience.c ++ ++ + ############################################################################### + ### MacOS X installation + ### +*** ../vim-8.1.0359/src/diff.c 2018-06-03 14:42:17.840505115 +0200 +--- src/diff.c 2018-09-10 17:36:06.542197741 +0200 +*************** +*** 9,31 **** + + /* + * diff.c: code for diff'ing two, three or four buffers. + */ + + #include "vim.h" + + #if defined(FEAT_DIFF) || defined(PROTO) + + static int diff_busy = FALSE; /* ex_diffgetput() is busy */ + + /* flags obtained from the 'diffopt' option */ +! #define DIFF_FILLER 1 /* display filler lines */ +! #define DIFF_ICASE 2 /* ignore case */ +! #define DIFF_IWHITE 4 /* ignore change in white space */ +! #define DIFF_HORIZONTAL 8 /* horizontal splits */ +! #define DIFF_VERTICAL 16 /* vertical splits */ +! #define DIFF_HIDDEN_OFF 32 /* diffoff when hidden */ + static int diff_flags = DIFF_FILLER; + + #define LBUFLEN 50 /* length of line in diff file */ + + static int diff_a_works = MAYBE; /* TRUE when "diff -a" works, FALSE when it +--- 9,40 ---- + + /* + * diff.c: code for diff'ing two, three or four buffers. ++ * ++ * There are three ways to diff: ++ * - Shell out to an external diff program, using files. ++ * - Use the compiled-in xdiff library. ++ * - Let 'diffexpr' do the work, using files. + */ + + #include "vim.h" ++ #include "xdiff/xdiff.h" + + #if defined(FEAT_DIFF) || defined(PROTO) + + static int diff_busy = FALSE; /* ex_diffgetput() is busy */ + + /* flags obtained from the 'diffopt' option */ +! #define DIFF_FILLER 1 // display filler lines +! #define DIFF_ICASE 2 // ignore case +! #define DIFF_IWHITE 4 // ignore change in white space +! #define DIFF_HORIZONTAL 8 // horizontal splits +! #define DIFF_VERTICAL 16 // vertical splits +! #define DIFF_HIDDEN_OFF 32 // diffoff when hidden +! #define DIFF_INTERNAL 64 // use internal xdiff algorithm + static int diff_flags = DIFF_FILLER; + ++ static long diff_algorithm = 0; ++ + #define LBUFLEN 50 /* length of line in diff file */ + + static int diff_a_works = MAYBE; /* TRUE when "diff -a" works, FALSE when it +*************** +*** 36,57 **** + checked yet */ + #endif + + static int diff_buf_idx(buf_T *buf); + static int diff_buf_idx_tp(buf_T *buf, tabpage_T *tp); + static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T line2, long amount, long amount_after); + static void diff_check_unchanged(tabpage_T *tp, diff_T *dp); + static int diff_check_sanity(tabpage_T *tp, diff_T *dp); + static void diff_redraw(int dofold); +! static int diff_write(buf_T *buf, char_u *fname); +! static void diff_file(char_u *tmp_orig, char_u *tmp_new, char_u *tmp_diff); + static int diff_equal_entry(diff_T *dp, int idx1, int idx2); + static int diff_cmp(char_u *s1, char_u *s2); + #ifdef FEAT_FOLDING + static void diff_fold_update(diff_T *dp, int skip_idx); + #endif +! static void diff_read(int idx_orig, int idx_new, char_u *fname); + static void diff_copy_entry(diff_T *dprev, diff_T *dp, int idx_orig, int idx_new); + static diff_T *diff_alloc_new(tabpage_T *tp, diff_T *dprev, diff_T *dp); + + #ifndef USE_CR + # define tag_fgets vim_fgets +--- 45,89 ---- + checked yet */ + #endif + ++ // used for diff input ++ typedef struct { ++ char_u *din_fname; // used for external diff ++ mmfile_t din_mmfile; // used for internal diff ++ } diffin_T; ++ ++ // used for diff result ++ typedef struct { ++ char_u *dout_fname; // used for external diff ++ garray_T dout_ga; // used for internal diff ++ } diffout_T; ++ ++ // two diff inputs and one result ++ typedef struct { ++ diffin_T dio_orig; // original file input ++ diffin_T dio_new; // new file input ++ diffout_T dio_diff; // diff result ++ int dio_internal; // using internal diff ++ } diffio_T; ++ + static int diff_buf_idx(buf_T *buf); + static int diff_buf_idx_tp(buf_T *buf, tabpage_T *tp); + static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T line2, long amount, long amount_after); + static void diff_check_unchanged(tabpage_T *tp, diff_T *dp); + static int diff_check_sanity(tabpage_T *tp, diff_T *dp); + static void diff_redraw(int dofold); +! static int check_external_diff(diffio_T *diffio); +! static int diff_file(diffio_T *diffio); + static int diff_equal_entry(diff_T *dp, int idx1, int idx2); + static int diff_cmp(char_u *s1, char_u *s2); + #ifdef FEAT_FOLDING + static void diff_fold_update(diff_T *dp, int skip_idx); + #endif +! static void diff_read(int idx_orig, int idx_new, diffout_T *fname); + static void diff_copy_entry(diff_T *dprev, diff_T *dp, int idx_orig, int idx_new); + static diff_T *diff_alloc_new(tabpage_T *tp, diff_T *dprev, diff_T *dp); ++ static int parse_diff_ed(char_u *line, linenr_T *lnum_orig, long *count_orig, linenr_T *lnum_new, long *count_new); ++ static int parse_diff_unified(char_u *line, linenr_T *lnum_orig, long *count_orig, linenr_T *lnum_new, long *count_new); ++ static int xdiff_out(void *priv, mmbuffer_t *mb, int nbuf); + + #ifndef USE_CR + # define tag_fgets vim_fgets +*************** +*** 631,711 **** + } + } + + /* +! * Write buffer "buf" to file "name". +! * Always use 'fileformat' set to "unix". +! * Return FAIL for failure + */ + static int +! diff_write(buf_T *buf, char_u *fname) + { + int r; + char_u *save_ff; + + save_ff = buf->b_p_ff; + buf->b_p_ff = vim_strsave((char_u *)FF_UNIX); +! r = buf_write(buf, fname, NULL, (linenr_T)1, buf->b_ml.ml_line_count, +! NULL, FALSE, FALSE, FALSE, TRUE); + free_string_option(buf->b_p_ff); + buf->b_p_ff = save_ff; + return r; + } + + /* + * Completely update the diffs for the buffers involved. + * This uses the ordinary "diff" command. + * The buffers are written to a file, also for unmodified buffers (the file + * could have been produced by autocommands, e.g. the netrw plugin). + */ + void +! ex_diffupdate( +! exarg_T *eap) /* can be NULL */ + { +- buf_T *buf; + int idx_orig; + int idx_new; +! char_u *tmp_orig; +! char_u *tmp_new; +! char_u *tmp_diff; +! FILE *fd; +! int ok; +! int io_error = FALSE; + +! /* Delete all diffblocks. */ + diff_clear(curtab); + curtab->tp_diff_invalid = FALSE; + +! /* Use the first buffer as the original text. */ + for (idx_orig = 0; idx_orig < DB_COUNT; ++idx_orig) + if (curtab->tp_diffbuf[idx_orig] != NULL) + break; + if (idx_orig == DB_COUNT) + return; + +! /* Only need to do something when there is another buffer. */ + for (idx_new = idx_orig + 1; idx_new < DB_COUNT; ++idx_new) + if (curtab->tp_diffbuf[idx_new] != NULL) + break; + if (idx_new == DB_COUNT) + return; + +! /* We need three temp file names. */ +! tmp_orig = vim_tempname('o', TRUE); +! tmp_new = vim_tempname('n', TRUE); +! tmp_diff = vim_tempname('d', TRUE); +! if (tmp_orig == NULL || tmp_new == NULL || tmp_diff == NULL) +! goto theend; + +! /* +! * Do a quick test if "diff" really works. Otherwise it looks like there +! * are no differences. Can't use the return value, it's non-zero when +! * there are differences. +! * May try twice, first with "-a" and then without. +! */ + for (;;) + { + ok = FALSE; +! fd = mch_fopen((char *)tmp_orig, "w"); + if (fd == NULL) + io_error = TRUE; + else +--- 663,952 ---- + } + } + ++ static void ++ clear_diffin(diffin_T *din) ++ { ++ if (din->din_fname == NULL) ++ { ++ vim_free(din->din_mmfile.ptr); ++ din->din_mmfile.ptr = NULL; ++ } ++ else ++ mch_remove(din->din_fname); ++ } ++ ++ static void ++ clear_diffout(diffout_T *dout) ++ { ++ if (dout->dout_fname == NULL) ++ ga_clear_strings(&dout->dout_ga); ++ else ++ mch_remove(dout->dout_fname); ++ } ++ + /* +! * Write buffer "buf" to a memory buffer. +! * Return FAIL for failure. + */ + static int +! diff_write_buffer(buf_T *buf, diffin_T *din) +! { +! linenr_T lnum; +! char_u *s; +! long len = 0; +! char_u *ptr; +! +! // xdiff requires one big block of memory with all the text. +! for (lnum = 1; lnum <= buf->b_ml.ml_line_count; ++lnum) +! len += STRLEN(ml_get_buf(buf, lnum, FALSE)) + 1; +! ptr = lalloc(len, TRUE); +! if (ptr == NULL) +! { +! // Allocating memory failed. This can happen, because we try to read +! // the whole buffer text into memory. Set the failed flag, the diff +! // will be retried with external diff. The flag is never reset. +! buf->b_diff_failed = TRUE; +! if (p_verbose > 0) +! { +! verbose_enter(); +! smsg((char_u *) +! _("Not enough memory to use internal diff for buffer \"%s\""), +! buf->b_fname); +! verbose_leave(); +! } +! return FAIL; +! } +! din->din_mmfile.ptr = (char *)ptr; +! din->din_mmfile.size = len; +! +! len = 0; +! for (lnum = 1; lnum <= buf->b_ml.ml_line_count; ++lnum) +! { +! for (s = ml_get_buf(buf, lnum, FALSE); *s != NUL; ) +! { +! if (diff_flags & DIFF_ICASE) +! { +! int c; +! +! // xdiff doesn't support ignoring case, fold-case the text. +! #ifdef FEAT_MBYTE +! int orig_len; +! char_u cbuf[MB_MAXBYTES + 1]; +! +! c = PTR2CHAR(s); +! c = enc_utf8 ? utf_fold(c) : MB_TOLOWER(c); +! orig_len = MB_PTR2LEN(s); +! if (mb_char2bytes(c, cbuf) != orig_len) +! // TODO: handle byte length difference +! mch_memmove(ptr + len, s, orig_len); +! else +! mch_memmove(ptr + len, cbuf, orig_len); +! +! s += orig_len; +! len += orig_len; +! #else +! c = *s++; +! ptr[len++] = TOLOWER_LOC(c); +! #endif +! } +! else +! ptr[len++] = *s++; +! } +! ptr[len++] = NL; +! } +! return OK; +! } +! +! /* +! * Write buffer "buf" to file or memory buffer. +! * Return FAIL for failure. +! */ +! static int +! diff_write(buf_T *buf, diffin_T *din) + { + int r; + char_u *save_ff; + ++ if (din->din_fname == NULL) ++ return diff_write_buffer(buf, din); ++ ++ // Always use 'fileformat' set to "unix". + save_ff = buf->b_p_ff; + buf->b_p_ff = vim_strsave((char_u *)FF_UNIX); +! r = buf_write(buf, din->din_fname, NULL, +! (linenr_T)1, buf->b_ml.ml_line_count, +! NULL, FALSE, FALSE, FALSE, TRUE); + free_string_option(buf->b_p_ff); + buf->b_p_ff = save_ff; + return r; + } + + /* ++ * Update the diffs for all buffers involved. ++ */ ++ static void ++ diff_try_update( ++ diffio_T *dio, ++ int idx_orig, ++ exarg_T *eap) // "eap" can be NULL ++ { ++ buf_T *buf; ++ int idx_new; ++ ++ if (dio->dio_internal) ++ { ++ ga_init2(&dio->dio_diff.dout_ga, sizeof(char *), 1000); ++ } ++ else ++ { ++ // We need three temp file names. ++ dio->dio_orig.din_fname = vim_tempname('o', TRUE); ++ dio->dio_new.din_fname = vim_tempname('n', TRUE); ++ dio->dio_diff.dout_fname = vim_tempname('d', TRUE); ++ if (dio->dio_orig.din_fname == NULL ++ || dio->dio_new.din_fname == NULL ++ || dio->dio_diff.dout_fname == NULL) ++ goto theend; ++ } ++ ++ // Check external diff is actually working. ++ if (!dio->dio_internal && check_external_diff(dio) == FAIL) ++ goto theend; ++ ++ // :diffupdate! ++ if (eap != NULL && eap->forceit) ++ for (idx_new = idx_orig; idx_new < DB_COUNT; ++idx_new) ++ { ++ buf = curtab->tp_diffbuf[idx_new]; ++ if (buf_valid(buf)) ++ buf_check_timestamp(buf, FALSE); ++ } ++ ++ // Write the first buffer to a tempfile or mmfile_t. ++ buf = curtab->tp_diffbuf[idx_orig]; ++ if (diff_write(buf, &dio->dio_orig) == FAIL) ++ goto theend; ++ ++ // Make a difference between the first buffer and every other. ++ for (idx_new = idx_orig + 1; idx_new < DB_COUNT; ++idx_new) ++ { ++ buf = curtab->tp_diffbuf[idx_new]; ++ if (buf == NULL || buf->b_ml.ml_mfp == NULL) ++ continue; // skip buffer that isn't loaded ++ ++ // Write the other buffer and diff with the first one. ++ if (diff_write(buf, &dio->dio_new) == FAIL) ++ continue; ++ if (diff_file(dio) == FAIL) ++ continue; ++ ++ // Read the diff output and add each entry to the diff list. ++ diff_read(idx_orig, idx_new, &dio->dio_diff); ++ ++ clear_diffin(&dio->dio_new); ++ clear_diffout(&dio->dio_diff); ++ } ++ clear_diffin(&dio->dio_orig); ++ ++ theend: ++ vim_free(dio->dio_orig.din_fname); ++ vim_free(dio->dio_new.din_fname); ++ vim_free(dio->dio_diff.dout_fname); ++ } ++ ++ /* ++ * Return TRUE if the options are set to use the internal diff library. ++ * Note that if the internal diff failed for one of the buffers, the external ++ * diff will be used anyway. ++ */ ++ static int ++ diff_internal(void) ++ { ++ return (diff_flags & DIFF_INTERNAL) != 0 && *p_dex == NUL; ++ } ++ ++ /* ++ * Return TRUE if the internal diff failed for one of the diff buffers. ++ */ ++ static int ++ diff_internal_failed(void) ++ { ++ int idx; ++ ++ // Only need to do something when there is another buffer. ++ for (idx = 0; idx < DB_COUNT; ++idx) ++ if (curtab->tp_diffbuf[idx] != NULL ++ && curtab->tp_diffbuf[idx]->b_diff_failed) ++ return TRUE; ++ return FALSE; ++ } ++ ++ /* + * Completely update the diffs for the buffers involved. + * This uses the ordinary "diff" command. + * The buffers are written to a file, also for unmodified buffers (the file + * could have been produced by autocommands, e.g. the netrw plugin). + */ + void +! ex_diffupdate(exarg_T *eap) // "eap" can be NULL + { + int idx_orig; + int idx_new; +! diffio_T diffio; + +! // Delete all diffblocks. + diff_clear(curtab); + curtab->tp_diff_invalid = FALSE; + +! // Use the first buffer as the original text. + for (idx_orig = 0; idx_orig < DB_COUNT; ++idx_orig) + if (curtab->tp_diffbuf[idx_orig] != NULL) + break; + if (idx_orig == DB_COUNT) + return; + +! // Only need to do something when there is another buffer. + for (idx_new = idx_orig + 1; idx_new < DB_COUNT; ++idx_new) + if (curtab->tp_diffbuf[idx_new] != NULL) + break; + if (idx_new == DB_COUNT) + return; + +! // Only use the internal method if it did not fail for one of the buffers. +! vim_memset(&diffio, 0, sizeof(diffio)); +! diffio.dio_internal = diff_internal() && !diff_internal_failed(); +! +! diff_try_update(&diffio, idx_orig, eap); +! if (diffio.dio_internal && diff_internal_failed()) +! { +! // Internal diff failed, use external diff instead. +! vim_memset(&diffio, 0, sizeof(diffio)); +! diff_try_update(&diffio, idx_orig, eap); +! } + +! // force updating cursor position on screen +! curwin->w_valid_cursor.lnum = 0; +! +! diff_redraw(TRUE); +! } +! +! /* +! * Do a quick test if "diff" really works. Otherwise it looks like there +! * are no differences. Can't use the return value, it's non-zero when +! * there are differences. +! */ +! static int +! check_external_diff(diffio_T *diffio) +! { +! FILE *fd; +! int ok; +! int io_error = FALSE; +! +! // May try twice, first with "-a" and then without. + for (;;) + { + ok = FALSE; +! fd = mch_fopen((char *)diffio->dio_orig.din_fname, "w"); + if (fd == NULL) + io_error = TRUE; + else +*************** +*** 713,719 **** + if (fwrite("line1\n", (size_t)6, (size_t)1, fd) != 1) + io_error = TRUE; + fclose(fd); +! fd = mch_fopen((char *)tmp_new, "w"); + if (fd == NULL) + io_error = TRUE; + else +--- 954,960 ---- + if (fwrite("line1\n", (size_t)6, (size_t)1, fd) != 1) + io_error = TRUE; + fclose(fd); +! fd = mch_fopen((char *)diffio->dio_new.din_fname, "w"); + if (fd == NULL) + io_error = TRUE; + else +*************** +*** 721,728 **** + if (fwrite("line2\n", (size_t)6, (size_t)1, fd) != 1) + io_error = TRUE; + fclose(fd); +! diff_file(tmp_orig, tmp_new, tmp_diff); +! fd = mch_fopen((char *)tmp_diff, "r"); + if (fd == NULL) + io_error = TRUE; + else +--- 962,970 ---- + if (fwrite("line2\n", (size_t)6, (size_t)1, fd) != 1) + io_error = TRUE; + fclose(fd); +! fd = NULL; +! if (diff_file(diffio) == OK) +! fd = mch_fopen((char *)diffio->dio_diff.dout_fname, "r"); + if (fd == NULL) + io_error = TRUE; + else +*************** +*** 739,748 **** + } + fclose(fd); + } +! mch_remove(tmp_diff); +! mch_remove(tmp_new); + } +! mch_remove(tmp_orig); + } + + #ifdef FEAT_EVAL +--- 981,990 ---- + } + fclose(fd); + } +! mch_remove(diffio->dio_diff.dout_fname); +! mch_remove(diffio->dio_new.din_fname); + } +! mch_remove(diffio->dio_orig.din_fname); + } + + #ifdef FEAT_EVAL +*************** +*** 785,882 **** + #if defined(MSWIN) + diff_bin_works = MAYBE; + #endif +! goto theend; + } + +! /* :diffupdate! */ +! if (eap != NULL && eap->forceit) +! for (idx_new = idx_orig; idx_new < DB_COUNT; ++idx_new) +! { +! buf = curtab->tp_diffbuf[idx_new]; +! if (buf_valid(buf)) +! buf_check_timestamp(buf, FALSE); +! } +! +! /* Write the first buffer to a tempfile. */ +! buf = curtab->tp_diffbuf[idx_orig]; +! if (diff_write(buf, tmp_orig) == FAIL) +! goto theend; +! +! /* Make a difference between the first buffer and every other. */ +! for (idx_new = idx_orig + 1; idx_new < DB_COUNT; ++idx_new) +! { +! buf = curtab->tp_diffbuf[idx_new]; +! if (buf == NULL || buf->b_ml.ml_mfp == NULL) +! continue; /* skip buffer that isn't loaded */ +! if (diff_write(buf, tmp_new) == FAIL) +! continue; +! diff_file(tmp_orig, tmp_new, tmp_diff); + +! /* Read the diff output and add each entry to the diff list. */ +! diff_read(idx_orig, idx_new, tmp_diff); +! mch_remove(tmp_diff); +! mch_remove(tmp_new); +! } +! mch_remove(tmp_orig); + +! /* force updating cursor position on screen */ +! curwin->w_valid_cursor.lnum = 0; + +! diff_redraw(TRUE); + +! theend: +! vim_free(tmp_orig); +! vim_free(tmp_new); +! vim_free(tmp_diff); + } + + /* + * Make a diff between files "tmp_orig" and "tmp_new", results in "tmp_diff". + */ +! static void +! diff_file( +! char_u *tmp_orig, +! char_u *tmp_new, +! char_u *tmp_diff) + { + char_u *cmd; + size_t len; + + #ifdef FEAT_EVAL + if (*p_dex != NUL) +! /* Use 'diffexpr' to generate the diff file. */ + eval_diff(tmp_orig, tmp_new, tmp_diff); + else + #endif + { + len = STRLEN(tmp_orig) + STRLEN(tmp_new) + + STRLEN(tmp_diff) + STRLEN(p_srr) + 27; + cmd = alloc((unsigned)len); +! if (cmd != NULL) +! { +! /* We don't want $DIFF_OPTIONS to get in the way. */ +! if (getenv("DIFF_OPTIONS")) +! vim_setenv((char_u *)"DIFF_OPTIONS", (char_u *)""); +! +! /* Build the diff command and execute it. Always use -a, binary +! * differences are of no use. Ignore errors, diff returns +! * non-zero when differences have been found. */ +! vim_snprintf((char *)cmd, len, "diff %s%s%s%s%s %s", +! diff_a_works == FALSE ? "" : "-a ", + #if defined(MSWIN) +! diff_bin_works == TRUE ? "--binary " : "", + #else +! "", + #endif +! (diff_flags & DIFF_IWHITE) ? "-b " : "", +! (diff_flags & DIFF_ICASE) ? "-i " : "", +! tmp_orig, tmp_new); +! append_redir(cmd, (int)len, p_srr, tmp_diff); +! block_autocmds(); /* Avoid ShellCmdPost stuff */ +! (void)call_shell(cmd, SHELL_FILTER|SHELL_SILENT|SHELL_DOOUT); +! unblock_autocmds(); +! vim_free(cmd); +! } + } + } + +--- 1027,1127 ---- + #if defined(MSWIN) + diff_bin_works = MAYBE; + #endif +! return FAIL; + } ++ return OK; ++ } + +! /* +! * Invoke the xdiff function. +! */ +! static int +! diff_file_internal(diffio_T *diffio) +! { +! xpparam_t param; +! xdemitconf_t emit_cfg; +! xdemitcb_t emit_cb; + +! vim_memset(¶m, 0, sizeof(param)); +! vim_memset(&emit_cfg, 0, sizeof(emit_cfg)); +! vim_memset(&emit_cb, 0, sizeof(emit_cb)); + +! param.flags = diff_algorithm; + +! if (diff_flags & DIFF_IWHITE) +! param.flags |= XDF_IGNORE_WHITESPACE_CHANGE; + +! emit_cfg.ctxlen = 0; // don't need any diff_context here +! emit_cb.priv = &diffio->dio_diff; +! emit_cb.outf = xdiff_out; +! if (xdl_diff(&diffio->dio_orig.din_mmfile, +! &diffio->dio_new.din_mmfile, +! ¶m, &emit_cfg, &emit_cb) < 0) +! { +! EMSG(_("E960: Problem creating the internal diff")); +! return FAIL; +! } +! return OK; + } + + /* + * Make a diff between files "tmp_orig" and "tmp_new", results in "tmp_diff". ++ * return OK or FAIL; + */ +! static int +! diff_file(diffio_T *dio) + { + char_u *cmd; + size_t len; ++ char_u *tmp_orig = dio->dio_orig.din_fname; ++ char_u *tmp_new = dio->dio_new.din_fname; ++ char_u *tmp_diff = dio->dio_diff.dout_fname; + + #ifdef FEAT_EVAL + if (*p_dex != NUL) +! { +! // Use 'diffexpr' to generate the diff file. + eval_diff(tmp_orig, tmp_new, tmp_diff); ++ return OK; ++ } + else + #endif ++ // Use xdiff for generating the diff. ++ if (dio->dio_internal) ++ { ++ return diff_file_internal(dio); ++ } ++ else + { + len = STRLEN(tmp_orig) + STRLEN(tmp_new) + + STRLEN(tmp_diff) + STRLEN(p_srr) + 27; + cmd = alloc((unsigned)len); +! if (cmd == NULL) +! return FAIL; +! +! // We don't want $DIFF_OPTIONS to get in the way. +! if (getenv("DIFF_OPTIONS")) +! vim_setenv((char_u *)"DIFF_OPTIONS", (char_u *)""); +! +! // Build the diff command and execute it. Always use -a, binary +! // differences are of no use. Ignore errors, diff returns +! // non-zero when differences have been found. +! vim_snprintf((char *)cmd, len, "diff %s%s%s%s%s %s", +! diff_a_works == FALSE ? "" : "-a ", + #if defined(MSWIN) +! diff_bin_works == TRUE ? "--binary " : "", + #else +! "", + #endif +! (diff_flags & DIFF_IWHITE) ? "-b " : "", +! (diff_flags & DIFF_ICASE) ? "-i " : "", +! tmp_orig, tmp_new); +! append_redir(cmd, (int)len, p_srr, tmp_diff); +! block_autocmds(); // avoid ShellCmdPost stuff +! (void)call_shell(cmd, SHELL_FILTER|SHELL_SILENT|SHELL_DOOUT); +! unblock_autocmds(); +! vim_free(cmd); +! return OK; + } + } + +*************** +*** 1282,1370 **** + */ + static void + diff_read( +! int idx_orig, /* idx of original file */ +! int idx_new, /* idx of new file */ +! char_u *fname) /* name of diff output file */ + { +! FILE *fd; + diff_T *dprev = NULL; + diff_T *dp = curtab->tp_first_diff; + diff_T *dn, *dpl; +- long f1, l1, f2, l2; + char_u linebuf[LBUFLEN]; /* only need to hold the diff line */ +! int difftype; +! char_u *p; + long off; + int i; + linenr_T lnum_orig, lnum_new; + long count_orig, count_new; + int notset = TRUE; /* block "*dp" not set yet */ + +! fd = mch_fopen((char *)fname, "r"); +! if (fd == NULL) + { +! EMSG(_("E98: Cannot read diff output")); +! return; + } +! +! for (;;) + { +! if (tag_fgets(linebuf, LBUFLEN, fd)) +! break; /* end of file */ +! if (!isdigit(*linebuf)) +! continue; /* not the start of a diff block */ +! +! /* This line must be one of three formats: +! * {first}[,{last}]c{first}[,{last}] +! * {first}a{first}[,{last}] +! * {first}[,{last}]d{first} +! */ +! p = linebuf; +! f1 = getdigits(&p); +! if (*p == ',') +! { +! ++p; +! l1 = getdigits(&p); +! } +! else +! l1 = f1; +! if (*p != 'a' && *p != 'c' && *p != 'd') +! continue; /* invalid diff format */ +! difftype = *p++; +! f2 = getdigits(&p); +! if (*p == ',') + { +! ++p; +! l2 = getdigits(&p); + } +! else +! l2 = f2; +! if (l1 < f1 || l2 < f2) +! continue; /* invalid line range */ + +! if (difftype == 'a') + { +! lnum_orig = f1 + 1; +! count_orig = 0; + } + else + { +! lnum_orig = f1; +! count_orig = l1 - f1 + 1; + } +! if (difftype == 'd') + { +! lnum_new = f2 + 1; +! count_new = 0; + } + else + { +! lnum_new = f2; +! count_new = l2 - f2 + 1; + } + +! /* Go over blocks before the change, for which orig and new are equal. +! * Copy blocks from orig to new. */ + while (dp != NULL + && lnum_orig > dp->df_lnum[idx_orig] + dp->df_count[idx_orig]) + { +--- 1527,1631 ---- + */ + static void + diff_read( +! int idx_orig, // idx of original file +! int idx_new, // idx of new file +! diffout_T *dout) // diff output + { +! FILE *fd = NULL; +! int line_idx = 0; + diff_T *dprev = NULL; + diff_T *dp = curtab->tp_first_diff; + diff_T *dn, *dpl; + char_u linebuf[LBUFLEN]; /* only need to hold the diff line */ +! char_u *line; + long off; + int i; + linenr_T lnum_orig, lnum_new; + long count_orig, count_new; + int notset = TRUE; /* block "*dp" not set yet */ ++ enum { ++ DIFF_ED, ++ DIFF_UNIFIED, ++ DIFF_NONE ++ } diffstyle = DIFF_NONE; + +! if (dout->dout_fname == NULL) + { +! diffstyle = DIFF_UNIFIED; + } +! else + { +! fd = mch_fopen((char *)dout->dout_fname, "r"); +! if (fd == NULL) + { +! EMSG(_("E98: Cannot read diff output")); +! return; + } +! } + +! for (;;) +! { +! if (fd == NULL) + { +! if (line_idx >= dout->dout_ga.ga_len) +! break; // did last line +! line = ((char_u **)dout->dout_ga.ga_data)[line_idx++]; + } + else + { +! if (tag_fgets(linebuf, LBUFLEN, fd)) +! break; // end of file +! line = linebuf; +! } +! +! if (diffstyle == DIFF_NONE) +! { +! // Determine diff style. +! // ed like diff looks like this: +! // {first}[,{last}]c{first}[,{last}] +! // {first}a{first}[,{last}] +! // {first}[,{last}]d{first} +! // +! // unified diff looks like this: +! // --- file1 2018-03-20 13:23:35.783153140 +0100 +! // +++ file2 2018-03-20 13:23:41.183156066 +0100 +! // @@ -1,3 +1,5 @@ +! if (isdigit(*line)) +! diffstyle = DIFF_ED; +! else if ((STRNCMP(line, "@@ ", 3) == 0)) +! diffstyle = DIFF_UNIFIED; +! else if ((STRNCMP(line, "--- ", 4) == 0) +! && (tag_fgets(linebuf, LBUFLEN, fd) == 0) +! && (STRNCMP(line, "+++ ", 4) == 0) +! && (tag_fgets(linebuf, LBUFLEN, fd) == 0) +! && (STRNCMP(line, "@@ ", 3) == 0)) +! diffstyle = DIFF_UNIFIED; +! } +! +! if (diffstyle == DIFF_ED) +! { +! if (!isdigit(*line)) +! continue; // not the start of a diff block +! if (parse_diff_ed(line, &lnum_orig, &count_orig, +! &lnum_new, &count_new) == FAIL) +! continue; + } +! else if (diffstyle == DIFF_UNIFIED) + { +! if (STRNCMP(line, "@@ ", 3) != 0) +! continue; // not the start of a diff block +! if (parse_diff_unified(line, &lnum_orig, &count_orig, +! &lnum_new, &count_new) == FAIL) +! continue; + } + else + { +! EMSG(_("E959: Invalid diff format.")); +! break; + } + +! // Go over blocks before the change, for which orig and new are equal. +! // Copy blocks from orig to new. + while (dp != NULL + && lnum_orig > dp->df_lnum[idx_orig] + dp->df_count[idx_orig]) + { +*************** +*** 1379,1392 **** + && lnum_orig <= dp->df_lnum[idx_orig] + dp->df_count[idx_orig] + && lnum_orig + count_orig >= dp->df_lnum[idx_orig]) + { +! /* New block overlaps with existing block(s). +! * First find last block that overlaps. */ + for (dpl = dp; dpl->df_next != NULL; dpl = dpl->df_next) + if (lnum_orig + count_orig < dpl->df_next->df_lnum[idx_orig]) + break; + +! /* If the newly found block starts before the old one, set the +! * start back a number of lines. */ + off = dp->df_lnum[idx_orig] - lnum_orig; + if (off > 0) + { +--- 1640,1653 ---- + && lnum_orig <= dp->df_lnum[idx_orig] + dp->df_count[idx_orig] + && lnum_orig + count_orig >= dp->df_lnum[idx_orig]) + { +! // New block overlaps with existing block(s). +! // First find last block that overlaps. + for (dpl = dp; dpl->df_next != NULL; dpl = dpl->df_next) + if (lnum_orig + count_orig < dpl->df_next->df_lnum[idx_orig]) + break; + +! // If the newly found block starts before the old one, set the +! // start back a number of lines. + off = dp->df_lnum[idx_orig] - lnum_orig; + if (off > 0) + { +*************** +*** 1398,1421 **** + } + else if (notset) + { +! /* new block inside existing one, adjust new block */ + dp->df_lnum[idx_new] = lnum_new + off; + dp->df_count[idx_new] = count_new - off; + } + else +! /* second overlap of new block with existing block */ + dp->df_count[idx_new] += count_new - count_orig + + dpl->df_lnum[idx_orig] + dpl->df_count[idx_orig] + - (dp->df_lnum[idx_orig] + dp->df_count[idx_orig]); + +! /* Adjust the size of the block to include all the lines to the +! * end of the existing block or the new diff, whatever ends last. */ + off = (lnum_orig + count_orig) + - (dpl->df_lnum[idx_orig] + dpl->df_count[idx_orig]); + if (off < 0) + { +! /* new change ends in existing block, adjust the end if not +! * done already */ + if (notset) + dp->df_count[idx_new] += -off; + off = 0; +--- 1659,1682 ---- + } + else if (notset) + { +! // new block inside existing one, adjust new block + dp->df_lnum[idx_new] = lnum_new + off; + dp->df_count[idx_new] = count_new - off; + } + else +! // second overlap of new block with existing block + dp->df_count[idx_new] += count_new - count_orig + + dpl->df_lnum[idx_orig] + dpl->df_count[idx_orig] + - (dp->df_lnum[idx_orig] + dp->df_count[idx_orig]); + +! // Adjust the size of the block to include all the lines to the +! // end of the existing block or the new diff, whatever ends last. + off = (lnum_orig + count_orig) + - (dpl->df_lnum[idx_orig] + dpl->df_count[idx_orig]); + if (off < 0) + { +! // new change ends in existing block, adjust the end if not +! // done already + if (notset) + dp->df_count[idx_new] += -off; + off = 0; +*************** +*** 1425,1431 **** + dp->df_count[i] = dpl->df_lnum[i] + dpl->df_count[i] + - dp->df_lnum[i] + off; + +! /* Delete the diff blocks that have been merged into one. */ + dn = dp->df_next; + dp->df_next = dpl->df_next; + while (dn != dp->df_next) +--- 1686,1692 ---- + dp->df_count[i] = dpl->df_lnum[i] + dpl->df_count[i] + - dp->df_lnum[i] + off; + +! // Delete the diff blocks that have been merged into one. + dn = dp->df_next; + dp->df_next = dpl->df_next; + while (dn != dp->df_next) +*************** +*** 1437,1443 **** + } + else + { +! /* Allocate a new diffblock. */ + dp = diff_alloc_new(curtab, dprev, dp); + if (dp == NULL) + goto done; +--- 1698,1704 ---- + } + else + { +! // Allocate a new diffblock. + dp = diff_alloc_new(curtab, dprev, dp); + if (dp == NULL) + goto done; +*************** +*** 1447,1463 **** + dp->df_lnum[idx_new] = lnum_new; + dp->df_count[idx_new] = count_new; + +! /* Set values for other buffers, these must be equal to the +! * original buffer, otherwise there would have been a change +! * already. */ + for (i = idx_orig + 1; i < idx_new; ++i) + if (curtab->tp_diffbuf[i] != NULL) + diff_copy_entry(dprev, dp, idx_orig, i); + } +! notset = FALSE; /* "*dp" has been set */ + } + +! /* for remaining diff blocks orig and new are equal */ + while (dp != NULL) + { + if (notset) +--- 1708,1724 ---- + dp->df_lnum[idx_new] = lnum_new; + dp->df_count[idx_new] = count_new; + +! // Set values for other buffers, these must be equal to the +! // original buffer, otherwise there would have been a change +! // already. + for (i = idx_orig + 1; i < idx_new; ++i) + if (curtab->tp_diffbuf[i] != NULL) + diff_copy_entry(dprev, dp, idx_orig, i); + } +! notset = FALSE; // "*dp" has been set + } + +! // for remaining diff blocks orig and new are equal + while (dp != NULL) + { + if (notset) +*************** +*** 1468,1474 **** + } + + done: +! fclose(fd); + } + + /* +--- 1729,1736 ---- + } + + done: +! if (fd != NULL) +! fclose(fd); + } + + /* +*************** +*** 1860,1865 **** +--- 2122,2128 ---- + int diff_context_new = 6; + int diff_flags_new = 0; + int diff_foldcolumn_new = 2; ++ long diff_algorithm_new = 0; + tabpage_T *tp; + + p = p_dip; +*************** +*** 1905,1910 **** +--- 2168,2208 ---- + p += 9; + diff_flags_new |= DIFF_HIDDEN_OFF; + } ++ else if (STRNCMP(p, "indent-heuristic", 16) == 0) ++ { ++ p += 16; ++ diff_algorithm_new |= XDF_INDENT_HEURISTIC; ++ } ++ else if (STRNCMP(p, "internal", 8) == 0) ++ { ++ p += 8; ++ diff_flags_new |= DIFF_INTERNAL; ++ } ++ else if (STRNCMP(p, "algorithm:", 10) == 0) ++ { ++ p += 10; ++ if (STRNCMP(p, "myers", 5) == 0) ++ { ++ p += 5; ++ diff_algorithm_new = 0; ++ } ++ else if (STRNCMP(p, "minimal", 7) == 0) ++ { ++ p += 7; ++ diff_algorithm_new = XDF_NEED_MINIMAL; ++ } ++ else if (STRNCMP(p, "patience", 8) == 0) ++ { ++ p += 8; ++ diff_algorithm_new = XDF_PATIENCE_DIFF; ++ } ++ else if (STRNCMP(p, "histogram", 9) == 0) ++ { ++ p += 9; ++ diff_algorithm_new = XDF_HISTOGRAM_DIFF; ++ } ++ } ++ + if (*p != ',' && *p != NUL) + return FAIL; + if (*p == ',') +*************** +*** 1916,1928 **** + return FAIL; + + /* If "icase" or "iwhite" was added or removed, need to update the diff. */ +! if (diff_flags != diff_flags_new) + FOR_ALL_TABPAGES(tp) + tp->tp_diff_invalid = TRUE; + + diff_flags = diff_flags_new; + diff_context = diff_context_new; + diff_foldcolumn = diff_foldcolumn_new; + + diff_redraw(TRUE); + +--- 2214,2227 ---- + return FAIL; + + /* If "icase" or "iwhite" was added or removed, need to update the diff. */ +! if (diff_flags != diff_flags_new || diff_algorithm != diff_algorithm_new) + FOR_ALL_TABPAGES(tp) + tp->tp_diff_invalid = TRUE; + + diff_flags = diff_flags_new; + diff_context = diff_context_new; + diff_foldcolumn = diff_foldcolumn_new; ++ diff_algorithm = diff_algorithm_new; + + diff_redraw(TRUE); + +*************** +*** 2690,2693 **** +--- 2989,3144 ---- + return n; + } + ++ /* ++ * Handle an ED style diff line. ++ * Return FAIL if the line does not contain diff info. ++ */ ++ static int ++ parse_diff_ed( ++ char_u *line, ++ linenr_T *lnum_orig, ++ long *count_orig, ++ linenr_T *lnum_new, ++ long *count_new) ++ { ++ char_u *p; ++ long f1, l1, f2, l2; ++ int difftype; ++ ++ // The line must be one of three formats: ++ // change: {first}[,{last}]c{first}[,{last}] ++ // append: {first}a{first}[,{last}] ++ // delete: {first}[,{last}]d{first} ++ p = line; ++ f1 = getdigits(&p); ++ if (*p == ',') ++ { ++ ++p; ++ l1 = getdigits(&p); ++ } ++ else ++ l1 = f1; ++ if (*p != 'a' && *p != 'c' && *p != 'd') ++ return FAIL; // invalid diff format ++ difftype = *p++; ++ f2 = getdigits(&p); ++ if (*p == ',') ++ { ++ ++p; ++ l2 = getdigits(&p); ++ } ++ else ++ l2 = f2; ++ if (l1 < f1 || l2 < f2) ++ return FAIL; ++ ++ if (difftype == 'a') ++ { ++ *lnum_orig = f1 + 1; ++ *count_orig = 0; ++ } ++ else ++ { ++ *lnum_orig = f1; ++ *count_orig = l1 - f1 + 1; ++ } ++ if (difftype == 'd') ++ { ++ *lnum_new = f2 + 1; ++ *count_new = 0; ++ } ++ else ++ { ++ *lnum_new = f2; ++ *count_new = l2 - f2 + 1; ++ } ++ return OK; ++ } ++ ++ /* ++ * Parses unified diff with zero(!) context lines. ++ * Return FAIL if there is no diff information in "line". ++ */ ++ static int ++ parse_diff_unified( ++ char_u *line, ++ linenr_T *lnum_orig, ++ long *count_orig, ++ linenr_T *lnum_new, ++ long *count_new) ++ { ++ char_u *p; ++ long oldline, oldcount, newline, newcount; ++ ++ // Parse unified diff hunk header: ++ // @@ -oldline,oldcount +newline,newcount @@ ++ p = line; ++ if (*p++ == '@' && *p++ == '@' && *p++ == ' ' && *p++ == '-') ++ { ++ oldline = getdigits(&p); ++ if (*p == ',') ++ { ++ ++p; ++ oldcount = getdigits(&p); ++ } ++ else ++ oldcount = 1; ++ if (*p++ == ' ' && *p++ == '+') ++ { ++ newline = getdigits(&p); ++ if (*p == ',') ++ { ++ ++p; ++ newcount = getdigits(&p); ++ } ++ else ++ newcount = 1; ++ } ++ else ++ return FAIL; // invalid diff format ++ ++ if (oldcount == 0) ++ oldline += 1; ++ if (newcount == 0) ++ newline += 1; ++ if (newline == 0) ++ newline = 1; ++ ++ *lnum_orig = oldline; ++ *count_orig = oldcount; ++ *lnum_new = newline; ++ *count_new = newcount; ++ ++ return OK; ++ } ++ ++ return FAIL; ++ } ++ ++ /* ++ * Callback function for the xdl_diff() function. ++ * Stores the diff output in a grow array. ++ */ ++ static int ++ xdiff_out(void *priv, mmbuffer_t *mb, int nbuf) ++ { ++ diffout_T *dout = (diffout_T *)priv; ++ int i; ++ char_u *p; ++ ++ for (i = 0; i < nbuf; i++) ++ { ++ // We are only interested in the header lines, skip text lines. ++ if (STRNCMP(mb[i].ptr, "@@ ", 3) != 0) ++ continue; ++ if (ga_grow(&dout->dout_ga, 1) == FAIL) ++ return -1; ++ p = vim_strnsave((char_u *)mb[i].ptr, mb[i].size); ++ if (p == NULL) ++ return -1; ++ ((char_u **)dout->dout_ga.ga_data)[dout->dout_ga.ga_len++] = p; ++ } ++ return 0; ++ } ++ + #endif /* FEAT_DIFF */ +*** ../vim-8.1.0359/src/structs.h 2018-09-06 16:27:20.664831945 +0200 +--- src/structs.h 2018-09-10 17:36:24.457997346 +0200 +*************** +*** 2433,2439 **** + term_T *b_term; /* When not NULL this buffer is for a terminal + * window. */ + #endif +! + }; /* file_buffer */ + + +--- 2433,2441 ---- + term_T *b_term; /* When not NULL this buffer is for a terminal + * window. */ + #endif +! #ifdef FEAT_DIFF +! int b_diff_failed; // internal diff failed for this buffer +! #endif + }; /* file_buffer */ + + +*** ../vim-8.1.0359/src/testdir/dumps/Test_diff_01.dump 2018-09-10 17:44:36.056826154 +0200 +--- src/testdir/dumps/Test_diff_01.dump 2018-09-10 17:36:51.625695584 +0200 +*************** +*** 0 **** +--- 1,20 ---- ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|0+0#0000000#5fd7ff255| @33 ++ | +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|2+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|2+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|3+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|3+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|4+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|4+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|5+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|5+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|6+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|6+0#0000000#ffffff0| @33 ++ |++0#0000e05#a8a8a8255| |+|-@1| @1|4| |l|i|n|e|s|:| |7|-@19||+1#0000000#ffffff0|++0#0000e05#a8a8a8255| |+|-@1| @1|4| |l|i|n|e|s|:| |7|-@19 ++ | @1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ |X+3#0000000&|f|i|l|e|1| @12|1|,|1| @11|A|l@1| |X+1&&|f|i|l|e|2| @12|1|,|1| @11|A|l@1 ++ |:+0&&> @73 +*** ../vim-8.1.0359/src/testdir/dumps/Test_diff_02.dump 2018-09-10 17:44:36.060826113 +0200 +--- src/testdir/dumps/Test_diff_02.dump 2018-09-10 17:36:51.625695584 +0200 +*************** +*** 0 **** +--- 1,20 ---- ++ | +0#0000e05#a8a8a8255@1|0+0#0000000#5fd7ff255| @33||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34 ++ | +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|2+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|2+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|3+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|3+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|4+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|4+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|5+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|5+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|6+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|6+0#0000000#ffffff0| @33 ++ |++0#0000e05#a8a8a8255| |+|-@1| @1|4| |l|i|n|e|s|:| |7|-@19||+1#0000000#ffffff0|++0#0000e05#a8a8a8255| |+|-@1| @1|4| |l|i|n|e|s|:| |7|-@19 ++ | @1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ |X+3#0000000&|f|i|l|e|1| @12|1|,|1| @11|A|l@1| |X+1&&|f|i|l|e|2| @12|1|,|1| @11|A|l@1 ++ |:+0&&> @73 +*** ../vim-8.1.0359/src/testdir/dumps/Test_diff_03.dump 2018-09-10 17:44:36.064826075 +0200 +--- src/testdir/dumps/Test_diff_03.dump 2018-09-10 17:36:51.625695584 +0200 +*************** +*** 0 **** +--- 1,20 ---- ++ |++0#0000e05#a8a8a8255| |+|-@1| @1|4| |l|i|n|e|s|:| |1|-@19||+1#0000000#ffffff0|++0#0000e05#a8a8a8255| |+|-@1| @1|4| |l|i|n|e|s|:| |1|-@19 ++ | @1|5+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|5+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|6+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|6+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|7+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|7+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|8+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|8+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|9+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|9+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0|0| @32||+1&&| +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0|0| @32 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|1+0#0000000#5fd7ff255@1| @32 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ |X+3#0000000&|f|i|l|e|1| @12|1|,|1| @11|A|l@1| |X+1&&|f|i|l|e|2| @12|1|,|1| @11|A|l@1 ++ |:+0&&> @73 +*** ../vim-8.1.0359/src/testdir/dumps/Test_diff_04.dump 2018-09-10 17:44:36.068826034 +0200 +--- src/testdir/dumps/Test_diff_04.dump 2018-09-10 17:36:51.625695584 +0200 +*************** +*** 0 **** +--- 1,20 ---- ++ |++0#0000e05#a8a8a8255| |+|-@1| @1|4| |l|i|n|e|s|:| |1|-@19||+1#0000000#ffffff0|++0#0000e05#a8a8a8255| |+|-@1| @1|4| |l|i|n|e|s|:| |1|-@19 ++ | @1|5+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|5+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|6+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|6+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|7+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|7+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|8+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|8+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|9+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|9+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0|0| @32||+1&&| +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0|0| @32 ++ | +0#0000e05#a8a8a8255@1|1+0#0000000#5fd7ff255@1| @32||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ |X+3#0000000&|f|i|l|e|1| @12|1|,|1| @11|A|l@1| |X+1&&|f|i|l|e|2| @12|1|,|1| @11|A|l@1 ++ |:+0&&> @73 +*** ../vim-8.1.0359/src/testdir/dumps/Test_diff_05.dump 2018-09-10 17:44:36.072825994 +0200 +--- src/testdir/dumps/Test_diff_05.dump 2018-09-10 17:36:51.625695584 +0200 +*************** +*** 0 **** +--- 1,20 ---- ++ | +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|2+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|2+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|3+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|3+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|4+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|4+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|4+0#0000000#5fd7ff255| @33 ++ | +0#0000e05#a8a8a8255@1|5+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|5+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|6+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|6+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|7+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|7+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|8+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|8+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|9+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|9+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0|0| @32||+1&&| +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0|0| @32 ++ | +0#0000e05#a8a8a8255@1|1+0#0000000#5fd7ff255@1| @32||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ |X+3#0000000&|f|i|l|e|1| @12|1|,|1| @11|A|l@1| |X+1&&|f|i|l|e|2| @12|1|,|1| @11|A|l@1 ++ |:+0&&> @73 +*** ../vim-8.1.0359/src/testdir/dumps/Test_diff_06.dump 2018-09-10 17:44:36.072825994 +0200 +--- src/testdir/dumps/Test_diff_06.dump 2018-09-10 17:36:51.625695584 +0200 +*************** +*** 0 **** +--- 1,20 ---- ++ | +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|2+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|2+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|3+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|3+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|4+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|4+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|4+0#0000000#5fd7ff255| @33||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34 ++ | +0#0000e05#a8a8a8255@1|5+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|5+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|6+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|6+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|7+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|7+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|8+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|8+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|9+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|9+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0|0| @32||+1&&| +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0|0| @32 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|1+0#0000000#5fd7ff255@1| @32 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ |X+3#0000000&|f|i|l|e|1| @12|1|,|1| @11|A|l@1| |X+1&&|f|i|l|e|2| @12|1|,|1| @11|A|l@1 ++ |:+0&&> @73 +*** ../vim-8.1.0359/src/testdir/dumps/Test_diff_07.dump 2018-09-10 17:44:36.076825953 +0200 +--- src/testdir/dumps/Test_diff_07.dump 2018-09-10 17:36:51.625695584 +0200 +*************** +*** 0 **** +--- 1,20 ---- ++ | +0#0000e05#a8a8a8255@1>#+0#0000000#ffffff0|i|n|c|l|u|d|e| |<|s|t|d|i|o|.|h|>| @16||+1&&| +0#0000e05#a8a8a8255@1|#+0#0000000#ffffff0|i|n|c|l|u|d|e| |<|s|t|d|i|o|.|h|>| @16 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34 ++ | +0#0000e05#a8a8a8255@1|/+2#0000000#ff404010@1| |F|r|o|b|s| |f|o@1| |h|e|a|r|t|i|l|y| +0&#ffd7ff255@13||+1&#ffffff0| +0#0000e05#a8a8a8255@1|i+2#0000000#ff404010|n|t| |f|i|b|(|i|n|t| |n|)| +0&#ffd7ff255@20 ++ | +0#0000e05#a8a8a8255@1|i+0#0000000#5fd7ff255|n|t| |f|r|o|b|n|i|t|z|(|i|n|t| |f|o@1|)| @13||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34 ++ | +0#0000e05#a8a8a8255@1|{+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|{+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@3|i|n+2&#ff404010|t| |i|;| +0&#ffd7ff255@24||+1&#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@3|i|f+2&#ff404010|(|n| |>| |2|)| +0&#ffd7ff255@21 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@3|f|o|r|(|i| |=| |0|;| |i| |<| |1|0|;| |i|+@1|)| @7||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|{| @29||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|{| @29 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@7|p+2&#ff404010|r|i|n|t|f|(|"|Y|o|u|r| |a|n|s|w|e|r| |i|s|:| |"|)+0&#ffd7ff255|;||+1&#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@7|r+2&#ff404010|e|t|u|r|n| |f|i|b|(|n|-|1|)| |+| |f|i|b|(|n|-|2|)+0&#ffd7ff255|; ++ | +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@7|p|r|i|n|t|f|(|"|%|d|\|n|"|,| |f|o@1|)|;| @6||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|}| @29||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|}| @29 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@3|r|e|t|u|r|n| |1|;| @21 ++ | +0#0000e05#a8a8a8255@1|}+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|}+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34 ++ | +0#0000e05#a8a8a8255@1|i+2#0000000#ff404010|n|t| |f|a|c|t|(|i|n|t| |n|)| +0&#ffd7ff255@19||+1&#ffffff0| +0#0000e05#a8a8a8255@1|/+2#0000000#ff404010@1| |F|r|o|b|s| |f|o@1| |h|e|a|r|t|i|l|y| +0&#ffd7ff255@13 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|i+0#0000000#5fd7ff255|n|t| |f|r|o|b|n|i|t|z|(|i|n|t| |f|o@1|)| @13 ++ | +0#0000e05#a8a8a8255@1|{+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|{+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@3|i|f+2&#ff404010|(|n| |>| |1|)| +0&#ffd7ff255@21||+1&#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@3|i|n+2&#ff404010|t| |i|;| +0&#ffd7ff255@24 ++ |X+3&#ffffff0|f|i|l|e|1| @12|1|,|1| @11|T|o|p| |X+1&&|f|i|l|e|2| @12|1|,|1| @11|T|o|p ++ |:+0&&|s|e|t| |d|i|f@1|o|p|t|+|=|i|n|t|e|r|n|a|l| @52 +*** ../vim-8.1.0359/src/testdir/dumps/Test_diff_08.dump 2018-09-10 17:44:36.080825913 +0200 +--- src/testdir/dumps/Test_diff_08.dump 2018-09-10 17:36:51.625695584 +0200 +*************** +*** 0 **** +--- 1,20 ---- ++ | +0#0000e05#a8a8a8255@1>#+0#0000000#ffffff0|i|n|c|l|u|d|e| |<|s|t|d|i|o|.|h|>| @16||+1&&| +0#0000e05#a8a8a8255@1|#+0#0000000#ffffff0|i|n|c|l|u|d|e| |<|s|t|d|i|o|.|h|>| @16 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|i+0#0000000#5fd7ff255|n|t| |f|i|b|(|i|n|t| |n|)| @20 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|{+0#0000000#5fd7ff255| @33 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@3|i|f|(|n| |>| |2|)| @21 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@3|{| @29 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@7|r|e|t|u|r|n| |f|i|b|(|n|-|1|)| |+| |f|i|b|(|n|-|2|)|; ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@3|}| @29 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@3|r|e|t|u|r|n| |1|;| @21 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|}+0#0000000#5fd7ff255| @33 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@34 ++ | +0#0000e05#a8a8a8255@1|/+0#0000000#ffffff0@1| |F|r|o|b|s| |f|o@1| |h|e|a|r|t|i|l|y| @13||+1&&| +0#0000e05#a8a8a8255@1|/+0#0000000#ffffff0@1| |F|r|o|b|s| |f|o@1| |h|e|a|r|t|i|l|y| @13 ++ | +0#0000e05#a8a8a8255@1|i+0#0000000#ffffff0|n|t| |f|r|o|b|n|i|t|z|(|i|n|t| |f|o@1|)| @13||+1&&| +0#0000e05#a8a8a8255@1|i+0#0000000#ffffff0|n|t| |f|r|o|b|n|i|t|z|(|i|n|t| |f|o@1|)| @13 ++ | +0#0000e05#a8a8a8255@1|{+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|{+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|i|n|t| |i|;| @24||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|i|n|t| |i|;| @24 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|f|o|r|(|i| |=| |0|;| |i| |<| |1|0|;| |i|+@1|)| @7||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|f|o|r|(|i| |=| |0|;| |i| |<| |1|0|;| |i|+@1|)| @7 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|{| @29||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|{| @29 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@7|p|r|i|n|t|f|(|"|Y|o|u|r| |a|n|s|w|e|r| |i|s|:| |"|)|;||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34 ++ |X+3#0000000#ffffff0|f|i|l|e|1| @12|1|,|1| @11|T|o|p| |X+1&&|f|i|l|e|2| @12|1|,|1| @11|T|o|p ++ |:+0&&|s|e|t| |d|i|f@1|o|p|t|+|=|a|l|g|o|r|i|t|h|m|:|p|a|t|i|e|n|c|e| @42 +*** ../vim-8.1.0359/src/testdir/dumps/Test_diff_09.dump 2018-09-10 17:44:36.084825872 +0200 +--- src/testdir/dumps/Test_diff_09.dump 2018-09-10 17:36:51.625695584 +0200 +*************** +*** 0 **** +--- 1,20 ---- ++ | +0#0000e05#a8a8a8255@1>#+0#0000000#ffffff0|i|n|c|l|u|d|e| |<|s|t|d|i|o|.|h|>| @16||+1&&| +0#0000e05#a8a8a8255@1|#+0#0000000#ffffff0|i|n|c|l|u|d|e| |<|s|t|d|i|o|.|h|>| @16 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|i+0#0000000#5fd7ff255|n|t| |f|i|b|(|i|n|t| |n|)| @20 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|{+0#0000000#5fd7ff255| @33 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@3|i|f|(|n| |>| |2|)| @21 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@3|{| @29 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@7|r|e|t|u|r|n| |f|i|b|(|n|-|1|)| |+| |f|i|b|(|n|-|2|)|; ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@3|}| @29 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@3|r|e|t|u|r|n| |1|;| @21 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|}+0#0000000#5fd7ff255| @33 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@34 ++ | +0#0000e05#a8a8a8255@1|/+0#0000000#ffffff0@1| |F|r|o|b|s| |f|o@1| |h|e|a|r|t|i|l|y| @13||+1&&| +0#0000e05#a8a8a8255@1|/+0#0000000#ffffff0@1| |F|r|o|b|s| |f|o@1| |h|e|a|r|t|i|l|y| @13 ++ | +0#0000e05#a8a8a8255@1|i+0#0000000#ffffff0|n|t| |f|r|o|b|n|i|t|z|(|i|n|t| |f|o@1|)| @13||+1&&| +0#0000e05#a8a8a8255@1|i+0#0000000#ffffff0|n|t| |f|r|o|b|n|i|t|z|(|i|n|t| |f|o@1|)| @13 ++ | +0#0000e05#a8a8a8255@1|{+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|{+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|i|n|t| |i|;| @24||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|i|n|t| |i|;| @24 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|f|o|r|(|i| |=| |0|;| |i| |<| |1|0|;| |i|+@1|)| @7||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|f|o|r|(|i| |=| |0|;| |i| |<| |1|0|;| |i|+@1|)| @7 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|{| @29||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|{| @29 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@7|p|r|i|n|t|f|(|"|Y|o|u|r| |a|n|s|w|e|r| |i|s|:| |"|)|;||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34 ++ |X+3#0000000#ffffff0|f|i|l|e|1| @12|1|,|1| @11|T|o|p| |X+1&&|f|i|l|e|2| @12|1|,|1| @11|T|o|p ++ |:+0&&|s|e|t| |d|i|f@1|o|p|t|+|=|a|l|g|o|r|i|t|h|m|:|p|a|t|i|e|n|c|e| @42 +*** ../vim-8.1.0359/src/testdir/dumps/Test_diff_10.dump 2018-09-10 17:44:36.088825834 +0200 +--- src/testdir/dumps/Test_diff_10.dump 2018-09-10 17:36:51.625695584 +0200 +*************** +*** 0 **** +--- 1,20 ---- ++ | +0#0000e05#a8a8a8255@1> +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@1|d|e|f| |f|i|n|a|l|i|z|e|(|v|a|l|u|e|s|)| @12||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@1|d|e|f| |f|i|n|a|l|i|z|e|(|v|a|l|u|e|s|)| @12 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|v|a|l|u|e|s|.|e|a|c|h| |d|o| |||v||| @12||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|v|a|l|u|e|s|.|e|a|c|h| |d|o| |||v||| @12 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@5|v|.|p|r|e|p|a|r|e| @19 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@3|e|n|d| @27 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@34 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@3|v|a|l|u|e|s|.|e|a|c|h| |d|o| |||v||| @12 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@5|v|.|f|i|n|a|l|i|z|e| @18||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@5|v|.|f|i|n|a|l|i|z|e| @18 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|e|n|d| @27||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|e|n|d| @27 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ |X+3#0000000&|f|i|l|e|1| @12|1|,|0|-|1| @9|A|l@1| |X+1&&|f|i|l|e|2| @12|1|,|0|-|1| @9|A|l@1 ++ |:+0&&|s|e|t| |d|i|f@1|o|p|t|+|=|i|n|t|e|r|n|a|l| @52 +*** ../vim-8.1.0359/src/testdir/dumps/Test_diff_11.dump 2018-09-10 17:44:36.092825793 +0200 +--- src/testdir/dumps/Test_diff_11.dump 2018-09-10 17:36:51.625695584 +0200 +*************** +*** 0 **** +--- 1,20 ---- ++ | +0#0000e05#a8a8a8255@1> +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@1|d|e|f| |f|i|n|a|l|i|z|e|(|v|a|l|u|e|s|)| @12||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@1|d|e|f| |f|i|n|a|l|i|z|e|(|v|a|l|u|e|s|)| @12 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@3|v|a|l|u|e|s|.|e|a|c|h| |d|o| |||v||| @12 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@5|v|.|p|r|e|p|a|r|e| @19 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@3|e|n|d| @27 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@34 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|v|a|l|u|e|s|.|e|a|c|h| |d|o| |||v||| @12||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|v|a|l|u|e|s|.|e|a|c|h| |d|o| |||v||| @12 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@5|v|.|f|i|n|a|l|i|z|e| @18||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@5|v|.|f|i|n|a|l|i|z|e| @18 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|e|n|d| @27||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|e|n|d| @27 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ |X+3#0000000&|f|i|l|e|1| @12|1|,|0|-|1| @9|A|l@1| |X+1&&|f|i|l|e|2| @12|1|,|0|-|1| @9|A|l@1 ++ |:+0&&|s|e|t| |d|i|f@1|o|p|t|+|=|i|n|d|e|n|t|-|h|e|u|r|i|s|t|i|c| @44 +*** ../vim-8.1.0359/src/testdir/dumps/Test_diff_12.dump 2018-09-10 17:44:36.096825753 +0200 +--- src/testdir/dumps/Test_diff_12.dump 2018-09-10 17:36:51.625695584 +0200 +*************** +*** 0 **** +--- 1,20 ---- ++ |++0#0000e05#a8a8a8255| |+|-@1| |1|0| |l|i|n|e|s|:| |1|-@19||+1#0000000#ffffff0|++0#0000e05#a8a8a8255| |+|-@1| |1|0| |l|i|n|e|s|:| |1|-@19 ++ | @1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ |X+3#0000000&|f|i|l|e|1| @12|1|,|1| @11|A|l@1| |X+1&&|f|i|l|e|2| @12|1|,|1| @11|A|l@1 ++ |:+0&&> @73 +*** ../vim-8.1.0359/src/testdir/dumps/Test_diff_13.dump 2018-09-10 17:44:36.096825753 +0200 +--- src/testdir/dumps/Test_diff_13.dump 2018-09-10 17:36:51.625695584 +0200 +*************** +*** 0 **** +--- 1,20 ---- ++ |-+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@34||+1&&|-+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@34 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ |X+3#0000000&|f|i|l|e|1| @12|0|,|0|-|1| @9|A|l@1| |X+1&&|f|i|l|e|2| @12|0|,|0|-|1| @9|A|l@1 ++ |:+0&&> @73 +*** ../vim-8.1.0359/src/testdir/dumps/Test_diff_14.dump 2018-09-10 17:44:36.100825712 +0200 +--- src/testdir/dumps/Test_diff_14.dump 2018-09-10 17:36:51.625695584 +0200 +*************** +*** 0 **** +--- 1,20 ---- ++ | +0#0000e05#a8a8a8255@1|a+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|b+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|b+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|c+0#0000000#ffd7ff255|d| @32||+1&#ffffff0| +0#0000e05#a8a8a8255@1|c+0#0000000#ffd7ff255|D|e+2&#ff404010| +0&#ffd7ff255@31 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ |X+3#0000000&|f|i|l|e|1| @12|1|,|1| @11|A|l@1| |X+1&&|f|i|l|e|2| @12|1|,|1| @11|A|l@1 ++ |:+0&&> @73 +*** ../vim-8.1.0359/src/testdir/dumps/Test_diff_15.dump 2018-09-10 17:44:36.104825672 +0200 +--- src/testdir/dumps/Test_diff_15.dump 2018-09-10 17:36:51.625695584 +0200 +*************** +*** 0 **** +--- 1,20 ---- ++ | +0#0000e05#a8a8a8255@1>i+0#0000000#ffffff0|n|t| |m|a|i|n|(|)| @24||+1&&| +0#0000e05#a8a8a8255@1|i+0#0000000#ffffff0|n|t| |m|a|i|n|(|)| @24 ++ | +0#0000e05#a8a8a8255@1|{+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|{+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@2|i|f| |(|0|)| @25 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@2|{| @30 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@2|p|r|i|n|t|f|(|"|H|e|l@1|o|,| |W|o|r|l|d|!|"|)|;| @7||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@5|p|r|i|n|t|f|(|"|H|e|l@1|o|,| |W|o|r|l|d|!|"|)|;| @4 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@2|r|e|t|u|r|n| |0|;| @22||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@5|r|e|t|u|r|n| |0|;| @19 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@2|}| @30 ++ | +0#0000e05#a8a8a8255@1|}+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|}+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ |X+3#0000000&|f|i|l|e|1| @12|1|,|1| @11|A|l@1| |X+1&&|f|i|l|e|2| @12|1|,|1| @11|A|l@1 ++ |:+0&&|s|e|t| |d|i|f@1|o|p|t|&|v|i|m| |d|i|f@1|o|p|t|+|=|f|i|l@1|e|r| |d|i|f@1|o|p|t|+|=|i|w|h|i|t|e| @26 +*** ../vim-8.1.0359/src/testdir/dumps/Test_diff_16.dump 2018-09-10 17:44:36.108825631 +0200 +--- src/testdir/dumps/Test_diff_16.dump 2018-09-10 17:36:51.625695584 +0200 +*************** +*** 0 **** +--- 1,20 ---- ++ | +0#0000e05#a8a8a8255@1>i+0#0000000#ffffff0|n|t| |m|a|i|n|(|)| @24||+1&&| +0#0000e05#a8a8a8255@1|i+0#0000000#ffffff0|n|t| |m|a|i|n|(|)| @24 ++ | +0#0000e05#a8a8a8255@1|{+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|{+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@2|i|f| |(|0|)| @25 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@2|{| @30 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@2|p|r|i|n|t|f|(|"|H|e|l@1|o|,| |W|o|r|l|d|!|"|)|;| @7||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@5|p|r|i|n|t|f|(|"|H|e|l@1|o|,| |W|o|r|l|d|!|"|)|;| @4 ++ | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@2|r|e|t|u|r|n| |0|;| @22||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@5|r|e|t|u|r|n| |0|;| @19 ++ | +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@2|}| @30 ++ | +0#0000e05#a8a8a8255@1|}+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|}+0#0000000#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ | +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33||+1#0000000&| +0#0000e05#a8a8a8255@1|~+0#4040ff13#ffffff0| @33 ++ |X+3#0000000&|f|i|l|e|1| @12|1|,|1| @11|A|l@1| |X+1&&|f|i|l|e|2| @12|1|,|1| @11|A|l@1 ++ |:+0&&|s|e|t| |d|i|f@1|o|p|t|+|=|i|n|t|e|r|n|a|l| @52 +*** ../vim-8.1.0359/src/testdir/test_diffmode.vim 2017-12-01 20:25:59.000000000 +0100 +--- src/testdir/test_diffmode.vim 2018-09-10 17:38:33.584583735 +0200 +*************** +*** 1,4 **** +--- 1,6 ---- + " Tests for diff mode ++ source shared.vim ++ source screendump.vim + + func Test_diff_fold_sync() + enew! +*************** +*** 33,38 **** +--- 35,52 ---- + endfunc + + func Test_vert_split() ++ set diffopt=filler ++ call Common_vert_split() ++ set diffopt& ++ endfunc ++ ++ func Test_vert_split_internal() ++ set diffopt=internal,filler ++ call Common_vert_split() ++ set diffopt& ++ endfunc ++ ++ func Common_vert_split() + " Disable the title to avoid xterm keeping the wrong one. + set notitle noicon + new +*************** +*** 275,284 **** + bwipe! + endfunc + +! func Test_diffopt_icase() +! set diffopt=icase,foldcolumn:0 +! +! e one + call setline(1, ['One', 'Two', 'Three', 'Four', 'Fi#ve']) + redraw + let normattr = screenattr(1, 1) +--- 295,302 ---- + bwipe! + endfunc + +! func Common_icase_test() +! edit one + call setline(1, ['One', 'Two', 'Three', 'Four', 'Fi#ve']) + redraw + let normattr = screenattr(1, 1) +*************** +*** 300,331 **** + + diffoff! + %bwipe! + set diffopt& + endfunc + +! func Test_diffopt_iwhite() +! set diffopt=iwhite,foldcolumn:0 + +! e one +! " Difference in trailing spaces should be ignored, + " but not other space differences. +! call setline(1, ["One \t", 'Two', 'Three', 'Four']) + redraw + let normattr = screenattr(1, 1) + diffthis + + botright vert new two +! call setline(1, ["One\t ", "Two\t ", 'Three', ' Four']) + diffthis + + redraw + call assert_equal(normattr, screenattr(1, 1)) + call assert_equal(normattr, screenattr(2, 1)) + call assert_equal(normattr, screenattr(3, 1)) +! call assert_notequal(normattr, screenattr(4, 1)) + + diffoff! + %bwipe! + set diffopt& + endfunc + +--- 318,371 ---- + + diffoff! + %bwipe! ++ endfunc ++ ++ func Test_diffopt_icase() ++ set diffopt=icase,foldcolumn:0 ++ call Common_icase_test() + set diffopt& + endfunc + +! func Test_diffopt_icase_internal() +! set diffopt=icase,foldcolumn:0,internal +! call Common_icase_test() +! set diffopt& +! endfunc + +! func Common_iwhite_test() +! edit one +! " Difference in trailing spaces and amount of spaces should be ignored, + " but not other space differences. +! call setline(1, ["One \t", 'Two', 'Three', 'one two', 'one two', 'Four']) + redraw + let normattr = screenattr(1, 1) + diffthis + + botright vert new two +! call setline(1, ["One\t ", "Two\t ", 'Three', 'one two', 'onetwo', ' Four']) + diffthis + + redraw + call assert_equal(normattr, screenattr(1, 1)) + call assert_equal(normattr, screenattr(2, 1)) + call assert_equal(normattr, screenattr(3, 1)) +! call assert_equal(normattr, screenattr(4, 1)) +! call assert_notequal(normattr, screenattr(5, 1)) +! call assert_notequal(normattr, screenattr(6, 1)) + + diffoff! + %bwipe! ++ endfunc ++ ++ func Test_diffopt_iwhite() ++ set diffopt=iwhite,foldcolumn:0 ++ call Common_iwhite_test() ++ set diffopt& ++ endfunc ++ ++ func Test_diffopt_iwhite_internal() ++ set diffopt=internal,iwhite,foldcolumn:0 ++ call Common_iwhite_test() + set diffopt& + endfunc + +*************** +*** 339,346 **** +--- 379,391 ---- + + set diffopt=context:2 + call assert_equal('+-- 2 lines: 1', foldtextresult(1)) ++ set diffopt=internal,context:2 ++ call assert_equal('+-- 2 lines: 1', foldtextresult(1)) ++ + set diffopt=context:1 + call assert_equal('+-- 3 lines: 1', foldtextresult(1)) ++ set diffopt=internal,context:1 ++ call assert_equal('+-- 3 lines: 1', foldtextresult(1)) + + diffoff! + %bwipe! +*************** +*** 348,354 **** + endfunc + + func Test_diffopt_horizontal() +! set diffopt=horizontal + diffsplit + + call assert_equal(&columns, winwidth(1)) +--- 393,399 ---- + endfunc + + func Test_diffopt_horizontal() +! set diffopt=internal,horizontal + diffsplit + + call assert_equal(&columns, winwidth(1)) +*************** +*** 362,368 **** + endfunc + + func Test_diffopt_vertical() +! set diffopt=vertical + diffsplit + + call assert_equal(&lines - 2, winheight(1)) +--- 407,413 ---- + endfunc + + func Test_diffopt_vertical() +! set diffopt=internal,vertical + diffsplit + + call assert_equal(&lines - 2, winheight(1)) +*************** +*** 376,382 **** + endfunc + + func Test_diffopt_hiddenoff() +! set diffopt=filler,foldcolumn:0,hiddenoff + e! one + call setline(1, ['Two', 'Three']) + redraw +--- 421,427 ---- + endfunc + + func Test_diffopt_hiddenoff() +! set diffopt=internal,filler,foldcolumn:0,hiddenoff + e! one + call setline(1, ['Two', 'Three']) + redraw +*************** +*** 399,405 **** + endfunc + + func Test_diffoff_hidden() +! set diffopt=filler,foldcolumn:0 + e! one + call setline(1, ['Two', 'Three']) + redraw +--- 444,450 ---- + endfunc + + func Test_diffoff_hidden() +! set diffopt=internal,filler,foldcolumn:0 + e! one + call setline(1, ['Two', 'Three']) + redraw +*************** +*** 629,631 **** +--- 674,791 ---- + bwipe! + bwipe! + endfunc ++ ++ func WriteDiffFiles(list1, list2) ++ call writefile(a:list1, 'Xfile1') ++ call writefile(a:list2, 'Xfile2') ++ endfunc ++ ++ " Verify a screendump with both the external and external diff. ++ func VerifyBoth(buf, dumpfile, extra) ++ call term_sendkeys(a:buf, ":diffupdate!\<cr>") ++ " trailing : for leaving the cursor on the command line ++ for cmd in [":set diffopt=filler" . a:extra . "\<cr>:", ":set diffopt+=internal\<cr>:"] ++ call term_sendkeys(a:buf, cmd) ++ if VerifyScreenDump(a:buf, a:dumpfile, {}, cmd =~ 'internal' ? 'internal' : 'external') ++ break " don't let the next iteration overwrite the "failed" file. ++ endif ++ endfor ++ endfunc ++ ++ func Test_diff_screen() ++ if !CanRunVimInTerminal() || !has('menu') ++ return ++ endif ++ " clean up already existing swap files, just in case ++ call delete('.Xfile1.swp') ++ call delete('.Xfile2.swp') ++ ++ " Test 1: Add a line in beginning of file 2 ++ call WriteDiffFiles([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) ++ let buf = RunVimInTerminal('-d Xfile1 Xfile2', {}) ++ " Set autoread mode, ,so that Vim won't complain once we re-write the test ++ " files ++ call term_sendkeys(buf, ":set autoread\<cr>\<c-w>w:set autoread\<cr>\<c-w>w") ++ ++ call VerifyBoth(buf, 'Test_diff_01', '') ++ ++ " Test 2: Add a line in beginning of file 1 ++ call WriteDiffFiles([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) ++ call VerifyBoth(buf, 'Test_diff_02', '') ++ ++ " Test 3: Add a line at the end of file 2 ++ call WriteDiffFiles([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) ++ call VerifyBoth(buf, 'Test_diff_03', '') ++ ++ " Test 4: Add a line at the end of file 1 ++ call WriteDiffFiles([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) ++ call VerifyBoth(buf, 'Test_diff_04', '') ++ ++ " Test 5: Add a line in the middle of file 2, remove on at the end of file 1 ++ call WriteDiffFiles([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10]) ++ call VerifyBoth(buf, 'Test_diff_05', '') ++ ++ " Test 6: Add a line in the middle of file 1, remove on at the end of file 2 ++ call WriteDiffFiles([1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) ++ call VerifyBoth(buf, 'Test_diff_06', '') ++ ++ " Test 7 - 9: Test normal/patience/histogram diff algorithm ++ call WriteDiffFiles(['#include <stdio.h>', '', '// Frobs foo heartily', 'int frobnitz(int foo)', '{', ++ \ ' int i;', ' for(i = 0; i < 10; i++)', ' {', ' printf("Your answer is: ");', ++ \ ' printf("%d\n", foo);', ' }', '}', '', 'int fact(int n)', '{', ' if(n > 1)', ' {', ++ \ ' return fact(n-1) * n;', ' }', ' return 1;', '}', '', 'int main(int argc, char **argv)', ++ \ '{', ' frobnitz(fact(10));', '}'], ++ \ ['#include <stdio.h>', '', 'int fib(int n)', '{', ' if(n > 2)', ' {', ++ \ ' return fib(n-1) + fib(n-2);', ' }', ' return 1;', '}', '', '// Frobs foo heartily', ++ \ 'int frobnitz(int foo)', '{', ' int i;', ' for(i = 0; i < 10; i++)', ' {', ++ \ ' printf("%d\n", foo);', ' }', '}', '', ++ \ 'int main(int argc, char **argv)', '{', ' frobnitz(fib(10));', '}']) ++ call term_sendkeys(buf, ":diffupdate!\<cr>") ++ call term_sendkeys(buf, ":set diffopt+=internal\<cr>") ++ call VerifyScreenDump(buf, 'Test_diff_07', {}) ++ ++ call term_sendkeys(buf, ":set diffopt+=algorithm:patience\<cr>") ++ call VerifyScreenDump(buf, 'Test_diff_08', {}) ++ ++ call term_sendkeys(buf, ":set diffopt+=algorithm:histogram\<cr>") ++ call VerifyScreenDump(buf, 'Test_diff_09', {}) ++ ++ " Test 10-11: normal/indent-heuristic ++ call term_sendkeys(buf, ":set diffopt&vim\<cr>") ++ call WriteDiffFiles(['', ' def finalize(values)', '', ' values.each do |v|', ' v.finalize', ' end'], ++ \ ['', ' def finalize(values)', '', ' values.each do |v|', ' v.prepare', ' end', '', ++ \ ' values.each do |v|', ' v.finalize', ' end']) ++ call term_sendkeys(buf, ":diffupdate!\<cr>") ++ call term_sendkeys(buf, ":set diffopt+=internal\<cr>") ++ call VerifyScreenDump(buf, 'Test_diff_10', {}) ++ ++ call term_sendkeys(buf, ":set diffopt+=indent-heuristic\<cr>") ++ call VerifyScreenDump(buf, 'Test_diff_11', {}) ++ ++ " Test 12: diff the same file ++ call WriteDiffFiles([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) ++ call VerifyBoth(buf, 'Test_diff_12', '') ++ ++ " Test 13: diff an empty file ++ call WriteDiffFiles([], []) ++ call VerifyBoth(buf, 'Test_diff_13', '') ++ ++ " Test 14: test diffopt+=icase ++ call WriteDiffFiles(['a', 'b', 'cd'], ['A', 'b', 'cDe']) ++ call VerifyBoth(buf, 'Test_diff_14', " diffopt+=filler diffopt+=icase") ++ ++ " Test 15-16: test diffopt+=iwhite ++ call WriteDiffFiles(['int main()', '{', ' printf("Hello, World!");', ' return 0;', '}'], ++ \ ['int main()', '{', ' if (0)', ' {', ' printf("Hello, World!");', ' return 0;', ' }', '}']) ++ call term_sendkeys(buf, ":diffupdate!\<cr>") ++ call term_sendkeys(buf, ":set diffopt&vim diffopt+=filler diffopt+=iwhite\<cr>") ++ call VerifyScreenDump(buf, 'Test_diff_15', {}) ++ call term_sendkeys(buf, ":set diffopt+=internal\<cr>") ++ call VerifyScreenDump(buf, 'Test_diff_16', {}) ++ ++ " clean up ++ call StopVimInTerminal(buf) ++ call delete('Xfile1') ++ call delete('Xfile2') ++ endfunc ++ +*** ../vim-8.1.0359/src/xdiff/COPYING 1970-01-01 01:00:00.000000000 +0100 +--- src/xdiff/COPYING 2018-09-10 17:39:20.324083781 +0200 +*************** +*** 0 **** +--- 1,504 ---- ++ GNU LESSER GENERAL PUBLIC LICENSE ++ Version 2.1, February 1999 ++ ++ Copyright (C) 1991, 1999 Free Software Foundation, Inc. ++ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ Everyone is permitted to copy and distribute verbatim copies ++ of this license document, but changing it is not allowed. ++ ++ [This is the first released version of the Lesser GPL. It also counts ++ as the successor of the GNU Library Public License, version 2, hence ++ the version number 2.1.] ++ ++ Preamble ++ ++ The licenses for most software are designed to take away your ++ freedom to share and change it. By contrast, the GNU General Public ++ Licenses are intended to guarantee your freedom to share and change ++ free software--to make sure the software is free for all its users. ++ ++ This license, the Lesser General Public License, applies to some ++ specially designated software packages--typically libraries--of the ++ Free Software Foundation and other authors who decide to use it. You ++ can use it too, but we suggest you first think carefully about whether ++ this license or the ordinary General Public License is the better ++ strategy to use in any particular case, based on the explanations below. ++ ++ When we speak of free software, we are referring to freedom of use, ++ not price. Our General Public Licenses are designed to make sure that ++ you have the freedom to distribute copies of free software (and charge ++ for this service if you wish); that you receive source code or can get ++ it if you want it; that you can change the software and use pieces of ++ it in new free programs; and that you are informed that you can do ++ these things. ++ ++ To protect your rights, we need to make restrictions that forbid ++ distributors to deny you these rights or to ask you to surrender these ++ rights. These restrictions translate to certain responsibilities for ++ you if you distribute copies of the library or if you modify it. ++ ++ For example, if you distribute copies of the library, whether gratis ++ or for a fee, you must give the recipients all the rights that we gave ++ you. You must make sure that they, too, receive or can get the source ++ code. If you link other code with the library, you must provide ++ complete object files to the recipients, so that they can relink them ++ with the library after making changes to the library and recompiling ++ it. And you must show them these terms so they know their rights. ++ ++ We protect your rights with a two-step method: (1) we copyright the ++ library, and (2) we offer you this license, which gives you legal ++ permission to copy, distribute and/or modify the library. ++ ++ To protect each distributor, we want to make it very clear that ++ there is no warranty for the free library. Also, if the library is ++ modified by someone else and passed on, the recipients should know ++ that what they have is not the original version, so that the original ++ author's reputation will not be affected by problems that might be ++ introduced by others. ++ ++ Finally, software patents pose a constant threat to the existence of ++ any free program. We wish to make sure that a company cannot ++ effectively restrict the users of a free program by obtaining a ++ restrictive license from a patent holder. Therefore, we insist that ++ any patent license obtained for a version of the library must be ++ consistent with the full freedom of use specified in this license. ++ ++ Most GNU software, including some libraries, is covered by the ++ ordinary GNU General Public License. This license, the GNU Lesser ++ General Public License, applies to certain designated libraries, and ++ is quite different from the ordinary General Public License. We use ++ this license for certain libraries in order to permit linking those ++ libraries into non-free programs. ++ ++ When a program is linked with a library, whether statically or using ++ a shared library, the combination of the two is legally speaking a ++ combined work, a derivative of the original library. The ordinary ++ General Public License therefore permits such linking only if the ++ entire combination fits its criteria of freedom. The Lesser General ++ Public License permits more lax criteria for linking other code with ++ the library. ++ ++ We call this license the "Lesser" General Public License because it ++ does Less to protect the user's freedom than the ordinary General ++ Public License. It also provides other free software developers Less ++ of an advantage over competing non-free programs. These disadvantages ++ are the reason we use the ordinary General Public License for many ++ libraries. However, the Lesser license provides advantages in certain ++ special circumstances. ++ ++ For example, on rare occasions, there may be a special need to ++ encourage the widest possible use of a certain library, so that it becomes ++ a de-facto standard. To achieve this, non-free programs must be ++ allowed to use the library. A more frequent case is that a free ++ library does the same job as widely used non-free libraries. In this ++ case, there is little to gain by limiting the free library to free ++ software only, so we use the Lesser General Public License. ++ ++ In other cases, permission to use a particular library in non-free ++ programs enables a greater number of people to use a large body of ++ free software. For example, permission to use the GNU C Library in ++ non-free programs enables many more people to use the whole GNU ++ operating system, as well as its variant, the GNU/Linux operating ++ system. ++ ++ Although the Lesser General Public License is Less protective of the ++ users' freedom, it does ensure that the user of a program that is ++ linked with the Library has the freedom and the wherewithal to run ++ that program using a modified version of the Library. ++ ++ The precise terms and conditions for copying, distribution and ++ modification follow. Pay close attention to the difference between a ++ "work based on the library" and a "work that uses the library". The ++ former contains code derived from the library, whereas the latter must ++ be combined with the library in order to run. ++ ++ GNU LESSER GENERAL PUBLIC LICENSE ++ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION ++ ++ 0. This License Agreement applies to any software library or other ++ program which contains a notice placed by the copyright holder or ++ other authorized party saying it may be distributed under the terms of ++ this Lesser General Public License (also called "this License"). ++ Each licensee is addressed as "you". ++ ++ A "library" means a collection of software functions and/or data ++ prepared so as to be conveniently linked with application programs ++ (which use some of those functions and data) to form executables. ++ ++ The "Library", below, refers to any such software library or work ++ which has been distributed under these terms. A "work based on the ++ Library" means either the Library or any derivative work under ++ copyright law: that is to say, a work containing the Library or a ++ portion of it, either verbatim or with modifications and/or translated ++ straightforwardly into another language. (Hereinafter, translation is ++ included without limitation in the term "modification".) ++ ++ "Source code" for a work means the preferred form of the work for ++ making modifications to it. For a library, complete source code means ++ all the source code for all modules it contains, plus any associated ++ interface definition files, plus the scripts used to control compilation ++ and installation of the library. ++ ++ Activities other than copying, distribution and modification are not ++ covered by this License; they are outside its scope. The act of ++ running a program using the Library is not restricted, and output from ++ such a program is covered only if its contents constitute a work based ++ on the Library (independent of the use of the Library in a tool for ++ writing it). Whether that is true depends on what the Library does ++ and what the program that uses the Library does. ++ ++ 1. You may copy and distribute verbatim copies of the Library's ++ complete source code as you receive it, in any medium, provided that ++ you conspicuously and appropriately publish on each copy an ++ appropriate copyright notice and disclaimer of warranty; keep intact ++ all the notices that refer to this License and to the absence of any ++ warranty; and distribute a copy of this License along with the ++ Library. ++ ++ You may charge a fee for the physical act of transferring a copy, ++ and you may at your option offer warranty protection in exchange for a ++ fee. ++ ++ 2. You may modify your copy or copies of the Library or any portion ++ of it, thus forming a work based on the Library, and copy and ++ distribute such modifications or work under the terms of Section 1 ++ above, provided that you also meet all of these conditions: ++ ++ a) The modified work must itself be a software library. ++ ++ b) You must cause the files modified to carry prominent notices ++ stating that you changed the files and the date of any change. ++ ++ c) You must cause the whole of the work to be licensed at no ++ charge to all third parties under the terms of this License. ++ ++ d) If a facility in the modified Library refers to a function or a ++ table of data to be supplied by an application program that uses ++ the facility, other than as an argument passed when the facility ++ is invoked, then you must make a good faith effort to ensure that, ++ in the event an application does not supply such function or ++ table, the facility still operates, and performs whatever part of ++ its purpose remains meaningful. ++ ++ (For example, a function in a library to compute square roots has ++ a purpose that is entirely well-defined independent of the ++ application. Therefore, Subsection 2d requires that any ++ application-supplied function or table used by this function must ++ be optional: if the application does not supply it, the square ++ root function must still compute square roots.) ++ ++ These requirements apply to the modified work as a whole. If ++ identifiable sections of that work are not derived from the Library, ++ and can be reasonably considered independent and separate works in ++ themselves, then this License, and its terms, do not apply to those ++ sections when you distribute them as separate works. But when you ++ distribute the same sections as part of a whole which is a work based ++ on the Library, the distribution of the whole must be on the terms of ++ this License, whose permissions for other licensees extend to the ++ entire whole, and thus to each and every part regardless of who wrote ++ it. ++ ++ Thus, it is not the intent of this section to claim rights or contest ++ your rights to work written entirely by you; rather, the intent is to ++ exercise the right to control the distribution of derivative or ++ collective works based on the Library. ++ ++ In addition, mere aggregation of another work not based on the Library ++ with the Library (or with a work based on the Library) on a volume of ++ a storage or distribution medium does not bring the other work under ++ the scope of this License. ++ ++ 3. You may opt to apply the terms of the ordinary GNU General Public ++ License instead of this License to a given copy of the Library. To do ++ this, you must alter all the notices that refer to this License, so ++ that they refer to the ordinary GNU General Public License, version 2, ++ instead of to this License. (If a newer version than version 2 of the ++ ordinary GNU General Public License has appeared, then you can specify ++ that version instead if you wish.) Do not make any other change in ++ these notices. ++ ++ Once this change is made in a given copy, it is irreversible for ++ that copy, so the ordinary GNU General Public License applies to all ++ subsequent copies and derivative works made from that copy. ++ ++ This option is useful when you wish to copy part of the code of ++ the Library into a program that is not a library. ++ ++ 4. You may copy and distribute the Library (or a portion or ++ derivative of it, under Section 2) in object code or executable form ++ under the terms of Sections 1 and 2 above provided that you accompany ++ it with the complete corresponding machine-readable source code, which ++ must be distributed under the terms of Sections 1 and 2 above on a ++ medium customarily used for software interchange. ++ ++ If distribution of object code is made by offering access to copy ++ from a designated place, then offering equivalent access to copy the ++ source code from the same place satisfies the requirement to ++ distribute the source code, even though third parties are not ++ compelled to copy the source along with the object code. ++ ++ 5. A program that contains no derivative of any portion of the ++ Library, but is designed to work with the Library by being compiled or ++ linked with it, is called a "work that uses the Library". Such a ++ work, in isolation, is not a derivative work of the Library, and ++ therefore falls outside the scope of this License. ++ ++ However, linking a "work that uses the Library" with the Library ++ creates an executable that is a derivative of the Library (because it ++ contains portions of the Library), rather than a "work that uses the ++ library". The executable is therefore covered by this License. ++ Section 6 states terms for distribution of such executables. ++ ++ When a "work that uses the Library" uses material from a header file ++ that is part of the Library, the object code for the work may be a ++ derivative work of the Library even though the source code is not. ++ Whether this is true is especially significant if the work can be ++ linked without the Library, or if the work is itself a library. The ++ threshold for this to be true is not precisely defined by law. ++ ++ If such an object file uses only numerical parameters, data ++ structure layouts and accessors, and small macros and small inline ++ functions (ten lines or less in length), then the use of the object ++ file is unrestricted, regardless of whether it is legally a derivative ++ work. (Executables containing this object code plus portions of the ++ Library will still fall under Section 6.) ++ ++ Otherwise, if the work is a derivative of the Library, you may ++ distribute the object code for the work under the terms of Section 6. ++ Any executables containing that work also fall under Section 6, ++ whether or not they are linked directly with the Library itself. ++ ++ 6. As an exception to the Sections above, you may also combine or ++ link a "work that uses the Library" with the Library to produce a ++ work containing portions of the Library, and distribute that work ++ under terms of your choice, provided that the terms permit ++ modification of the work for the customer's own use and reverse ++ engineering for debugging such modifications. ++ ++ You must give prominent notice with each copy of the work that the ++ Library is used in it and that the Library and its use are covered by ++ this License. You must supply a copy of this License. If the work ++ during execution displays copyright notices, you must include the ++ copyright notice for the Library among them, as well as a reference ++ directing the user to the copy of this License. Also, you must do one ++ of these things: ++ ++ a) Accompany the work with the complete corresponding ++ machine-readable source code for the Library including whatever ++ changes were used in the work (which must be distributed under ++ Sections 1 and 2 above); and, if the work is an executable linked ++ with the Library, with the complete machine-readable "work that ++ uses the Library", as object code and/or source code, so that the ++ user can modify the Library and then relink to produce a modified ++ executable containing the modified Library. (It is understood ++ that the user who changes the contents of definitions files in the ++ Library will not necessarily be able to recompile the application ++ to use the modified definitions.) ++ ++ b) Use a suitable shared library mechanism for linking with the ++ Library. A suitable mechanism is one that (1) uses at run time a ++ copy of the library already present on the user's computer system, ++ rather than copying library functions into the executable, and (2) ++ will operate properly with a modified version of the library, if ++ the user installs one, as long as the modified version is ++ interface-compatible with the version that the work was made with. ++ ++ c) Accompany the work with a written offer, valid for at ++ least three years, to give the same user the materials ++ specified in Subsection 6a, above, for a charge no more ++ than the cost of performing this distribution. ++ ++ d) If distribution of the work is made by offering access to copy ++ from a designated place, offer equivalent access to copy the above ++ specified materials from the same place. ++ ++ e) Verify that the user has already received a copy of these ++ materials or that you have already sent this user a copy. ++ ++ For an executable, the required form of the "work that uses the ++ Library" must include any data and utility programs needed for ++ reproducing the executable from it. However, as a special exception, ++ the materials to be distributed need not include anything that is ++ normally distributed (in either source or binary form) with the major ++ components (compiler, kernel, and so on) of the operating system on ++ which the executable runs, unless that component itself accompanies ++ the executable. ++ ++ It may happen that this requirement contradicts the license ++ restrictions of other proprietary libraries that do not normally ++ accompany the operating system. Such a contradiction means you cannot ++ use both them and the Library together in an executable that you ++ distribute. ++ ++ 7. You may place library facilities that are a work based on the ++ Library side-by-side in a single library together with other library ++ facilities not covered by this License, and distribute such a combined ++ library, provided that the separate distribution of the work based on ++ the Library and of the other library facilities is otherwise ++ permitted, and provided that you do these two things: ++ ++ a) Accompany the combined library with a copy of the same work ++ based on the Library, uncombined with any other library ++ facilities. This must be distributed under the terms of the ++ Sections above. ++ ++ b) Give prominent notice with the combined library of the fact ++ that part of it is a work based on the Library, and explaining ++ where to find the accompanying uncombined form of the same work. ++ ++ 8. You may not copy, modify, sublicense, link with, or distribute ++ the Library except as expressly provided under this License. Any ++ attempt otherwise to copy, modify, sublicense, link with, or ++ distribute the Library is void, and will automatically terminate your ++ rights under this License. However, parties who have received copies, ++ or rights, from you under this License will not have their licenses ++ terminated so long as such parties remain in full compliance. ++ ++ 9. You are not required to accept this License, since you have not ++ signed it. However, nothing else grants you permission to modify or ++ distribute the Library or its derivative works. These actions are ++ prohibited by law if you do not accept this License. Therefore, by ++ modifying or distributing the Library (or any work based on the ++ Library), you indicate your acceptance of this License to do so, and ++ all its terms and conditions for copying, distributing or modifying ++ the Library or works based on it. ++ ++ 10. Each time you redistribute the Library (or any work based on the ++ Library), the recipient automatically receives a license from the ++ original licensor to copy, distribute, link with or modify the Library ++ subject to these terms and conditions. You may not impose any further ++ restrictions on the recipients' exercise of the rights granted herein. ++ You are not responsible for enforcing compliance by third parties with ++ this License. ++ ++ 11. If, as a consequence of a court judgment or allegation of patent ++ infringement or for any other reason (not limited to patent issues), ++ conditions are imposed on you (whether by court order, agreement or ++ otherwise) that contradict the conditions of this License, they do not ++ excuse you from the conditions of this License. If you cannot ++ distribute so as to satisfy simultaneously your obligations under this ++ License and any other pertinent obligations, then as a consequence you ++ may not distribute the Library at all. For example, if a patent ++ license would not permit royalty-free redistribution of the Library by ++ all those who receive copies directly or indirectly through you, then ++ the only way you could satisfy both it and this License would be to ++ refrain entirely from distribution of the Library. ++ ++ If any portion of this section is held invalid or unenforceable under any ++ particular circumstance, the balance of the section is intended to apply, ++ and the section as a whole is intended to apply in other circumstances. ++ ++ It is not the purpose of this section to induce you to infringe any ++ patents or other property right claims or to contest validity of any ++ such claims; this section has the sole purpose of protecting the ++ integrity of the free software distribution system which is ++ implemented by public license practices. Many people have made ++ generous contributions to the wide range of software distributed ++ through that system in reliance on consistent application of that ++ system; it is up to the author/donor to decide if he or she is willing ++ to distribute software through any other system and a licensee cannot ++ impose that choice. ++ ++ This section is intended to make thoroughly clear what is believed to ++ be a consequence of the rest of this License. ++ ++ 12. If the distribution and/or use of the Library is restricted in ++ certain countries either by patents or by copyrighted interfaces, the ++ original copyright holder who places the Library under this License may add ++ an explicit geographical distribution limitation excluding those countries, ++ so that distribution is permitted only in or among countries not thus ++ excluded. In such case, this License incorporates the limitation as if ++ written in the body of this License. ++ ++ 13. The Free Software Foundation may publish revised and/or new ++ versions of the Lesser General Public License from time to time. ++ Such new versions will be similar in spirit to the present version, ++ but may differ in detail to address new problems or concerns. ++ ++ Each version is given a distinguishing version number. If the Library ++ specifies a version number of this License which applies to it and ++ "any later version", you have the option of following the terms and ++ conditions either of that version or of any later version published by ++ the Free Software Foundation. If the Library does not specify a ++ license version number, you may choose any version ever published by ++ the Free Software Foundation. ++ ++ 14. If you wish to incorporate parts of the Library into other free ++ programs whose distribution conditions are incompatible with these, ++ write to the author to ask for permission. For software which is ++ copyrighted by the Free Software Foundation, write to the Free ++ Software Foundation; we sometimes make exceptions for this. Our ++ decision will be guided by the two goals of preserving the free status ++ of all derivatives of our free software and of promoting the sharing ++ and reuse of software generally. ++ ++ NO WARRANTY ++ ++ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO ++ WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. ++ EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR ++ OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY ++ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE ++ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE ++ LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME ++ THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ++ ++ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN ++ WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY ++ AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU ++ FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR ++ CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE ++ LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING ++ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A ++ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF ++ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH ++ DAMAGES. ++ ++ END OF TERMS AND CONDITIONS ++ ++ How to Apply These Terms to Your New Libraries ++ ++ If you develop a new library, and you want it to be of the greatest ++ possible use to the public, we recommend making it free software that ++ everyone can redistribute and change. You can do so by permitting ++ redistribution under these terms (or, alternatively, under the terms of the ++ ordinary General Public License). ++ ++ To apply these terms, attach the following notices to the library. It is ++ safest to attach them to the start of each source file to most effectively ++ convey the exclusion of warranty; and each file should have at least the ++ "copyright" line and a pointer to where the full notice is found. ++ ++ <one line to give the library's name and a brief idea of what it does.> ++ Copyright (C) <year> <name of author> ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ This library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with this library; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ ++ Also add information on how to contact you by electronic and paper mail. ++ ++ You should also get your employer (if you work as a programmer) or your ++ school, if any, to sign a "copyright disclaimer" for the library, if ++ necessary. Here is a sample; alter the names: ++ ++ Yoyodyne, Inc., hereby disclaims all copyright interest in the ++ library `Frob' (a library for tweaking knobs) written by James Random Hacker. ++ ++ <signature of Ty Coon>, 1 April 1990 ++ Ty Coon, President of Vice ++ ++ That's all there is to it! ++ ++ +*** ../vim-8.1.0359/src/xdiff/xdiff.h 1970-01-01 01:00:00.000000000 +0100 +--- src/xdiff/xdiff.h 2018-09-10 17:39:20.324083781 +0200 +*************** +*** 0 **** +--- 1,142 ---- ++ /* ++ * LibXDiff by Davide Libenzi ( File Differential Library ) ++ * Copyright (C) 2003 Davide Libenzi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see ++ * <http://www.gnu.org/licenses/>. ++ * ++ * Davide Libenzi <davidel@xmailserver.org> ++ * ++ */ ++ ++ #if !defined(XDIFF_H) ++ #define XDIFF_H ++ ++ #ifdef __cplusplus ++ extern "C" { ++ #endif /* #ifdef __cplusplus */ ++ ++ /* xpparm_t.flags */ ++ #define XDF_NEED_MINIMAL (1 << 0) ++ ++ #define XDF_IGNORE_WHITESPACE (1 << 1) ++ #define XDF_IGNORE_WHITESPACE_CHANGE (1 << 2) ++ #define XDF_IGNORE_WHITESPACE_AT_EOL (1 << 3) ++ #define XDF_IGNORE_CR_AT_EOL (1 << 4) ++ #define XDF_WHITESPACE_FLAGS (XDF_IGNORE_WHITESPACE | \ ++ XDF_IGNORE_WHITESPACE_CHANGE | \ ++ XDF_IGNORE_WHITESPACE_AT_EOL | \ ++ XDF_IGNORE_CR_AT_EOL) ++ ++ #define XDF_IGNORE_BLANK_LINES (1 << 7) ++ ++ #define XDF_PATIENCE_DIFF (1 << 14) ++ #define XDF_HISTOGRAM_DIFF (1 << 15) ++ #define XDF_DIFF_ALGORITHM_MASK (XDF_PATIENCE_DIFF | XDF_HISTOGRAM_DIFF) ++ #define XDF_DIFF_ALG(x) ((x) & XDF_DIFF_ALGORITHM_MASK) ++ ++ #define XDF_INDENT_HEURISTIC (1 << 23) ++ ++ /* xdemitconf_t.flags */ ++ #define XDL_EMIT_FUNCNAMES (1 << 0) ++ #define XDL_EMIT_FUNCCONTEXT (1 << 2) ++ ++ /* merge simplification levels */ ++ #define XDL_MERGE_MINIMAL 0 ++ #define XDL_MERGE_EAGER 1 ++ #define XDL_MERGE_ZEALOUS 2 ++ #define XDL_MERGE_ZEALOUS_ALNUM 3 ++ ++ /* merge favor modes */ ++ #define XDL_MERGE_FAVOR_OURS 1 ++ #define XDL_MERGE_FAVOR_THEIRS 2 ++ #define XDL_MERGE_FAVOR_UNION 3 ++ ++ /* merge output styles */ ++ #define XDL_MERGE_DIFF3 1 ++ ++ typedef struct s_mmfile { ++ char *ptr; ++ long size; ++ } mmfile_t; ++ ++ typedef struct s_mmbuffer { ++ char *ptr; ++ long size; ++ } mmbuffer_t; ++ ++ typedef struct s_xpparam { ++ unsigned long flags; ++ ++ /* See Documentation/diff-options.txt. */ ++ char **anchors; ++ size_t anchors_nr; ++ } xpparam_t; ++ ++ typedef struct s_xdemitcb { ++ void *priv; ++ int (*outf)(void *, mmbuffer_t *, int); ++ } xdemitcb_t; ++ ++ typedef long (*find_func_t)(const char *line, long line_len, char *buffer, long buffer_size, void *priv); ++ ++ typedef int (*xdl_emit_hunk_consume_func_t)(long start_a, long count_a, ++ long start_b, long count_b, ++ void *cb_data); ++ ++ typedef struct s_xdemitconf { ++ long ctxlen; ++ long interhunkctxlen; ++ unsigned long flags; ++ find_func_t find_func; ++ void *find_func_priv; ++ xdl_emit_hunk_consume_func_t hunk_func; ++ } xdemitconf_t; ++ ++ typedef struct s_bdiffparam { ++ long bsize; ++ } bdiffparam_t; ++ ++ ++ #define xdl_malloc(x) malloc(x) ++ #define xdl_free(ptr) free(ptr) ++ #define xdl_realloc(ptr,x) realloc(ptr,x) ++ ++ void *xdl_mmfile_first(mmfile_t *mmf, long *size); ++ long xdl_mmfile_size(mmfile_t *mmf); ++ ++ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, ++ xdemitconf_t const *xecfg, xdemitcb_t *ecb); ++ ++ typedef struct s_xmparam { ++ xpparam_t xpp; ++ int marker_size; ++ int level; ++ int favor; ++ int style; ++ const char *ancestor; /* label for orig */ ++ const char *file1; /* label for mf1 */ ++ const char *file2; /* label for mf2 */ ++ } xmparam_t; ++ ++ #define DEFAULT_CONFLICT_MARKER_SIZE 7 ++ ++ int xdl_merge(mmfile_t *orig, mmfile_t *mf1, mmfile_t *mf2, ++ xmparam_t const *xmp, mmbuffer_t *result); ++ ++ #ifdef __cplusplus ++ } ++ #endif /* #ifdef __cplusplus */ ++ ++ #endif /* #if !defined(XDIFF_H) */ +*** ../vim-8.1.0359/src/xdiff/xdiffi.c 1970-01-01 01:00:00.000000000 +0100 +--- src/xdiff/xdiffi.c 2018-09-10 17:39:20.324083781 +0200 +*************** +*** 0 **** +--- 1,1043 ---- ++ /* ++ * LibXDiff by Davide Libenzi ( File Differential Library ) ++ * Copyright (C) 2003 Davide Libenzi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see ++ * <http://www.gnu.org/licenses/>. ++ * ++ * Davide Libenzi <davidel@xmailserver.org> ++ * ++ */ ++ ++ #include "xinclude.h" ++ ++ #define XDL_MAX_COST_MIN 256 ++ #define XDL_HEUR_MIN_COST 256 ++ #define XDL_LINE_MAX (long)((1UL << (CHAR_BIT * sizeof(long) - 1)) - 1) ++ #define XDL_SNAKE_CNT 20 ++ #define XDL_K_HEUR 4 ++ ++ typedef struct s_xdpsplit { ++ long i1, i2; ++ int min_lo, min_hi; ++ } xdpsplit_t; ++ ++ /* ++ * See "An O(ND) Difference Algorithm and its Variations", by Eugene Myers. ++ * Basically considers a "box" (off1, off2, lim1, lim2) and scan from both ++ * the forward diagonal starting from (off1, off2) and the backward diagonal ++ * starting from (lim1, lim2). If the K values on the same diagonal crosses ++ * returns the furthest point of reach. We might end up having to expensive ++ * cases using this algorithm is full, so a little bit of heuristic is needed ++ * to cut the search and to return a suboptimal point. ++ */ ++ static long xdl_split(unsigned long const *ha1, long off1, long lim1, ++ unsigned long const *ha2, long off2, long lim2, ++ long *kvdf, long *kvdb, int need_min, xdpsplit_t *spl, ++ xdalgoenv_t *xenv) { ++ long dmin = off1 - lim2, dmax = lim1 - off2; ++ long fmid = off1 - off2, bmid = lim1 - lim2; ++ long odd = (fmid - bmid) & 1; ++ long fmin = fmid, fmax = fmid; ++ long bmin = bmid, bmax = bmid; ++ long ec, d, i1, i2, prev1, best, dd, v, k; ++ ++ /* ++ * Set initial diagonal values for both forward and backward path. ++ */ ++ kvdf[fmid] = off1; ++ kvdb[bmid] = lim1; ++ ++ for (ec = 1;; ec++) { ++ int got_snake = 0; ++ ++ /* ++ * We need to extent the diagonal "domain" by one. If the next ++ * values exits the box boundaries we need to change it in the ++ * opposite direction because (max - min) must be a power of two. ++ * Also we initialize the external K value to -1 so that we can ++ * avoid extra conditions check inside the core loop. ++ */ ++ if (fmin > dmin) ++ kvdf[--fmin - 1] = -1; ++ else ++ ++fmin; ++ if (fmax < dmax) ++ kvdf[++fmax + 1] = -1; ++ else ++ --fmax; ++ ++ for (d = fmax; d >= fmin; d -= 2) { ++ if (kvdf[d - 1] >= kvdf[d + 1]) ++ i1 = kvdf[d - 1] + 1; ++ else ++ i1 = kvdf[d + 1]; ++ prev1 = i1; ++ i2 = i1 - d; ++ for (; i1 < lim1 && i2 < lim2 && ha1[i1] == ha2[i2]; i1++, i2++); ++ if (i1 - prev1 > xenv->snake_cnt) ++ got_snake = 1; ++ kvdf[d] = i1; ++ if (odd && bmin <= d && d <= bmax && kvdb[d] <= i1) { ++ spl->i1 = i1; ++ spl->i2 = i2; ++ spl->min_lo = spl->min_hi = 1; ++ return ec; ++ } ++ } ++ ++ /* ++ * We need to extent the diagonal "domain" by one. If the next ++ * values exits the box boundaries we need to change it in the ++ * opposite direction because (max - min) must be a power of two. ++ * Also we initialize the external K value to -1 so that we can ++ * avoid extra conditions check inside the core loop. ++ */ ++ if (bmin > dmin) ++ kvdb[--bmin - 1] = XDL_LINE_MAX; ++ else ++ ++bmin; ++ if (bmax < dmax) ++ kvdb[++bmax + 1] = XDL_LINE_MAX; ++ else ++ --bmax; ++ ++ for (d = bmax; d >= bmin; d -= 2) { ++ if (kvdb[d - 1] < kvdb[d + 1]) ++ i1 = kvdb[d - 1]; ++ else ++ i1 = kvdb[d + 1] - 1; ++ prev1 = i1; ++ i2 = i1 - d; ++ for (; i1 > off1 && i2 > off2 && ha1[i1 - 1] == ha2[i2 - 1]; i1--, i2--); ++ if (prev1 - i1 > xenv->snake_cnt) ++ got_snake = 1; ++ kvdb[d] = i1; ++ if (!odd && fmin <= d && d <= fmax && i1 <= kvdf[d]) { ++ spl->i1 = i1; ++ spl->i2 = i2; ++ spl->min_lo = spl->min_hi = 1; ++ return ec; ++ } ++ } ++ ++ if (need_min) ++ continue; ++ ++ /* ++ * If the edit cost is above the heuristic trigger and if ++ * we got a good snake, we sample current diagonals to see ++ * if some of the, have reached an "interesting" path. Our ++ * measure is a function of the distance from the diagonal ++ * corner (i1 + i2) penalized with the distance from the ++ * mid diagonal itself. If this value is above the current ++ * edit cost times a magic factor (XDL_K_HEUR) we consider ++ * it interesting. ++ */ ++ if (got_snake && ec > xenv->heur_min) { ++ for (best = 0, d = fmax; d >= fmin; d -= 2) { ++ dd = d > fmid ? d - fmid: fmid - d; ++ i1 = kvdf[d]; ++ i2 = i1 - d; ++ v = (i1 - off1) + (i2 - off2) - dd; ++ ++ if (v > XDL_K_HEUR * ec && v > best && ++ off1 + xenv->snake_cnt <= i1 && i1 < lim1 && ++ off2 + xenv->snake_cnt <= i2 && i2 < lim2) { ++ for (k = 1; ha1[i1 - k] == ha2[i2 - k]; k++) ++ if (k == xenv->snake_cnt) { ++ best = v; ++ spl->i1 = i1; ++ spl->i2 = i2; ++ break; ++ } ++ } ++ } ++ if (best > 0) { ++ spl->min_lo = 1; ++ spl->min_hi = 0; ++ return ec; ++ } ++ ++ for (best = 0, d = bmax; d >= bmin; d -= 2) { ++ dd = d > bmid ? d - bmid: bmid - d; ++ i1 = kvdb[d]; ++ i2 = i1 - d; ++ v = (lim1 - i1) + (lim2 - i2) - dd; ++ ++ if (v > XDL_K_HEUR * ec && v > best && ++ off1 < i1 && i1 <= lim1 - xenv->snake_cnt && ++ off2 < i2 && i2 <= lim2 - xenv->snake_cnt) { ++ for (k = 0; ha1[i1 + k] == ha2[i2 + k]; k++) ++ if (k == xenv->snake_cnt - 1) { ++ best = v; ++ spl->i1 = i1; ++ spl->i2 = i2; ++ break; ++ } ++ } ++ } ++ if (best > 0) { ++ spl->min_lo = 0; ++ spl->min_hi = 1; ++ return ec; ++ } ++ } ++ ++ /* ++ * Enough is enough. We spent too much time here and now we collect ++ * the furthest reaching path using the (i1 + i2) measure. ++ */ ++ if (ec >= xenv->mxcost) { ++ long fbest, fbest1, bbest, bbest1; ++ ++ fbest = fbest1 = -1; ++ for (d = fmax; d >= fmin; d -= 2) { ++ i1 = XDL_MIN(kvdf[d], lim1); ++ i2 = i1 - d; ++ if (lim2 < i2) ++ i1 = lim2 + d, i2 = lim2; ++ if (fbest < i1 + i2) { ++ fbest = i1 + i2; ++ fbest1 = i1; ++ } ++ } ++ ++ bbest = bbest1 = XDL_LINE_MAX; ++ for (d = bmax; d >= bmin; d -= 2) { ++ i1 = XDL_MAX(off1, kvdb[d]); ++ i2 = i1 - d; ++ if (i2 < off2) ++ i1 = off2 + d, i2 = off2; ++ if (i1 + i2 < bbest) { ++ bbest = i1 + i2; ++ bbest1 = i1; ++ } ++ } ++ ++ if ((lim1 + lim2) - bbest < fbest - (off1 + off2)) { ++ spl->i1 = fbest1; ++ spl->i2 = fbest - fbest1; ++ spl->min_lo = 1; ++ spl->min_hi = 0; ++ } else { ++ spl->i1 = bbest1; ++ spl->i2 = bbest - bbest1; ++ spl->min_lo = 0; ++ spl->min_hi = 1; ++ } ++ return ec; ++ } ++ } ++ } ++ ++ ++ /* ++ * Rule: "Divide et Impera". Recursively split the box in sub-boxes by calling ++ * the box splitting function. Note that the real job (marking changed lines) ++ * is done in the two boundary reaching checks. ++ */ ++ int xdl_recs_cmp(diffdata_t *dd1, long off1, long lim1, ++ diffdata_t *dd2, long off2, long lim2, ++ long *kvdf, long *kvdb, int need_min, xdalgoenv_t *xenv) { ++ unsigned long const *ha1 = dd1->ha, *ha2 = dd2->ha; ++ ++ /* ++ * Shrink the box by walking through each diagonal snake (SW and NE). ++ */ ++ for (; off1 < lim1 && off2 < lim2 && ha1[off1] == ha2[off2]; off1++, off2++); ++ for (; off1 < lim1 && off2 < lim2 && ha1[lim1 - 1] == ha2[lim2 - 1]; lim1--, lim2--); ++ ++ /* ++ * If one dimension is empty, then all records on the other one must ++ * be obviously changed. ++ */ ++ if (off1 == lim1) { ++ char *rchg2 = dd2->rchg; ++ long *rindex2 = dd2->rindex; ++ ++ for (; off2 < lim2; off2++) ++ rchg2[rindex2[off2]] = 1; ++ } else if (off2 == lim2) { ++ char *rchg1 = dd1->rchg; ++ long *rindex1 = dd1->rindex; ++ ++ for (; off1 < lim1; off1++) ++ rchg1[rindex1[off1]] = 1; ++ } else { ++ xdpsplit_t spl; ++ spl.i1 = spl.i2 = 0; ++ ++ /* ++ * Divide ... ++ */ ++ if (xdl_split(ha1, off1, lim1, ha2, off2, lim2, kvdf, kvdb, ++ need_min, &spl, xenv) < 0) { ++ ++ return -1; ++ } ++ ++ /* ++ * ... et Impera. ++ */ ++ if (xdl_recs_cmp(dd1, off1, spl.i1, dd2, off2, spl.i2, ++ kvdf, kvdb, spl.min_lo, xenv) < 0 || ++ xdl_recs_cmp(dd1, spl.i1, lim1, dd2, spl.i2, lim2, ++ kvdf, kvdb, spl.min_hi, xenv) < 0) { ++ ++ return -1; ++ } ++ } ++ ++ return 0; ++ } ++ ++ ++ int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, ++ xdfenv_t *xe) { ++ long ndiags; ++ long *kvd, *kvdf, *kvdb; ++ xdalgoenv_t xenv; ++ diffdata_t dd1, dd2; ++ ++ if (XDF_DIFF_ALG(xpp->flags) == XDF_PATIENCE_DIFF) ++ return xdl_do_patience_diff(mf1, mf2, xpp, xe); ++ ++ if (XDF_DIFF_ALG(xpp->flags) == XDF_HISTOGRAM_DIFF) ++ return xdl_do_histogram_diff(mf1, mf2, xpp, xe); ++ ++ if (xdl_prepare_env(mf1, mf2, xpp, xe) < 0) { ++ ++ return -1; ++ } ++ ++ /* ++ * Allocate and setup K vectors to be used by the differential algorithm. ++ * One is to store the forward path and one to store the backward path. ++ */ ++ ndiags = xe->xdf1.nreff + xe->xdf2.nreff + 3; ++ if (!(kvd = (long *) xdl_malloc((2 * ndiags + 2) * sizeof(long)))) { ++ ++ xdl_free_env(xe); ++ return -1; ++ } ++ kvdf = kvd; ++ kvdb = kvdf + ndiags; ++ kvdf += xe->xdf2.nreff + 1; ++ kvdb += xe->xdf2.nreff + 1; ++ ++ xenv.mxcost = xdl_bogosqrt(ndiags); ++ if (xenv.mxcost < XDL_MAX_COST_MIN) ++ xenv.mxcost = XDL_MAX_COST_MIN; ++ xenv.snake_cnt = XDL_SNAKE_CNT; ++ xenv.heur_min = XDL_HEUR_MIN_COST; ++ ++ dd1.nrec = xe->xdf1.nreff; ++ dd1.ha = xe->xdf1.ha; ++ dd1.rchg = xe->xdf1.rchg; ++ dd1.rindex = xe->xdf1.rindex; ++ dd2.nrec = xe->xdf2.nreff; ++ dd2.ha = xe->xdf2.ha; ++ dd2.rchg = xe->xdf2.rchg; ++ dd2.rindex = xe->xdf2.rindex; ++ ++ if (xdl_recs_cmp(&dd1, 0, dd1.nrec, &dd2, 0, dd2.nrec, ++ kvdf, kvdb, (xpp->flags & XDF_NEED_MINIMAL) != 0, &xenv) < 0) { ++ ++ xdl_free(kvd); ++ xdl_free_env(xe); ++ return -1; ++ } ++ ++ xdl_free(kvd); ++ ++ return 0; ++ } ++ ++ ++ static xdchange_t *xdl_add_change(xdchange_t *xscr, long i1, long i2, long chg1, long chg2) { ++ xdchange_t *xch; ++ ++ if (!(xch = (xdchange_t *) xdl_malloc(sizeof(xdchange_t)))) ++ return NULL; ++ ++ xch->next = xscr; ++ xch->i1 = i1; ++ xch->i2 = i2; ++ xch->chg1 = chg1; ++ xch->chg2 = chg2; ++ xch->ignore = 0; ++ ++ return xch; ++ } ++ ++ ++ static int recs_match(xrecord_t *rec1, xrecord_t *rec2, long flags) ++ { ++ return (rec1->ha == rec2->ha && ++ xdl_recmatch(rec1->ptr, rec1->size, ++ rec2->ptr, rec2->size, ++ flags)); ++ } ++ ++ /* ++ * If a line is indented more than this, get_indent() just returns this value. ++ * This avoids having to do absurd amounts of work for data that are not ++ * human-readable text, and also ensures that the output of get_indent fits within ++ * an int. ++ */ ++ #define MAX_INDENT 200 ++ ++ /* ++ * Return the amount of indentation of the specified line, treating TAB as 8 ++ * columns. Return -1 if line is empty or contains only whitespace. Clamp the ++ * output value at MAX_INDENT. ++ */ ++ static int get_indent(xrecord_t *rec) ++ { ++ long i; ++ int ret = 0; ++ ++ for (i = 0; i < rec->size; i++) { ++ char c = rec->ptr[i]; ++ ++ if (!XDL_ISSPACE(c)) ++ return ret; ++ else if (c == ' ') ++ ret += 1; ++ else if (c == '\t') ++ ret += 8 - ret % 8; ++ /* ignore other whitespace characters */ ++ ++ if (ret >= MAX_INDENT) ++ return MAX_INDENT; ++ } ++ ++ /* The line contains only whitespace. */ ++ return -1; ++ } ++ ++ /* ++ * If more than this number of consecutive blank rows are found, just return this ++ * value. This avoids requiring O(N^2) work for pathological cases, and also ++ * ensures that the output of score_split fits in an int. ++ */ ++ #define MAX_BLANKS 20 ++ ++ /* Characteristics measured about a hypothetical split position. */ ++ struct split_measurement { ++ /* ++ * Is the split at the end of the file (aside from any blank lines)? ++ */ ++ int end_of_file; ++ ++ /* ++ * How much is the line immediately following the split indented (or -1 if ++ * the line is blank): ++ */ ++ int indent; ++ ++ /* ++ * How many consecutive lines above the split are blank? ++ */ ++ int pre_blank; ++ ++ /* ++ * How much is the nearest non-blank line above the split indented (or -1 ++ * if there is no such line)? ++ */ ++ int pre_indent; ++ ++ /* ++ * How many lines after the line following the split are blank? ++ */ ++ int post_blank; ++ ++ /* ++ * How much is the nearest non-blank line after the line following the ++ * split indented (or -1 if there is no such line)? ++ */ ++ int post_indent; ++ }; ++ ++ struct split_score { ++ /* The effective indent of this split (smaller is preferred). */ ++ int effective_indent; ++ ++ /* Penalty for this split (smaller is preferred). */ ++ int penalty; ++ }; ++ ++ /* ++ * Fill m with information about a hypothetical split of xdf above line split. ++ */ ++ static void measure_split(const xdfile_t *xdf, long split, ++ struct split_measurement *m) ++ { ++ long i; ++ ++ if (split >= xdf->nrec) { ++ m->end_of_file = 1; ++ m->indent = -1; ++ } else { ++ m->end_of_file = 0; ++ m->indent = get_indent(xdf->recs[split]); ++ } ++ ++ m->pre_blank = 0; ++ m->pre_indent = -1; ++ for (i = split - 1; i >= 0; i--) { ++ m->pre_indent = get_indent(xdf->recs[i]); ++ if (m->pre_indent != -1) ++ break; ++ m->pre_blank += 1; ++ if (m->pre_blank == MAX_BLANKS) { ++ m->pre_indent = 0; ++ break; ++ } ++ } ++ ++ m->post_blank = 0; ++ m->post_indent = -1; ++ for (i = split + 1; i < xdf->nrec; i++) { ++ m->post_indent = get_indent(xdf->recs[i]); ++ if (m->post_indent != -1) ++ break; ++ m->post_blank += 1; ++ if (m->post_blank == MAX_BLANKS) { ++ m->post_indent = 0; ++ break; ++ } ++ } ++ } ++ ++ /* ++ * The empirically-determined weight factors used by score_split() below. ++ * Larger values means that the position is a less favorable place to split. ++ * ++ * Note that scores are only ever compared against each other, so multiplying ++ * all of these weight/penalty values by the same factor wouldn't change the ++ * heuristic's behavior. Still, we need to set that arbitrary scale *somehow*. ++ * In practice, these numbers are chosen to be large enough that they can be ++ * adjusted relative to each other with sufficient precision despite using ++ * integer math. ++ */ ++ ++ /* Penalty if there are no non-blank lines before the split */ ++ #define START_OF_FILE_PENALTY 1 ++ ++ /* Penalty if there are no non-blank lines after the split */ ++ #define END_OF_FILE_PENALTY 21 ++ ++ /* Multiplier for the number of blank lines around the split */ ++ #define TOTAL_BLANK_WEIGHT (-30) ++ ++ /* Multiplier for the number of blank lines after the split */ ++ #define POST_BLANK_WEIGHT 6 ++ ++ /* ++ * Penalties applied if the line is indented more than its predecessor ++ */ ++ #define RELATIVE_INDENT_PENALTY (-4) ++ #define RELATIVE_INDENT_WITH_BLANK_PENALTY 10 ++ ++ /* ++ * Penalties applied if the line is indented less than both its predecessor and ++ * its successor ++ */ ++ #define RELATIVE_OUTDENT_PENALTY 24 ++ #define RELATIVE_OUTDENT_WITH_BLANK_PENALTY 17 ++ ++ /* ++ * Penalties applied if the line is indented less than its predecessor but not ++ * less than its successor ++ */ ++ #define RELATIVE_DEDENT_PENALTY 23 ++ #define RELATIVE_DEDENT_WITH_BLANK_PENALTY 17 ++ ++ /* ++ * We only consider whether the sum of the effective indents for splits are ++ * less than (-1), equal to (0), or greater than (+1) each other. The resulting ++ * value is multiplied by the following weight and combined with the penalty to ++ * determine the better of two scores. ++ */ ++ #define INDENT_WEIGHT 60 ++ ++ /* ++ * How far do we slide a hunk at most? ++ */ ++ #define INDENT_HEURISTIC_MAX_SLIDING 100 ++ ++ /* ++ * Compute a badness score for the hypothetical split whose measurements are ++ * stored in m. The weight factors were determined empirically using the tools and ++ * corpus described in ++ * ++ * https://github.com/mhagger/diff-slider-tools ++ * ++ * Also see that project if you want to improve the weights based on, for example, ++ * a larger or more diverse corpus. ++ */ ++ static void score_add_split(const struct split_measurement *m, struct split_score *s) ++ { ++ /* ++ * A place to accumulate penalty factors (positive makes this index more ++ * favored): ++ */ ++ int post_blank, total_blank, indent, any_blanks; ++ ++ if (m->pre_indent == -1 && m->pre_blank == 0) ++ s->penalty += START_OF_FILE_PENALTY; ++ ++ if (m->end_of_file) ++ s->penalty += END_OF_FILE_PENALTY; ++ ++ /* ++ * Set post_blank to the number of blank lines following the split, ++ * including the line immediately after the split: ++ */ ++ post_blank = (m->indent == -1) ? 1 + m->post_blank : 0; ++ total_blank = m->pre_blank + post_blank; ++ ++ /* Penalties based on nearby blank lines: */ ++ s->penalty += TOTAL_BLANK_WEIGHT * total_blank; ++ s->penalty += POST_BLANK_WEIGHT * post_blank; ++ ++ if (m->indent != -1) ++ indent = m->indent; ++ else ++ indent = m->post_indent; ++ ++ any_blanks = (total_blank != 0); ++ ++ /* Note that the effective indent is -1 at the end of the file: */ ++ s->effective_indent += indent; ++ ++ if (indent == -1) { ++ /* No additional adjustments needed. */ ++ } else if (m->pre_indent == -1) { ++ /* No additional adjustments needed. */ ++ } else if (indent > m->pre_indent) { ++ /* ++ * The line is indented more than its predecessor. ++ */ ++ s->penalty += any_blanks ? ++ RELATIVE_INDENT_WITH_BLANK_PENALTY : ++ RELATIVE_INDENT_PENALTY; ++ } else if (indent == m->pre_indent) { ++ /* ++ * The line has the same indentation level as its predecessor. ++ * No additional adjustments needed. ++ */ ++ } else { ++ /* ++ * The line is indented less than its predecessor. It could be ++ * the block terminator of the previous block, but it could ++ * also be the start of a new block (e.g., an "else" block, or ++ * maybe the previous block didn't have a block terminator). ++ * Try to distinguish those cases based on what comes next: ++ */ ++ if (m->post_indent != -1 && m->post_indent > indent) { ++ /* ++ * The following line is indented more. So it is likely ++ * that this line is the start of a block. ++ */ ++ s->penalty += any_blanks ? ++ RELATIVE_OUTDENT_WITH_BLANK_PENALTY : ++ RELATIVE_OUTDENT_PENALTY; ++ } else { ++ /* ++ * That was probably the end of a block. ++ */ ++ s->penalty += any_blanks ? ++ RELATIVE_DEDENT_WITH_BLANK_PENALTY : ++ RELATIVE_DEDENT_PENALTY; ++ } ++ } ++ } ++ ++ static int score_cmp(struct split_score *s1, struct split_score *s2) ++ { ++ /* -1 if s1.effective_indent < s2->effective_indent, etc. */ ++ int cmp_indents = ((s1->effective_indent > s2->effective_indent) - ++ (s1->effective_indent < s2->effective_indent)); ++ ++ return INDENT_WEIGHT * cmp_indents + (s1->penalty - s2->penalty); ++ } ++ ++ /* ++ * Represent a group of changed lines in an xdfile_t (i.e., a contiguous group ++ * of lines that was inserted or deleted from the corresponding version of the ++ * file). We consider there to be such a group at the beginning of the file, at ++ * the end of the file, and between any two unchanged lines, though most such ++ * groups will usually be empty. ++ * ++ * If the first line in a group is equal to the line following the group, then ++ * the group can be slid down. Similarly, if the last line in a group is equal ++ * to the line preceding the group, then the group can be slid up. See ++ * group_slide_down() and group_slide_up(). ++ * ++ * Note that loops that are testing for changed lines in xdf->rchg do not need ++ * index bounding since the array is prepared with a zero at position -1 and N. ++ */ ++ struct xdlgroup { ++ /* ++ * The index of the first changed line in the group, or the index of ++ * the unchanged line above which the (empty) group is located. ++ */ ++ long start; ++ ++ /* ++ * The index of the first unchanged line after the group. For an empty ++ * group, end is equal to start. ++ */ ++ long end; ++ }; ++ ++ /* ++ * Initialize g to point at the first group in xdf. ++ */ ++ static void group_init(xdfile_t *xdf, struct xdlgroup *g) ++ { ++ g->start = g->end = 0; ++ while (xdf->rchg[g->end]) ++ g->end++; ++ } ++ ++ /* ++ * Move g to describe the next (possibly empty) group in xdf and return 0. If g ++ * is already at the end of the file, do nothing and return -1. ++ */ ++ static inline int group_next(xdfile_t *xdf, struct xdlgroup *g) ++ { ++ if (g->end == xdf->nrec) ++ return -1; ++ ++ g->start = g->end + 1; ++ for (g->end = g->start; xdf->rchg[g->end]; g->end++) ++ ; ++ ++ return 0; ++ } ++ ++ /* ++ * Move g to describe the previous (possibly empty) group in xdf and return 0. ++ * If g is already at the beginning of the file, do nothing and return -1. ++ */ ++ static inline int group_previous(xdfile_t *xdf, struct xdlgroup *g) ++ { ++ if (g->start == 0) ++ return -1; ++ ++ g->end = g->start - 1; ++ for (g->start = g->end; xdf->rchg[g->start - 1]; g->start--) ++ ; ++ ++ return 0; ++ } ++ ++ /* ++ * If g can be slid toward the end of the file, do so, and if it bumps into a ++ * following group, expand this group to include it. Return 0 on success or -1 ++ * if g cannot be slid down. ++ */ ++ static int group_slide_down(xdfile_t *xdf, struct xdlgroup *g, long flags) ++ { ++ if (g->end < xdf->nrec && ++ recs_match(xdf->recs[g->start], xdf->recs[g->end], flags)) { ++ xdf->rchg[g->start++] = 0; ++ xdf->rchg[g->end++] = 1; ++ ++ while (xdf->rchg[g->end]) ++ g->end++; ++ ++ return 0; ++ } else { ++ return -1; ++ } ++ } ++ ++ /* ++ * If g can be slid toward the beginning of the file, do so, and if it bumps ++ * into a previous group, expand this group to include it. Return 0 on success ++ * or -1 if g cannot be slid up. ++ */ ++ static int group_slide_up(xdfile_t *xdf, struct xdlgroup *g, long flags) ++ { ++ if (g->start > 0 && ++ recs_match(xdf->recs[g->start - 1], xdf->recs[g->end - 1], flags)) { ++ xdf->rchg[--g->start] = 1; ++ xdf->rchg[--g->end] = 0; ++ ++ while (xdf->rchg[g->start - 1]) ++ g->start--; ++ ++ return 0; ++ } else { ++ return -1; ++ } ++ } ++ ++ static void xdl_bug(const char *msg) ++ { ++ fprintf(stderr, "BUG: %s\n", msg); ++ exit(1); ++ } ++ ++ /* ++ * Move back and forward change groups for a consistent and pretty diff output. ++ * This also helps in finding joinable change groups and reducing the diff ++ * size. ++ */ ++ int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) { ++ struct xdlgroup g, go; ++ long earliest_end, end_matching_other; ++ long groupsize; ++ ++ group_init(xdf, &g); ++ group_init(xdfo, &go); ++ ++ while (1) { ++ /* If the group is empty in the to-be-compacted file, skip it: */ ++ if (g.end == g.start) ++ goto next; ++ ++ /* ++ * Now shift the change up and then down as far as possible in ++ * each direction. If it bumps into any other changes, merge them. ++ */ ++ do { ++ groupsize = g.end - g.start; ++ ++ /* ++ * Keep track of the last "end" index that causes this ++ * group to align with a group of changed lines in the ++ * other file. -1 indicates that we haven't found such ++ * a match yet: ++ */ ++ end_matching_other = -1; ++ ++ /* Shift the group backward as much as possible: */ ++ while (!group_slide_up(xdf, &g, flags)) ++ if (group_previous(xdfo, &go)) ++ xdl_bug("group sync broken sliding up"); ++ ++ /* ++ * This is this highest that this group can be shifted. ++ * Record its end index: ++ */ ++ earliest_end = g.end; ++ ++ if (go.end > go.start) ++ end_matching_other = g.end; ++ ++ /* Now shift the group forward as far as possible: */ ++ while (1) { ++ if (group_slide_down(xdf, &g, flags)) ++ break; ++ if (group_next(xdfo, &go)) ++ xdl_bug("group sync broken sliding down"); ++ ++ if (go.end > go.start) ++ end_matching_other = g.end; ++ } ++ } while (groupsize != g.end - g.start); ++ ++ /* ++ * If the group can be shifted, then we can possibly use this ++ * freedom to produce a more intuitive diff. ++ * ++ * The group is currently shifted as far down as possible, so the ++ * heuristics below only have to handle upwards shifts. ++ */ ++ ++ if (g.end == earliest_end) { ++ /* no shifting was possible */ ++ } else if (end_matching_other != -1) { ++ /* ++ * Move the possibly merged group of changes back to line ++ * up with the last group of changes from the other file ++ * that it can align with. ++ */ ++ while (go.end == go.start) { ++ if (group_slide_up(xdf, &g, flags)) ++ xdl_bug("match disappeared"); ++ if (group_previous(xdfo, &go)) ++ xdl_bug("group sync broken sliding to match"); ++ } ++ } else if (flags & XDF_INDENT_HEURISTIC) { ++ /* ++ * Indent heuristic: a group of pure add/delete lines ++ * implies two splits, one between the end of the "before" ++ * context and the start of the group, and another between ++ * the end of the group and the beginning of the "after" ++ * context. Some splits are aesthetically better and some ++ * are worse. We compute a badness "score" for each split, ++ * and add the scores for the two splits to define a ++ * "score" for each position that the group can be shifted ++ * to. Then we pick the shift with the lowest score. ++ */ ++ long shift, best_shift = -1; ++ struct split_score best_score; ++ ++ shift = earliest_end; ++ if (g.end - groupsize - 1 > shift) ++ shift = g.end - groupsize - 1; ++ if (g.end - INDENT_HEURISTIC_MAX_SLIDING > shift) ++ shift = g.end - INDENT_HEURISTIC_MAX_SLIDING; ++ for (; shift <= g.end; shift++) { ++ struct split_measurement m; ++ struct split_score score = {0, 0}; ++ ++ measure_split(xdf, shift, &m); ++ score_add_split(&m, &score); ++ measure_split(xdf, shift - groupsize, &m); ++ score_add_split(&m, &score); ++ if (best_shift == -1 || ++ score_cmp(&score, &best_score) <= 0) { ++ best_score.effective_indent = score.effective_indent; ++ best_score.penalty = score.penalty; ++ best_shift = shift; ++ } ++ } ++ ++ while (g.end > best_shift) { ++ if (group_slide_up(xdf, &g, flags)) ++ xdl_bug("best shift unreached"); ++ if (group_previous(xdfo, &go)) ++ xdl_bug("group sync broken sliding to blank line"); ++ } ++ } ++ ++ next: ++ /* Move past the just-processed group: */ ++ if (group_next(xdf, &g)) ++ break; ++ if (group_next(xdfo, &go)) ++ xdl_bug("group sync broken moving to next group"); ++ } ++ ++ if (!group_next(xdfo, &go)) ++ xdl_bug("group sync broken at end of file"); ++ ++ return 0; ++ } ++ ++ ++ int xdl_build_script(xdfenv_t *xe, xdchange_t **xscr) { ++ xdchange_t *cscr = NULL, *xch; ++ char *rchg1 = xe->xdf1.rchg, *rchg2 = xe->xdf2.rchg; ++ long i1, i2, l1, l2; ++ ++ /* ++ * Trivial. Collects "groups" of changes and creates an edit script. ++ */ ++ for (i1 = xe->xdf1.nrec, i2 = xe->xdf2.nrec; i1 >= 0 || i2 >= 0; i1--, i2--) ++ if (rchg1[i1 - 1] || rchg2[i2 - 1]) { ++ for (l1 = i1; rchg1[i1 - 1]; i1--); ++ for (l2 = i2; rchg2[i2 - 1]; i2--); ++ ++ if (!(xch = xdl_add_change(cscr, i1, i2, l1 - i1, l2 - i2))) { ++ xdl_free_script(cscr); ++ return -1; ++ } ++ cscr = xch; ++ } ++ ++ *xscr = cscr; ++ ++ return 0; ++ } ++ ++ ++ void xdl_free_script(xdchange_t *xscr) { ++ xdchange_t *xch; ++ ++ while ((xch = xscr) != NULL) { ++ xscr = xscr->next; ++ xdl_free(xch); ++ } ++ } ++ ++ static int xdl_call_hunk_func(xdfenv_t *xe UNUSED, xdchange_t *xscr, xdemitcb_t *ecb, ++ xdemitconf_t const *xecfg) ++ { ++ xdchange_t *xch, *xche; ++ ++ for (xch = xscr; xch; xch = xche->next) { ++ xche = xdl_get_hunk(&xch, xecfg); ++ if (!xch) ++ break; ++ if (xecfg->hunk_func(xch->i1, xche->i1 + xche->chg1 - xch->i1, ++ xch->i2, xche->i2 + xche->chg2 - xch->i2, ++ ecb->priv) < 0) ++ return -1; ++ } ++ return 0; ++ } ++ ++ static void xdl_mark_ignorable(xdchange_t *xscr, xdfenv_t *xe, long flags) ++ { ++ xdchange_t *xch; ++ ++ for (xch = xscr; xch; xch = xch->next) { ++ int ignore = 1; ++ xrecord_t **rec; ++ long i; ++ ++ rec = &xe->xdf1.recs[xch->i1]; ++ for (i = 0; i < xch->chg1 && ignore; i++) ++ ignore = xdl_blankline(rec[i]->ptr, rec[i]->size, flags); ++ ++ rec = &xe->xdf2.recs[xch->i2]; ++ for (i = 0; i < xch->chg2 && ignore; i++) ++ ignore = xdl_blankline(rec[i]->ptr, rec[i]->size, flags); ++ ++ xch->ignore = ignore; ++ } ++ } ++ ++ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, ++ xdemitconf_t const *xecfg, xdemitcb_t *ecb) { ++ xdchange_t *xscr; ++ xdfenv_t xe; ++ emit_func_t ef = xecfg->hunk_func ? xdl_call_hunk_func : xdl_emit_diff; ++ ++ if (xdl_do_diff(mf1, mf2, xpp, &xe) < 0) { ++ ++ return -1; ++ } ++ if (xdl_change_compact(&xe.xdf1, &xe.xdf2, xpp->flags) < 0 || ++ xdl_change_compact(&xe.xdf2, &xe.xdf1, xpp->flags) < 0 || ++ xdl_build_script(&xe, &xscr) < 0) { ++ ++ xdl_free_env(&xe); ++ return -1; ++ } ++ if (xscr) { ++ if (xpp->flags & XDF_IGNORE_BLANK_LINES) ++ xdl_mark_ignorable(xscr, &xe, xpp->flags); ++ ++ if (ef(&xe, xscr, ecb, xecfg) < 0) { ++ ++ xdl_free_script(xscr); ++ xdl_free_env(&xe); ++ return -1; ++ } ++ xdl_free_script(xscr); ++ } ++ xdl_free_env(&xe); ++ ++ return 0; ++ } +*** ../vim-8.1.0359/src/xdiff/xdiffi.h 1970-01-01 01:00:00.000000000 +0100 +--- src/xdiff/xdiffi.h 2018-09-10 17:39:20.324083781 +0200 +*************** +*** 0 **** +--- 1,64 ---- ++ /* ++ * LibXDiff by Davide Libenzi ( File Differential Library ) ++ * Copyright (C) 2003 Davide Libenzi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see ++ * <http://www.gnu.org/licenses/>. ++ * ++ * Davide Libenzi <davidel@xmailserver.org> ++ * ++ */ ++ ++ #if !defined(XDIFFI_H) ++ #define XDIFFI_H ++ ++ ++ typedef struct s_diffdata { ++ long nrec; ++ unsigned long const *ha; ++ long *rindex; ++ char *rchg; ++ } diffdata_t; ++ ++ typedef struct s_xdalgoenv { ++ long mxcost; ++ long snake_cnt; ++ long heur_min; ++ } xdalgoenv_t; ++ ++ typedef struct s_xdchange { ++ struct s_xdchange *next; ++ long i1, i2; ++ long chg1, chg2; ++ int ignore; ++ } xdchange_t; ++ ++ ++ ++ int xdl_recs_cmp(diffdata_t *dd1, long off1, long lim1, ++ diffdata_t *dd2, long off2, long lim2, ++ long *kvdf, long *kvdb, int need_min, xdalgoenv_t *xenv); ++ int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, ++ xdfenv_t *xe); ++ int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags); ++ int xdl_build_script(xdfenv_t *xe, xdchange_t **xscr); ++ void xdl_free_script(xdchange_t *xscr); ++ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, ++ xdemitconf_t const *xecfg); ++ int xdl_do_patience_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, ++ xdfenv_t *env); ++ int xdl_do_histogram_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, ++ xdfenv_t *env); ++ ++ #endif /* #if !defined(XDIFFI_H) */ +*** ../vim-8.1.0359/src/xdiff/xemit.c 1970-01-01 01:00:00.000000000 +0100 +--- src/xdiff/xemit.c 2018-09-10 17:39:20.324083781 +0200 +*************** +*** 0 **** +--- 1,312 ---- ++ /* ++ * LibXDiff by Davide Libenzi ( File Differential Library ) ++ * Copyright (C) 2003 Davide Libenzi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see ++ * <http://www.gnu.org/licenses/>. ++ * ++ * Davide Libenzi <davidel@xmailserver.org> ++ * ++ */ ++ ++ #include "xinclude.h" ++ ++ static long xdl_get_rec(xdfile_t *xdf, long ri, char const **rec) { ++ ++ *rec = xdf->recs[ri]->ptr; ++ ++ return xdf->recs[ri]->size; ++ } ++ ++ ++ static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *ecb) { ++ long size, psize = strlen(pre); ++ char const *rec; ++ ++ size = xdl_get_rec(xdf, ri, &rec); ++ if (xdl_emit_diffrec(rec, size, pre, psize, ecb) < 0) { ++ ++ return -1; ++ } ++ ++ return 0; ++ } ++ ++ ++ /* ++ * Starting at the passed change atom, find the latest change atom to be included ++ * inside the differential hunk according to the specified configuration. ++ * Also advance xscr if the first changes must be discarded. ++ */ ++ xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg) ++ { ++ xdchange_t *xch, *xchp, *lxch; ++ long max_common = 2 * xecfg->ctxlen + xecfg->interhunkctxlen; ++ long max_ignorable = xecfg->ctxlen; ++ unsigned long ignored = 0; /* number of ignored blank lines */ ++ ++ /* remove ignorable changes that are too far before other changes */ ++ for (xchp = *xscr; xchp && xchp->ignore; xchp = xchp->next) { ++ xch = xchp->next; ++ ++ if (xch == NULL || ++ xch->i1 - (xchp->i1 + xchp->chg1) >= max_ignorable) ++ *xscr = xch; ++ } ++ ++ if (*xscr == NULL) ++ return NULL; ++ ++ lxch = *xscr; ++ ++ for (xchp = *xscr, xch = xchp->next; xch; xchp = xch, xch = xch->next) { ++ long distance = xch->i1 - (xchp->i1 + xchp->chg1); ++ if (distance > max_common) ++ break; ++ ++ if (distance < max_ignorable && (!xch->ignore || lxch == xchp)) { ++ lxch = xch; ++ ignored = 0; ++ } else if (distance < max_ignorable && xch->ignore) { ++ ignored += xch->chg2; ++ } else if (lxch != xchp && ++ xch->i1 + (long)ignored - (lxch->i1 + lxch->chg1) > max_common) { ++ break; ++ } else if (!xch->ignore) { ++ lxch = xch; ++ ignored = 0; ++ } else { ++ ignored += xch->chg2; ++ } ++ } ++ ++ return lxch; ++ } ++ ++ ++ static long def_ff(const char *rec, long len, char *buf, long sz, void *priv UNUSED) ++ { ++ if (len > 0 && ++ (isalpha((unsigned char)*rec) || /* identifier? */ ++ *rec == '_' || /* also identifier? */ ++ *rec == '$')) { /* identifiers from VMS and other esoterico */ ++ if (len > sz) ++ len = sz; ++ while (0 < len && isspace((unsigned char)rec[len - 1])) ++ len--; ++ memcpy(buf, rec, len); ++ return len; ++ } ++ return -1; ++ } ++ ++ static long match_func_rec(xdfile_t *xdf, xdemitconf_t const *xecfg, long ri, ++ char *buf, long sz) ++ { ++ const char *rec; ++ long len = xdl_get_rec(xdf, ri, &rec); ++ if (!xecfg->find_func) ++ return def_ff(rec, len, buf, sz, xecfg->find_func_priv); ++ return xecfg->find_func(rec, len, buf, sz, xecfg->find_func_priv); ++ } ++ ++ static int is_func_rec(xdfile_t *xdf, xdemitconf_t const *xecfg, long ri) ++ { ++ char dummy[1]; ++ return match_func_rec(xdf, xecfg, ri, dummy, sizeof(dummy)) >= 0; ++ } ++ ++ struct func_line { ++ long len; ++ char buf[80]; ++ }; ++ ++ static long get_func_line(xdfenv_t *xe, xdemitconf_t const *xecfg, ++ struct func_line *func_line, long start, long limit) ++ { ++ long l, size, step = (start > limit) ? -1 : 1; ++ char *buf, dummy[1]; ++ ++ buf = func_line ? func_line->buf : dummy; ++ size = func_line ? sizeof(func_line->buf) : sizeof(dummy); ++ ++ for (l = start; l != limit && 0 <= l && l < xe->xdf1.nrec; l += step) { ++ long len = match_func_rec(&xe->xdf1, xecfg, l, buf, size); ++ if (len >= 0) { ++ if (func_line) ++ func_line->len = len; ++ return l; ++ } ++ } ++ return -1; ++ } ++ ++ static int is_empty_rec(xdfile_t *xdf, long ri) ++ { ++ const char *rec; ++ long len = xdl_get_rec(xdf, ri, &rec); ++ ++ while (len > 0 && XDL_ISSPACE(*rec)) { ++ rec++; ++ len--; ++ } ++ return !len; ++ } ++ ++ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, ++ xdemitconf_t const *xecfg) { ++ long s1, s2, e1, e2, lctx; ++ xdchange_t *xch, *xche; ++ long funclineprev = -1; ++ struct func_line func_line = { 0 }; ++ ++ for (xch = xscr; xch; xch = xche->next) { ++ xche = xdl_get_hunk(&xch, xecfg); ++ if (!xch) ++ break; ++ ++ s1 = XDL_MAX(xch->i1 - xecfg->ctxlen, 0); ++ s2 = XDL_MAX(xch->i2 - xecfg->ctxlen, 0); ++ ++ if (xecfg->flags & XDL_EMIT_FUNCCONTEXT) { ++ long fs1, i1 = xch->i1; ++ ++ /* Appended chunk? */ ++ if (i1 >= xe->xdf1.nrec) { ++ long i2 = xch->i2; ++ ++ /* ++ * We don't need additional context if ++ * a whole function was added. ++ */ ++ while (i2 < xe->xdf2.nrec) { ++ if (is_func_rec(&xe->xdf2, xecfg, i2)) ++ goto post_context_calculation; ++ i2++; ++ } ++ ++ /* ++ * Otherwise get more context from the ++ * pre-image. ++ */ ++ i1 = xe->xdf1.nrec - 1; ++ } ++ ++ fs1 = get_func_line(xe, xecfg, NULL, i1, -1); ++ while (fs1 > 0 && !is_empty_rec(&xe->xdf1, fs1 - 1) && ++ !is_func_rec(&xe->xdf1, xecfg, fs1 - 1)) ++ fs1--; ++ if (fs1 < 0) ++ fs1 = 0; ++ if (fs1 < s1) { ++ s2 -= s1 - fs1; ++ s1 = fs1; ++ } ++ } ++ ++ post_context_calculation: ++ lctx = xecfg->ctxlen; ++ lctx = XDL_MIN(lctx, xe->xdf1.nrec - (xche->i1 + xche->chg1)); ++ lctx = XDL_MIN(lctx, xe->xdf2.nrec - (xche->i2 + xche->chg2)); ++ ++ e1 = xche->i1 + xche->chg1 + lctx; ++ e2 = xche->i2 + xche->chg2 + lctx; ++ ++ if (xecfg->flags & XDL_EMIT_FUNCCONTEXT) { ++ long fe1 = get_func_line(xe, xecfg, NULL, ++ xche->i1 + xche->chg1, ++ xe->xdf1.nrec); ++ while (fe1 > 0 && is_empty_rec(&xe->xdf1, fe1 - 1)) ++ fe1--; ++ if (fe1 < 0) ++ fe1 = xe->xdf1.nrec; ++ if (fe1 > e1) { ++ e2 += fe1 - e1; ++ e1 = fe1; ++ } ++ ++ /* ++ * Overlap with next change? Then include it ++ * in the current hunk and start over to find ++ * its new end. ++ */ ++ if (xche->next) { ++ long l = XDL_MIN(xche->next->i1, ++ xe->xdf1.nrec - 1); ++ if (l - xecfg->ctxlen <= e1 || ++ get_func_line(xe, xecfg, NULL, l, e1) < 0) { ++ xche = xche->next; ++ goto post_context_calculation; ++ } ++ } ++ } ++ ++ /* ++ * Emit current hunk header. ++ */ ++ ++ if (xecfg->flags & XDL_EMIT_FUNCNAMES) { ++ get_func_line(xe, xecfg, &func_line, ++ s1 - 1, funclineprev); ++ funclineprev = s1 - 1; ++ } ++ if (xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2, ++ func_line.buf, func_line.len, ecb) < 0) ++ return -1; ++ ++ /* ++ * Emit pre-context. ++ */ ++ for (; s2 < xch->i2; s2++) ++ if (xdl_emit_record(&xe->xdf2, s2, " ", ecb) < 0) ++ return -1; ++ ++ for (s1 = xch->i1, s2 = xch->i2;; xch = xch->next) { ++ /* ++ * Merge previous with current change atom. ++ */ ++ for (; s1 < xch->i1 && s2 < xch->i2; s1++, s2++) ++ if (xdl_emit_record(&xe->xdf2, s2, " ", ecb) < 0) ++ return -1; ++ ++ /* ++ * Removes lines from the first file. ++ */ ++ for (s1 = xch->i1; s1 < xch->i1 + xch->chg1; s1++) ++ if (xdl_emit_record(&xe->xdf1, s1, "-", ecb) < 0) ++ return -1; ++ ++ /* ++ * Adds lines from the second file. ++ */ ++ for (s2 = xch->i2; s2 < xch->i2 + xch->chg2; s2++) ++ if (xdl_emit_record(&xe->xdf2, s2, "+", ecb) < 0) ++ return -1; ++ ++ if (xch == xche) ++ break; ++ s1 = xch->i1 + xch->chg1; ++ s2 = xch->i2 + xch->chg2; ++ } ++ ++ /* ++ * Emit post-context. ++ */ ++ for (s2 = xche->i2 + xche->chg2; s2 < e2; s2++) ++ if (xdl_emit_record(&xe->xdf2, s2, " ", ecb) < 0) ++ return -1; ++ } ++ ++ return 0; ++ } +*** ../vim-8.1.0359/src/xdiff/xemit.h 1970-01-01 01:00:00.000000000 +0100 +--- src/xdiff/xemit.h 2018-09-10 17:39:20.324083781 +0200 +*************** +*** 0 **** +--- 1,36 ---- ++ /* ++ * LibXDiff by Davide Libenzi ( File Differential Library ) ++ * Copyright (C) 2003 Davide Libenzi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see ++ * <http://www.gnu.org/licenses/>. ++ * ++ * Davide Libenzi <davidel@xmailserver.org> ++ * ++ */ ++ ++ #if !defined(XEMIT_H) ++ #define XEMIT_H ++ ++ ++ typedef int (*emit_func_t)(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, ++ xdemitconf_t const *xecfg); ++ ++ xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg); ++ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, ++ xdemitconf_t const *xecfg); ++ ++ ++ ++ #endif /* #if !defined(XEMIT_H) */ +*** ../vim-8.1.0359/src/xdiff/xhistogram.c 1970-01-01 01:00:00.000000000 +0100 +--- src/xdiff/xhistogram.c 2018-09-10 17:39:20.324083781 +0200 +*************** +*** 0 **** +--- 1,386 ---- ++ /* ++ * Copyright (C) 2010, Google Inc. ++ * and other copyright owners as documented in JGit's IP log. ++ * ++ * This program and the accompanying materials are made available ++ * under the terms of the Eclipse Distribution License v1.0 which ++ * accompanies this distribution, is reproduced below, and is ++ * available at http://www.eclipse.org/org/documents/edl-v10.php ++ * ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or ++ * without modification, are permitted provided that the following ++ * conditions are met: ++ * ++ * - Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * ++ * - Redistributions in binary form must reproduce the above ++ * copyright notice, this list of conditions and the following ++ * disclaimer in the documentation and/or other materials provided ++ * with the distribution. ++ * ++ * - Neither the name of the Eclipse Foundation, Inc. nor the ++ * names of its contributors may be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND ++ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, ++ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR ++ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ++ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++ #include "xinclude.h" ++ #include "xtypes.h" ++ #include "xdiff.h" ++ ++ #define MAX_PTR INT_MAX ++ #define MAX_CNT INT_MAX ++ ++ #define LINE_END(n) (line##n + count##n - 1) ++ #define LINE_END_PTR(n) (*line##n + *count##n - 1) ++ ++ struct histindex { ++ struct record { ++ unsigned int ptr, cnt; ++ struct record *next; ++ } **records, /* an occurrence */ ++ **line_map; /* map of line to record chain */ ++ chastore_t rcha; ++ unsigned int *next_ptrs; ++ unsigned int table_bits, ++ records_size, ++ line_map_size; ++ ++ unsigned int max_chain_length, ++ key_shift, ++ ptr_shift; ++ ++ unsigned int cnt, ++ has_common; ++ ++ xdfenv_t *env; ++ xpparam_t const *xpp; ++ }; ++ ++ struct region { ++ unsigned int begin1, end1; ++ unsigned int begin2, end2; ++ }; ++ ++ #define LINE_MAP(i, a) (i->line_map[(a) - i->ptr_shift]) ++ ++ #define NEXT_PTR(index, ptr) \ ++ (index->next_ptrs[(ptr) - index->ptr_shift]) ++ ++ #define CNT(index, ptr) \ ++ ((LINE_MAP(index, ptr))->cnt) ++ ++ #define REC(env, s, l) \ ++ (env->xdf##s.recs[l - 1]) ++ ++ static int cmp_recs(xpparam_t const *xpp, ++ xrecord_t *r1, xrecord_t *r2) ++ { ++ return r1->ha == r2->ha && ++ xdl_recmatch(r1->ptr, r1->size, r2->ptr, r2->size, ++ xpp->flags); ++ } ++ ++ #define CMP_ENV(xpp, env, s1, l1, s2, l2) \ ++ (cmp_recs(xpp, REC(env, s1, l1), REC(env, s2, l2))) ++ ++ #define CMP(i, s1, l1, s2, l2) \ ++ (cmp_recs(i->xpp, REC(i->env, s1, l1), REC(i->env, s2, l2))) ++ ++ #define TABLE_HASH(index, side, line) \ ++ XDL_HASHLONG((REC(index->env, side, line))->ha, index->table_bits) ++ ++ static int scanA(struct histindex *index, int line1, int count1) ++ { ++ int ptr, tbl_idx; ++ unsigned int chain_len; ++ struct record **rec_chain, *rec; ++ ++ for (ptr = LINE_END(1); line1 <= ptr; ptr--) { ++ tbl_idx = TABLE_HASH(index, 1, ptr); ++ rec_chain = index->records + tbl_idx; ++ rec = *rec_chain; ++ ++ chain_len = 0; ++ while (rec) { ++ if (CMP(index, 1, rec->ptr, 1, ptr)) { ++ /* ++ * ptr is identical to another element. Insert ++ * it onto the front of the existing element ++ * chain. ++ */ ++ NEXT_PTR(index, ptr) = rec->ptr; ++ rec->ptr = ptr; ++ /* cap rec->cnt at MAX_CNT */ ++ rec->cnt = XDL_MIN(MAX_CNT, rec->cnt + 1); ++ LINE_MAP(index, ptr) = rec; ++ goto continue_scan; ++ } ++ ++ rec = rec->next; ++ chain_len++; ++ } ++ ++ if (chain_len == index->max_chain_length) ++ return -1; ++ ++ /* ++ * This is the first time we have ever seen this particular ++ * element in the sequence. Construct a new chain for it. ++ */ ++ if (!(rec = xdl_cha_alloc(&index->rcha))) ++ return -1; ++ rec->ptr = ptr; ++ rec->cnt = 1; ++ rec->next = *rec_chain; ++ *rec_chain = rec; ++ LINE_MAP(index, ptr) = rec; ++ ++ continue_scan: ++ ; /* no op */ ++ } ++ ++ return 0; ++ } ++ ++ static int try_lcs(struct histindex *index, struct region *lcs, int b_ptr, ++ int line1, int count1, int line2, int count2) ++ { ++ unsigned int b_next = b_ptr + 1; ++ struct record *rec = index->records[TABLE_HASH(index, 2, b_ptr)]; ++ unsigned int as, ae, bs, be, np, rc; ++ int should_break; ++ ++ for (; rec; rec = rec->next) { ++ if (rec->cnt > index->cnt) { ++ if (!index->has_common) ++ index->has_common = CMP(index, 1, rec->ptr, 2, b_ptr); ++ continue; ++ } ++ ++ as = rec->ptr; ++ if (!CMP(index, 1, as, 2, b_ptr)) ++ continue; ++ ++ index->has_common = 1; ++ for (;;) { ++ should_break = 0; ++ np = NEXT_PTR(index, as); ++ bs = b_ptr; ++ ae = as; ++ be = bs; ++ rc = rec->cnt; ++ ++ while (line1 < (int)as && line2 < (int)bs ++ && CMP(index, 1, as - 1, 2, bs - 1)) { ++ as--; ++ bs--; ++ if (1 < rc) ++ rc = XDL_MIN(rc, CNT(index, as)); ++ } ++ while ((int)ae < LINE_END(1) && (int)be < LINE_END(2) ++ && CMP(index, 1, ae + 1, 2, be + 1)) { ++ ae++; ++ be++; ++ if (1 < rc) ++ rc = XDL_MIN(rc, CNT(index, ae)); ++ } ++ ++ if (b_next <= be) ++ b_next = be + 1; ++ if (lcs->end1 - lcs->begin1 < ae - as || rc < index->cnt) { ++ lcs->begin1 = as; ++ lcs->begin2 = bs; ++ lcs->end1 = ae; ++ lcs->end2 = be; ++ index->cnt = rc; ++ } ++ ++ if (np == 0) ++ break; ++ ++ while (np <= ae) { ++ np = NEXT_PTR(index, np); ++ if (np == 0) { ++ should_break = 1; ++ break; ++ } ++ } ++ ++ if (should_break) ++ break; ++ ++ as = np; ++ } ++ } ++ return b_next; ++ } ++ ++ static int fall_back_to_classic_diff(xpparam_t const *xpp, xdfenv_t *env, ++ int line1, int count1, int line2, int count2) ++ { ++ xpparam_t xpparam; ++ xpparam.flags = xpp->flags & ~XDF_DIFF_ALGORITHM_MASK; ++ ++ return xdl_fall_back_diff(env, &xpparam, ++ line1, count1, line2, count2); ++ } ++ ++ static inline void free_index(struct histindex *index) ++ { ++ xdl_free(index->records); ++ xdl_free(index->line_map); ++ xdl_free(index->next_ptrs); ++ xdl_cha_free(&index->rcha); ++ } ++ ++ static int find_lcs(xpparam_t const *xpp, xdfenv_t *env, ++ struct region *lcs, ++ int line1, int count1, int line2, int count2) ++ { ++ int b_ptr; ++ int sz, ret = -1; ++ struct histindex index; ++ ++ memset(&index, 0, sizeof(index)); ++ ++ index.env = env; ++ index.xpp = xpp; ++ ++ index.records = NULL; ++ index.line_map = NULL; ++ /* in case of early xdl_cha_free() */ ++ index.rcha.head = NULL; ++ ++ index.table_bits = xdl_hashbits(count1); ++ sz = index.records_size = 1 << index.table_bits; ++ sz *= sizeof(struct record *); ++ if (!(index.records = (struct record **) xdl_malloc(sz))) ++ goto cleanup; ++ memset(index.records, 0, sz); ++ ++ sz = index.line_map_size = count1; ++ sz *= sizeof(struct record *); ++ if (!(index.line_map = (struct record **) xdl_malloc(sz))) ++ goto cleanup; ++ memset(index.line_map, 0, sz); ++ ++ sz = index.line_map_size; ++ sz *= sizeof(unsigned int); ++ if (!(index.next_ptrs = (unsigned int *) xdl_malloc(sz))) ++ goto cleanup; ++ memset(index.next_ptrs, 0, sz); ++ ++ /* lines / 4 + 1 comes from xprepare.c:xdl_prepare_ctx() */ ++ if (xdl_cha_init(&index.rcha, sizeof(struct record), count1 / 4 + 1) < 0) ++ goto cleanup; ++ ++ index.ptr_shift = line1; ++ index.max_chain_length = 64; ++ ++ if (scanA(&index, line1, count1)) ++ goto cleanup; ++ ++ index.cnt = index.max_chain_length + 1; ++ ++ for (b_ptr = line2; b_ptr <= LINE_END(2); ) ++ b_ptr = try_lcs(&index, lcs, b_ptr, line1, count1, line2, count2); ++ ++ if (index.has_common && index.max_chain_length < index.cnt) ++ ret = 1; ++ else ++ ret = 0; ++ ++ cleanup: ++ free_index(&index); ++ return ret; ++ } ++ ++ static int histogram_diff(xpparam_t const *xpp, xdfenv_t *env, ++ int line1, int count1, int line2, int count2) ++ { ++ struct region lcs; ++ int lcs_found; ++ int result; ++ redo: ++ result = -1; ++ ++ if (count1 <= 0 && count2 <= 0) ++ return 0; ++ ++ if (LINE_END(1) >= MAX_PTR) ++ return -1; ++ ++ if (!count1) { ++ while(count2--) ++ env->xdf2.rchg[line2++ - 1] = 1; ++ return 0; ++ } else if (!count2) { ++ while(count1--) ++ env->xdf1.rchg[line1++ - 1] = 1; ++ return 0; ++ } ++ ++ memset(&lcs, 0, sizeof(lcs)); ++ lcs_found = find_lcs(xpp, env, &lcs, line1, count1, line2, count2); ++ if (lcs_found < 0) ++ goto out; ++ else if (lcs_found) ++ result = fall_back_to_classic_diff(xpp, env, line1, count1, line2, count2); ++ else { ++ if (lcs.begin1 == 0 && lcs.begin2 == 0) { ++ while (count1--) ++ env->xdf1.rchg[line1++ - 1] = 1; ++ while (count2--) ++ env->xdf2.rchg[line2++ - 1] = 1; ++ result = 0; ++ } else { ++ result = histogram_diff(xpp, env, ++ line1, lcs.begin1 - line1, ++ line2, lcs.begin2 - line2); ++ if (result) ++ goto out; ++ /* ++ * result = histogram_diff(xpp, env, ++ * lcs.end1 + 1, LINE_END(1) - lcs.end1, ++ * lcs.end2 + 1, LINE_END(2) - lcs.end2); ++ * but let's optimize tail recursion ourself: ++ */ ++ count1 = LINE_END(1) - lcs.end1; ++ line1 = lcs.end1 + 1; ++ count2 = LINE_END(2) - lcs.end2; ++ line2 = lcs.end2 + 1; ++ goto redo; ++ } ++ } ++ out: ++ return result; ++ } ++ ++ int xdl_do_histogram_diff(mmfile_t *file1, mmfile_t *file2, ++ xpparam_t const *xpp, xdfenv_t *env) ++ { ++ if (xdl_prepare_env(file1, file2, xpp, env) < 0) ++ return -1; ++ ++ return histogram_diff(xpp, env, ++ env->xdf1.dstart + 1, env->xdf1.dend - env->xdf1.dstart + 1, ++ env->xdf2.dstart + 1, env->xdf2.dend - env->xdf2.dstart + 1); ++ } +*** ../vim-8.1.0359/src/xdiff/xinclude.h 1970-01-01 01:00:00.000000000 +0100 +--- src/xdiff/xinclude.h 2018-09-10 17:39:20.324083781 +0200 +*************** +*** 0 **** +--- 1,61 ---- ++ /* ++ * LibXDiff by Davide Libenzi ( File Differential Library ) ++ * Copyright (C) 2003 Davide Libenzi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see ++ * <http://www.gnu.org/licenses/>. ++ * ++ * Davide Libenzi <davidel@xmailserver.org> ++ * ++ */ ++ ++ /* defines HAVE_ATTRIBUTE_UNUSED */ ++ #ifdef HAVE_CONFIG_H ++ # include "../auto/config.h" ++ #endif ++ ++ /* Mark unused function arguments with UNUSED, so that gcc -Wunused-parameter ++ * can be used to check for mistakes. */ ++ #ifdef HAVE_ATTRIBUTE_UNUSED ++ # define UNUSED __attribute__((unused)) ++ #else ++ # define UNUSED ++ #endif ++ ++ #if defined(_MSC_VER) ++ # define inline __inline ++ #endif ++ ++ #if !defined(XINCLUDE_H) ++ #define XINCLUDE_H ++ ++ #include <ctype.h> ++ #include <stdio.h> ++ #include <stdlib.h> ++ #if !defined(_WIN32) ++ #include <unistd.h> ++ #endif ++ #include <string.h> ++ #include <limits.h> ++ ++ #include "xmacros.h" ++ #include "xdiff.h" ++ #include "xtypes.h" ++ #include "xutils.h" ++ #include "xprepare.h" ++ #include "xdiffi.h" ++ #include "xemit.h" ++ ++ ++ #endif /* #if !defined(XINCLUDE_H) */ +*** ../vim-8.1.0359/src/xdiff/xmacros.h 1970-01-01 01:00:00.000000000 +0100 +--- src/xdiff/xmacros.h 2018-09-10 17:39:20.324083781 +0200 +*************** +*** 0 **** +--- 1,54 ---- ++ /* ++ * LibXDiff by Davide Libenzi ( File Differential Library ) ++ * Copyright (C) 2003 Davide Libenzi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see ++ * <http://www.gnu.org/licenses/>. ++ * ++ * Davide Libenzi <davidel@xmailserver.org> ++ * ++ */ ++ ++ #if !defined(XMACROS_H) ++ #define XMACROS_H ++ ++ ++ ++ ++ #define XDL_MIN(a, b) ((a) < (b) ? (a): (b)) ++ #define XDL_MAX(a, b) ((a) > (b) ? (a): (b)) ++ #define XDL_ABS(v) ((v) >= 0 ? (v): -(v)) ++ #define XDL_ISDIGIT(c) ((c) >= '0' && (c) <= '9') ++ #define XDL_ISSPACE(c) (isspace((unsigned char)(c))) ++ #define XDL_ADDBITS(v,b) ((v) + ((v) >> (b))) ++ #define XDL_MASKBITS(b) ((1UL << (b)) - 1) ++ #define XDL_HASHLONG(v,b) (XDL_ADDBITS((unsigned long)(v), b) & XDL_MASKBITS(b)) ++ #define XDL_PTRFREE(p) do { if (p) { xdl_free(p); (p) = NULL; } } while (0) ++ #define XDL_LE32_PUT(p, v) \ ++ do { \ ++ unsigned char *__p = (unsigned char *) (p); \ ++ *__p++ = (unsigned char) (v); \ ++ *__p++ = (unsigned char) ((v) >> 8); \ ++ *__p++ = (unsigned char) ((v) >> 16); \ ++ *__p = (unsigned char) ((v) >> 24); \ ++ } while (0) ++ #define XDL_LE32_GET(p, v) \ ++ do { \ ++ unsigned char const *__p = (unsigned char const *) (p); \ ++ (v) = (unsigned long) __p[0] | ((unsigned long) __p[1]) << 8 | \ ++ ((unsigned long) __p[2]) << 16 | ((unsigned long) __p[3]) << 24; \ ++ } while (0) ++ ++ ++ #endif /* #if !defined(XMACROS_H) */ +*** ../vim-8.1.0359/src/xdiff/xpatience.c 1970-01-01 01:00:00.000000000 +0100 +--- src/xdiff/xpatience.c 2018-09-10 17:39:20.324083781 +0200 +*************** +*** 0 **** +--- 1,390 ---- ++ /* ++ * LibXDiff by Davide Libenzi ( File Differential Library ) ++ * Copyright (C) 2003-2016 Davide Libenzi, Johannes E. Schindelin ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see ++ * <http://www.gnu.org/licenses/>. ++ * ++ * Davide Libenzi <davidel@xmailserver.org> ++ * ++ */ ++ #include "xinclude.h" ++ #include "xtypes.h" ++ #include "xdiff.h" ++ ++ /* ++ * The basic idea of patience diff is to find lines that are unique in ++ * both files. These are intuitively the ones that we want to see as ++ * common lines. ++ * ++ * The maximal ordered sequence of such line pairs (where ordered means ++ * that the order in the sequence agrees with the order of the lines in ++ * both files) naturally defines an initial set of common lines. ++ * ++ * Now, the algorithm tries to extend the set of common lines by growing ++ * the line ranges where the files have identical lines. ++ * ++ * Between those common lines, the patience diff algorithm is applied ++ * recursively, until no unique line pairs can be found; these line ranges ++ * are handled by the well-known Myers algorithm. ++ */ ++ ++ #define NON_UNIQUE ULONG_MAX ++ ++ /* ++ * This is a hash mapping from line hash to line numbers in the first and ++ * second file. ++ */ ++ struct hashmap { ++ int nr, alloc; ++ struct entry { ++ unsigned long hash; ++ /* ++ * 0 = unused entry, 1 = first line, 2 = second, etc. ++ * line2 is NON_UNIQUE if the line is not unique ++ * in either the first or the second file. ++ */ ++ unsigned long line1, line2; ++ /* ++ * "next" & "previous" are used for the longest common ++ * sequence; ++ * initially, "next" reflects only the order in file1. ++ */ ++ struct entry *next, *previous; ++ ++ /* ++ * If 1, this entry can serve as an anchor. See ++ * Documentation/diff-options.txt for more information. ++ */ ++ unsigned anchor : 1; ++ } *entries, *first, *last; ++ /* were common records found? */ ++ unsigned long has_matches; ++ mmfile_t *file1, *file2; ++ xdfenv_t *env; ++ xpparam_t const *xpp; ++ }; ++ ++ static int is_anchor(xpparam_t const *xpp, const char *line) ++ { ++ size_t i; ++ for (i = 0; i < xpp->anchors_nr; i++) { ++ if (!strncmp(line, xpp->anchors[i], strlen(xpp->anchors[i]))) ++ return 1; ++ } ++ return 0; ++ } ++ ++ /* The argument "pass" is 1 for the first file, 2 for the second. */ ++ static void insert_record(xpparam_t const *xpp, int line, struct hashmap *map, ++ int pass) ++ { ++ xrecord_t **records = pass == 1 ? ++ map->env->xdf1.recs : map->env->xdf2.recs; ++ xrecord_t *record = records[line - 1], *other; ++ /* ++ * After xdl_prepare_env() (or more precisely, due to ++ * xdl_classify_record()), the "ha" member of the records (AKA lines) ++ * is _not_ the hash anymore, but a linearized version of it. In ++ * other words, the "ha" member is guaranteed to start with 0 and ++ * the second record's ha can only be 0 or 1, etc. ++ * ++ * So we multiply ha by 2 in the hope that the hashing was ++ * "unique enough". ++ */ ++ int index = (int)((record->ha << 1) % map->alloc); ++ ++ while (map->entries[index].line1) { ++ other = map->env->xdf1.recs[map->entries[index].line1 - 1]; ++ if (map->entries[index].hash != record->ha || ++ !xdl_recmatch(record->ptr, record->size, ++ other->ptr, other->size, ++ map->xpp->flags)) { ++ if (++index >= map->alloc) ++ index = 0; ++ continue; ++ } ++ if (pass == 2) ++ map->has_matches = 1; ++ if (pass == 1 || map->entries[index].line2) ++ map->entries[index].line2 = NON_UNIQUE; ++ else ++ map->entries[index].line2 = line; ++ return; ++ } ++ if (pass == 2) ++ return; ++ map->entries[index].line1 = line; ++ map->entries[index].hash = record->ha; ++ map->entries[index].anchor = is_anchor(xpp, map->env->xdf1.recs[line - 1]->ptr); ++ if (!map->first) ++ map->first = map->entries + index; ++ if (map->last) { ++ map->last->next = map->entries + index; ++ map->entries[index].previous = map->last; ++ } ++ map->last = map->entries + index; ++ map->nr++; ++ } ++ ++ /* ++ * This function has to be called for each recursion into the inter-hunk ++ * parts, as previously non-unique lines can become unique when being ++ * restricted to a smaller part of the files. ++ * ++ * It is assumed that env has been prepared using xdl_prepare(). ++ */ ++ static int fill_hashmap(mmfile_t *file1, mmfile_t *file2, ++ xpparam_t const *xpp, xdfenv_t *env, ++ struct hashmap *result, ++ int line1, int count1, int line2, int count2) ++ { ++ result->file1 = file1; ++ result->file2 = file2; ++ result->xpp = xpp; ++ result->env = env; ++ ++ /* We know exactly how large we want the hash map */ ++ result->alloc = count1 * 2; ++ result->entries = (struct entry *) ++ xdl_malloc(result->alloc * sizeof(struct entry)); ++ if (!result->entries) ++ return -1; ++ memset(result->entries, 0, result->alloc * sizeof(struct entry)); ++ ++ /* First, fill with entries from the first file */ ++ while (count1--) ++ insert_record(xpp, line1++, result, 1); ++ ++ /* Then search for matches in the second file */ ++ while (count2--) ++ insert_record(xpp, line2++, result, 2); ++ ++ return 0; ++ } ++ ++ /* ++ * Find the longest sequence with a smaller last element (meaning a smaller ++ * line2, as we construct the sequence with entries ordered by line1). ++ */ ++ static int binary_search(struct entry **sequence, int longest, ++ struct entry *entry) ++ { ++ int left = -1, right = longest; ++ ++ while (left + 1 < right) { ++ int middle = left + (right - left) / 2; ++ /* by construction, no two entries can be equal */ ++ if (sequence[middle]->line2 > entry->line2) ++ right = middle; ++ else ++ left = middle; ++ } ++ /* return the index in "sequence", _not_ the sequence length */ ++ return left; ++ } ++ ++ /* ++ * The idea is to start with the list of common unique lines sorted by ++ * the order in file1. For each of these pairs, the longest (partial) ++ * sequence whose last element's line2 is smaller is determined. ++ * ++ * For efficiency, the sequences are kept in a list containing exactly one ++ * item per sequence length: the sequence with the smallest last ++ * element (in terms of line2). ++ */ ++ static struct entry *find_longest_common_sequence(struct hashmap *map) ++ { ++ struct entry **sequence = xdl_malloc(map->nr * sizeof(struct entry *)); ++ int longest = 0, i; ++ struct entry *entry; ++ ++ /* ++ * If not -1, this entry in sequence must never be overridden. ++ * Therefore, overriding entries before this has no effect, so ++ * do not do that either. ++ */ ++ int anchor_i = -1; ++ ++ for (entry = map->first; entry; entry = entry->next) { ++ if (!entry->line2 || entry->line2 == NON_UNIQUE) ++ continue; ++ i = binary_search(sequence, longest, entry); ++ entry->previous = i < 0 ? NULL : sequence[i]; ++ ++i; ++ if (i <= anchor_i) ++ continue; ++ sequence[i] = entry; ++ if (entry->anchor) { ++ anchor_i = i; ++ longest = anchor_i + 1; ++ } else if (i == longest) { ++ longest++; ++ } ++ } ++ ++ /* No common unique lines were found */ ++ if (!longest) { ++ xdl_free(sequence); ++ return NULL; ++ } ++ ++ /* Iterate starting at the last element, adjusting the "next" members */ ++ entry = sequence[longest - 1]; ++ entry->next = NULL; ++ while (entry->previous) { ++ entry->previous->next = entry; ++ entry = entry->previous; ++ } ++ xdl_free(sequence); ++ return entry; ++ } ++ ++ static int match(struct hashmap *map, int line1, int line2) ++ { ++ xrecord_t *record1 = map->env->xdf1.recs[line1 - 1]; ++ xrecord_t *record2 = map->env->xdf2.recs[line2 - 1]; ++ return xdl_recmatch(record1->ptr, record1->size, ++ record2->ptr, record2->size, map->xpp->flags); ++ } ++ ++ static int patience_diff(mmfile_t *file1, mmfile_t *file2, ++ xpparam_t const *xpp, xdfenv_t *env, ++ int line1, int count1, int line2, int count2); ++ ++ static int walk_common_sequence(struct hashmap *map, struct entry *first, ++ int line1, int count1, int line2, int count2) ++ { ++ int end1 = line1 + count1, end2 = line2 + count2; ++ int next1, next2; ++ ++ for (;;) { ++ /* Try to grow the line ranges of common lines */ ++ if (first) { ++ next1 = first->line1; ++ next2 = first->line2; ++ while (next1 > line1 && next2 > line2 && ++ match(map, next1 - 1, next2 - 1)) { ++ next1--; ++ next2--; ++ } ++ } else { ++ next1 = end1; ++ next2 = end2; ++ } ++ while (line1 < next1 && line2 < next2 && ++ match(map, line1, line2)) { ++ line1++; ++ line2++; ++ } ++ ++ /* Recurse */ ++ if (next1 > line1 || next2 > line2) { ++ struct hashmap submap; ++ ++ memset(&submap, 0, sizeof(submap)); ++ if (patience_diff(map->file1, map->file2, ++ map->xpp, map->env, ++ line1, next1 - line1, ++ line2, next2 - line2)) ++ return -1; ++ } ++ ++ if (!first) ++ return 0; ++ ++ while (first->next && ++ first->next->line1 == first->line1 + 1 && ++ first->next->line2 == first->line2 + 1) ++ first = first->next; ++ ++ line1 = first->line1 + 1; ++ line2 = first->line2 + 1; ++ ++ first = first->next; ++ } ++ } ++ ++ static int fall_back_to_classic_diff(struct hashmap *map, ++ int line1, int count1, int line2, int count2) ++ { ++ xpparam_t xpp; ++ xpp.flags = map->xpp->flags & ~XDF_DIFF_ALGORITHM_MASK; ++ ++ return xdl_fall_back_diff(map->env, &xpp, ++ line1, count1, line2, count2); ++ } ++ ++ /* ++ * Recursively find the longest common sequence of unique lines, ++ * and if none was found, ask xdl_do_diff() to do the job. ++ * ++ * This function assumes that env was prepared with xdl_prepare_env(). ++ */ ++ static int patience_diff(mmfile_t *file1, mmfile_t *file2, ++ xpparam_t const *xpp, xdfenv_t *env, ++ int line1, int count1, int line2, int count2) ++ { ++ struct hashmap map; ++ struct entry *first; ++ int result = 0; ++ ++ /* trivial case: one side is empty */ ++ if (!count1) { ++ while(count2--) ++ env->xdf2.rchg[line2++ - 1] = 1; ++ return 0; ++ } else if (!count2) { ++ while(count1--) ++ env->xdf1.rchg[line1++ - 1] = 1; ++ return 0; ++ } ++ ++ memset(&map, 0, sizeof(map)); ++ if (fill_hashmap(file1, file2, xpp, env, &map, ++ line1, count1, line2, count2)) ++ return -1; ++ ++ /* are there any matching lines at all? */ ++ if (!map.has_matches) { ++ while(count1--) ++ env->xdf1.rchg[line1++ - 1] = 1; ++ while(count2--) ++ env->xdf2.rchg[line2++ - 1] = 1; ++ xdl_free(map.entries); ++ return 0; ++ } ++ ++ first = find_longest_common_sequence(&map); ++ if (first) ++ result = walk_common_sequence(&map, first, ++ line1, count1, line2, count2); ++ else ++ result = fall_back_to_classic_diff(&map, ++ line1, count1, line2, count2); ++ ++ xdl_free(map.entries); ++ return result; ++ } ++ ++ int xdl_do_patience_diff(mmfile_t *file1, mmfile_t *file2, ++ xpparam_t const *xpp, xdfenv_t *env) ++ { ++ if (xdl_prepare_env(file1, file2, xpp, env) < 0) ++ return -1; ++ ++ /* environment is cleaned up in xdl_diff() */ ++ return patience_diff(file1, file2, xpp, env, ++ 1, env->xdf1.nrec, 1, env->xdf2.nrec); ++ } +*** ../vim-8.1.0359/src/xdiff/xprepare.c 1970-01-01 01:00:00.000000000 +0100 +--- src/xdiff/xprepare.c 2018-09-10 17:39:20.324083781 +0200 +*************** +*** 0 **** +--- 1,483 ---- ++ /* ++ * LibXDiff by Davide Libenzi ( File Differential Library ) ++ * Copyright (C) 2003 Davide Libenzi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see ++ * <http://www.gnu.org/licenses/>. ++ * ++ * Davide Libenzi <davidel@xmailserver.org> ++ * ++ */ ++ ++ #include "xinclude.h" ++ ++ ++ #define XDL_KPDIS_RUN 4 ++ #define XDL_MAX_EQLIMIT 1024 ++ #define XDL_SIMSCAN_WINDOW 100 ++ #define XDL_GUESS_NLINES1 256 ++ #define XDL_GUESS_NLINES2 20 ++ ++ ++ typedef struct s_xdlclass { ++ struct s_xdlclass *next; ++ unsigned long ha; ++ char const *line; ++ long size; ++ long idx; ++ long len1, len2; ++ } xdlclass_t; ++ ++ typedef struct s_xdlclassifier { ++ unsigned int hbits; ++ long hsize; ++ xdlclass_t **rchash; ++ chastore_t ncha; ++ xdlclass_t **rcrecs; ++ long alloc; ++ long count; ++ long flags; ++ } xdlclassifier_t; ++ ++ ++ ++ ++ static int xdl_init_classifier(xdlclassifier_t *cf, long size, long flags); ++ static void xdl_free_classifier(xdlclassifier_t *cf); ++ static int xdl_classify_record(unsigned int pass, xdlclassifier_t *cf, xrecord_t **rhash, ++ unsigned int hbits, xrecord_t *rec); ++ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_t const *xpp, ++ xdlclassifier_t *cf, xdfile_t *xdf); ++ static void xdl_free_ctx(xdfile_t *xdf); ++ static int xdl_clean_mmatch(char const *dis, long i, long s, long e); ++ static int xdl_cleanup_records(xdlclassifier_t *cf, xdfile_t *xdf1, xdfile_t *xdf2); ++ static int xdl_trim_ends(xdfile_t *xdf1, xdfile_t *xdf2); ++ static int xdl_optimize_ctxs(xdlclassifier_t *cf, xdfile_t *xdf1, xdfile_t *xdf2); ++ ++ ++ ++ ++ static int xdl_init_classifier(xdlclassifier_t *cf, long size, long flags) { ++ cf->flags = flags; ++ ++ cf->hbits = xdl_hashbits((unsigned int) size); ++ cf->hsize = 1 << cf->hbits; ++ ++ if (xdl_cha_init(&cf->ncha, sizeof(xdlclass_t), size / 4 + 1) < 0) { ++ ++ return -1; ++ } ++ if (!(cf->rchash = (xdlclass_t **) xdl_malloc(cf->hsize * sizeof(xdlclass_t *)))) { ++ ++ xdl_cha_free(&cf->ncha); ++ return -1; ++ } ++ memset(cf->rchash, 0, cf->hsize * sizeof(xdlclass_t *)); ++ ++ cf->alloc = size; ++ if (!(cf->rcrecs = (xdlclass_t **) xdl_malloc(cf->alloc * sizeof(xdlclass_t *)))) { ++ ++ xdl_free(cf->rchash); ++ xdl_cha_free(&cf->ncha); ++ return -1; ++ } ++ ++ cf->count = 0; ++ ++ return 0; ++ } ++ ++ ++ static void xdl_free_classifier(xdlclassifier_t *cf) { ++ ++ xdl_free(cf->rcrecs); ++ xdl_free(cf->rchash); ++ xdl_cha_free(&cf->ncha); ++ } ++ ++ ++ static int xdl_classify_record(unsigned int pass, xdlclassifier_t *cf, xrecord_t **rhash, ++ unsigned int hbits, xrecord_t *rec) { ++ long hi; ++ char const *line; ++ xdlclass_t *rcrec; ++ xdlclass_t **rcrecs; ++ ++ line = rec->ptr; ++ hi = (long) XDL_HASHLONG(rec->ha, cf->hbits); ++ for (rcrec = cf->rchash[hi]; rcrec; rcrec = rcrec->next) ++ if (rcrec->ha == rec->ha && ++ xdl_recmatch(rcrec->line, rcrec->size, ++ rec->ptr, rec->size, cf->flags)) ++ break; ++ ++ if (!rcrec) { ++ if (!(rcrec = xdl_cha_alloc(&cf->ncha))) { ++ ++ return -1; ++ } ++ rcrec->idx = cf->count++; ++ if (cf->count > cf->alloc) { ++ cf->alloc *= 2; ++ if (!(rcrecs = (xdlclass_t **) xdl_realloc(cf->rcrecs, cf->alloc * sizeof(xdlclass_t *)))) { ++ ++ return -1; ++ } ++ cf->rcrecs = rcrecs; ++ } ++ cf->rcrecs[rcrec->idx] = rcrec; ++ rcrec->line = line; ++ rcrec->size = rec->size; ++ rcrec->ha = rec->ha; ++ rcrec->len1 = rcrec->len2 = 0; ++ rcrec->next = cf->rchash[hi]; ++ cf->rchash[hi] = rcrec; ++ } ++ ++ (pass == 1) ? rcrec->len1++ : rcrec->len2++; ++ ++ rec->ha = (unsigned long) rcrec->idx; ++ ++ hi = (long) XDL_HASHLONG(rec->ha, hbits); ++ rec->next = rhash[hi]; ++ rhash[hi] = rec; ++ ++ return 0; ++ } ++ ++ ++ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_t const *xpp, ++ xdlclassifier_t *cf, xdfile_t *xdf) { ++ unsigned int hbits; ++ long nrec, hsize, bsize; ++ unsigned long hav; ++ char const *blk, *cur, *top, *prev; ++ xrecord_t *crec; ++ xrecord_t **recs, **rrecs; ++ xrecord_t **rhash; ++ unsigned long *ha; ++ char *rchg; ++ long *rindex; ++ ++ ha = NULL; ++ rindex = NULL; ++ rchg = NULL; ++ rhash = NULL; ++ recs = NULL; ++ ++ if (xdl_cha_init(&xdf->rcha, sizeof(xrecord_t), narec / 4 + 1) < 0) ++ goto abort; ++ if (!(recs = (xrecord_t **) xdl_malloc(narec * sizeof(xrecord_t *)))) ++ goto abort; ++ ++ if (XDF_DIFF_ALG(xpp->flags) == XDF_HISTOGRAM_DIFF) ++ hbits = hsize = 0; ++ else { ++ hbits = xdl_hashbits((unsigned int) narec); ++ hsize = 1 << hbits; ++ if (!(rhash = (xrecord_t **) xdl_malloc(hsize * sizeof(xrecord_t *)))) ++ goto abort; ++ memset(rhash, 0, hsize * sizeof(xrecord_t *)); ++ } ++ ++ nrec = 0; ++ if ((cur = blk = xdl_mmfile_first(mf, &bsize)) != NULL) { ++ for (top = blk + bsize; cur < top; ) { ++ prev = cur; ++ hav = xdl_hash_record(&cur, top, xpp->flags); ++ if (nrec >= narec) { ++ narec *= 2; ++ if (!(rrecs = (xrecord_t **) xdl_realloc(recs, narec * sizeof(xrecord_t *)))) ++ goto abort; ++ recs = rrecs; ++ } ++ if (!(crec = xdl_cha_alloc(&xdf->rcha))) ++ goto abort; ++ crec->ptr = prev; ++ crec->size = (long) (cur - prev); ++ crec->ha = hav; ++ recs[nrec++] = crec; ++ ++ if ((XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF) && ++ xdl_classify_record(pass, cf, rhash, hbits, crec) < 0) ++ goto abort; ++ } ++ } ++ ++ if (!(rchg = (char *) xdl_malloc((nrec + 2) * sizeof(char)))) ++ goto abort; ++ memset(rchg, 0, (nrec + 2) * sizeof(char)); ++ ++ if (!(rindex = (long *) xdl_malloc((nrec + 1) * sizeof(long)))) ++ goto abort; ++ if (!(ha = (unsigned long *) xdl_malloc((nrec + 1) * sizeof(unsigned long)))) ++ goto abort; ++ ++ xdf->nrec = nrec; ++ xdf->recs = recs; ++ xdf->hbits = hbits; ++ xdf->rhash = rhash; ++ xdf->rchg = rchg + 1; ++ xdf->rindex = rindex; ++ xdf->nreff = 0; ++ xdf->ha = ha; ++ xdf->dstart = 0; ++ xdf->dend = nrec - 1; ++ ++ return 0; ++ ++ abort: ++ xdl_free(ha); ++ xdl_free(rindex); ++ xdl_free(rchg); ++ xdl_free(rhash); ++ xdl_free(recs); ++ xdl_cha_free(&xdf->rcha); ++ return -1; ++ } ++ ++ ++ static void xdl_free_ctx(xdfile_t *xdf) { ++ ++ xdl_free(xdf->rhash); ++ xdl_free(xdf->rindex); ++ xdl_free(xdf->rchg - 1); ++ xdl_free(xdf->ha); ++ xdl_free(xdf->recs); ++ xdl_cha_free(&xdf->rcha); ++ } ++ ++ ++ int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, ++ xdfenv_t *xe) { ++ long enl1, enl2, sample; ++ xdlclassifier_t cf; ++ ++ memset(&cf, 0, sizeof(cf)); ++ ++ /* ++ * For histogram diff, we can afford a smaller sample size and ++ * thus a poorer estimate of the number of lines, as the hash ++ * table (rhash) won't be filled up/grown. The number of lines ++ * (nrecs) will be updated correctly anyway by ++ * xdl_prepare_ctx(). ++ */ ++ sample = (XDF_DIFF_ALG(xpp->flags) == XDF_HISTOGRAM_DIFF ++ ? XDL_GUESS_NLINES2 : XDL_GUESS_NLINES1); ++ ++ enl1 = xdl_guess_lines(mf1, sample) + 1; ++ enl2 = xdl_guess_lines(mf2, sample) + 1; ++ ++ if (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF && ++ xdl_init_classifier(&cf, enl1 + enl2 + 1, xpp->flags) < 0) ++ return -1; ++ ++ if (xdl_prepare_ctx(1, mf1, enl1, xpp, &cf, &xe->xdf1) < 0) { ++ ++ xdl_free_classifier(&cf); ++ return -1; ++ } ++ if (xdl_prepare_ctx(2, mf2, enl2, xpp, &cf, &xe->xdf2) < 0) { ++ ++ xdl_free_ctx(&xe->xdf1); ++ xdl_free_classifier(&cf); ++ return -1; ++ } ++ ++ if ((XDF_DIFF_ALG(xpp->flags) != XDF_PATIENCE_DIFF) && ++ (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF) && ++ xdl_optimize_ctxs(&cf, &xe->xdf1, &xe->xdf2) < 0) { ++ ++ xdl_free_ctx(&xe->xdf2); ++ xdl_free_ctx(&xe->xdf1); ++ xdl_free_classifier(&cf); ++ return -1; ++ } ++ ++ if (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF) ++ xdl_free_classifier(&cf); ++ ++ return 0; ++ } ++ ++ ++ void xdl_free_env(xdfenv_t *xe) { ++ ++ xdl_free_ctx(&xe->xdf2); ++ xdl_free_ctx(&xe->xdf1); ++ } ++ ++ ++ static int xdl_clean_mmatch(char const *dis, long i, long s, long e) { ++ long r, rdis0, rpdis0, rdis1, rpdis1; ++ ++ /* ++ * Limits the window the is examined during the similar-lines ++ * scan. The loops below stops when dis[i - r] == 1 (line that ++ * has no match), but there are corner cases where the loop ++ * proceed all the way to the extremities by causing huge ++ * performance penalties in case of big files. ++ */ ++ if (i - s > XDL_SIMSCAN_WINDOW) ++ s = i - XDL_SIMSCAN_WINDOW; ++ if (e - i > XDL_SIMSCAN_WINDOW) ++ e = i + XDL_SIMSCAN_WINDOW; ++ ++ /* ++ * Scans the lines before 'i' to find a run of lines that either ++ * have no match (dis[j] == 0) or have multiple matches (dis[j] > 1). ++ * Note that we always call this function with dis[i] > 1, so the ++ * current line (i) is already a multimatch line. ++ */ ++ for (r = 1, rdis0 = 0, rpdis0 = 1; (i - r) >= s; r++) { ++ if (!dis[i - r]) ++ rdis0++; ++ else if (dis[i - r] == 2) ++ rpdis0++; ++ else ++ break; ++ } ++ /* ++ * If the run before the line 'i' found only multimatch lines, we ++ * return 0 and hence we don't make the current line (i) discarded. ++ * We want to discard multimatch lines only when they appear in the ++ * middle of runs with nomatch lines (dis[j] == 0). ++ */ ++ if (rdis0 == 0) ++ return 0; ++ for (r = 1, rdis1 = 0, rpdis1 = 1; (i + r) <= e; r++) { ++ if (!dis[i + r]) ++ rdis1++; ++ else if (dis[i + r] == 2) ++ rpdis1++; ++ else ++ break; ++ } ++ /* ++ * If the run after the line 'i' found only multimatch lines, we ++ * return 0 and hence we don't make the current line (i) discarded. ++ */ ++ if (rdis1 == 0) ++ return 0; ++ rdis1 += rdis0; ++ rpdis1 += rpdis0; ++ ++ return rpdis1 * XDL_KPDIS_RUN < (rpdis1 + rdis1); ++ } ++ ++ ++ /* ++ * Try to reduce the problem complexity, discard records that have no ++ * matches on the other file. Also, lines that have multiple matches ++ * might be potentially discarded if they happear in a run of discardable. ++ */ ++ static int xdl_cleanup_records(xdlclassifier_t *cf, xdfile_t *xdf1, xdfile_t *xdf2) { ++ long i, nm, nreff, mlim; ++ xrecord_t **recs; ++ xdlclass_t *rcrec; ++ char *dis, *dis1, *dis2; ++ ++ if (!(dis = (char *) xdl_malloc(xdf1->nrec + xdf2->nrec + 2))) { ++ ++ return -1; ++ } ++ memset(dis, 0, xdf1->nrec + xdf2->nrec + 2); ++ dis1 = dis; ++ dis2 = dis1 + xdf1->nrec + 1; ++ ++ if ((mlim = xdl_bogosqrt(xdf1->nrec)) > XDL_MAX_EQLIMIT) ++ mlim = XDL_MAX_EQLIMIT; ++ for (i = xdf1->dstart, recs = &xdf1->recs[xdf1->dstart]; i <= xdf1->dend; i++, recs++) { ++ rcrec = cf->rcrecs[(*recs)->ha]; ++ nm = rcrec ? rcrec->len2 : 0; ++ dis1[i] = (nm == 0) ? 0: (nm >= mlim) ? 2: 1; ++ } ++ ++ if ((mlim = xdl_bogosqrt(xdf2->nrec)) > XDL_MAX_EQLIMIT) ++ mlim = XDL_MAX_EQLIMIT; ++ for (i = xdf2->dstart, recs = &xdf2->recs[xdf2->dstart]; i <= xdf2->dend; i++, recs++) { ++ rcrec = cf->rcrecs[(*recs)->ha]; ++ nm = rcrec ? rcrec->len1 : 0; ++ dis2[i] = (nm == 0) ? 0: (nm >= mlim) ? 2: 1; ++ } ++ ++ for (nreff = 0, i = xdf1->dstart, recs = &xdf1->recs[xdf1->dstart]; ++ i <= xdf1->dend; i++, recs++) { ++ if (dis1[i] == 1 || ++ (dis1[i] == 2 && !xdl_clean_mmatch(dis1, i, xdf1->dstart, xdf1->dend))) { ++ xdf1->rindex[nreff] = i; ++ xdf1->ha[nreff] = (*recs)->ha; ++ nreff++; ++ } else ++ xdf1->rchg[i] = 1; ++ } ++ xdf1->nreff = nreff; ++ ++ for (nreff = 0, i = xdf2->dstart, recs = &xdf2->recs[xdf2->dstart]; ++ i <= xdf2->dend; i++, recs++) { ++ if (dis2[i] == 1 || ++ (dis2[i] == 2 && !xdl_clean_mmatch(dis2, i, xdf2->dstart, xdf2->dend))) { ++ xdf2->rindex[nreff] = i; ++ xdf2->ha[nreff] = (*recs)->ha; ++ nreff++; ++ } else ++ xdf2->rchg[i] = 1; ++ } ++ xdf2->nreff = nreff; ++ ++ xdl_free(dis); ++ ++ return 0; ++ } ++ ++ ++ /* ++ * Early trim initial and terminal matching records. ++ */ ++ static int xdl_trim_ends(xdfile_t *xdf1, xdfile_t *xdf2) { ++ long i, lim; ++ xrecord_t **recs1, **recs2; ++ ++ recs1 = xdf1->recs; ++ recs2 = xdf2->recs; ++ for (i = 0, lim = XDL_MIN(xdf1->nrec, xdf2->nrec); i < lim; ++ i++, recs1++, recs2++) ++ if ((*recs1)->ha != (*recs2)->ha) ++ break; ++ ++ xdf1->dstart = xdf2->dstart = i; ++ ++ recs1 = xdf1->recs + xdf1->nrec - 1; ++ recs2 = xdf2->recs + xdf2->nrec - 1; ++ for (lim -= i, i = 0; i < lim; i++, recs1--, recs2--) ++ if ((*recs1)->ha != (*recs2)->ha) ++ break; ++ ++ xdf1->dend = xdf1->nrec - i - 1; ++ xdf2->dend = xdf2->nrec - i - 1; ++ ++ return 0; ++ } ++ ++ ++ static int xdl_optimize_ctxs(xdlclassifier_t *cf, xdfile_t *xdf1, xdfile_t *xdf2) { ++ ++ if (xdl_trim_ends(xdf1, xdf2) < 0 || ++ xdl_cleanup_records(cf, xdf1, xdf2) < 0) { ++ ++ return -1; ++ } ++ ++ return 0; ++ } +*** ../vim-8.1.0359/src/xdiff/xprepare.h 1970-01-01 01:00:00.000000000 +0100 +--- src/xdiff/xprepare.h 2018-09-10 17:39:20.324083781 +0200 +*************** +*** 0 **** +--- 1,34 ---- ++ /* ++ * LibXDiff by Davide Libenzi ( File Differential Library ) ++ * Copyright (C) 2003 Davide Libenzi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see ++ * <http://www.gnu.org/licenses/>. ++ * ++ * Davide Libenzi <davidel@xmailserver.org> ++ * ++ */ ++ ++ #if !defined(XPREPARE_H) ++ #define XPREPARE_H ++ ++ ++ ++ int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, ++ xdfenv_t *xe); ++ void xdl_free_env(xdfenv_t *xe); ++ ++ ++ ++ #endif /* #if !defined(XPREPARE_H) */ +*** ../vim-8.1.0359/src/xdiff/xtypes.h 1970-01-01 01:00:00.000000000 +0100 +--- src/xdiff/xtypes.h 2018-09-10 17:39:20.324083781 +0200 +*************** +*** 0 **** +--- 1,67 ---- ++ /* ++ * LibXDiff by Davide Libenzi ( File Differential Library ) ++ * Copyright (C) 2003 Davide Libenzi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see ++ * <http://www.gnu.org/licenses/>. ++ * ++ * Davide Libenzi <davidel@xmailserver.org> ++ * ++ */ ++ ++ #if !defined(XTYPES_H) ++ #define XTYPES_H ++ ++ ++ ++ typedef struct s_chanode { ++ struct s_chanode *next; ++ long icurr; ++ } chanode_t; ++ ++ typedef struct s_chastore { ++ chanode_t *head, *tail; ++ long isize, nsize; ++ chanode_t *ancur; ++ chanode_t *sncur; ++ long scurr; ++ } chastore_t; ++ ++ typedef struct s_xrecord { ++ struct s_xrecord *next; ++ char const *ptr; ++ long size; ++ unsigned long ha; ++ } xrecord_t; ++ ++ typedef struct s_xdfile { ++ chastore_t rcha; ++ long nrec; ++ unsigned int hbits; ++ xrecord_t **rhash; ++ long dstart, dend; ++ xrecord_t **recs; ++ char *rchg; ++ long *rindex; ++ long nreff; ++ unsigned long *ha; ++ } xdfile_t; ++ ++ typedef struct s_xdfenv { ++ xdfile_t xdf1, xdf2; ++ } xdfenv_t; ++ ++ ++ ++ #endif /* #if !defined(XTYPES_H) */ +*** ../vim-8.1.0359/src/xdiff/xutils.c 1970-01-01 01:00:00.000000000 +0100 +--- src/xdiff/xutils.c 2018-09-10 17:39:20.324083781 +0200 +*************** +*** 0 **** +--- 1,425 ---- ++ /* ++ * LibXDiff by Davide Libenzi ( File Differential Library ) ++ * Copyright (C) 2003 Davide Libenzi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see ++ * <http://www.gnu.org/licenses/>. ++ * ++ * Davide Libenzi <davidel@xmailserver.org> ++ * ++ */ ++ ++ #include <limits.h> ++ #include <assert.h> ++ #include "xinclude.h" ++ ++ ++ ++ ++ long xdl_bogosqrt(long n) { ++ long i; ++ ++ /* ++ * Classical integer square root approximation using shifts. ++ */ ++ for (i = 1; n > 0; n >>= 2) ++ i <<= 1; ++ ++ return i; ++ } ++ ++ ++ int xdl_emit_diffrec(char const *rec, long size, char const *pre, long psize, ++ xdemitcb_t *ecb) { ++ int i = 2; ++ mmbuffer_t mb[3]; ++ ++ mb[0].ptr = (char *) pre; ++ mb[0].size = psize; ++ mb[1].ptr = (char *) rec; ++ mb[1].size = size; ++ if (size > 0 && rec[size - 1] != '\n') { ++ mb[2].ptr = (char *) "\n\\ No newline at end of file\n"; ++ mb[2].size = strlen(mb[2].ptr); ++ i++; ++ } ++ if (ecb->outf(ecb->priv, mb, i) < 0) { ++ ++ return -1; ++ } ++ ++ return 0; ++ } ++ ++ void *xdl_mmfile_first(mmfile_t *mmf, long *size) ++ { ++ *size = mmf->size; ++ return mmf->ptr; ++ } ++ ++ ++ long xdl_mmfile_size(mmfile_t *mmf) ++ { ++ return mmf->size; ++ } ++ ++ ++ int xdl_cha_init(chastore_t *cha, long isize, long icount) { ++ ++ cha->head = cha->tail = NULL; ++ cha->isize = isize; ++ cha->nsize = icount * isize; ++ cha->ancur = cha->sncur = NULL; ++ cha->scurr = 0; ++ ++ return 0; ++ } ++ ++ ++ void xdl_cha_free(chastore_t *cha) { ++ chanode_t *cur, *tmp; ++ ++ for (cur = cha->head; (tmp = cur) != NULL;) { ++ cur = cur->next; ++ xdl_free(tmp); ++ } ++ } ++ ++ ++ void *xdl_cha_alloc(chastore_t *cha) { ++ chanode_t *ancur; ++ void *data; ++ ++ if (!(ancur = cha->ancur) || ancur->icurr == cha->nsize) { ++ if (!(ancur = (chanode_t *) xdl_malloc(sizeof(chanode_t) + cha->nsize))) { ++ ++ return NULL; ++ } ++ ancur->icurr = 0; ++ ancur->next = NULL; ++ if (cha->tail) ++ cha->tail->next = ancur; ++ if (!cha->head) ++ cha->head = ancur; ++ cha->tail = ancur; ++ cha->ancur = ancur; ++ } ++ ++ data = (char *) ancur + sizeof(chanode_t) + ancur->icurr; ++ ancur->icurr += cha->isize; ++ ++ return data; ++ } ++ ++ long xdl_guess_lines(mmfile_t *mf, long sample) { ++ long nl = 0, size, tsize = 0; ++ char const *data, *cur, *top; ++ ++ if ((cur = data = xdl_mmfile_first(mf, &size)) != NULL) { ++ for (top = data + size; nl < sample && cur < top; ) { ++ nl++; ++ if (!(cur = memchr(cur, '\n', top - cur))) ++ cur = top; ++ else ++ cur++; ++ } ++ tsize += (long) (cur - data); ++ } ++ ++ if (nl && tsize) ++ nl = xdl_mmfile_size(mf) / (tsize / nl); ++ ++ return nl + 1; ++ } ++ ++ int xdl_blankline(const char *line, long size, long flags) ++ { ++ long i; ++ ++ if (!(flags & XDF_WHITESPACE_FLAGS)) ++ return (size <= 1); ++ ++ for (i = 0; i < size && XDL_ISSPACE(line[i]); i++) ++ ; ++ ++ return (i == size); ++ } ++ ++ /* ++ * Have we eaten everything on the line, except for an optional ++ * CR at the very end? ++ */ ++ static int ends_with_optional_cr(const char *l, long s, long i) ++ { ++ int complete = s && l[s-1] == '\n'; ++ ++ if (complete) ++ s--; ++ if (s == i) ++ return 1; ++ /* do not ignore CR at the end of an incomplete line */ ++ if (complete && s == i + 1 && l[i] == '\r') ++ return 1; ++ return 0; ++ } ++ ++ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags) ++ { ++ int i1, i2; ++ ++ if (s1 == s2 && !memcmp(l1, l2, s1)) ++ return 1; ++ if (!(flags & XDF_WHITESPACE_FLAGS)) ++ return 0; ++ ++ i1 = 0; ++ i2 = 0; ++ ++ /* ++ * -w matches everything that matches with -b, and -b in turn ++ * matches everything that matches with --ignore-space-at-eol, ++ * which in turn matches everything that matches with --ignore-cr-at-eol. ++ * ++ * Each flavor of ignoring needs different logic to skip whitespaces ++ * while we have both sides to compare. ++ */ ++ if (flags & XDF_IGNORE_WHITESPACE) { ++ goto skip_ws; ++ while (i1 < s1 && i2 < s2) { ++ if (l1[i1++] != l2[i2++]) ++ return 0; ++ skip_ws: ++ while (i1 < s1 && XDL_ISSPACE(l1[i1])) ++ i1++; ++ while (i2 < s2 && XDL_ISSPACE(l2[i2])) ++ i2++; ++ } ++ } else if (flags & XDF_IGNORE_WHITESPACE_CHANGE) { ++ while (i1 < s1 && i2 < s2) { ++ if (XDL_ISSPACE(l1[i1]) && XDL_ISSPACE(l2[i2])) { ++ /* Skip matching spaces and try again */ ++ while (i1 < s1 && XDL_ISSPACE(l1[i1])) ++ i1++; ++ while (i2 < s2 && XDL_ISSPACE(l2[i2])) ++ i2++; ++ continue; ++ } ++ if (l1[i1++] != l2[i2++]) ++ return 0; ++ } ++ } else if (flags & XDF_IGNORE_WHITESPACE_AT_EOL) { ++ while (i1 < s1 && i2 < s2 && l1[i1] == l2[i2]) { ++ i1++; ++ i2++; ++ } ++ } else if (flags & XDF_IGNORE_CR_AT_EOL) { ++ /* Find the first difference and see how the line ends */ ++ while (i1 < s1 && i2 < s2 && l1[i1] == l2[i2]) { ++ i1++; ++ i2++; ++ } ++ return (ends_with_optional_cr(l1, s1, i1) && ++ ends_with_optional_cr(l2, s2, i2)); ++ } ++ ++ /* ++ * After running out of one side, the remaining side must have ++ * nothing but whitespace for the lines to match. Note that ++ * ignore-whitespace-at-eol case may break out of the loop ++ * while there still are characters remaining on both lines. ++ */ ++ if (i1 < s1) { ++ while (i1 < s1 && XDL_ISSPACE(l1[i1])) ++ i1++; ++ if (s1 != i1) ++ return 0; ++ } ++ if (i2 < s2) { ++ while (i2 < s2 && XDL_ISSPACE(l2[i2])) ++ i2++; ++ return (s2 == i2); ++ } ++ return 1; ++ } ++ ++ static unsigned long xdl_hash_record_with_whitespace(char const **data, ++ char const *top, long flags) { ++ unsigned long ha = 5381; ++ char const *ptr = *data; ++ int cr_at_eol_only = (flags & XDF_WHITESPACE_FLAGS) == XDF_IGNORE_CR_AT_EOL; ++ ++ for (; ptr < top && *ptr != '\n'; ptr++) { ++ if (cr_at_eol_only) { ++ /* do not ignore CR at the end of an incomplete line */ ++ if (*ptr == '\r' && ++ (ptr + 1 < top && ptr[1] == '\n')) ++ continue; ++ } ++ else if (XDL_ISSPACE(*ptr)) { ++ const char *ptr2 = ptr; ++ int at_eol; ++ while (ptr + 1 < top && XDL_ISSPACE(ptr[1]) ++ && ptr[1] != '\n') ++ ptr++; ++ at_eol = (top <= ptr + 1 || ptr[1] == '\n'); ++ if (flags & XDF_IGNORE_WHITESPACE) ++ ; /* already handled */ ++ else if (flags & XDF_IGNORE_WHITESPACE_CHANGE ++ && !at_eol) { ++ ha += (ha << 5); ++ ha ^= (unsigned long) ' '; ++ } ++ else if (flags & XDF_IGNORE_WHITESPACE_AT_EOL ++ && !at_eol) { ++ while (ptr2 != ptr + 1) { ++ ha += (ha << 5); ++ ha ^= (unsigned long) *ptr2; ++ ptr2++; ++ } ++ } ++ continue; ++ } ++ ha += (ha << 5); ++ ha ^= (unsigned long) *ptr; ++ } ++ *data = ptr < top ? ptr + 1: ptr; ++ ++ return ha; ++ } ++ ++ unsigned long xdl_hash_record(char const **data, char const *top, long flags) { ++ unsigned long ha = 5381; ++ char const *ptr = *data; ++ ++ if (flags & XDF_WHITESPACE_FLAGS) ++ return xdl_hash_record_with_whitespace(data, top, flags); ++ ++ for (; ptr < top && *ptr != '\n'; ptr++) { ++ ha += (ha << 5); ++ ha ^= (unsigned long) *ptr; ++ } ++ *data = ptr < top ? ptr + 1: ptr; ++ ++ return ha; ++ } ++ ++ unsigned int xdl_hashbits(unsigned int size) { ++ unsigned int val = 1, bits = 0; ++ ++ for (; val < size && bits < CHAR_BIT * sizeof(unsigned int); val <<= 1, bits++); ++ return bits ? bits: 1; ++ } ++ ++ ++ int xdl_num_out(char *out, long val) { ++ char *ptr, *str = out; ++ char buf[32]; ++ ++ ptr = buf + sizeof(buf) - 1; ++ *ptr = '\0'; ++ if (val < 0) { ++ *--ptr = '-'; ++ val = -val; ++ } ++ for (; val && ptr > buf; val /= 10) ++ *--ptr = "0123456789"[val % 10]; ++ if (*ptr) ++ for (; *ptr; ptr++, str++) ++ *str = *ptr; ++ else ++ *str++ = '0'; ++ *str = '\0'; ++ ++ return str - out; ++ } ++ ++ int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2, ++ const char *func, long funclen, xdemitcb_t *ecb) { ++ int nb = 0; ++ mmbuffer_t mb; ++ char buf[128]; ++ ++ memcpy(buf, "@@ -", 4); ++ nb += 4; ++ ++ nb += xdl_num_out(buf + nb, c1 ? s1: s1 - 1); ++ ++ if (c1 != 1) { ++ memcpy(buf + nb, ",", 1); ++ nb += 1; ++ ++ nb += xdl_num_out(buf + nb, c1); ++ } ++ ++ memcpy(buf + nb, " +", 2); ++ nb += 2; ++ ++ nb += xdl_num_out(buf + nb, c2 ? s2: s2 - 1); ++ ++ if (c2 != 1) { ++ memcpy(buf + nb, ",", 1); ++ nb += 1; ++ ++ nb += xdl_num_out(buf + nb, c2); ++ } ++ ++ memcpy(buf + nb, " @@", 3); ++ nb += 3; ++ if (func && funclen) { ++ buf[nb++] = ' '; ++ if (funclen > (long)sizeof(buf) - nb - 1) ++ funclen = sizeof(buf) - nb - 1; ++ memcpy(buf + nb, func, funclen); ++ nb += funclen; ++ } ++ buf[nb++] = '\n'; ++ ++ mb.ptr = buf; ++ mb.size = nb; ++ if (ecb->outf(ecb->priv, &mb, 1) < 0) ++ return -1; ++ ++ return 0; ++ } ++ ++ int xdl_fall_back_diff(xdfenv_t *diff_env, xpparam_t const *xpp, ++ int line1, int count1, int line2, int count2) ++ { ++ /* ++ * This probably does not work outside Git, since ++ * we have a very simple mmfile structure. ++ * ++ * Note: ideally, we would reuse the prepared environment, but ++ * the libxdiff interface does not (yet) allow for diffing only ++ * ranges of lines instead of the whole files. ++ */ ++ mmfile_t subfile1, subfile2; ++ xdfenv_t env; ++ ++ subfile1.ptr = (char *)diff_env->xdf1.recs[line1 - 1]->ptr; ++ subfile1.size = diff_env->xdf1.recs[line1 + count1 - 2]->ptr + ++ diff_env->xdf1.recs[line1 + count1 - 2]->size - subfile1.ptr; ++ subfile2.ptr = (char *)diff_env->xdf2.recs[line2 - 1]->ptr; ++ subfile2.size = diff_env->xdf2.recs[line2 + count2 - 2]->ptr + ++ diff_env->xdf2.recs[line2 + count2 - 2]->size - subfile2.ptr; ++ if (xdl_do_diff(&subfile1, &subfile2, xpp, &env) < 0) ++ return -1; ++ ++ memcpy(diff_env->xdf1.rchg + line1 - 1, env.xdf1.rchg, count1); ++ memcpy(diff_env->xdf2.rchg + line2 - 1, env.xdf2.rchg, count2); ++ ++ xdl_free_env(&env); ++ ++ return 0; ++ } +*** ../vim-8.1.0359/src/xdiff/xutils.h 1970-01-01 01:00:00.000000000 +0100 +--- src/xdiff/xutils.h 2018-09-10 17:39:20.324083781 +0200 +*************** +*** 0 **** +--- 1,47 ---- ++ /* ++ * LibXDiff by Davide Libenzi ( File Differential Library ) ++ * Copyright (C) 2003 Davide Libenzi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see ++ * <http://www.gnu.org/licenses/>. ++ * ++ * Davide Libenzi <davidel@xmailserver.org> ++ * ++ */ ++ ++ #if !defined(XUTILS_H) ++ #define XUTILS_H ++ ++ ++ ++ long xdl_bogosqrt(long n); ++ int xdl_emit_diffrec(char const *rec, long size, char const *pre, long psize, ++ xdemitcb_t *ecb); ++ int xdl_cha_init(chastore_t *cha, long isize, long icount); ++ void xdl_cha_free(chastore_t *cha); ++ void *xdl_cha_alloc(chastore_t *cha); ++ long xdl_guess_lines(mmfile_t *mf, long sample); ++ int xdl_blankline(const char *line, long size, long flags); ++ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags); ++ unsigned long xdl_hash_record(char const **data, char const *top, long flags); ++ unsigned int xdl_hashbits(unsigned int size); ++ int xdl_num_out(char *out, long val); ++ int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2, ++ const char *func, long funclen, xdemitcb_t *ecb); ++ int xdl_fall_back_diff(xdfenv_t *diff_env, xpparam_t const *xpp, ++ int line1, int count1, int line2, int count2); ++ ++ ++ ++ #endif /* #if !defined(XUTILS_H) */ +*** ../vim-8.1.0359/src/xdiff/README.txt 1970-01-01 01:00:00.000000000 +0100 +--- src/xdiff/README.txt 2018-09-10 17:39:20.324083781 +0200 +*************** +*** 0 **** +--- 1,14 ---- ++ The files in this directory come from the xdiff implementation in git. ++ You can find it here: https://github.com/git/git/tree/master/xdiff ++ The files were last updated 2018 September 10. ++ ++ This is originally based on libxdiff, which can be found here: ++ http://www.xmailserver.org/xdiff-lib.html ++ ++ The git version was used because it has been maintained and improved. ++ And since it's part of git it is expected to be reliable. ++ ++ The code is distributed under the GNU LGPL license. It is included in the ++ COPYING file. ++ ++ The first work for including xdiff in Vim was done by Christian Brabandt. +*** ../vim-8.1.0359/src/version.c 2018-09-09 22:02:21.165859748 +0200 +--- src/version.c 2018-09-10 17:23:11.443756983 +0200 +*************** +*** 796,797 **** +--- 796,799 ---- + { /* Add new patch number below this line */ ++ /**/ ++ 360, + /**/ + +-- +'Well, here's something to occupy you and keep your mind off things.' +'It won't work, I have an exceptionally large mind.' + -- Douglas Adams, "The Hitchhiker's Guide to the Galaxy" + + /// 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 /// |