From d4a1aabe372ccb95aec968f4d54503231b1f956c Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 8 Sep 2018 15:10:34 +0200 Subject: [PATCH 01/16] patch 8.1.0352: browsing compressed tar files does not always work Problem: Browsing compressed tar files does not always work. Solution: Use the "file" command to get the compression type. --- runtime/autoload/tar.vim | 34 +++++++++++++++++++++++----------- src/version.c | 2 ++ 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/runtime/autoload/tar.vim b/runtime/autoload/tar.vim index d92fe1b180..dc670dbd14 100644 --- a/runtime/autoload/tar.vim +++ b/runtime/autoload/tar.vim @@ -153,15 +153,14 @@ fun! tar#Browse(tarfile) let tarfile=substitute(system("cygpath -u ".shellescape(tarfile,0)),'\n$','','e') endif - let gzip_command = s:get_gzip_command(tarfile) - let curlast= line("$") if tarfile =~# '\.\(gz\|tgz\)$' + let gzip_command = s:get_gzip_command(tarfile) " call Decho("1: exe silent r! gzip -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - ") exe "sil! r! " . gzip_command . " -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - " elseif tarfile =~# '\.lrp' " call Decho("2: exe silent r! cat -- ".shellescape(tarfile,1)."|gzip -d -c -|".g:tar_cmd." -".g:tar_browseoptions." - ") - exe "sil! r! cat -- ".shellescape(tarfile,1)."|" . gzip_command . " -d -c -|".g:tar_cmd." -".g:tar_browseoptions." - " + exe "sil! r! cat -- ".shellescape(tarfile,1)."|gzip -d -c -|".g:tar_cmd." -".g:tar_browseoptions." - " elseif tarfile =~# '\.\(bz2\|tbz\|tb2\)$' " call Decho("3: exe silent r! bzip2 -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - ") exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - " @@ -291,17 +290,16 @@ fun! tar#Read(fname,mode) let tar_secure= " " endif - let gzip_command = s:get_gzip_command(tarfile) - if tarfile =~# '\.bz2$' " call Decho("7: exe silent r! bzip2 -d -c ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp) exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp elseif tarfile =~# '\.\(gz\|tgz\)$' + let gzip_command = s:get_gzip_command(tarfile) " call Decho("5: exe silent r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd.' -'.g:tar_readoptions.' - '.tar_secure.shellescape(fname,1)) exe "sil! r! " . gzip_command . " -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp elseif tarfile =~# '\.lrp$' " call Decho("6: exe silent r! cat ".shellescape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp) - exe "sil! r! cat -- ".shellescape(tarfile,1)." | " . gzip_command . " -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp + exe "sil! r! cat -- ".shellescape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp elseif tarfile =~# '\.lzma$' " call Decho("7: exe silent r! lzma -d -c ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp) exe "sil! r! lzma -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp @@ -589,8 +587,9 @@ fun! tar#Vimuntar(...) " if necessary, decompress the tarball; then, extract it if tartail =~ '\.tgz' - if executable("bzip2") - silent exe "!bzip2 -d ".shellescape(tartail) + let gzip_command = s:get_gzip_command(tarfile) + if executable(gzip_command) + silent exe "!" . gzip_command . " -d ".shellescape(tartail) elseif executable("gunzip") silent exe "!gunzip ".shellescape(tartail) elseif executable("gzip") @@ -630,11 +629,24 @@ fun! tar#Vimuntar(...) endfun func s:get_gzip_command(file) - if a:file =~# 'z$' && executable('bzip2') - " Some .tgz files are actually compressed with bzip2. Since bzip2 can - " handle the format from gzip, use it if the command exists. + " Try using the "file" command to get the actual compression type, since + " there is no standard way for the naming: ".tgz", ".tbz", ".txz", etc. + " If the "file" command doesn't work fall back to just using the file name. + if a:file =~# 'z$' + let filetype = system('file ' . a:file) + if filetype =~ 'bzip2 compressed' && executable('bzip2') + return 'bzip2' + endif + if filetype =~ 'XZ compressed' && executable('xz') + return 'xz' + endif + endif + if a:file =~# 'bz2$' return 'bzip2' endif + if a:file =~# 'xz$' + return 'xz' + endif return 'gzip' endfunc diff --git a/src/version.c b/src/version.c index ba1ac1a19c..772acc925d 100644 --- a/src/version.c +++ b/src/version.c @@ -794,6 +794,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 352, /**/ 351, /**/ From 99396d4cbf78d313a454c7448acc07412d2e45b7 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 8 Sep 2018 18:21:16 +0200 Subject: [PATCH 02/16] patch 8.1.0353: an "after" directory of a package is appended to 'rtp' Problem: An "after" directory of a package is appended to 'rtp', which will be after the user's "after" directory. () Solution: Insert the package "after" directory before any other "after" directory in 'rtp'. (closes #3409) --- src/ex_cmds2.c | 102 +++++++++++++++++++++++++---------- src/testdir/test_packadd.vim | 20 ++++++- src/version.c | 2 + 3 files changed, 96 insertions(+), 28 deletions(-) diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c index a58b955f3c..08eb181787 100644 --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -3691,14 +3691,17 @@ source_all_matches(char_u *pat) add_pack_dir_to_rtp(char_u *fname) { char_u *p4, *p3, *p2, *p1, *p; - char_u *insp; + char_u *entry; + char_u *insp = NULL; int c; char_u *new_rtp; int keep; size_t oldlen; size_t addlen; + size_t new_rtp_len; char_u *afterdir = NULL; size_t afterlen = 0; + char_u *after_insp = NULL; char_u *ffname = NULL; size_t fname_len; char_u *buf = NULL; @@ -3725,54 +3728,99 @@ add_pack_dir_to_rtp(char_u *fname) if (ffname == NULL) return FAIL; - /* Find "ffname" in "p_rtp", ignoring '/' vs '\' differences. */ + // Find "ffname" in "p_rtp", ignoring '/' vs '\' differences. + // Also stop at the first "after" directory. fname_len = STRLEN(ffname); - insp = p_rtp; buf = alloc(MAXPATHL); if (buf == NULL) goto theend; - while (*insp != NUL) + for (entry = p_rtp; *entry != NUL; ) { - copy_option_part(&insp, buf, MAXPATHL, ","); - add_pathsep(buf); - rtp_ffname = fix_fname(buf); - if (rtp_ffname == NULL) - goto theend; - match = vim_fnamencmp(rtp_ffname, ffname, fname_len) == 0; - vim_free(rtp_ffname); - if (match) + char_u *cur_entry = entry; + + copy_option_part(&entry, buf, MAXPATHL, ","); + if (insp == NULL) + { + add_pathsep(buf); + rtp_ffname = fix_fname(buf); + if (rtp_ffname == NULL) + goto theend; + match = vim_fnamencmp(rtp_ffname, ffname, fname_len) == 0; + vim_free(rtp_ffname); + if (match) + // Insert "ffname" after this entry (and comma). + insp = entry; + } + + if ((p = (char_u *)strstr((char *)buf, "after")) != NULL + && p > buf + && vim_ispathsep(p[-1]) + && (vim_ispathsep(p[5]) || p[5] == NUL || p[5] == ',')) + { + if (insp == NULL) + // Did not find "ffname" before the first "after" directory, + // insert it before this entry. + insp = cur_entry; + after_insp = cur_entry; break; + } } - if (*insp == NUL) - /* not found, append at the end */ + if (insp == NULL) + // Both "fname" and "after" not found, append at the end. insp = p_rtp + STRLEN(p_rtp); - else - /* append after the matching directory. */ - --insp; - /* check if rtp/pack/name/start/name/after exists */ + // check if rtp/pack/name/start/name/after exists afterdir = concat_fnames(fname, (char_u *)"after", TRUE); if (afterdir != NULL && mch_isdir(afterdir)) - afterlen = STRLEN(afterdir) + 1; /* add one for comma */ + afterlen = STRLEN(afterdir) + 1; // add one for comma oldlen = STRLEN(p_rtp); - addlen = STRLEN(fname) + 1; /* add one for comma */ - new_rtp = alloc((int)(oldlen + addlen + afterlen + 1)); - /* add one for NUL */ + addlen = STRLEN(fname) + 1; // add one for comma + new_rtp = alloc((int)(oldlen + addlen + afterlen + 1)); // add one for NUL if (new_rtp == NULL) goto theend; + + // We now have 'rtp' parts: {keep}{keep_after}{rest}. + // Create new_rtp, first: {keep},{fname} keep = (int)(insp - p_rtp); mch_memmove(new_rtp, p_rtp, keep); - new_rtp[keep] = ','; - mch_memmove(new_rtp + keep + 1, fname, addlen); - if (p_rtp[keep] != NUL) - mch_memmove(new_rtp + keep + addlen, p_rtp + keep, oldlen - keep + 1); - if (afterlen > 0) + new_rtp_len = keep; + if (*insp == NUL) + new_rtp[new_rtp_len++] = ','; // add comma before + mch_memmove(new_rtp + new_rtp_len, fname, addlen - 1); + new_rtp_len += addlen - 1; + if (*insp != NUL) + new_rtp[new_rtp_len++] = ','; // add comma after + + if (afterlen > 0 && after_insp != NULL) { + int keep_after = (int)(after_insp - p_rtp); + + // Add to new_rtp: {keep},{fname}{keep_after},{afterdir} + mch_memmove(new_rtp + new_rtp_len, p_rtp + keep, + keep_after - keep); + new_rtp_len += keep_after - keep; + mch_memmove(new_rtp + new_rtp_len, afterdir, afterlen - 1); + new_rtp_len += afterlen - 1; + new_rtp[new_rtp_len++] = ','; + keep = keep_after; + } + + if (p_rtp[keep] != NUL) + // Append rest: {keep},{fname}{keep_after},{afterdir}{rest} + mch_memmove(new_rtp + new_rtp_len, p_rtp + keep, oldlen - keep + 1); + else + new_rtp[new_rtp_len] = NUL; + + if (afterlen > 0 && after_insp == NULL) + { + // Append afterdir when "after" was not found: + // {keep},{fname}{rest},{afterdir} STRCAT(new_rtp, ","); STRCAT(new_rtp, afterdir); } + set_option_value((char_u *)"rtp", 0L, new_rtp, 0); vim_free(new_rtp); retval = OK; diff --git a/src/testdir/test_packadd.vim b/src/testdir/test_packadd.vim index 64bd8d2b23..f511a4d587 100644 --- a/src/testdir/test_packadd.vim +++ b/src/testdir/test_packadd.vim @@ -12,6 +12,11 @@ func TearDown() endfunc func Test_packadd() + if !exists('s:plugdir') + echomsg 'when running this test manually, call SetUp() first' + return + endif + call mkdir(s:plugdir . '/plugin/also', 'p') call mkdir(s:plugdir . '/ftdetect', 'p') call mkdir(s:plugdir . '/after', 'p') @@ -19,6 +24,14 @@ func Test_packadd() let rtp = &rtp filetype on + let rtp_entries = split(rtp, ',') + for entry in rtp_entries + if entry =~? '\' + let first_after_entry = entry + break + endif + endfor + exe 'split ' . s:plugdir . '/plugin/test.vim' call setline(1, 'let g:plugin_works = 42') wq @@ -38,7 +51,12 @@ func Test_packadd() call assert_equal(17, g:ftdetect_works) call assert_true(len(&rtp) > len(rtp)) call assert_match('/testdir/Xdir/pack/mine/opt/mytest\($\|,\)', &rtp) - call assert_match('/testdir/Xdir/pack/mine/opt/mytest/after$', &rtp) + + let new_after = match(&rtp, '/testdir/Xdir/pack/mine/opt/mytest/after,') + let old_after = match(&rtp, ',' . first_after_entry . '\>') + call assert_true(new_after > 0, 'rtp is ' . &rtp) + call assert_true(old_after > 0, 'rtp is ' . &rtp) + call assert_true(new_after < old_after, 'rtp is ' . &rtp) " NOTE: '/.../opt/myte' forwardly matches with '/.../opt/mytest' call mkdir(fnamemodify(s:plugdir, ':h') . '/myte', 'p') diff --git a/src/version.c b/src/version.c index 772acc925d..840f288773 100644 --- a/src/version.c +++ b/src/version.c @@ -794,6 +794,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 353, /**/ 352, /**/ From 53c8a478cc4265549597b00214e0da812154742e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 8 Sep 2018 19:12:12 +0200 Subject: [PATCH 03/16] patch 8.1.0354: packadd test fails on MS-Windows Problem: Packadd test fails on MS-Windows. Solution: Ignore difference between forward and backward slashes. --- src/testdir/test_packadd.vim | 5 +++-- src/version.c | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/testdir/test_packadd.vim b/src/testdir/test_packadd.vim index f511a4d587..6d0565b864 100644 --- a/src/testdir/test_packadd.vim +++ b/src/testdir/test_packadd.vim @@ -53,9 +53,10 @@ func Test_packadd() call assert_match('/testdir/Xdir/pack/mine/opt/mytest\($\|,\)', &rtp) let new_after = match(&rtp, '/testdir/Xdir/pack/mine/opt/mytest/after,') - let old_after = match(&rtp, ',' . first_after_entry . '\>') + let forwarded = substitute(first_after_entry, '\\', '[/\\\\]', 'g') + let old_after = match(&rtp, ',' . forwarded . '\>') call assert_true(new_after > 0, 'rtp is ' . &rtp) - call assert_true(old_after > 0, 'rtp is ' . &rtp) + call assert_true(old_after > 0, 'match ' . forwarded . ' in ' . &rtp) call assert_true(new_after < old_after, 'rtp is ' . &rtp) " NOTE: '/.../opt/myte' forwardly matches with '/.../opt/mytest' diff --git a/src/version.c b/src/version.c index 840f288773..480d20e8b1 100644 --- a/src/version.c +++ b/src/version.c @@ -794,6 +794,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 354, /**/ 353, /**/ From a750ac2288eae4f751185597885552e9b6e4d27c Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 9 Sep 2018 15:27:59 +0200 Subject: [PATCH 04/16] patch 8.1.0355: incorrect adjusting the popup menu for the preview window Problem: Incorrect adjusting the popup menu for the preview window. Solution: Compute position and height properl. (Ronan Pigott) Also show at least ten items. (closes #3414) --- src/popupmnu.c | 21 +++++++++++++++------ src/version.c | 2 ++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/popupmnu.c b/src/popupmnu.c index 5248217255..0f920dc69e 100644 --- a/src/popupmnu.c +++ b/src/popupmnu.c @@ -141,8 +141,8 @@ pum_display( if (p_ph > 0 && pum_height > p_ph) pum_height = p_ph; - /* Put the pum below "pum_win_row" if possible. If there are few lines decide - * on where there is more room. */ + /* Put the pum below "pum_win_row" if possible. If there are few lines + * decide on where there is more room. */ if (pum_win_row + 2 >= below_row - pum_height && pum_win_row - above_row > (below_row - above_row) / 2) { @@ -196,11 +196,20 @@ pum_display( return; #if defined(FEAT_QUICKFIX) - /* If there is a preview window at the above avoid drawing over it. */ - if (pvwin != NULL && pum_row < above_row && pum_height > above_row) + // If there is a preview window at the above avoid drawing over it. + // Do keep at least 10 entries. + if (pvwin != NULL && pum_row < above_row && pum_height > 10) { - pum_row += above_row; - pum_height -= above_row; + if (pum_win_row - above_row < 10) + { + pum_row = pum_win_row - 10; + pum_height = 10; + } + else + { + pum_row = above_row; + pum_height = pum_win_row - above_row; + } } #endif diff --git a/src/version.c b/src/version.c index 480d20e8b1..26825b9f81 100644 --- a/src/version.c +++ b/src/version.c @@ -794,6 +794,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 355, /**/ 354, /**/ From 99f043a57d0be35ef72572b0429cf51525c3cd2b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 9 Sep 2018 15:54:14 +0200 Subject: [PATCH 05/16] patch 8.1.0356: using :s with 'incsearch' prevents CTRL-R CTRL-W Problem: Using :s with 'incsearch' prevents CTRL-R CTRL-W. (Boris Staletic) Solution: When past the pattern put cursor back in the start position. (closes #3413) --- src/ex_getln.c | 21 ++++++++++++--------- src/testdir/test_search.vim | 36 ++++++++++++++++++++++++++++++++++++ src/version.c | 2 ++ 3 files changed, 50 insertions(+), 9 deletions(-) diff --git a/src/ex_getln.c b/src/ex_getln.c index 80f210a5b0..9a8806c14b 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -462,7 +462,7 @@ may_do_incsearch_highlighting( incsearch_state_T *is_state) { int skiplen, patlen; - int i; + int found; // do_search() result pos_T end_pos; struct cmdline_info save_ccline; #ifdef FEAT_RELTIME @@ -508,7 +508,7 @@ may_do_incsearch_highlighting( // If there is no pattern, don't do anything. if (patlen == 0 && !use_last_pat) { - i = 0; + found = 0; set_no_hlsearch(TRUE); // turn off previous highlight redraw_all_later(SOME_VALID); } @@ -528,7 +528,7 @@ may_do_incsearch_highlighting( if (search_first_line != 0) search_flags += SEARCH_START; ccline.cmdbuff[skiplen + patlen] = NUL; - i = do_search(NULL, firstc == ':' ? '/' : firstc, + found = do_search(NULL, firstc == ':' ? '/' : firstc, ccline.cmdbuff + skiplen, count, search_flags, #ifdef FEAT_RELTIME &tm, NULL @@ -543,7 +543,7 @@ may_do_incsearch_highlighting( || curwin->w_cursor.lnum > search_last_line) { // match outside of address range - i = 0; + found = 0; curwin->w_cursor = is_state->search_start; } @@ -552,13 +552,13 @@ may_do_incsearch_highlighting( { (void)vpeekc(); // remove from input stream got_int = FALSE; // don't abandon the command line - i = 0; + found = 0; } else if (char_avail()) // cancelled searching because a char was typed is_state->incsearch_postponed = TRUE; } - if (i != 0) + if (found != 0) highlight_match = TRUE; // highlight position else highlight_match = FALSE; // remove highlight @@ -569,7 +569,7 @@ may_do_incsearch_highlighting( changed_cline_bef_curs(); update_topline(); - if (i != 0) + if (found != 0) { pos_T save_pos = curwin->w_cursor; @@ -604,8 +604,11 @@ may_do_incsearch_highlighting( restore_cmdline(&save_ccline); restore_last_search_pattern(); - // Leave it at the end to make CTRL-R CTRL-W work. - if (i != 0) + // Leave it at the end to make CTRL-R CTRL-W work. But not when beyond the + // end of the pattern, e.g. for ":s/pat/". + if (ccline.cmdbuff[skiplen + patlen] != NUL) + curwin->w_cursor = is_state->search_start; + else if (found != 0) curwin->w_cursor = end_pos; msg_starthere(); diff --git a/src/testdir/test_search.vim b/src/testdir/test_search.vim index f96e54abe2..79f864502c 100644 --- a/src/testdir/test_search.vim +++ b/src/testdir/test_search.vim @@ -1060,6 +1060,42 @@ func Test_keep_last_search_pattern() set noincsearch endfunc +func Test_word_under_cursor_after_match() + if !exists('+incsearch') + return + endif + new + call setline(1, 'foo bar') + set incsearch + call test_override("char_avail", 1) + try + call feedkeys("/foo\\\", 'ntx') + catch /E486:/ + endtry + call assert_equal('foobar', @/) + + bwipe! + call test_override("ALL", 0) + set noincsearch +endfunc + +func Test_subst_word_under_cursor() + if !exists('+incsearch') + return + endif + new + call setline(1, ['int SomeLongName;', 'for (xxx = 1; xxx < len; ++xxx)']) + set incsearch + call test_override("char_avail", 1) + call feedkeys("/LongName\", 'ntx') + call feedkeys(":%s/xxx/\\/g\", 'ntx') + call assert_equal('for (SomeLongName = 1; SomeLongName < len; ++SomeLongName)', getline(2)) + + bwipe! + call test_override("ALL", 0) + set noincsearch +endfunc + func Test_search_undefined_behaviour() if !has("terminal") return diff --git a/src/version.c b/src/version.c index 26825b9f81..b3b4716815 100644 --- a/src/version.c +++ b/src/version.c @@ -794,6 +794,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 356, /**/ 355, /**/ From 02c972153d0f36fd1ae4e7069869f51dc11c6c7d Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 9 Sep 2018 15:56:06 +0200 Subject: [PATCH 06/16] patch 8.1.0357: instructions for tests are outdated Problem: Instructions for tests are outdated. (Jason Franklin) Solution: Update the text. --- src/testdir/README.txt | 39 ++++++++++++++++++++++++++++----------- src/version.c | 2 ++ 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/testdir/README.txt b/src/testdir/README.txt index 7aa185f0a8..c6492598ce 100644 --- a/src/testdir/README.txt +++ b/src/testdir/README.txt @@ -15,23 +15,40 @@ TO ADD A NEW STYLE TEST: 1) Create a test_.vim file. 2) Add test_.res to NEW_TESTS in Make_all.mak in alphabetical order. -3) Also add an entry in src/Makefile. +3) Also add an entry "test_" in src/Make_all.mak. 4) Use make test_.res to run a single test in src/testdir/. Use make test_ to run a single test in src/. +At 2), instead of running the test separately, it can be included in +"test_alot". Do this for quick tests without side effects. The test runs a +bit faster, because Vim doesn't have to be started, one Vim instance runs many +tests. + + What you can use (see test_assert.vim for an example): + - Call assert_equal(), assert_true(), assert_false(), etc. -- Use try/catch to check for exceptions. -- Use alloc_fail() to have memory allocation fail. This makes it possible - to check memory allocation failures are handled gracefully. You need to - change the source code to add an ID to the allocation. Update LAST_ID_USED - above alloc_id() to the highest ID used. -- Use disable_char_avail_for_testing(1) if char_avail() must return FALSE for - a while. E.g. to trigger the CursorMovedI autocommand event. - See test_cursor_func.vim for an example + +- Use assert_fails() to check for expected errors. + +- Use try/catch to avoid an exception aborts the test. + +- Use alloc_fail() to have memory allocation fail. This makes it possible to + check memory allocation failures are handled gracefully. You need to change + +- the source code to add an ID to the allocation. Update LAST_ID_USED above + alloc_id() to the highest ID used. + +- Use test_override() to make Vim behave differently, e.g. if char_avail() + must return FALSE for a while. E.g. to trigger the CursorMovedI autocommand + event. + +- See test_cursor_func.vim for an example. + - If the bug that is being tested isn't fixed yet, you can throw an exception - so that it's clear this still needs work. E.g.: - throw "Skipped: Bug with and popupmenu not fixed yet" + with "Skipped" so that it's clear this still needs work. E.g.: throw + "Skipped: Bug with and popupmenu not fixed yet" + - See the start of runtest.vim for more help. diff --git a/src/version.c b/src/version.c index b3b4716815..a594aa2aea 100644 --- a/src/version.c +++ b/src/version.c @@ -794,6 +794,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 357, /**/ 356, /**/ From a5c48c2698291e59244a705af1b7dbc60e03b09c Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 9 Sep 2018 19:56:07 +0200 Subject: [PATCH 07/16] patch 8.1.0358: crash when using term_dumpwrite() after the job finished Problem: Crash when using term_dumpwrite() after the job finished. Solution: Check for a finished job and give an error message. --- src/terminal.c | 5 +++++ src/version.c | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/terminal.c b/src/terminal.c index 8524560a4d..0c7630c620 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -3871,6 +3871,11 @@ f_term_dumpwrite(typval_T *argvars, typval_T *rettv UNUSED) if (buf == NULL) return; term = buf->b_term; + if (term->tl_vterm == NULL) + { + EMSG(_("E958: Job already finished")); + return; + } if (argvars[2].v_type != VAR_UNKNOWN) { diff --git a/src/version.c b/src/version.c index a594aa2aea..67bfbd1644 100644 --- a/src/version.c +++ b/src/version.c @@ -794,6 +794,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 358, /**/ 357, /**/ From 6f8bdab8e2ffec07aea03447f87c80b50e01f430 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 9 Sep 2018 22:02:24 +0200 Subject: [PATCH 08/16] patch 8.1.0359: no clue what test failed when using a screendump twice Problem: No clue what test failed when using a screendump twice. Solution: Add an extra argument to VerifyScreenDump(). --- src/testdir/screendump.vim | 14 +++++++++++--- src/version.c | 2 ++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/testdir/screendump.vim b/src/testdir/screendump.vim index e601ae6cd3..1b74c1b33e 100644 --- a/src/testdir/screendump.vim +++ b/src/testdir/screendump.vim @@ -93,8 +93,11 @@ endfunc " Verify that Vim running in terminal buffer "buf" matches the screen dump. " "options" is passed to term_dumpwrite(). " The file name used is "dumps/{filename}.dump". +" Optionally an extra argument can be passed which is prepended to the error +" message. Use this when using the same dump file with different options. " Will wait for up to a second for the screen dump to match. -func VerifyScreenDump(buf, filename, options) +" Returns non-zero when verification fails. +func VerifyScreenDump(buf, filename, options, ...) let reference = 'dumps/' . a:filename . '.dump' let testfile = a:filename . '.dump.failed' @@ -108,10 +111,15 @@ func VerifyScreenDump(buf, filename, options) endif if i == 100 " Leave the test file around for inspection. - call assert_report('See dump file difference: call term_dumpdiff("' . testfile . '", "' . reference . '")') - break + let msg = 'See dump file difference: call term_dumpdiff("' . testfile . '", "' . reference . '")' + if a:0 == 1 + let msg = a:1 . ': ' . msg + endif + call assert_report(msg) + return 1 endif sleep 10m let i += 1 endwhile + return 0 endfunc diff --git a/src/version.c b/src/version.c index 67bfbd1644..73bcab1094 100644 --- a/src/version.c +++ b/src/version.c @@ -794,6 +794,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 359, /**/ 358, /**/ From 93a1df2c205c8399d96c172d9483e0793d32892a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 10 Sep 2018 11:51:50 +0200 Subject: [PATCH 09/16] Update runtime files. --- runtime/doc/eval.txt | 7 +- runtime/doc/options.txt | 2 +- runtime/doc/syntax.txt | 6 ++ runtime/doc/tags | 3 + runtime/doc/terminal.txt | 13 +++- runtime/doc/todo.txt | 33 +++++---- runtime/ftplugin/vim.vim | 11 ++- runtime/syntax/sh.vim | 29 ++++---- runtime/syntax/tex.vim | 132 +--------------------------------- runtime/tutor/tutor.ru | 12 ++-- runtime/tutor/tutor.ru.cp1251 | 12 ++-- 11 files changed, 85 insertions(+), 175 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index d51b92ce5f..21cb4abade 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -5978,11 +5978,14 @@ match({expr}, {pat} [, {start} [, {count}]]) *match()* When {expr} is a |List| then this returns the index of the first item where {pat} matches. Each item is used as a String, |Lists| and |Dictionaries| are used as echoed. + Otherwise, {expr} is used as a String. The result is a Number, which gives the index (byte offset) in {expr} where {pat} matches. + A match at the first character or |List| item returns zero. If there is no match -1 is returned. + For getting submatches see |matchlist()|. Example: > :echo match("testing", "ing") " results in 4 @@ -8386,7 +8389,9 @@ term_dumpwrite({buf}, {filename} [, {options}]) Dump the contents of the terminal screen of {buf} in the file {filename}. This uses a format that can be used with |term_dumpload()| and |term_dumpdiff()|. - If {filename} already exists an error is given. *E953* + If the job in the terminal already finished an error is given: + *E958* + If {filename} already exists an error is given: *E953* Also see |terminal-diff|. {options} is a dictionary with these optional entries: diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index b5e9626bb8..fca2e4662e 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -846,7 +846,7 @@ A jump table for the options with a short description can be found at |Q_op|. '{A-Z0-9}, or `{A-Z0-9} command takes one to another file. Note that for some commands the 'autowrite' option is not used, see 'autowriteall' for that. - Some buffers will not be written, specifically when 'buttype' is + Some buffers will not be written, specifically when 'buftype' is "nowrite", "nofile", "terminal" or "prompt". *'autowriteall'* *'awa'* *'noautowriteall'* *'noawa'* diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index 8d9029a4a3..3d987ff73c 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -3211,6 +3211,12 @@ by syntax/tex.vim. Please consider uploading any extensions that you write, which typically would go in $HOME/after/syntax/tex/[pkgname].vim, to http://vim.sf.net/. +I've included some support for various popular packages on my website: > + + http://www.drchip.org/astronaut/vim/index.html#LATEXPKGS +< +The syntax files there go into your .../after/syntax/tex/ directory. + *tex-error* *g:tex_no_error* Tex: Excessive Error Highlighting? ~ diff --git a/runtime/doc/tags b/runtime/doc/tags index 9f6f3bde3e..2b38270231 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -4626,6 +4626,7 @@ E954 options.txt /*E954* E955 eval.txt /*E955* E956 pattern.txt /*E956* E957 eval.txt /*E957* +E958 eval.txt /*E958* E96 diff.txt /*E96* E97 diff.txt /*E97* E98 diff.txt /*E98* @@ -5463,6 +5464,7 @@ channel-drop channel.txt /*channel-drop* channel-functions usr_41.txt /*channel-functions* channel-mode channel.txt /*channel-mode* channel-more channel.txt /*channel-more* +channel-noblock channel.txt /*channel-noblock* channel-open channel.txt /*channel-open* channel-open-options channel.txt /*channel-open-options* channel-raw channel.txt /*channel-raw* @@ -7183,6 +7185,7 @@ job-err_io channel.txt /*job-err_io* job-exit_cb channel.txt /*job-exit_cb* job-functions usr_41.txt /*job-functions* job-in_io channel.txt /*job-in_io* +job-noblock channel.txt /*job-noblock* job-options channel.txt /*job-options* job-out_cb channel.txt /*job-out_cb* job-out_io channel.txt /*job-out_io* diff --git a/runtime/doc/terminal.txt b/runtime/doc/terminal.txt index b954715b8a..abc3d94fb4 100644 --- a/runtime/doc/terminal.txt +++ b/runtime/doc/terminal.txt @@ -617,7 +617,18 @@ This will open a window consisting of three parts: 3. The contents of the second dump You can usually see what differs in the second part. Use the 'ruler' to -relate it to the position in the first or second dump. +relate it to the position in the first or second dump. Letters indicate the +kind of difference: + X different character + > cursor in first but not in second + < cursor in second but not in first + w character width differs (single vs double width) + f foreground color differs + b background color differs + a attribute differs (bold, underline, reverse, etc.) + ? character missing in both + + character missing in first + - character missing in second Alternatively, press "s" to swap the first and second dump. Do this several times so that you can spot the difference in the context of the text. diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index 38773e02a2..964b154e5f 100644 --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -38,8 +38,10 @@ browser use: https://github.com/vim/vim/issues/1234 *known-bugs* -------------------- Known bugs and current work ----------------------- +tar plugin: use "file" to check compression type, use bzip2 only when it +recognizes bzip2 or file ends in .bz2 + 'incsearch' with :s: (#3321) -- :/foo/s// changes last search pattern. Also E486. - :s/foo using CTRL-G moves to another line, should not happen, or use the correct line (it uses the last but one line) (Lifepillar, Aug 18, #3345) - Also support range: :/foo/,/bar/delete @@ -103,6 +105,9 @@ Does not build with MinGW out of the box: Crash when mixing matchadd and substitute()? (Max Christian Pohle, 2018 May 13, #2910) Can't reproduce? +Patch to add script line number to script ID. (ichizok, Ozaki Kiichi, 2018 Aug +24, #3362) + Errors found with random data: heap-buffer-overflow in alist_add (#2472) @@ -125,8 +130,8 @@ Related to bracketed paste. I cannot reproduce it. Patch in pull request #2967: Allow white space in sign text. (Ben Jackson) Test fails in AppVeyor. -Patch to add script line number to script ID. (ichizok, Ozaki Kiichi, 2018 Aug -24, #3362) +Job_info() returns command without backslashes. (Daniel Hahler, 2018 Sep 3, +#3404) Removing flags from 'cpoptions' breaks the Winbar buttons in termdebug. (Dominique Pelle, 2018 Jul 16) @@ -134,6 +139,10 @@ Removing flags from 'cpoptions' breaks the Winbar buttons in termdebug. Problem with two buffers with the same name a/b, if it didn't exist before and is created outside of Vim. (dskloetg, 2018 Jul 16, #3219) +Invalid memory access with old regexp engine. (Dominique Pelle, 2018 Sep 3, +#3405) Introduced by 8.0.1517, which was fixing another memory access error. +(Sep 8) + Memory leak in test_assert: ==19127== by 0x2640D7: alloc (misc2.c:874) ==19127== by 0x2646D6: vim_strsave (misc2.c:1315) @@ -188,8 +197,12 @@ Olaf Dabrunz is working on this. (10 Jan 2016) 9 Instead invoking an external diff program, use builtin code. One can be found here: http://www.ioplex.com/~miallen/libmba/dl/src/diff.c It's complicated and badly documented. -Alternative: use the xdiff library. Unfinished Patch from Christian Brabandt, -2018 Mar 20, #2732) +Alternative: use the xdiff library from git. Unfinished Patch from Christian +Brabandt, 2018 Mar 20, #2732) +Note that this is NOT libxdiff. +-> avoid writing all the text to a file, use in-memory only +-> add option to use external diff above a certain size. +-> when making changes, diff only the part of the buffer that changed. Difference between two regexp engines: #3373 @@ -202,6 +215,9 @@ includes the first screen line. (2018 Aug 23, #3368) Refactored HTML indent file. (Michael Lee, #1821) +Test for user name completeion ":e ~s" fails because we don't get all +user names. Is there another function to get more? (2018 Sep 3, Stuckrad) + Patch to add getregpoint() and setreg() with an option to set "". (Andy Massimino, 2018 Aug 24, #3370) Better name? @@ -348,13 +364,6 @@ Add the debug command line history to viminfo. Avoid that "sign unplace id" does a redraw right away, esp. when there is a sequence of these commands. (Andy Stewart, 2018 Mar 16) -ch_sendraw() with long string does not try to read in between, which may cause -a deadlock if the reading side is waiting for the write to finish. (Nate -Bosch, 2018 Jan 13, #2548) -Perhaps just make chunks of 1024 bytes? -Probably better: Make the write non-blocking -Also a problem on MS-Windows: #2828. - Add Makefiles to the runtime/spell directory tree, since nobody uses Aap. Will have to explain the manual steps (downloading the .aff and .dic files, applying the diff, etc. diff --git a/runtime/ftplugin/vim.vim b/runtime/ftplugin/vim.vim index a0f0f3a1b1..c1cd8bb62c 100644 --- a/runtime/ftplugin/vim.vim +++ b/runtime/ftplugin/vim.vim @@ -67,10 +67,10 @@ if !exists("no_plugin_maps") && !exists("no_vim_maps") vnoremap [[ m':exe "normal! gv"call search('^\s*fu\%[nction]\>', "bW") nnoremap ]] m':call search('^\s*fu\%[nction]\>', "W") vnoremap ]] m':exe "normal! gv"call search('^\s*fu\%[nction]\>', "W") - nnoremap [] m':call search('^\s*endf*\%[unction]\>', "bW") - vnoremap [] m':exe "normal! gv"call search('^\s*endf*\%[unction]\>', "bW") - nnoremap ][ m':call search('^\s*endf*\%[unction]\>', "W") - vnoremap ][ m':exe "normal! gv"call search('^\s*endf*\%[unction]\>', "W") + nnoremap [] m':call search('^\s*endf\%[unction]\>', "bW") + vnoremap [] m':exe "normal! gv"call search('^\s*endf\%[unction]\>', "bW") + nnoremap ][ m':call search('^\s*endf\%[unction]\>', "W") + vnoremap ][ m':exe "normal! gv"call search('^\s*endf\%[unction]\>', "W") " Move around comments nnoremap ]" :call search('^\(\s*".*\n\)\@ @@ -87,8 +87,7 @@ if exists("loaded_matchit") \ '\<\(wh\%[ile]\|for\)\>:\:\:\,' . \ '\:\:\,' . \ '\:\:\:\,' . - \ '\\)\@!\S:\,' . - \ '(:)' + \ '\\)\@!\S:\,' " Ignore syntax region commands and settings, any 'en*' would clobber " if-endif. " - set spl=de,en diff --git a/runtime/syntax/sh.vim b/runtime/syntax/sh.vim index 167300c524..5e0d1fd76a 100644 --- a/runtime/syntax/sh.vim +++ b/runtime/syntax/sh.vim @@ -2,8 +2,8 @@ " Language: shell (sh) Korn shell (ksh) bash (sh) " Maintainer: Charles E. Campbell " Previous Maintainer: Lennart Schultz -" Last Change: Jul 31, 2018 -" Version: 179 +" Last Change: Sep 04, 2018 +" Version: 182 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SH " For options and settings, please use: :help ft-sh-syntax " This file includes many ideas from Eric Brunet (eric.brunet@ens.fr) @@ -151,6 +151,7 @@ syn cluster shPPSRightList contains=shComment,shDeref,shDerefSimple,shEscape,shP syn cluster shSubShList contains=@shCommandSubList,shCommandSubBQ,shCaseEsac,shColon,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shIf,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq,shOperator syn cluster shTestList contains=shCharClass,shCommandSub,shCommandSubBQ,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shSpecialDQ,shExDoubleQuote,shExpr,shExSingleQuote,shNumber,shOperator,shSingleQuote,shTest,shTestOpr syn cluster shNoZSList contains=shSpecialNoZS +syn cluster shForList contains=shTestOpr,shNumber,shDerefSimple,shDeref,shCommandSub,shCommandSubBQ,shArithmetic " Echo: {{{1 " ==== @@ -243,7 +244,7 @@ syn match shCharClass contained "\[:\(backspace\|escape\|return\|xdigit\|alnum ShFoldIfDoFor syn region shDo transparent matchgroup=shConditional start="\" matchgroup=shConditional end="\" contains=@shLoopList ShFoldIfDoFor syn region shIf transparent matchgroup=shConditional start="\+ end="\<;\_s*then\>" end="\" contains=@shIfList ShFoldIfDoFor syn region shFor matchgroup=shLoop start="\ -" Last Change: Mar 30, 2018 -" Version: 109 +" Last Change: Sep 09, 2018 +" Version: 110 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_TEX " " Notes: {{{1 @@ -596,7 +596,6 @@ if s:tex_fast =~# 'v' if exists("g:tex_verbspell") && g:tex_verbspell syn region texZone start="\\begin{[vV]erbatim}" end="\\end{[vV]erbatim}\|%stopzone\>" contains=@Spell " listings package: - syn region texZone start="\\begin{lstlisting}" end="\\end{lstlisting}\|%stopzone\>" contains=@Spell if b:tex_stylish syn region texZone start="\\verb\*\=\z([^\ta-zA-Z@]\)" end="\z1\|%stopzone\>" contains=@Spell else @@ -683,13 +682,7 @@ if has("conceal") && &enc == 'utf-8' \ ['approx' , '≈'], \ ['ast' , '∗'], \ ['asymp' , '≍'], - \ ['backepsilon' , '∍'], - \ ['backsimeq' , '≃'], \ ['backslash' , '∖'], - \ ['barwedge' , '⊼'], - \ ['because' , '∵'], - \ ['beth' , 'ܒ'], - \ ['between' , '≬'], \ ['bigcap' , '∩'], \ ['bigcirc' , '○'], \ ['bigcup' , '∪'], @@ -701,38 +694,18 @@ if has("conceal") && &enc == 'utf-8' \ ['bigtriangleup' , '∆'], \ ['bigvee' , '⋁'], \ ['bigwedge' , '⋀'], - \ ['blacksquare' , '∎'], \ ['bot' , '⊥'], \ ['bowtie' , '⋈'], - \ ['boxdot' , '⊡'], - \ ['boxminus' , '⊟'], - \ ['boxplus' , '⊞'], - \ ['boxtimes' , '⊠'], - \ ['Box' , '☐'], \ ['bullet' , '•'], - \ ['bumpeq' , '≏'], - \ ['Bumpeq' , '≎'], \ ['cap' , '∩'], - \ ['Cap' , '⋒'], \ ['cdot' , '·'], \ ['cdots' , '⋯'], \ ['circ' , '∘'], - \ ['circeq' , '≗'], - \ ['circlearrowleft', '↺'], - \ ['circlearrowright', '↻'], - \ ['circledast' , '⊛'], - \ ['circledcirc' , '⊚'], \ ['clubsuit' , '♣'], - \ ['complement' , '∁'], \ ['cong' , '≅'], \ ['coprod' , '∐'], \ ['copyright' , '©'], \ ['cup' , '∪'], - \ ['Cup' , '⋓'], - \ ['curlyeqprec' , '⋞'], - \ ['curlyeqsucc' , '⋟'], - \ ['curlyvee' , '⋎'], - \ ['curlywedge' , '⋏'], \ ['dagger' , '†'], \ ['dashv' , '⊣'], \ ['ddagger' , '‡'], @@ -741,50 +714,27 @@ if has("conceal") && &enc == 'utf-8' \ ['diamondsuit' , '♢'], \ ['div' , '÷'], \ ['doteq' , '≐'], - \ ['doteqdot' , '≑'], - \ ['dotplus' , '∔'], \ ['dots' , '…'], - \ ['dotsb' , '⋯'], - \ ['dotsc' , '…'], - \ ['dotsi' , '⋯'], - \ ['dotso' , '…'], - \ ['doublebarwedge' , '⩞'], \ ['downarrow' , '↓'], \ ['Downarrow' , '⇓'], \ ['ell' , 'ℓ'], \ ['emptyset' , '∅'], - \ ['eqcirc' , '≖'], - \ ['eqsim' , '≂'], - \ ['eqslantgtr' , '⪖'], - \ ['eqslantless' , '⪕'], \ ['equiv' , '≡'], - \ ['eth' , 'ð'], \ ['exists' , '∃'], - \ ['fallingdotseq' , '≒'], \ ['flat' , '♭'], \ ['forall' , '∀'], \ ['frown' , '⁔'], \ ['ge' , '≥'], \ ['geq' , '≥'], - \ ['geqq' , '≧'], \ ['gets' , '←'], - \ ['gimel' , 'ℷ'], \ ['gg' , '⟫'], - \ ['gneqq' , '≩'], - \ ['gtrdot' , '⋗'], - \ ['gtreqless' , '⋛'], - \ ['gtrless' , '≷'], - \ ['gtrsim' , '≳'], \ ['hbar' , 'ℏ'], \ ['heartsuit' , '♡'], \ ['hookleftarrow' , '↩'], \ ['hookrightarrow' , '↪'], \ ['iff' , '⇔'], - \ ['iiint' , '∭'], - \ ['iint' , '∬'], \ ['Im' , 'ℑ'], \ ['imath' , 'ɩ'], - \ ['implies' , '⇒'], \ ['in' , '∈'], \ ['infty' , '∞'], \ ['int' , '∫'], @@ -793,69 +743,33 @@ if has("conceal") && &enc == 'utf-8' \ ['lceil' , '⌈'], \ ['ldots' , '…'], \ ['le' , '≤'], - \ ['leadsto' , '↝'], \ ['left(' , '('], \ ['left\[' , '['], \ ['left\\{' , '{'], \ ['leftarrow' , '←'], \ ['Leftarrow' , '⇐'], - \ ['leftarrowtail' , '↢'], \ ['leftharpoondown', '↽'], \ ['leftharpoonup' , '↼'], \ ['leftrightarrow' , '↔'], \ ['Leftrightarrow' , '⇔'], - \ ['leftrightsquigarrow', '↭'], - \ ['leftthreetimes' , '⋋'], \ ['leq' , '≤'], \ ['leq' , '≤'], - \ ['leqq' , '≦'], - \ ['lessdot' , '⋖'], - \ ['lesseqgtr' , '⋚'], - \ ['lesssim' , '≲'], \ ['lfloor' , '⌊'], \ ['ll' , '≪'], \ ['lmoustache' , '╭'], - \ ['lneqq' , '≨'], \ ['lor' , '∨'], - \ ['ltimes' , '⋉'], \ ['mapsto' , '↦'], - \ ['measuredangle' , '∡'], \ ['mid' , '∣'], \ ['models' , '╞'], \ ['mp' , '∓'], \ ['nabla' , '∇'], \ ['natural' , '♮'], - \ ['ncong' , '≇'], \ ['ne' , '≠'], \ ['nearrow' , '↗'], \ ['neg' , '¬'], \ ['neq' , '≠'], - \ ['nexists' , '∄'], - \ ['ngeq' , '≱'], - \ ['ngeqq' , '≱'], - \ ['ngtr' , '≯'], \ ['ni' , '∋'], - \ ['nleftarrow' , '↚'], - \ ['nLeftarrow' , '⇍'], - \ ['nLeftrightarrow', '⇎'], - \ ['nleq' , '≰'], - \ ['nleqq' , '≰'], - \ ['nless' , '≮'], - \ ['nmid' , '∤'], \ ['notin' , '∉'], - \ ['nparallel' , '∦'], - \ ['nprec' , '⊀'], - \ ['nrightarrow' , '↛'], - \ ['nRightarrow' , '⇏'], - \ ['nsim' , '≁'], - \ ['nsucc' , '⊁'], - \ ['ntriangleleft' , '⋪'], - \ ['ntrianglelefteq', '⋬'], - \ ['ntriangleright' , '⋫'], - \ ['ntrianglerighteq', '⋭'], - \ ['nvdash' , '⊬'], - \ ['nvDash' , '⊭'], - \ ['nVdash' , '⊮'], \ ['nwarrow' , '↖'], \ ['odot' , '⊙'], \ ['oint' , '∮'], @@ -868,15 +782,9 @@ if has("conceal") && &enc == 'utf-8' \ ['parallel' , '║'], \ ['partial' , '∂'], \ ['perp' , '⊥'], - \ ['pitchfork' , '⋔'], \ ['pm' , '±'], \ ['prec' , '≺'], - \ ['precapprox' , '⪷'], - \ ['preccurlyeq' , '≼'], \ ['preceq' , '⪯'], - \ ['precnapprox' , '⪹'], - \ ['precneqq' , '⪵'], - \ ['precsim' , '≾'], \ ['prime' , '′'], \ ['prod' , '∏'], \ ['propto' , '∝'], @@ -888,13 +796,8 @@ if has("conceal") && &enc == 'utf-8' \ ['right\\}' , '}'], \ ['rightarrow' , '→'], \ ['Rightarrow' , '⇒'], - \ ['rightarrowtail' , '↣'], \ ['rightleftharpoons', '⇌'], - \ ['rightsquigarrow', '↝'], - \ ['rightthreetimes', '⋌'], - \ ['risingdotseq' , '≓'], \ ['rmoustache' , '╮'], - \ ['rtimes' , '⋊'], \ ['S' , '§'], \ ['searrow' , '↘'], \ ['setminus' , '∖'], @@ -903,7 +806,6 @@ if has("conceal") && &enc == 'utf-8' \ ['simeq' , '⋍'], \ ['smile' , '‿'], \ ['spadesuit' , '♠'], - \ ['sphericalangle' , '∢'], \ ['sqcap' , '⊓'], \ ['sqcup' , '⊔'], \ ['sqsubset' , '⊏'], @@ -912,60 +814,30 @@ if has("conceal") && &enc == 'utf-8' \ ['sqsupseteq' , '⊒'], \ ['star' , '✫'], \ ['subset' , '⊂'], - \ ['Subset' , '⋐'], \ ['subseteq' , '⊆'], - \ ['subseteqq' , '⫅'], - \ ['subsetneq' , '⊊'], - \ ['subsetneqq' , '⫋'], \ ['succ' , '≻'], - \ ['succapprox' , '⪸'], - \ ['succcurlyeq' , '≽'], \ ['succeq' , '⪰'], - \ ['succnapprox' , '⪺'], - \ ['succneqq' , '⪶'], - \ ['succsim' , '≿'], \ ['sum' , '∑'], \ ['supset' , '⊃'], - \ ['Supset' , '⋑'], \ ['supseteq' , '⊇'], - \ ['supseteqq' , '⫆'], - \ ['supsetneq' , '⊋'], - \ ['supsetneqq' , '⫌'], \ ['surd' , '√'], \ ['swarrow' , '↙'], - \ ['therefore' , '∴'], \ ['times' , '×'], \ ['to' , '→'], \ ['top' , '⊤'], \ ['triangle' , '∆'], \ ['triangleleft' , '⊲'], - \ ['trianglelefteq' , '⊴'], - \ ['triangleq' , '≜'], \ ['triangleright' , '⊳'], - \ ['trianglerighteq', '⊵'], - \ ['twoheadleftarrow', '↞'], - \ ['twoheadrightarrow', '↠'], - \ ['ulcorner' , '⌜'], \ ['uparrow' , '↑'], \ ['Uparrow' , '⇑'], \ ['updownarrow' , '↕'], \ ['Updownarrow' , '⇕'], - \ ['urcorner' , '⌝'], - \ ['varnothing' , '∅'], - \ ['vartriangle' , '∆'], \ ['vdash' , '⊢'], - \ ['vDash' , '⊨'], - \ ['Vdash' , '⊩'], \ ['vdots' , '⋮'], \ ['vee' , '∨'], - \ ['veebar' , '⊻'], - \ ['Vvdash' , '⊪'], \ ['wedge' , '∧'], \ ['wp' , '℘'], \ ['wr' , '≀']] -" \ ['jmath' , 'X'] -" \ ['uminus' , 'X'] -" \ ['uplus' , 'X'] if &ambw == "double" || exists("g:tex_usedblwidth") let s:texMathList= s:texMathList + [ \ ['right\\rangle' , '〉'], diff --git a/runtime/tutor/tutor.ru b/runtime/tutor/tutor.ru index be6c1bd2f3..f4bc62e863 100644 --- a/runtime/tutor/tutor.ru +++ b/runtime/tutor/tutor.ru @@ -540,7 +540,7 @@ ---> "" `'; . -! , +! , . ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -607,15 +607,15 @@ . 4. `' `' , - :s/old/new + :s// `' `' , - :s/old/new/g + :s///g , - :#,#s/old/new/g + :#,#s///g `' `' , - :%s/old/new/g + :%s///g , 'c' - :%s/old/new/gc + :%s///gc ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5.1: diff --git a/runtime/tutor/tutor.ru.cp1251 b/runtime/tutor/tutor.ru.cp1251 index 1cff3eae7d..39a0019b85 100644 --- a/runtime/tutor/tutor.ru.cp1251 +++ b/runtime/tutor/tutor.ru.cp1251 @@ -540,7 +540,7 @@ ---> "" `'; . -! , +! , . ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -607,15 +607,15 @@ . 4. `' `' , - :s/old/new + :s// `' `' , - :s/old/new/g + :s///g , - :#,#s/old/new/g + :#,#s///g `' `' , - :%s/old/new/g + :%s///g , 'c' - :%s/old/new/gc + :%s///gc ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5.1: From e828b7621cf9065a3582be0c4dd1e0e846e335bf Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 10 Sep 2018 17:51:58 +0200 Subject: [PATCH 10/16] patch 8.1.0360: using an external diff program is slow and inflexible Problem: Using an external diff program is slow and inflexible. Solution: Include the xdiff library. (Christian Brabandt, closes #2732) Use it by default. --- Filelist | 14 + runtime/doc/diff.txt | 9 +- runtime/doc/options.txt | 30 +- src/Make_cyg_ming.mak | 53 ++ src/Make_mvc.mak | 41 +- src/Makefile | 53 +- src/diff.c | 831 ++++++++++++++++----- src/structs.h | 4 +- src/testdir/dumps/Test_diff_01.dump | 20 + src/testdir/dumps/Test_diff_02.dump | 20 + src/testdir/dumps/Test_diff_03.dump | 20 + src/testdir/dumps/Test_diff_04.dump | 20 + src/testdir/dumps/Test_diff_05.dump | 20 + src/testdir/dumps/Test_diff_06.dump | 20 + src/testdir/dumps/Test_diff_07.dump | 20 + src/testdir/dumps/Test_diff_08.dump | 20 + src/testdir/dumps/Test_diff_09.dump | 20 + src/testdir/dumps/Test_diff_10.dump | 20 + src/testdir/dumps/Test_diff_11.dump | 20 + src/testdir/dumps/Test_diff_12.dump | 20 + src/testdir/dumps/Test_diff_13.dump | 20 + src/testdir/dumps/Test_diff_14.dump | 20 + src/testdir/dumps/Test_diff_15.dump | 20 + src/testdir/dumps/Test_diff_16.dump | 20 + src/testdir/test_diffmode.vim | 184 ++++- src/version.c | 2 + src/xdiff/COPYING | 504 +++++++++++++ src/xdiff/README.txt | 14 + src/xdiff/xdiff.h | 142 ++++ src/xdiff/xdiffi.c | 1043 +++++++++++++++++++++++++++ src/xdiff/xdiffi.h | 64 ++ src/xdiff/xemit.c | 312 ++++++++ src/xdiff/xemit.h | 36 + src/xdiff/xhistogram.c | 386 ++++++++++ src/xdiff/xinclude.h | 61 ++ src/xdiff/xmacros.h | 54 ++ src/xdiff/xpatience.c | 390 ++++++++++ src/xdiff/xprepare.c | 483 +++++++++++++ src/xdiff/xprepare.h | 34 + src/xdiff/xtypes.h | 67 ++ src/xdiff/xutils.c | 425 +++++++++++ src/xdiff/xutils.h | 47 ++ 42 files changed, 5385 insertions(+), 218 deletions(-) create mode 100644 src/testdir/dumps/Test_diff_01.dump create mode 100644 src/testdir/dumps/Test_diff_02.dump create mode 100644 src/testdir/dumps/Test_diff_03.dump create mode 100644 src/testdir/dumps/Test_diff_04.dump create mode 100644 src/testdir/dumps/Test_diff_05.dump create mode 100644 src/testdir/dumps/Test_diff_06.dump create mode 100644 src/testdir/dumps/Test_diff_07.dump create mode 100644 src/testdir/dumps/Test_diff_08.dump create mode 100644 src/testdir/dumps/Test_diff_09.dump create mode 100644 src/testdir/dumps/Test_diff_10.dump create mode 100644 src/testdir/dumps/Test_diff_11.dump create mode 100644 src/testdir/dumps/Test_diff_12.dump create mode 100644 src/testdir/dumps/Test_diff_13.dump create mode 100644 src/testdir/dumps/Test_diff_14.dump create mode 100644 src/testdir/dumps/Test_diff_15.dump create mode 100644 src/testdir/dumps/Test_diff_16.dump create mode 100644 src/xdiff/COPYING create mode 100644 src/xdiff/README.txt create mode 100644 src/xdiff/xdiff.h create mode 100644 src/xdiff/xdiffi.c create mode 100644 src/xdiff/xdiffi.h create mode 100644 src/xdiff/xemit.c create mode 100644 src/xdiff/xemit.h create mode 100644 src/xdiff/xhistogram.c create mode 100644 src/xdiff/xinclude.h create mode 100644 src/xdiff/xmacros.h create mode 100644 src/xdiff/xpatience.c create mode 100644 src/xdiff/xprepare.c create mode 100644 src/xdiff/xprepare.h create mode 100644 src/xdiff/xtypes.h create mode 100644 src/xdiff/xutils.c create mode 100644 src/xdiff/xutils.h diff --git a/Filelist b/Filelist index f488839740..343a2bd5c4 100644 --- a/Filelist +++ b/Filelist @@ -273,6 +273,20 @@ SRC_ALL = \ 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 diff --git a/runtime/doc/diff.txt b/runtime/doc/diff.txt index d56aea72ad..6670f45c64 100644 --- a/runtime/doc/diff.txt +++ b/runtime/doc/diff.txt @@ -39,7 +39,9 @@ The second and following arguments may also be a directory name. Vim will 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'. +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,8 +346,9 @@ between file1 and file2: > 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: > +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 diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index fca2e4662e..16aa422151 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -2609,8 +2609,8 @@ A jump table for the options with a short description can be found at |Q_op|. {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|. + 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. @@ -2657,11 +2657,31 @@ A jump table for the options with a short description can be found at |Q_op|. foldcolumn:{n} Set the 'foldcolumn' option to {n} when starting diff mode. Without this 2 is used. - Examples: > + 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. - :set diffopt=filler,context:4 + 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=filler,foldcolumn:3 + :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) diff --git a/src/Make_cyg_ming.mak b/src/Make_cyg_ming.mak index 16cd71259c..2308135b52 100644 --- a/src/Make_cyg_ming.mak +++ b/src/Make_cyg_ming.mak @@ -166,6 +166,25 @@ else 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,6 +829,23 @@ OBJ += $(OUTDIR)/terminal.o \ $(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,6 +1091,23 @@ $(OUTDIR)/term_unicode.o: libvterm/src/unicode.c $(TERM_DEPS) $(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)) diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak index f32903392e..1131f2b05f 100644 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -813,6 +813,24 @@ CUI_OBJ = $(OUTDIR)\iscygpty.obj !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,12 +1222,12 @@ all: $(VIM).exe \ tee/tee.exe \ GvimExt/gvimext.dll -$(VIM).exe: $(OUTDIR) $(OBJ) $(GUI_OBJ) $(CUI_OBJ) $(OLE_OBJ) $(OLE_IDL) $(MZSCHEME_OBJ) \ +$(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) $(GUI_OBJ) $(CUI_OBJ) $(OLE_OBJ) \ + $(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,6 +1322,7 @@ $(NEW_TESTS): $(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,6 +1363,24 @@ $(OUTDIR)/dict.obj: $(OUTDIR) dict.c $(INCL) $(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) diff --git a/src/Makefile b/src/Makefile index f2fafa4dca..d0cf956270 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1400,6 +1400,32 @@ TERM_DEPS = \ 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,6 +1637,7 @@ BASIC_SRC = \ SRC = $(BASIC_SRC) \ $(GUI_SRC) \ $(TERM_SRC) \ + $(XDIFF_SRC) \ $(HANGULIN_SRC) \ $(LUA_SRC) \ $(MZSCHEME_SRC) \ @@ -1728,6 +1755,7 @@ OBJ_COMMON = \ $(WORKSHOP_OBJ) \ $(NETBEANS_OBJ) \ $(CHANNEL_OBJ) \ + $(XDIFF_OBJS) \ $(WSDEBUG_OBJ) # The files included by tests are not in OBJ_COMMON. @@ -2731,7 +2759,7 @@ SHADOWDIR = shadow 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 . + 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,7 +2943,7 @@ objects/crypt_zip.o: crypt_zip.c objects/dict.o: dict.c $(CCC) -o $@ dict.c -objects/diff.o: diff.c +objects/diff.o: diff.c $(XDIFF_INCL) $(CCC) -o $@ diff.c objects/digraph.o: digraph.c @@ -3229,6 +3257,27 @@ objects/term_unicode.o: libvterm/src/unicode.c $(TERM_DEPS) 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 ### diff --git a/src/diff.c b/src/diff.c index c67654f621..4c0792baae 100644 --- a/src/diff.c +++ b/src/diff.c @@ -9,23 +9,32 @@ /* * 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_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,22 +45,45 @@ static int diff_bin_works = MAYBE; /* TRUE when "diff --binary" works, FALSE 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 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 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, char_u *fname); +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,26 +663,224 @@ diff_redraw( } } + 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 file "name". - * Always use 'fileformat' set to "unix". - * Return FAIL for failure + * Write buffer "buf" to a memory buffer. + * Return FAIL for failure. */ static int -diff_write(buf_T *buf, char_u *fname) +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, fname, NULL, (linenr_T)1, buf->b_ml.ml_line_count, - NULL, FALSE, FALSE, FALSE, TRUE); + 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. @@ -658,54 +888,65 @@ diff_write(buf_T *buf, char_u *fname) * could have been produced by autocommands, e.g. the netrw plugin). */ void -ex_diffupdate( - exarg_T *eap) /* can be NULL */ +ex_diffupdate(exarg_T *eap) // "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; + diffio_T diffio; - /* Delete all diffblocks. */ + // Delete all diffblocks. diff_clear(curtab); curtab->tp_diff_invalid = FALSE; - /* Use the first buffer as the original text. */ + // 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. */ + // 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; + // 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(); - /* - * 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. - */ + 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 *)tmp_orig, "w"); + fd = mch_fopen((char *)diffio->dio_orig.din_fname, "w"); if (fd == NULL) io_error = TRUE; else @@ -713,7 +954,7 @@ ex_diffupdate( if (fwrite("line1\n", (size_t)6, (size_t)1, fd) != 1) io_error = TRUE; fclose(fd); - fd = mch_fopen((char *)tmp_new, "w"); + fd = mch_fopen((char *)diffio->dio_new.din_fname, "w"); if (fd == NULL) io_error = TRUE; else @@ -721,8 +962,9 @@ ex_diffupdate( 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"); + 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,10 +981,10 @@ ex_diffupdate( } fclose(fd); } - mch_remove(tmp_diff); - mch_remove(tmp_new); + mch_remove(diffio->dio_diff.dout_fname); + mch_remove(diffio->dio_new.din_fname); } - mch_remove(tmp_orig); + mch_remove(diffio->dio_orig.din_fname); } #ifdef FEAT_EVAL @@ -785,98 +1027,101 @@ ex_diffupdate( #if defined(MSWIN) diff_bin_works = MAYBE; #endif - goto theend; + return FAIL; } + return OK; +} - /* :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); - } +/* + * Invoke the xdiff function. + */ + static int +diff_file_internal(diffio_T *diffio) +{ + xpparam_t param; + xdemitconf_t emit_cfg; + xdemitcb_t emit_cb; - /* Write the first buffer to a tempfile. */ - buf = curtab->tp_diffbuf[idx_orig]; - if (diff_write(buf, tmp_orig) == FAIL) - goto theend; + vim_memset(¶m, 0, sizeof(param)); + vim_memset(&emit_cfg, 0, sizeof(emit_cfg)); + vim_memset(&emit_cb, 0, sizeof(emit_cb)); - /* Make a difference between the first buffer and every other. */ - for (idx_new = idx_orig + 1; idx_new < DB_COUNT; ++idx_new) + 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) { - 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); + EMSG(_("E960: Problem creating the internal diff")); + return FAIL; } - 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); + return OK; } /* * Make a diff between files "tmp_orig" and "tmp_new", results in "tmp_diff". + * return OK or FAIL; */ - static void -diff_file( - char_u *tmp_orig, - char_u *tmp_new, - char_u *tmp_diff) + 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. */ + { + // 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) - { - /* We don't want $DIFF_OPTIONS to get in the way. */ - if (getenv("DIFF_OPTIONS")) - vim_setenv((char_u *)"DIFF_OPTIONS", (char_u *)""); + if (cmd == NULL) + return FAIL; - /* 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 ", + // 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 " : "", + 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); - } + (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,89 +1527,105 @@ ex_diffoff(exarg_T *eap) */ 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 */ + int idx_orig, // idx of original file + int idx_new, // idx of new file + diffout_T *dout) // diff output { - FILE *fd; + FILE *fd = NULL; + int line_idx = 0; 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; + 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; - fd = mch_fopen((char *)fname, "r"); - if (fd == NULL) + if (dout->dout_fname == NULL) { - EMSG(_("E98: Cannot read diff output")); - return; + diffstyle = DIFF_UNIFIED; + } + else + { + fd = mch_fopen((char *)dout->dout_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 == ',') + if (fd == NULL) { - ++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; + if (line_idx >= dout->dout_ga.ga_len) + break; // did last line + line = ((char_u **)dout->dout_ga.ga_data)[line_idx++]; } 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; + if (tag_fgets(linebuf, LBUFLEN, fd)) + break; // end of file + line = linebuf; } - /* Go over blocks before the change, for which orig and new are equal. - * Copy blocks from orig to new. */ + 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,14 +1640,14 @@ diff_read( && 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. */ + // 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. */ + // 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,24 +1659,24 @@ diff_read( } else if (notset) { - /* new block inside existing one, adjust new block */ + // 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 */ + // 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. */ + // 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 */ + // new change ends in existing block, adjust the end if not + // done already if (notset) dp->df_count[idx_new] += -off; off = 0; @@ -1425,7 +1686,7 @@ diff_read( 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. */ + // 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,7 +1698,7 @@ diff_read( } else { - /* Allocate a new diffblock. */ + // Allocate a new diffblock. dp = diff_alloc_new(curtab, dprev, dp); if (dp == NULL) goto done; @@ -1447,17 +1708,17 @@ diff_read( 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. */ + // 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 */ + notset = FALSE; // "*dp" has been set } - /* for remaining diff blocks orig and new are equal */ + // for remaining diff blocks orig and new are equal while (dp != NULL) { if (notset) @@ -1468,7 +1729,8 @@ diff_read( } done: - fclose(fd); + if (fd != NULL) + fclose(fd); } /* @@ -1860,6 +2122,7 @@ diffopt_changed(void) 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,6 +2168,41 @@ diffopt_changed(void) 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,13 +2214,14 @@ diffopt_changed(void) return FAIL; /* If "icase" or "iwhite" was added or removed, need to update the diff. */ - if (diff_flags != diff_flags_new) + 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,4 +2989,156 @@ diff_lnum_win(linenr_T lnum, win_T *wp) 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 */ diff --git a/src/structs.h b/src/structs.h index 253f774abc..ee56bd3e40 100644 --- a/src/structs.h +++ b/src/structs.h @@ -2433,7 +2433,9 @@ struct file_buffer 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 */ diff --git a/src/testdir/dumps/Test_diff_01.dump b/src/testdir/dumps/Test_diff_01.dump new file mode 100644 index 0000000000..0dbce1f137 --- /dev/null +++ b/src/testdir/dumps/Test_diff_01.dump @@ -0,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 diff --git a/src/testdir/dumps/Test_diff_02.dump b/src/testdir/dumps/Test_diff_02.dump new file mode 100644 index 0000000000..78f7978843 --- /dev/null +++ b/src/testdir/dumps/Test_diff_02.dump @@ -0,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 diff --git a/src/testdir/dumps/Test_diff_03.dump b/src/testdir/dumps/Test_diff_03.dump new file mode 100644 index 0000000000..60916a831c --- /dev/null +++ b/src/testdir/dumps/Test_diff_03.dump @@ -0,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 diff --git a/src/testdir/dumps/Test_diff_04.dump b/src/testdir/dumps/Test_diff_04.dump new file mode 100644 index 0000000000..ba9cdd81ac --- /dev/null +++ b/src/testdir/dumps/Test_diff_04.dump @@ -0,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 diff --git a/src/testdir/dumps/Test_diff_05.dump b/src/testdir/dumps/Test_diff_05.dump new file mode 100644 index 0000000000..7a5d5403ed --- /dev/null +++ b/src/testdir/dumps/Test_diff_05.dump @@ -0,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 diff --git a/src/testdir/dumps/Test_diff_06.dump b/src/testdir/dumps/Test_diff_06.dump new file mode 100644 index 0000000000..8cd68fdf30 --- /dev/null +++ b/src/testdir/dumps/Test_diff_06.dump @@ -0,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 diff --git a/src/testdir/dumps/Test_diff_07.dump b/src/testdir/dumps/Test_diff_07.dump new file mode 100644 index 0000000000..97864c68da --- /dev/null +++ b/src/testdir/dumps/Test_diff_07.dump @@ -0,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 diff --git a/src/testdir/dumps/Test_diff_08.dump b/src/testdir/dumps/Test_diff_08.dump new file mode 100644 index 0000000000..6445a57767 --- /dev/null +++ b/src/testdir/dumps/Test_diff_08.dump @@ -0,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 diff --git a/src/testdir/dumps/Test_diff_09.dump b/src/testdir/dumps/Test_diff_09.dump new file mode 100644 index 0000000000..6445a57767 --- /dev/null +++ b/src/testdir/dumps/Test_diff_09.dump @@ -0,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 diff --git a/src/testdir/dumps/Test_diff_10.dump b/src/testdir/dumps/Test_diff_10.dump new file mode 100644 index 0000000000..70b9c8232c --- /dev/null +++ b/src/testdir/dumps/Test_diff_10.dump @@ -0,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 diff --git a/src/testdir/dumps/Test_diff_11.dump b/src/testdir/dumps/Test_diff_11.dump new file mode 100644 index 0000000000..0e4268ec75 --- /dev/null +++ b/src/testdir/dumps/Test_diff_11.dump @@ -0,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 diff --git a/src/testdir/dumps/Test_diff_12.dump b/src/testdir/dumps/Test_diff_12.dump new file mode 100644 index 0000000000..0ed4f91870 --- /dev/null +++ b/src/testdir/dumps/Test_diff_12.dump @@ -0,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 diff --git a/src/testdir/dumps/Test_diff_13.dump b/src/testdir/dumps/Test_diff_13.dump new file mode 100644 index 0000000000..cc1f1ad18d --- /dev/null +++ b/src/testdir/dumps/Test_diff_13.dump @@ -0,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 diff --git a/src/testdir/dumps/Test_diff_14.dump b/src/testdir/dumps/Test_diff_14.dump new file mode 100644 index 0000000000..5f9b75f388 --- /dev/null +++ b/src/testdir/dumps/Test_diff_14.dump @@ -0,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 diff --git a/src/testdir/dumps/Test_diff_15.dump b/src/testdir/dumps/Test_diff_15.dump new file mode 100644 index 0000000000..0eb1813921 --- /dev/null +++ b/src/testdir/dumps/Test_diff_15.dump @@ -0,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 diff --git a/src/testdir/dumps/Test_diff_16.dump b/src/testdir/dumps/Test_diff_16.dump new file mode 100644 index 0000000000..74ad5b64ce --- /dev/null +++ b/src/testdir/dumps/Test_diff_16.dump @@ -0,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 diff --git a/src/testdir/test_diffmode.vim b/src/testdir/test_diffmode.vim index d6c5c83fe5..c3c1eaf4a5 100644 --- a/src/testdir/test_diffmode.vim +++ b/src/testdir/test_diffmode.vim @@ -1,4 +1,6 @@ " Tests for diff mode +source shared.vim +source screendump.vim func Test_diff_fold_sync() enew! @@ -33,6 +35,18 @@ func Test_diff_fold_sync() 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,10 +289,8 @@ func Test_diffoff() bwipe! endfunc -func Test_diffopt_icase() - set diffopt=icase,foldcolumn:0 - - e one +func Common_icase_test() + edit one call setline(1, ['One', 'Two', 'Three', 'Four', 'Fi#ve']) redraw let normattr = screenattr(1, 1) @@ -300,32 +312,54 @@ func Test_diffopt_icase() diffoff! %bwipe! +endfunc + +func Test_diffopt_icase() + set diffopt=icase,foldcolumn:0 + call Common_icase_test() set diffopt& endfunc -func Test_diffopt_iwhite() - set diffopt=iwhite,foldcolumn:0 +func Test_diffopt_icase_internal() + set diffopt=icase,foldcolumn:0,internal + call Common_icase_test() + set diffopt& +endfunc - e one - " Difference in trailing spaces should be ignored, +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', 'Four']) + 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', ' Four']) + 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_notequal(normattr, screenattr(4, 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,8 +373,13 @@ func Test_diffopt_context() 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,7 +387,7 @@ func Test_diffopt_context() endfunc func Test_diffopt_horizontal() - set diffopt=horizontal + set diffopt=internal,horizontal diffsplit call assert_equal(&columns, winwidth(1)) @@ -362,7 +401,7 @@ func Test_diffopt_horizontal() endfunc func Test_diffopt_vertical() - set diffopt=vertical + set diffopt=internal,vertical diffsplit call assert_equal(&lines - 2, winheight(1)) @@ -376,7 +415,7 @@ func Test_diffopt_vertical() endfunc func Test_diffopt_hiddenoff() - set diffopt=filler,foldcolumn:0,hiddenoff + set diffopt=internal,filler,foldcolumn:0,hiddenoff e! one call setline(1, ['Two', 'Three']) redraw @@ -399,7 +438,7 @@ func Test_diffopt_hiddenoff() endfunc func Test_diffoff_hidden() - set diffopt=filler,foldcolumn:0 + set diffopt=internal,filler,foldcolumn:0 e! one call setline(1, ['Two', 'Three']) redraw @@ -629,3 +668,118 @@ func Test_diff_lastline() 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!\") + " trailing : for leaving the cursor on the command line + for cmd in [":set diffopt=filler" . a:extra . "\:", ":set diffopt+=internal\:"] + 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\\w:set autoread\\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 ', '', '// 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 ', '', '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!\") + call term_sendkeys(buf, ":set diffopt+=internal\") + call VerifyScreenDump(buf, 'Test_diff_07', {}) + + call term_sendkeys(buf, ":set diffopt+=algorithm:patience\") + call VerifyScreenDump(buf, 'Test_diff_08', {}) + + call term_sendkeys(buf, ":set diffopt+=algorithm:histogram\") + call VerifyScreenDump(buf, 'Test_diff_09', {}) + + " Test 10-11: normal/indent-heuristic + call term_sendkeys(buf, ":set diffopt&vim\") + 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!\") + call term_sendkeys(buf, ":set diffopt+=internal\") + call VerifyScreenDump(buf, 'Test_diff_10', {}) + + call term_sendkeys(buf, ":set diffopt+=indent-heuristic\") + 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!\") + call term_sendkeys(buf, ":set diffopt&vim diffopt+=filler diffopt+=iwhite\") + call VerifyScreenDump(buf, 'Test_diff_15', {}) + call term_sendkeys(buf, ":set diffopt+=internal\") + call VerifyScreenDump(buf, 'Test_diff_16', {}) + + " clean up + call StopVimInTerminal(buf) + call delete('Xfile1') + call delete('Xfile2') +endfunc + diff --git a/src/version.c b/src/version.c index 73bcab1094..9ba63af29e 100644 --- a/src/version.c +++ b/src/version.c @@ -794,6 +794,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 360, /**/ 359, /**/ diff --git a/src/xdiff/COPYING b/src/xdiff/COPYING new file mode 100644 index 0000000000..f3f1b3b65e --- /dev/null +++ b/src/xdiff/COPYING @@ -0,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. + + + Copyright (C) + + 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. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/src/xdiff/README.txt b/src/xdiff/README.txt new file mode 100644 index 0000000000..f77893d37f --- /dev/null +++ b/src/xdiff/README.txt @@ -0,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. diff --git a/src/xdiff/xdiff.h b/src/xdiff/xdiff.h new file mode 100644 index 0000000000..2356da5f78 --- /dev/null +++ b/src/xdiff/xdiff.h @@ -0,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 + * . + * + * Davide Libenzi + * + */ + +#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) */ diff --git a/src/xdiff/xdiffi.c b/src/xdiff/xdiffi.c new file mode 100644 index 0000000000..3dc90ae513 --- /dev/null +++ b/src/xdiff/xdiffi.c @@ -0,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 + * . + * + * Davide Libenzi + * + */ + +#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; +} diff --git a/src/xdiff/xdiffi.h b/src/xdiff/xdiffi.h new file mode 100644 index 0000000000..8f1c7c8b04 --- /dev/null +++ b/src/xdiff/xdiffi.h @@ -0,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 + * . + * + * Davide Libenzi + * + */ + +#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) */ diff --git a/src/xdiff/xemit.c b/src/xdiff/xemit.c new file mode 100644 index 0000000000..718b3ae90c --- /dev/null +++ b/src/xdiff/xemit.c @@ -0,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 + * . + * + * Davide Libenzi + * + */ + +#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; +} diff --git a/src/xdiff/xemit.h b/src/xdiff/xemit.h new file mode 100644 index 0000000000..1b9887e670 --- /dev/null +++ b/src/xdiff/xemit.h @@ -0,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 + * . + * + * Davide Libenzi + * + */ + +#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) */ diff --git a/src/xdiff/xhistogram.c b/src/xdiff/xhistogram.c new file mode 100644 index 0000000000..3fb8974dd4 --- /dev/null +++ b/src/xdiff/xhistogram.c @@ -0,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); +} diff --git a/src/xdiff/xinclude.h b/src/xdiff/xinclude.h new file mode 100644 index 0000000000..46b8608314 --- /dev/null +++ b/src/xdiff/xinclude.h @@ -0,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 + * . + * + * Davide Libenzi + * + */ + +/* 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 +#include +#include +#if !defined(_WIN32) +#include +#endif +#include +#include + +#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) */ diff --git a/src/xdiff/xmacros.h b/src/xdiff/xmacros.h new file mode 100644 index 0000000000..2809a28ca9 --- /dev/null +++ b/src/xdiff/xmacros.h @@ -0,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 + * . + * + * Davide Libenzi + * + */ + +#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) */ diff --git a/src/xdiff/xpatience.c b/src/xdiff/xpatience.c new file mode 100644 index 0000000000..1052d10a38 --- /dev/null +++ b/src/xdiff/xpatience.c @@ -0,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 + * . + * + * Davide Libenzi + * + */ +#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); +} diff --git a/src/xdiff/xprepare.c b/src/xdiff/xprepare.c new file mode 100644 index 0000000000..abeb8fb84e --- /dev/null +++ b/src/xdiff/xprepare.c @@ -0,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 + * . + * + * Davide Libenzi + * + */ + +#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; +} diff --git a/src/xdiff/xprepare.h b/src/xdiff/xprepare.h new file mode 100644 index 0000000000..947d9fc1bb --- /dev/null +++ b/src/xdiff/xprepare.h @@ -0,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 + * . + * + * Davide Libenzi + * + */ + +#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) */ diff --git a/src/xdiff/xtypes.h b/src/xdiff/xtypes.h new file mode 100644 index 0000000000..8442bd436e --- /dev/null +++ b/src/xdiff/xtypes.h @@ -0,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 + * . + * + * Davide Libenzi + * + */ + +#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) */ diff --git a/src/xdiff/xutils.c b/src/xdiff/xutils.c new file mode 100644 index 0000000000..4ab6ca8fdc --- /dev/null +++ b/src/xdiff/xutils.c @@ -0,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 + * . + * + * Davide Libenzi + * + */ + +#include +#include +#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; +} diff --git a/src/xdiff/xutils.h b/src/xdiff/xutils.h new file mode 100644 index 0000000000..fba7bae03c --- /dev/null +++ b/src/xdiff/xutils.h @@ -0,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 + * . + * + * Davide Libenzi + * + */ + +#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) */ From 6b0b83f768cf536b34ce4d3f2de6bf62324229aa Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 10 Sep 2018 19:03:05 +0200 Subject: [PATCH 11/16] patch 8.1.0361: remote user not used for completion Problem: Remote user not used for completion. (Stucki) Solution: Use $USER too. (Dominique Pelle, closes #3407) --- src/misc1.c | 73 +++++++++++++++++++++++++++++++++++++-------------- src/version.c | 2 ++ 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/src/misc1.c b/src/misc1.c index dca599f500..f9055e6e35 100644 --- a/src/misc1.c +++ b/src/misc1.c @@ -4716,6 +4716,25 @@ get_env_name( # endif } +/* + * Add a user name to the list of users in ga_users. + * Do nothing if user name is NULL or empty. + */ + static void +add_user(char_u *user, int need_copy) +{ + char_u *user_copy = (user != NULL && need_copy) + ? vim_strsave(user) : user; + + if (user_copy == NULL || *user_copy == NUL || ga_grow(&ga_users, 1) == FAIL) + { + if (need_copy) + vim_free(user); + return; + } + ((char_u **)(ga_users.ga_data))[ga_users.ga_len++] = user_copy; +} + /* * Find all user names for user completion. * Done only once and then cached. @@ -4733,26 +4752,15 @@ init_users(void) # if defined(HAVE_GETPWENT) && defined(HAVE_PWD_H) { - char_u* user; struct passwd* pw; setpwent(); while ((pw = getpwent()) != NULL) - /* pw->pw_name shouldn't be NULL but just in case... */ - if (pw->pw_name != NULL) - { - if (ga_grow(&ga_users, 1) == FAIL) - break; - user = vim_strsave((char_u*)pw->pw_name); - if (user == NULL) - break; - ((char_u **)(ga_users.ga_data))[ga_users.ga_len++] = user; - } + add_user((char_u *)pw->pw_name, TRUE); endpwent(); } # elif defined(WIN3264) { - char_u* user; DWORD nusers = 0, ntotal = 0, i; PUSER_INFO_0 uinfo; @@ -4760,19 +4768,44 @@ init_users(void) &nusers, &ntotal, NULL) == NERR_Success) { for (i = 0; i < nusers; i++) - { - if (ga_grow(&ga_users, 1) == FAIL) - break; - user = utf16_to_enc(uinfo[i].usri0_name, NULL); - if (user == NULL) - break; - ((char_u **)(ga_users.ga_data))[ga_users.ga_len++] = user; - } + add_user(utf16_to_enc(uinfo[i].usri0_name, NULL), FALSE); NetApiBufferFree(uinfo); } } # endif +# if defined(HAVE_GETPWNAM) + { + char_u *user_env = mch_getenv((char_u *)"USER"); + + // The $USER environment variable may be a valid remote user name (NIS, + // LDAP) not already listed by getpwent(), as getpwent() only lists + // local user names. If $USER is not already listed, check whether it + // is a valid remote user name using getpwnam() and if it is, add it to + // the list of user names. + + if (user_env != NULL && *user_env != NUL) + { + int i; + + for (i = 0; i < ga_users.ga_len; i++) + { + char_u *local_user = ((char_u **)ga_users.ga_data)[i]; + + if (STRCMP(local_user, user_env) == 0) + break; + } + + if (i == ga_users.ga_len) + { + struct passwd *pw = getpwnam((char *)user_env); + + if (pw != NULL) + add_user((char_u *)pw->pw_name, TRUE); + } + } + } +# endif } /* diff --git a/src/version.c b/src/version.c index 9ba63af29e..b3768a8fc2 100644 --- a/src/version.c +++ b/src/version.c @@ -794,6 +794,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 361, /**/ 360, /**/ From f29c1c6aa3f365c025890fab5fb9efbe88eb1761 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 10 Sep 2018 21:05:02 +0200 Subject: [PATCH 12/16] patch 8.1.0362: cannot get the script line number when executing a function Problem: Cannot get the script line number when executing a function. Solution: Store the line number besides the script ID. (Ozaki Kiichi, closes #3362) Also display the line number with ":verbose set". --- runtime/doc/cmdline.txt | 27 +- runtime/doc/eval.txt | 6 +- src/Make_all.mak | 4 +- src/buffer.c | 9 +- src/eval.c | 23 +- src/evalfunc.c | 5 +- src/ex_cmds2.c | 52 +- src/ex_docmd.c | 42 +- src/ex_getln.c | 6 +- src/fileio.c | 15 +- src/getchar.c | 8 +- src/globals.h | 4 +- src/main.c | 17 +- src/menu.c | 4 +- src/option.c | 898 ++++++++++++++++--------------- src/proto/eval.pro | 2 +- src/structs.h | 25 +- src/syntax.c | 18 +- src/term.c | 5 +- src/testdir/test_alot.vim | 1 + src/testdir/test_expand_func.vim | 66 +++ src/testdir/test_maparg.vim | 15 +- src/userfunc.c | 24 +- src/version.c | 2 + 24 files changed, 716 insertions(+), 562 deletions(-) create mode 100644 src/testdir/test_expand_func.vim diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt index df18ec6c45..3b2dd32060 100644 --- a/runtime/doc/cmdline.txt +++ b/runtime/doc/cmdline.txt @@ -832,11 +832,12 @@ it, no matter how many backslashes. \\# \# Also see |`=|. - *:* *:* *:* ** - *:* ** *:* ** - *:* ** *:* ** - *:* ** - ** *E495* *E496* *E497* *E499* *E500* + *:* ** *:* ** + *:* ** *:* ** + *:* ** *:* ** + *:* ** + *:* ** *:* ** + *:* ** *E499* *E500* Note: these are typed literally, they are not special keys! is replaced with the word under the cursor (like |star|) is replaced with the WORD under the cursor (see |WORD|) @@ -849,15 +850,16 @@ Note: these are typed literally, they are not special keys! |gf| uses) When executing autocommands, is replaced with the file name of the buffer being manipulated, or the file for a read or - write. + write. *E495* When executing autocommands, is replaced with the currently effective buffer number (for ":r file" and ":so file" it is the current buffer, the file being read/sourced is not in a - buffer). + buffer). *E496* When executing autocommands, is replaced with the match for - which this autocommand was executed. It differs from - only when the file name isn't used to match with - (for FileType, Syntax and SpellFileMissing events). + which this autocommand was executed. *E497* + It differs from only when the file name isn't used + to match with (for FileType, Syntax and SpellFileMissing + events). When executing a ":source" command, is replaced with the file name of the sourced file. *E498* When executing a function, is replaced with: @@ -867,9 +869,12 @@ Note: these are typed literally, they are not special keys! Note that filename-modifiers are useless when is used inside a function. When executing a ":source" command, is replaced with the - line number. *E842* + line number. *E842* When executing a function it's the line number relative to the start of the function. + When executing a script, is replaced with the line number. + It differs from in that is replaced with + the script line number in any situation. *E961* *filename-modifiers* *:_%:* *::8* *::p* *::.* *::~* *::h* *::t* *::r* *::e* *::s* *::gs* *::S* diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 21cb4abade..2ff124b691 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -3798,7 +3798,10 @@ expand({expr} [, {nosuf} [, {list}]]) *expand()* autocmd buffer number (as a String!) autocmd matched name sourced script file or function name - sourced script file line number + sourced script line number or function + line number + script file line number, also when in + a function word under the cursor WORD under the cursor the {clientid} of the last received @@ -5931,6 +5934,7 @@ maparg({name} [, {mode} [, {abbr} [, {dict}]]]) *maparg()* (|mapmode-ic|) "sid" The script local ID, used for mappings (||). + "lnum" The line number in "sid", zero if unknown. "nowait" Do not wait for other, longer mappings. (|:map-|). diff --git a/src/Make_all.mak b/src/Make_all.mak index 49ad4f0af8..79b8b94798 100644 --- a/src/Make_all.mak +++ b/src/Make_all.mak @@ -2,7 +2,8 @@ # Common Makefile, defines the list of tests to run. # -# Individual tests, including the ones part of test_alot +# Individual tests, including the ones part of test_alot. +# Please keep sorted up to test_alot. NEW_TESTS = \ test_arglist \ test_arabic \ @@ -52,6 +53,7 @@ NEW_TESTS = \ test_exists_autocmd \ test_expand \ test_expand_dllpath \ + test_expand_func \ test_expr \ test_expr_utf8 \ test_farsi \ diff --git a/src/buffer.c b/src/buffer.c index dcff94ba8b..0bf6aa9125 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -5412,7 +5412,7 @@ chk_modeline( char_u *save_sourcing_name; linenr_T save_sourcing_lnum; #ifdef FEAT_EVAL - scid_T save_SID; + sctx_T save_current_sctx; #endif prev = -1; @@ -5497,12 +5497,13 @@ chk_modeline( if (*s != NUL) /* skip over an empty "::" */ { #ifdef FEAT_EVAL - save_SID = current_SID; - current_SID = SID_MODELINE; + save_current_sctx = current_sctx; + current_sctx.sc_sid = SID_MODELINE; + current_sctx.sc_lnum = 0; #endif retval = do_set(s, OPT_MODELINE | OPT_LOCAL | flags); #ifdef FEAT_EVAL - current_SID = save_SID; + current_sctx = save_current_sctx; #endif if (retval == FAIL) /* stop if error found */ break; diff --git a/src/eval.c b/src/eval.c index 3a275213cb..358217a824 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1495,8 +1495,8 @@ list_vim_vars(int *first) static void list_script_vars(int *first) { - if (current_SID > 0 && current_SID <= ga_scripts.ga_len) - list_hashtable_vars(&SCRIPT_VARS(current_SID), + if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= ga_scripts.ga_len) + list_hashtable_vars(&SCRIPT_VARS(current_sctx.sc_sid), (char_u *)"s:", FALSE, first); } @@ -7202,7 +7202,7 @@ find_var_in_ht( /* Must be something like "s:", otherwise "ht" would be NULL. */ switch (htname) { - case 's': return &SCRIPT_SV(current_SID)->sv_var; + case 's': return &SCRIPT_SV(current_sctx.sc_sid)->sv_var; case 'g': return &globvars_var; case 'v': return &vimvars_var; case 'b': return &curbuf->b_bufvar; @@ -7286,8 +7286,8 @@ find_var_ht(char_u *name, char_u **varname) if (*name == 'l') /* l: local function variable */ return get_funccal_local_ht(); if (*name == 's' /* script variable */ - && current_SID > 0 && current_SID <= ga_scripts.ga_len) - return &SCRIPT_VARS(current_SID); + && current_sctx.sc_sid > 0 && current_sctx.sc_sid <= ga_scripts.ga_len) + return &SCRIPT_VARS(current_sctx.sc_sid); return NULL; } @@ -8729,20 +8729,25 @@ store_session_globals(FILE *fd) * Should only be invoked when 'verbose' is non-zero. */ void -last_set_msg(scid_T scriptID) +last_set_msg(sctx_T script_ctx) { char_u *p; - if (scriptID != 0) + if (script_ctx.sc_sid != 0) { - p = home_replace_save(NULL, get_scriptname(scriptID)); + p = home_replace_save(NULL, get_scriptname(script_ctx.sc_sid)); if (p != NULL) { verbose_enter(); MSG_PUTS(_("\n\tLast set from ")); MSG_PUTS(p); - vim_free(p); + if (script_ctx.sc_lnum > 0) + { + MSG_PUTS(_(" line ")); + msg_outnum((long)script_ctx.sc_lnum); + } verbose_leave(); + vim_free(p); } } } diff --git a/src/evalfunc.c b/src/evalfunc.c index 90fb8881b4..54e7dcdd39 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -4061,7 +4061,7 @@ common_function(typval_T *argvars, typval_T *rettv, int is_funcref) * also be called from another script. Using trans_function_name() * would also work, but some plugins depend on the name being * printable text. */ - sprintf(sid_buf, "%ld_", (long)current_SID); + sprintf(sid_buf, "%ld_", (long)current_sctx.sc_sid); name = alloc((int)(STRLEN(sid_buf) + STRLEN(s + off) + 1)); if (name != NULL) { @@ -7618,7 +7618,8 @@ get_maparg(typval_T *argvars, typval_T *rettv, int exact) dict_add_number(dict, "noremap", mp->m_noremap ? 1L : 0L); dict_add_number(dict, "expr", mp->m_expr ? 1L : 0L); dict_add_number(dict, "silent", mp->m_silent ? 1L : 0L); - dict_add_number(dict, "sid", (long)mp->m_script_ID); + dict_add_number(dict, "sid", (long)mp->m_script_ctx.sc_sid); + dict_add_number(dict, "lnum", (long)mp->m_script_ctx.sc_lnum); dict_add_number(dict, "buffer", (long)buffer_local); dict_add_number(dict, "nowait", mp->m_nowait ? 1L : 0L); dict_add_string(dict, "mode", mapmode); diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c index 08eb181787..28245d1781 100644 --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -1866,9 +1866,9 @@ script_prof_save( { scriptitem_T *si; - if (current_SID > 0 && current_SID <= script_items.ga_len) + if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= script_items.ga_len) { - si = &SCRIPT_ITEM(current_SID); + si = &SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && si->sn_pr_nest++ == 0) profile_start(&si->sn_pr_child); } @@ -1883,9 +1883,9 @@ script_prof_restore(proftime_T *tm) { scriptitem_T *si; - if (current_SID > 0 && current_SID <= script_items.ga_len) + if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= script_items.ga_len) { - si = &SCRIPT_ITEM(current_SID); + si = &SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && --si->sn_pr_nest == 0) { profile_end(&si->sn_pr_child); @@ -2003,8 +2003,8 @@ script_dump_profile(FILE *fd) int prof_def_func(void) { - if (current_SID > 0) - return SCRIPT_ITEM(current_SID).sn_pr_force; + if (current_sctx.sc_sid > 0) + return SCRIPT_ITEM(current_sctx.sc_sid).sn_pr_force; return FALSE; } @@ -4351,7 +4351,7 @@ do_source( char_u *firstline = NULL; int retval = FAIL; #ifdef FEAT_EVAL - scid_T save_current_SID; + sctx_T save_current_sctx; static scid_T last_current_SID = 0; void *save_funccalp; int save_debug_break_level = debug_break_level; @@ -4521,13 +4521,15 @@ do_source( * Check if this script was sourced before to finds its SID. * If it's new, generate a new SID. */ - save_current_SID = current_SID; + save_current_sctx = current_sctx; + current_sctx.sc_lnum = 0; # ifdef UNIX stat_ok = (mch_stat((char *)fname_exp, &st) >= 0); # endif - for (current_SID = script_items.ga_len; current_SID > 0; --current_SID) + for (current_sctx.sc_sid = script_items.ga_len; current_sctx.sc_sid > 0; + --current_sctx.sc_sid) { - si = &SCRIPT_ITEM(current_SID); + si = &SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_name != NULL && ( # ifdef UNIX @@ -4541,13 +4543,13 @@ do_source( fnamecmp(si->sn_name, fname_exp) == 0)) break; } - if (current_SID == 0) + if (current_sctx.sc_sid == 0) { - current_SID = ++last_current_SID; - if (ga_grow(&script_items, (int)(current_SID - script_items.ga_len)) - == FAIL) + current_sctx.sc_sid = ++last_current_SID; + if (ga_grow(&script_items, + (int)(current_sctx.sc_sid - script_items.ga_len)) == FAIL) goto almosttheend; - while (script_items.ga_len < current_SID) + while (script_items.ga_len < current_sctx.sc_sid) { ++script_items.ga_len; SCRIPT_ITEM(script_items.ga_len).sn_name = NULL; @@ -4555,7 +4557,7 @@ do_source( SCRIPT_ITEM(script_items.ga_len).sn_prof_on = FALSE; # endif } - si = &SCRIPT_ITEM(current_SID); + si = &SCRIPT_ITEM(current_sctx.sc_sid); si->sn_name = fname_exp; fname_exp = NULL; # ifdef UNIX @@ -4570,7 +4572,7 @@ do_source( # endif /* Allocate the local script variables to use for this script. */ - new_script_vars(current_SID); + new_script_vars(current_sctx.sc_sid); } # ifdef FEAT_PROFILE @@ -4626,7 +4628,7 @@ do_source( if (do_profiling == PROF_YES) { /* Get "si" again, "script_items" may have been reallocated. */ - si = &SCRIPT_ITEM(current_SID); + si = &SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on) { profile_end(&si->sn_pr_start); @@ -4671,7 +4673,7 @@ do_source( #ifdef FEAT_EVAL almosttheend: - current_SID = save_current_SID; + current_sctx = save_current_sctx; restore_funccal(save_funccalp); # ifdef FEAT_PROFILE if (do_profiling == PROF_YES) @@ -5090,9 +5092,9 @@ script_line_start(void) scriptitem_T *si; sn_prl_T *pp; - if (current_SID <= 0 || current_SID > script_items.ga_len) + if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len) return; - si = &SCRIPT_ITEM(current_SID); + si = &SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && sourcing_lnum >= 1) { /* Grow the array before starting the timer, so that the time spent @@ -5125,9 +5127,9 @@ script_line_exec(void) { scriptitem_T *si; - if (current_SID <= 0 || current_SID > script_items.ga_len) + if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len) return; - si = &SCRIPT_ITEM(current_SID); + si = &SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && si->sn_prl_idx >= 0) si->sn_prl_execed = TRUE; } @@ -5141,9 +5143,9 @@ script_line_end(void) scriptitem_T *si; sn_prl_T *pp; - if (current_SID <= 0 || current_SID > script_items.ga_len) + if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len) return; - si = &SCRIPT_ITEM(current_SID); + si = &SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && si->sn_prl_idx >= 0 && si->sn_prl_idx < si->sn_prl_ga.ga_len) { diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 767791776e..e9f661bcad 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -29,7 +29,7 @@ typedef struct ucmd int uc_compl; /* completion type */ int uc_addr_type; /* The command's address type */ # ifdef FEAT_EVAL - scid_T uc_scriptID; /* SID where the command was defined */ + sctx_T uc_script_ctx; /* SCTX where the command was defined */ # ifdef FEAT_CMDL_COMPL char_u *uc_compl_arg; /* completion argument if any */ # endif @@ -3340,7 +3340,8 @@ find_ucmd( if (xp != NULL) { xp->xp_arg = uc->uc_compl_arg; - xp->xp_scriptID = uc->uc_scriptID; + xp->xp_script_ctx = uc->uc_script_ctx; + xp->xp_script_ctx.sc_lnum += sourcing_lnum; } # endif # endif @@ -5920,7 +5921,8 @@ uc_add_command( cmd->uc_def = def; cmd->uc_compl = compl; #ifdef FEAT_EVAL - cmd->uc_scriptID = current_SID; + cmd->uc_script_ctx = current_sctx; + cmd->uc_script_ctx.sc_lnum += sourcing_lnum; # ifdef FEAT_CMDL_COMPL cmd->uc_compl_arg = compl_arg; # endif @@ -6141,7 +6143,7 @@ uc_list(char_u *name, size_t name_len) msg_outtrans_special(cmd->uc_rep, FALSE); #ifdef FEAT_EVAL if (p_verbose > 0) - last_set_msg(cmd->uc_scriptID); + last_set_msg(cmd->uc_script_ctx); #endif out_flush(); ui_breakcheck(); @@ -6906,7 +6908,7 @@ do_ucmd(exarg_T *eap) char_u *split_buf = NULL; ucmd_T *cmd; #ifdef FEAT_EVAL - scid_T save_current_SID = current_SID; + sctx_T save_current_sctx = current_sctx; #endif if (eap->cmdidx == CMD_USER) @@ -7007,12 +7009,12 @@ do_ucmd(exarg_T *eap) } #ifdef FEAT_EVAL - current_SID = cmd->uc_scriptID; + current_sctx.sc_sid = cmd->uc_script_ctx.sc_sid; #endif (void)do_cmdline(buf, eap->getline, eap->cookie, DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED); #ifdef FEAT_EVAL - current_SID = save_current_SID; + current_sctx = save_current_sctx; #endif vim_free(buf); vim_free(split_buf); @@ -10736,14 +10738,16 @@ find_cmdline_var(char_u *src, int *usedlen) "", /* ":so" file line number */ #define SPEC_SLNUM (SPEC_SFILE + 1) "", /* autocommand file name */ -#define SPEC_AFILE (SPEC_SLNUM + 1) +#define SPEC_AFILE (SPEC_SLNUM + 1) "", /* autocommand buffer number */ -#define SPEC_ABUF (SPEC_AFILE + 1) +#define SPEC_ABUF (SPEC_AFILE + 1) "", /* autocommand match name */ #define SPEC_AMATCH (SPEC_ABUF + 1) + "", /* script file line number */ +#define SPEC_SFLNUM (SPEC_AMATCH + 1) #ifdef FEAT_CLIENTSERVER "" -# define SPEC_CLIENT (SPEC_AMATCH + 1) +# define SPEC_CLIENT (SPEC_SFLNUM + 1) #endif }; @@ -10999,6 +11003,7 @@ eval_vars( return NULL; } break; + case SPEC_SLNUM: /* line in file for ":so" command */ if (sourcing_name == NULL || sourcing_lnum == 0) { @@ -11008,13 +11013,28 @@ eval_vars( sprintf((char *)strbuf, "%ld", (long)sourcing_lnum); result = strbuf; break; -#if defined(FEAT_CLIENTSERVER) + +#ifdef FEAT_EVAL + case SPEC_SFLNUM: /* line in script file */ + if (current_sctx.sc_lnum + sourcing_lnum == 0) + { + *errormsg = (char_u *)_("E961: no line number to use for \"\""); + return NULL; + } + sprintf((char *)strbuf, "%ld", + (long)(current_sctx.sc_lnum + sourcing_lnum)); + result = strbuf; + break; +#endif + +#ifdef FEAT_CLIENTSERVER case SPEC_CLIENT: /* Source of last submitted input */ sprintf((char *)strbuf, PRINTF_HEX_LONG_U, (long_u)clientWindow); result = strbuf; break; #endif + default: result = (char_u *)""; /* avoid gcc warning */ break; diff --git a/src/ex_getln.c b/src/ex_getln.c index 9a8806c14b..a72b9a4096 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -5591,7 +5591,7 @@ call_user_expand_func( { int keep = 0; typval_T args[4]; - int save_current_SID = current_SID; + sctx_T save_current_sctx = current_sctx; char_u *pat = NULL; void *ret; struct cmdline_info save_ccline; @@ -5621,12 +5621,12 @@ call_user_expand_func( save_ccline = ccline; ccline.cmdbuff = NULL; ccline.cmdprompt = NULL; - current_SID = xp->xp_scriptID; + current_sctx = xp->xp_script_ctx; ret = user_expand_func(xp->xp_arg, 3, args); ccline = save_ccline; - current_SID = save_current_SID; + current_sctx = save_current_sctx; if (ccline.cmdbuff != NULL) ccline.cmdbuff[ccline.cmdlen] = keep; diff --git a/src/fileio.c b/src/fileio.c index d00dc5e47b..056ac914d7 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -7700,7 +7700,7 @@ typedef struct AutoCmd char nested; /* If autocommands nest here */ char last; /* last command in list */ #ifdef FEAT_EVAL - scid_T scriptID; /* script ID where defined */ + sctx_T script_ctx; /* script context where defined */ #endif struct AutoCmd *next; /* Next AutoCmd in list */ } AutoCmd; @@ -7962,7 +7962,7 @@ show_autocmd(AutoPat *ap, event_T event) msg_outtrans(ac->cmd); #ifdef FEAT_EVAL if (p_verbose > 0) - last_set_msg(ac->scriptID); + last_set_msg(ac->script_ctx); #endif if (got_int) return; @@ -8845,7 +8845,8 @@ do_autocmd_event( return FAIL; ac->cmd = vim_strsave(cmd); #ifdef FEAT_EVAL - ac->scriptID = current_SID; + ac->script_ctx = current_sctx; + ac->script_ctx.sc_lnum += sourcing_lnum; #endif if (ac->cmd == NULL) { @@ -9412,7 +9413,7 @@ apply_autocmds_group( AutoPatCmd patcmd; AutoPat *ap; #ifdef FEAT_EVAL - scid_T save_current_SID; + sctx_T save_current_sctx; void *save_funccalp; char_u *save_cmdarg; long save_cmdbang; @@ -9621,7 +9622,7 @@ apply_autocmds_group( sourcing_lnum = 0; /* no line number here */ #ifdef FEAT_EVAL - save_current_SID = current_SID; + save_current_sctx = current_sctx; # ifdef FEAT_PROFILE if (do_profiling == PROF_YES) @@ -9725,7 +9726,7 @@ apply_autocmds_group( autocmd_bufnr = save_autocmd_bufnr; autocmd_match = save_autocmd_match; #ifdef FEAT_EVAL - current_SID = save_current_SID; + current_sctx = save_current_sctx; restore_funccal(save_funccalp); # ifdef FEAT_PROFILE if (do_profiling == PROF_YES) @@ -9949,7 +9950,7 @@ getnextac(int c UNUSED, void *cookie, int indent UNUSED) retval = vim_strsave(ac->cmd); autocmd_nested = ac->nested; #ifdef FEAT_EVAL - current_SID = ac->scriptID; + current_sctx = ac->script_ctx; #endif if (ac->last) acp->nextcmd = NULL; diff --git a/src/getchar.c b/src/getchar.c index 496e33fa86..cc8b344e11 100644 --- a/src/getchar.c +++ b/src/getchar.c @@ -3677,7 +3677,8 @@ do_map( mp->m_mode = mode; #ifdef FEAT_EVAL mp->m_expr = expr; - mp->m_script_ID = current_SID; + mp->m_script_ctx = current_sctx; + mp->m_script_ctx.sc_lnum += sourcing_lnum; #endif did_it = TRUE; } @@ -3783,7 +3784,8 @@ do_map( mp->m_mode = mode; #ifdef FEAT_EVAL mp->m_expr = expr; - mp->m_script_ID = current_SID; + mp->m_script_ctx = current_sctx; + mp->m_script_ctx.sc_lnum += sourcing_lnum; #endif /* add the new entry in front of the abbrlist or maphash[] list */ @@ -4097,7 +4099,7 @@ showmap( } #ifdef FEAT_EVAL if (p_verbose > 0) - last_set_msg(mp->m_script_ID); + last_set_msg(mp->m_script_ctx); #endif out_flush(); /* show one line at a time */ } diff --git a/src/globals.h b/src/globals.h index 3446cba751..3f5b61ff78 100644 --- a/src/globals.h +++ b/src/globals.h @@ -325,8 +325,8 @@ EXTERN int may_garbage_collect INIT(= FALSE); EXTERN int want_garbage_collect INIT(= FALSE); EXTERN int garbage_collect_at_exit INIT(= FALSE); -/* ID of script being sourced or was sourced to define the current function. */ -EXTERN scid_T current_SID INIT(= 0); +// Script CTX being sourced or was sourced to define the current function. +EXTERN sctx_T current_sctx INIT(= {0 COMMA 0}); #endif EXTERN int did_source_packages INIT(= FALSE); diff --git a/src/main.c b/src/main.c index d3a509be3f..cb0676ce56 100644 --- a/src/main.c +++ b/src/main.c @@ -2912,13 +2912,13 @@ exe_pre_commands(mparm_T *parmp) curwin->w_cursor.lnum = 0; /* just in case.. */ sourcing_name = (char_u *)_("pre-vimrc command line"); # ifdef FEAT_EVAL - current_SID = SID_CMDARG; + current_sctx.sc_sid = SID_CMDARG; # endif for (i = 0; i < cnt; ++i) do_cmdline_cmd(cmds[i]); sourcing_name = NULL; # ifdef FEAT_EVAL - current_SID = 0; + current_sctx.sc_sid = 0; # endif TIME_MSG("--cmd commands"); } @@ -2942,7 +2942,7 @@ exe_commands(mparm_T *parmp) curwin->w_cursor.lnum = 0; sourcing_name = (char_u *)"command line"; #ifdef FEAT_EVAL - current_SID = SID_CARG; + current_sctx.sc_sid = SID_CARG; #endif for (i = 0; i < parmp->n_commands; ++i) { @@ -2952,7 +2952,7 @@ exe_commands(mparm_T *parmp) } sourcing_name = NULL; #ifdef FEAT_EVAL - current_SID = 0; + current_sctx.sc_sid = 0; #endif if (curwin->w_cursor.lnum == 0) curwin->w_cursor.lnum = 1; @@ -3159,7 +3159,7 @@ process_env( char_u *save_sourcing_name; linenr_T save_sourcing_lnum; #ifdef FEAT_EVAL - scid_T save_sid; + sctx_T save_current_sctx; #endif if ((initstr = mch_getenv(env)) != NULL && *initstr != NUL) @@ -3171,14 +3171,15 @@ process_env( sourcing_name = env; sourcing_lnum = 0; #ifdef FEAT_EVAL - save_sid = current_SID; - current_SID = SID_ENV; + save_current_sctx = current_sctx; + current_sctx.sc_sid = SID_ENV; + current_sctx.sc_lnum = 0; #endif do_cmdline_cmd(initstr); sourcing_name = save_sourcing_name; sourcing_lnum = save_sourcing_lnum; #ifdef FEAT_EVAL - current_SID = save_sid; + current_sctx = save_current_sctx; #endif return OK; } diff --git a/src/menu.c b/src/menu.c index 58429dc8aa..d253e72cb5 100644 --- a/src/menu.c +++ b/src/menu.c @@ -2259,7 +2259,7 @@ execute_menu(exarg_T *eap, vimmenu_T *menu) /* Use the Insert mode entry when returning to Insert mode. */ if (restart_edit #ifdef FEAT_EVAL - && !current_SID + && !current_sctx.sc_sid #endif ) { @@ -2333,7 +2333,7 @@ execute_menu(exarg_T *eap, vimmenu_T *menu) * Otherwise put them in the typeahead buffer. */ if (eap == NULL #ifdef FEAT_EVAL - || current_SID != 0 + || current_sctx.sc_sid != 0 #endif ) { diff --git a/src/option.c b/src/option.c index a7a6ebbd92..98ef98a274 100644 --- a/src/option.c +++ b/src/option.c @@ -404,20 +404,20 @@ static char_u *p_vsts_nopaste; struct vimoption { - char *fullname; /* full option name */ - char *shortname; /* permissible abbreviation */ - long_u flags; /* see below */ - char_u *var; /* global option: pointer to variable; - * window-local option: VAR_WIN; - * buffer-local option: global value */ - idopt_T indir; /* global option: PV_NONE; - * local option: indirect option index */ - char_u *def_val[2]; /* default values for variable (vi and vim) */ + char *fullname; // full option name + char *shortname; // permissible abbreviation + long_u flags; // see below + char_u *var; // global option: pointer to variable; + // window-local option: VAR_WIN; + // buffer-local option: global value + idopt_T indir; // global option: PV_NONE; + // local option: indirect option index + char_u *def_val[2]; // default values for variable (vi and vim) #ifdef FEAT_EVAL - scid_T scriptID; /* script in which the option was last set */ -# define SCRIPTID_INIT , 0 + sctx_T script_ctx; // script context where the option was last set +# define SCTX_INIT , {0, 0} #else -# define SCRIPTID_INIT +# define SCTX_INIT #endif }; @@ -515,7 +515,7 @@ static struct vimoption options[] = #else (char_u *)224L, #endif - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"antialias", "anti", P_BOOL|P_VI_DEF|P_VIM|P_RCLR, #if defined(FEAT_GUI_MAC) (char_u *)&p_antialias, PV_NONE, @@ -524,35 +524,35 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)FALSE, (char_u *)FALSE} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"arabic", "arab", P_BOOL|P_VI_DEF|P_VIM|P_CURSWANT, #ifdef FEAT_ARABIC (char_u *)VAR_WIN, PV_ARAB, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"arabicshape", "arshape", P_BOOL|P_VI_DEF|P_VIM|P_RCLR, #ifdef FEAT_ARABIC (char_u *)&p_arshape, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"allowrevins", "ari", P_BOOL|P_VI_DEF|P_VIM, #ifdef FEAT_RIGHTLEFT (char_u *)&p_ari, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"altkeymap", "akm", P_BOOL|P_VI_DEF, #ifdef FEAT_FKMAP (char_u *)&p_altkeymap, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"ambiwidth", "ambw", P_STRING|P_VI_DEF|P_RCLR, #if defined(FEAT_MBYTE) (char_u *)&p_ambw, PV_NONE, @@ -561,7 +561,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"autochdir", "acd", P_BOOL|P_VI_DEF, #ifdef FEAT_AUTOCHDIR (char_u *)&p_acd, PV_NONE, @@ -570,22 +570,22 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"autoindent", "ai", P_BOOL|P_VI_DEF, (char_u *)&p_ai, PV_AI, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"autoprint", "ap", P_BOOL|P_VI_DEF, (char_u *)NULL, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"autoread", "ar", P_BOOL|P_VI_DEF, (char_u *)&p_ar, PV_AR, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"autowrite", "aw", P_BOOL|P_VI_DEF, (char_u *)&p_aw, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"autowriteall","awa", P_BOOL|P_VI_DEF, (char_u *)&p_awa, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"background", "bg", P_STRING|P_VI_DEF|P_RCLR, (char_u *)&p_bg, PV_NONE, { @@ -594,13 +594,13 @@ static struct vimoption options[] = #else (char_u *)"light", #endif - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"backspace", "bs", P_STRING|P_VI_DEF|P_VIM|P_ONECOMMA|P_NODUP, (char_u *)&p_bs, PV_NONE, - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"backup", "bk", P_BOOL|P_VI_DEF|P_VIM, (char_u *)&p_bk, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"backupcopy", "bkc", P_STRING|P_VIM|P_ONECOMMA|P_NODUP, (char_u *)&p_bkc, PV_BKC, #ifdef UNIX @@ -608,11 +608,11 @@ static struct vimoption options[] = #else {(char_u *)"auto", (char_u *)"auto"} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"backupdir", "bdir", P_STRING|P_EXPAND|P_VI_DEF|P_ONECOMMA |P_NODUP|P_SECURE, (char_u *)&p_bdir, PV_NONE, - {(char_u *)DFLT_BDIR, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)DFLT_BDIR, (char_u *)0L} SCTX_INIT}, {"backupext", "bex", P_STRING|P_VI_DEF|P_NFNAME, (char_u *)&p_bex, PV_NONE, { @@ -621,7 +621,7 @@ static struct vimoption options[] = #else (char_u *)"~", #endif - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"backupskip", "bsk", P_STRING|P_VI_DEF|P_ONECOMMA, #ifdef FEAT_WILDIGN (char_u *)&p_bsk, PV_NONE, @@ -630,7 +630,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"balloondelay","bdlay",P_NUM|P_VI_DEF, #ifdef FEAT_BEVAL (char_u *)&p_bdlay, PV_NONE, @@ -639,7 +639,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"ballooneval", "beval",P_BOOL|P_VI_DEF|P_NO_MKRC, #ifdef FEAT_BEVAL_GUI (char_u *)&p_beval, PV_NONE, @@ -648,7 +648,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"balloonevalterm", "bevalterm",P_BOOL|P_VI_DEF|P_NO_MKRC, #ifdef FEAT_BEVAL_TERM (char_u *)&p_bevalterm, PV_NONE, @@ -657,7 +657,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"balloonexpr", "bexpr", P_STRING|P_ALLOCED|P_VI_DEF|P_VIM, #if defined(FEAT_BEVAL) && defined(FEAT_EVAL) (char_u *)&p_bexpr, PV_BEXPR, @@ -666,26 +666,26 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"beautify", "bf", P_BOOL|P_VI_DEF, (char_u *)NULL, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"belloff", "bo", P_STRING|P_VI_DEF|P_COMMA|P_NODUP, (char_u *)&p_bo, PV_NONE, - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"binary", "bin", P_BOOL|P_VI_DEF|P_RSTAT, (char_u *)&p_bin, PV_BIN, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"bioskey", "biosk",P_BOOL|P_VI_DEF, (char_u *)NULL, PV_NONE, - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"bomb", NULL, P_BOOL|P_NO_MKRC|P_VI_DEF|P_RSTAT, #ifdef FEAT_MBYTE (char_u *)&p_bomb, PV_BOMB, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"breakat", "brk", P_STRING|P_VI_DEF|P_RALL|P_FLAGLIST, #ifdef FEAT_LINEBREAK (char_u *)&p_breakat, PV_NONE, @@ -694,7 +694,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"breakindent", "bri", P_BOOL|P_VI_DEF|P_VIM|P_RWIN, #ifdef FEAT_LINEBREAK (char_u *)VAR_WIN, PV_BRI, @@ -703,7 +703,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"breakindentopt", "briopt", P_STRING|P_ALLOCED|P_VI_DEF|P_RBUF |P_ONECOMMA|P_NODUP, #ifdef FEAT_LINEBREAK @@ -713,7 +713,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)"", (char_u *)NULL} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"browsedir", "bsdir",P_STRING|P_VI_DEF, #ifdef FEAT_BROWSE (char_u *)&p_bsdir, PV_NONE, @@ -722,19 +722,19 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"bufhidden", "bh", P_STRING|P_ALLOCED|P_VI_DEF|P_NOGLOB, (char_u *)&p_bh, PV_BH, {(char_u *)"", (char_u *)0L} - SCRIPTID_INIT}, + SCTX_INIT}, {"buflisted", "bl", P_BOOL|P_VI_DEF|P_NOGLOB, (char_u *)&p_bl, PV_BL, {(char_u *)1L, (char_u *)0L} - SCRIPTID_INIT}, + SCTX_INIT}, {"buftype", "bt", P_STRING|P_ALLOCED|P_VI_DEF|P_NOGLOB, (char_u *)&p_bt, PV_BT, {(char_u *)"", (char_u *)0L} - SCRIPTID_INIT}, + SCTX_INIT}, {"casemap", "cmp", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, #ifdef FEAT_MBYTE (char_u *)&p_cmp, PV_NONE, @@ -743,7 +743,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"cdpath", "cd", P_STRING|P_EXPAND|P_VI_DEF|P_COMMA|P_NODUP, #ifdef FEAT_SEARCHPATH (char_u *)&p_cdpath, PV_NONE, @@ -752,7 +752,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"cedit", NULL, P_STRING, #ifdef FEAT_CMDWIN (char_u *)&p_cedit, PV_NONE, @@ -761,7 +761,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"charconvert", "ccv", P_STRING|P_VI_DEF|P_SECURE, #if defined(FEAT_MBYTE) && defined(FEAT_EVAL) (char_u *)&p_ccv, PV_NONE, @@ -770,14 +770,14 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"cindent", "cin", P_BOOL|P_VI_DEF|P_VIM, #ifdef FEAT_CINDENT (char_u *)&p_cin, PV_CIN, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"cinkeys", "cink", P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP, #ifdef FEAT_CINDENT (char_u *)&p_cink, PV_CINK, @@ -786,14 +786,14 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"cinoptions", "cino", P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP, #ifdef FEAT_CINDENT (char_u *)&p_cino, PV_CINO, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"cinwords", "cinw", P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP, #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT) (char_u *)&p_cinw, PV_CINW, @@ -803,7 +803,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"clipboard", "cb", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, #ifdef FEAT_CLIPBOARD (char_u *)&p_cb, PV_NONE, @@ -817,27 +817,27 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)"", (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"cmdheight", "ch", P_NUM|P_VI_DEF|P_RALL, (char_u *)&p_ch, PV_NONE, - {(char_u *)1L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)1L, (char_u *)0L} SCTX_INIT}, {"cmdwinheight", "cwh", P_NUM|P_VI_DEF, #ifdef FEAT_CMDWIN (char_u *)&p_cwh, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)7L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)7L, (char_u *)0L} SCTX_INIT}, {"colorcolumn", "cc", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP|P_RWIN, #ifdef FEAT_SYN_HL (char_u *)VAR_WIN, PV_CC, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"columns", "co", P_NUM|P_NODEFAULT|P_NO_MKRC|P_VI_DEF|P_RCLR, (char_u *)&Columns, PV_NONE, - {(char_u *)80L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)80L, (char_u *)0L} SCTX_INIT}, {"comments", "com", P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA |P_NODUP|P_CURSWANT, #ifdef FEAT_COMMENTS @@ -848,7 +848,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"commentstring", "cms", P_STRING|P_ALLOCED|P_VI_DEF|P_CURSWANT, #ifdef FEAT_FOLDING (char_u *)&p_cms, PV_CMS, @@ -857,12 +857,12 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, /* P_PRI_MKRC isn't needed here, optval_default() * always returns TRUE for 'compatible' */ {"compatible", "cp", P_BOOL|P_RALL, (char_u *)&p_cp, PV_NONE, - {(char_u *)TRUE, (char_u *)FALSE} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)FALSE} SCTX_INIT}, {"complete", "cpt", P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP, #ifdef FEAT_INS_EXPAND (char_u *)&p_cpt, PV_CPT, @@ -871,7 +871,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"concealcursor","cocu", P_STRING|P_ALLOCED|P_RWIN|P_VI_DEF, #ifdef FEAT_CONCEAL (char_u *)VAR_WIN, PV_COCU, @@ -880,7 +880,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"conceallevel","cole", P_NUM|P_RWIN|P_VI_DEF, #ifdef FEAT_CONCEAL (char_u *)VAR_WIN, PV_COLE, @@ -888,7 +888,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, #endif {(char_u *)0L, (char_u *)0L} - SCRIPTID_INIT}, + SCTX_INIT}, {"completefunc", "cfu", P_STRING|P_ALLOCED|P_VI_DEF|P_SECURE, #ifdef FEAT_COMPL_FUNC (char_u *)&p_cfu, PV_CFU, @@ -897,7 +897,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"completeopt", "cot", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, #ifdef FEAT_INS_EXPAND (char_u *)&p_cot, PV_NONE, @@ -906,24 +906,24 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"confirm", "cf", P_BOOL|P_VI_DEF, #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) (char_u *)&p_confirm, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"conskey", "consk",P_BOOL|P_VI_DEF, (char_u *)NULL, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"copyindent", "ci", P_BOOL|P_VI_DEF|P_VIM, (char_u *)&p_ci, PV_CI, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"cpoptions", "cpo", P_STRING|P_VIM|P_RALL|P_FLAGLIST, (char_u *)&p_cpo, PV_NONE, {(char_u *)CPO_VI, (char_u *)CPO_VIM} - SCRIPTID_INIT}, + SCTX_INIT}, {"cryptmethod", "cm", P_STRING|P_ALLOCED|P_VI_DEF, #ifdef FEAT_CRYPT (char_u *)&p_cm, PV_CM, @@ -932,14 +932,14 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"cscopepathcomp", "cspc", P_NUM|P_VI_DEF|P_VIM, #ifdef FEAT_CSCOPE (char_u *)&p_cspc, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"cscopeprg", "csprg", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, #ifdef FEAT_CSCOPE (char_u *)&p_csprg, PV_NONE, @@ -948,7 +948,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"cscopequickfix", "csqf", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, #if defined(FEAT_CSCOPE) && defined(FEAT_QUICKFIX) (char_u *)&p_csqf, PV_NONE, @@ -957,55 +957,55 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"cscoperelative", "csre", P_BOOL|P_VI_DEF|P_VIM, #ifdef FEAT_CSCOPE (char_u *)&p_csre, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"cscopetag", "cst", P_BOOL|P_VI_DEF|P_VIM, #ifdef FEAT_CSCOPE (char_u *)&p_cst, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"cscopetagorder", "csto", P_NUM|P_VI_DEF|P_VIM, #ifdef FEAT_CSCOPE (char_u *)&p_csto, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"cscopeverbose", "csverb", P_BOOL|P_VI_DEF|P_VIM, #ifdef FEAT_CSCOPE (char_u *)&p_csverbose, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"cursorbind", "crb", P_BOOL|P_VI_DEF, (char_u *)VAR_WIN, PV_CRBIND, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"cursorcolumn", "cuc", P_BOOL|P_VI_DEF|P_RWIN, #ifdef FEAT_SYN_HL (char_u *)VAR_WIN, PV_CUC, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"cursorline", "cul", P_BOOL|P_VI_DEF|P_RWINONLY, #ifdef FEAT_SYN_HL (char_u *)VAR_WIN, PV_CUL, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"debug", NULL, P_STRING|P_VI_DEF, (char_u *)&p_debug, PV_NONE, - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"define", "def", P_STRING|P_ALLOCED|P_VI_DEF|P_CURSWANT, #ifdef FEAT_FIND_ID (char_u *)&p_def, PV_DEF, @@ -1014,28 +1014,28 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"delcombine", "deco", P_BOOL|P_VI_DEF|P_VIM, #ifdef FEAT_MBYTE (char_u *)&p_deco, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"dictionary", "dict", P_STRING|P_EXPAND|P_VI_DEF|P_ONECOMMA|P_NODUP|P_NDNAME, #ifdef FEAT_INS_EXPAND (char_u *)&p_dict, PV_DICT, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"diff", NULL, P_BOOL|P_VI_DEF|P_RWIN|P_NOGLOB, #ifdef FEAT_DIFF (char_u *)VAR_WIN, PV_DIFF, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"diffexpr", "dex", P_STRING|P_VI_DEF|P_SECURE|P_CURSWANT, #if defined(FEAT_DIFF) && defined(FEAT_EVAL) (char_u *)&p_dex, PV_NONE, @@ -1044,7 +1044,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"diffopt", "dip", P_STRING|P_ALLOCED|P_VI_DEF|P_RWIN|P_ONECOMMA |P_NODUP, #ifdef FEAT_DIFF @@ -1054,28 +1054,28 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)"", (char_u *)NULL} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"digraph", "dg", P_BOOL|P_VI_DEF|P_VIM, #ifdef FEAT_DIGRAPHS (char_u *)&p_dg, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"directory", "dir", P_STRING|P_EXPAND|P_VI_DEF|P_ONECOMMA |P_NODUP|P_SECURE, (char_u *)&p_dir, PV_NONE, - {(char_u *)DFLT_DIR, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)DFLT_DIR, (char_u *)0L} SCTX_INIT}, {"display", "dy", P_STRING|P_VI_DEF|P_ONECOMMA|P_RALL|P_NODUP, (char_u *)&p_dy, PV_NONE, - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"eadirection", "ead", P_STRING|P_VI_DEF, (char_u *)&p_ead, PV_NONE, {(char_u *)"both", (char_u *)0L} - SCRIPTID_INIT}, + SCTX_INIT}, {"edcompatible","ed", P_BOOL|P_VI_DEF, (char_u *)&p_ed, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"emoji", "emo", P_BOOL|P_VI_DEF|P_RCLR, #if defined(FEAT_MBYTE) (char_u *)&p_emoji, PV_NONE, @@ -1084,7 +1084,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"encoding", "enc", P_STRING|P_VI_DEF|P_RCLR|P_NO_ML, #ifdef FEAT_MBYTE (char_u *)&p_enc, PV_NONE, @@ -1093,19 +1093,19 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"endofline", "eol", P_BOOL|P_NO_MKRC|P_VI_DEF|P_RSTAT, (char_u *)&p_eol, PV_EOL, - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"equalalways", "ea", P_BOOL|P_VI_DEF|P_RALL, (char_u *)&p_ea, PV_NONE, - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"equalprg", "ep", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, (char_u *)&p_ep, PV_EP, - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"errorbells", "eb", P_BOOL|P_VI_DEF, (char_u *)&p_eb, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"errorfile", "ef", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, #ifdef FEAT_QUICKFIX (char_u *)&p_ef, PV_NONE, @@ -1114,7 +1114,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"errorformat", "efm", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, #ifdef FEAT_QUICKFIX (char_u *)&p_efm, PV_EFM, @@ -1123,19 +1123,19 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"esckeys", "ek", P_BOOL|P_VIM, (char_u *)&p_ek, PV_NONE, - {(char_u *)FALSE, (char_u *)TRUE} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)TRUE} SCTX_INIT}, {"eventignore", "ei", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, (char_u *)&p_ei, PV_NONE, - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"expandtab", "et", P_BOOL|P_VI_DEF|P_VIM, (char_u *)&p_et, PV_ET, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"exrc", "ex", P_BOOL|P_VI_DEF|P_SECURE, (char_u *)&p_exrc, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"fileencoding","fenc", P_STRING|P_ALLOCED|P_VI_DEF|P_RSTAT|P_RBUF |P_NO_MKRC, #ifdef FEAT_MBYTE @@ -1145,7 +1145,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"fileencodings","fencs", P_STRING|P_VI_DEF|P_ONECOMMA, #ifdef FEAT_MBYTE (char_u *)&p_fencs, PV_NONE, @@ -1154,15 +1154,15 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"fileformat", "ff", P_STRING|P_ALLOCED|P_VI_DEF|P_RSTAT|P_NO_MKRC |P_CURSWANT, (char_u *)&p_ff, PV_FF, - {(char_u *)DFLT_FF, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)DFLT_FF, (char_u *)0L} SCTX_INIT}, {"fileformats", "ffs", P_STRING|P_VIM|P_ONECOMMA|P_NODUP, (char_u *)&p_ffs, PV_NONE, {(char_u *)DFLT_FFS_VI, (char_u *)DFLT_FFS_VIM} - SCRIPTID_INIT}, + SCTX_INIT}, {"fileignorecase", "fic", P_BOOL|P_VI_DEF, (char_u *)&p_fic, PV_NONE, { @@ -1171,28 +1171,28 @@ static struct vimoption options[] = #else (char_u *)FALSE, #endif - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"filetype", "ft", P_STRING|P_ALLOCED|P_VI_DEF|P_NOGLOB|P_NFNAME, (char_u *)&p_ft, PV_FT, {(char_u *)"", (char_u *)0L} - SCRIPTID_INIT}, + SCTX_INIT}, {"fillchars", "fcs", P_STRING|P_VI_DEF|P_RALL|P_ONECOMMA|P_NODUP, (char_u *)&p_fcs, PV_NONE, {(char_u *)"vert:|,fold:-", (char_u *)0L} - SCRIPTID_INIT}, + SCTX_INIT}, {"fixendofline", "fixeol", P_BOOL|P_VI_DEF|P_RSTAT, (char_u *)&p_fixeol, PV_FIXEOL, - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"fkmap", "fk", P_BOOL|P_VI_DEF, #ifdef FEAT_FKMAP (char_u *)&p_fkmap, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"flash", "fl", P_BOOL|P_VI_DEF, (char_u *)NULL, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"foldclose", "fcl", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP|P_RWIN, #ifdef FEAT_FOLDING (char_u *)&p_fcl, PV_NONE, @@ -1201,7 +1201,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"foldcolumn", "fdc", P_NUM|P_VI_DEF|P_RWIN, #ifdef FEAT_FOLDING (char_u *)VAR_WIN, PV_FDC, @@ -1210,7 +1210,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"foldenable", "fen", P_BOOL|P_VI_DEF|P_RWIN, #ifdef FEAT_FOLDING (char_u *)VAR_WIN, PV_FEN, @@ -1219,7 +1219,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"foldexpr", "fde", P_STRING|P_ALLOCED|P_VIM|P_VI_DEF|P_RWIN, #if defined(FEAT_FOLDING) && defined(FEAT_EVAL) (char_u *)VAR_WIN, PV_FDE, @@ -1228,7 +1228,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"foldignore", "fdi", P_STRING|P_ALLOCED|P_VIM|P_VI_DEF|P_RWIN, #ifdef FEAT_FOLDING (char_u *)VAR_WIN, PV_FDI, @@ -1237,7 +1237,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"foldlevel", "fdl", P_NUM|P_VI_DEF|P_RWIN, #ifdef FEAT_FOLDING (char_u *)VAR_WIN, PV_FDL, @@ -1246,7 +1246,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"foldlevelstart","fdls", P_NUM|P_VI_DEF|P_CURSWANT, #ifdef FEAT_FOLDING (char_u *)&p_fdls, PV_NONE, @@ -1255,7 +1255,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"foldmarker", "fmr", P_STRING|P_ALLOCED|P_VIM|P_VI_DEF| P_RWIN|P_ONECOMMA|P_NODUP, #ifdef FEAT_FOLDING @@ -1265,7 +1265,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"foldmethod", "fdm", P_STRING|P_ALLOCED|P_VIM|P_VI_DEF|P_RWIN, #ifdef FEAT_FOLDING (char_u *)VAR_WIN, PV_FDM, @@ -1274,7 +1274,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"foldminlines","fml", P_NUM|P_VI_DEF|P_RWIN, #ifdef FEAT_FOLDING (char_u *)VAR_WIN, PV_FML, @@ -1283,7 +1283,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"foldnestmax", "fdn", P_NUM|P_VI_DEF|P_RWIN, #ifdef FEAT_FOLDING (char_u *)VAR_WIN, PV_FDN, @@ -1292,7 +1292,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"foldopen", "fdo", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP|P_CURSWANT, #ifdef FEAT_FOLDING (char_u *)&p_fdo, PV_NONE, @@ -1302,7 +1302,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"foldtext", "fdt", P_STRING|P_ALLOCED|P_VIM|P_VI_DEF|P_RWIN, #if defined(FEAT_FOLDING) && defined(FEAT_EVAL) (char_u *)VAR_WIN, PV_FDT, @@ -1311,7 +1311,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"formatexpr", "fex", P_STRING|P_ALLOCED|P_VI_DEF|P_VIM, #ifdef FEAT_EVAL (char_u *)&p_fex, PV_FEX, @@ -1320,18 +1320,18 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"formatoptions","fo", P_STRING|P_ALLOCED|P_VIM|P_FLAGLIST, (char_u *)&p_fo, PV_FO, {(char_u *)DFLT_FO_VI, (char_u *)DFLT_FO_VIM} - SCRIPTID_INIT}, + SCTX_INIT}, {"formatlistpat","flp", P_STRING|P_ALLOCED|P_VI_DEF, (char_u *)&p_flp, PV_FLP, {(char_u *)"^\\s*\\d\\+[\\]:.)}\\t ]\\s*", - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"formatprg", "fp", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, (char_u *)&p_fp, PV_FP, - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"fsync", "fs", P_BOOL|P_SECURE|P_VI_DEF, #ifdef HAVE_FSYNC (char_u *)&p_fs, PV_NONE, @@ -1340,13 +1340,13 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)FALSE, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"gdefault", "gd", P_BOOL|P_VI_DEF|P_VIM, (char_u *)&p_gd, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"graphic", "gr", P_BOOL|P_VI_DEF, (char_u *)NULL, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"grepformat", "gfm", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, #ifdef FEAT_QUICKFIX (char_u *)&p_gefm, PV_NONE, @@ -1355,7 +1355,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"grepprg", "gp", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, #ifdef FEAT_QUICKFIX (char_u *)&p_gp, PV_GP, @@ -1381,7 +1381,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"guicursor", "gcr", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, #ifdef CURSOR_SHAPE (char_u *)&p_guicursor, PV_NONE, @@ -1396,7 +1396,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"guifont", "gfn", P_STRING|P_VI_DEF|P_RCLR|P_ONECOMMA|P_NODUP, #ifdef FEAT_GUI (char_u *)&p_guifont, PV_NONE, @@ -1405,7 +1405,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"guifontset", "gfs", P_STRING|P_VI_DEF|P_RCLR|P_ONECOMMA, #if defined(FEAT_GUI) && defined(FEAT_XFONTSET) (char_u *)&p_guifontset, PV_NONE, @@ -1414,7 +1414,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"guifontwide", "gfw", P_STRING|P_VI_DEF|P_RCLR|P_ONECOMMA|P_NODUP, #if defined(FEAT_GUI) && defined(FEAT_MBYTE) (char_u *)&p_guifontwide, PV_NONE, @@ -1423,14 +1423,14 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"guiheadroom", "ghr", P_NUM|P_VI_DEF, #if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_X11) (char_u *)&p_ghr, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)50L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)50L, (char_u *)0L} SCTX_INIT}, {"guioptions", "go", P_STRING|P_VI_DEF|P_RALL|P_FLAGLIST, #if defined(FEAT_GUI) (char_u *)&p_go, PV_NONE, @@ -1443,14 +1443,14 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"guipty", NULL, P_BOOL|P_VI_DEF, #if defined(FEAT_GUI) (char_u *)&p_guipty, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"guitablabel", "gtl", P_STRING|P_VI_DEF|P_RWIN, #if defined(FEAT_GUI_TABLINE) (char_u *)&p_gtl, PV_NONE, @@ -1459,7 +1459,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"guitabtooltip", "gtt", P_STRING|P_VI_DEF|P_RWIN, #if defined(FEAT_GUI_TABLINE) (char_u *)&p_gtt, PV_NONE, @@ -1468,17 +1468,17 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"hardtabs", "ht", P_NUM|P_VI_DEF, (char_u *)NULL, PV_NONE, - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"helpfile", "hf", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, (char_u *)&p_hf, PV_NONE, {(char_u *)DFLT_HELPFILE, (char_u *)0L} - SCRIPTID_INIT}, + SCTX_INIT}, {"helpheight", "hh", P_NUM|P_VI_DEF, (char_u *)&p_hh, PV_NONE, - {(char_u *)20L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)20L, (char_u *)0L} SCTX_INIT}, {"helplang", "hlg", P_STRING|P_VI_DEF|P_ONECOMMA, #ifdef FEAT_MULTI_LANG (char_u *)&p_hlg, PV_NONE, @@ -1487,51 +1487,51 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"hidden", "hid", P_BOOL|P_VI_DEF, (char_u *)&p_hid, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"highlight", "hl", P_STRING|P_VI_DEF|P_RCLR|P_ONECOMMA|P_NODUP, (char_u *)&p_hl, PV_NONE, {(char_u *)HIGHLIGHT_INIT, (char_u *)0L} - SCRIPTID_INIT}, + SCTX_INIT}, {"history", "hi", P_NUM|P_VIM, (char_u *)&p_hi, PV_NONE, - {(char_u *)0L, (char_u *)50L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)50L} SCTX_INIT}, {"hkmap", "hk", P_BOOL|P_VI_DEF|P_VIM, #ifdef FEAT_RIGHTLEFT (char_u *)&p_hkmap, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"hkmapp", "hkp", P_BOOL|P_VI_DEF|P_VIM, #ifdef FEAT_RIGHTLEFT (char_u *)&p_hkmapp, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"hlsearch", "hls", P_BOOL|P_VI_DEF|P_VIM|P_RALL, (char_u *)&p_hls, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"icon", NULL, P_BOOL|P_VI_DEF, #ifdef FEAT_TITLE (char_u *)&p_icon, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"iconstring", NULL, P_STRING|P_VI_DEF, #ifdef FEAT_TITLE (char_u *)&p_iconstring, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"ignorecase", "ic", P_BOOL|P_VI_DEF, (char_u *)&p_ic, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"imactivatefunc","imaf",P_STRING|P_VI_DEF|P_SECURE, #if defined(FEAT_EVAL) && defined(FEAT_MBYTE) (char_u *)&p_imaf, PV_NONE, @@ -1540,21 +1540,21 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} # endif - SCRIPTID_INIT}, + SCTX_INIT}, {"imactivatekey","imak",P_STRING|P_VI_DEF, #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) (char_u *)&p_imak, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"imcmdline", "imc", P_BOOL|P_VI_DEF, #ifdef FEAT_MBYTE (char_u *)&p_imcmdline, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"imdisable", "imd", P_BOOL|P_VI_DEF, #ifdef FEAT_MBYTE (char_u *)&p_imdisable, PV_NONE, @@ -1566,15 +1566,15 @@ static struct vimoption options[] = #else {(char_u *)FALSE, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"iminsert", "imi", P_NUM|P_VI_DEF, (char_u *)&p_iminsert, PV_IMI, {(char_u *)B_IMODE_NONE, (char_u *)0L} - SCRIPTID_INIT}, + SCTX_INIT}, {"imsearch", "ims", P_NUM|P_VI_DEF, (char_u *)&p_imsearch, PV_IMS, {(char_u *)B_IMODE_USE_INSERT, (char_u *)0L} - SCRIPTID_INIT}, + SCTX_INIT}, {"imstatusfunc","imsf",P_STRING|P_VI_DEF|P_SECURE, #if defined(FEAT_EVAL) && defined(FEAT_MBYTE) (char_u *)&p_imsf, PV_NONE, @@ -1583,7 +1583,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"imstyle", "imst", P_NUM|P_VI_DEF|P_SECURE, #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) (char_u *)&p_imst, PV_NONE, @@ -1592,7 +1592,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"include", "inc", P_STRING|P_ALLOCED|P_VI_DEF, #ifdef FEAT_FIND_ID (char_u *)&p_inc, PV_INC, @@ -1601,7 +1601,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"includeexpr", "inex", P_STRING|P_ALLOCED|P_VI_DEF, #if defined(FEAT_FIND_ID) && defined(FEAT_EVAL) (char_u *)&p_inex, PV_INEX, @@ -1610,10 +1610,10 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"incsearch", "is", P_BOOL|P_VI_DEF|P_VIM, (char_u *)&p_is, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"indentexpr", "inde", P_STRING|P_ALLOCED|P_VI_DEF|P_VIM, #if defined(FEAT_CINDENT) && defined(FEAT_EVAL) (char_u *)&p_inde, PV_INDE, @@ -1622,7 +1622,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"indentkeys", "indk", P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP, #if defined(FEAT_CINDENT) && defined(FEAT_EVAL) (char_u *)&p_indk, PV_INDK, @@ -1631,13 +1631,13 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"infercase", "inf", P_BOOL|P_VI_DEF, (char_u *)&p_inf, PV_INF, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"insertmode", "im", P_BOOL|P_VI_DEF|P_VIM, (char_u *)&p_im, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"isfname", "isf", P_STRING|P_VI_DEF|P_COMMA|P_NODUP, (char_u *)&p_isf, PV_NONE, { @@ -1660,7 +1660,7 @@ static struct vimoption options[] = # endif # endif #endif - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"isident", "isi", P_STRING|P_VI_DEF|P_COMMA|P_NODUP, (char_u *)&p_isi, PV_NONE, { @@ -1677,7 +1677,7 @@ static struct vimoption options[] = (char_u *)"@,48-57,_,192-255", # endif #endif - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"iskeyword", "isk", P_STRING|P_ALLOCED|P_VIM|P_COMMA|P_NODUP, (char_u *)&p_isk, PV_ISK, { @@ -1696,7 +1696,7 @@ static struct vimoption options[] = ISK_LATIN1 # endif #endif - } SCRIPTID_INIT}, + } SCTX_INIT}, {"isprint", "isp", P_STRING|P_VI_DEF|P_RALL|P_COMMA|P_NODUP, (char_u *)&p_isp, PV_NONE, { @@ -1710,10 +1710,10 @@ static struct vimoption options[] = ISP_LATIN1, # endif #endif - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"joinspaces", "js", P_BOOL|P_VI_DEF|P_VIM, (char_u *)&p_js, PV_NONE, - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"key", NULL, P_STRING|P_ALLOCED|P_VI_DEF|P_NO_MKRC, #ifdef FEAT_CRYPT (char_u *)&p_key, PV_KEY, @@ -1722,7 +1722,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"keymap", "kmp", P_STRING|P_ALLOCED|P_VI_DEF|P_RBUF|P_RSTAT|P_NFNAME|P_PRI_MKRC, #ifdef FEAT_KEYMAP (char_u *)&p_keymap, PV_KMAP, @@ -1731,10 +1731,10 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)"", (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"keymodel", "km", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, (char_u *)&p_km, PV_NONE, - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"keywordprg", "kp", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, (char_u *)&p_kp, PV_KP, { @@ -1751,7 +1751,7 @@ static struct vimoption options[] = # endif # endif #endif - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"langmap", "lmap", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP|P_SECURE, #ifdef FEAT_LANGMAP (char_u *)&p_langmap, PV_NONE, @@ -1760,41 +1760,41 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, #endif - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"langmenu", "lm", P_STRING|P_VI_DEF|P_NFNAME, #if defined(FEAT_MENU) && defined(FEAT_MULTI_LANG) (char_u *)&p_lm, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"langnoremap", "lnr", P_BOOL|P_VI_DEF, #ifdef FEAT_LANGMAP (char_u *)&p_lnr, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"langremap", "lrm", P_BOOL|P_VI_DEF, #ifdef FEAT_LANGMAP (char_u *)&p_lrm, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"laststatus", "ls", P_NUM|P_VI_DEF|P_RALL, (char_u *)&p_ls, PV_NONE, - {(char_u *)1L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)1L, (char_u *)0L} SCTX_INIT}, {"lazyredraw", "lz", P_BOOL|P_VI_DEF, (char_u *)&p_lz, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"linebreak", "lbr", P_BOOL|P_VI_DEF|P_RWIN, #ifdef FEAT_LINEBREAK (char_u *)VAR_WIN, PV_LBR, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"lines", NULL, P_NUM|P_NODEFAULT|P_NO_MKRC|P_VI_DEF|P_RCLR, (char_u *)&Rows, PV_NONE, { @@ -1803,7 +1803,7 @@ static struct vimoption options[] = #else (char_u *)24L, #endif - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"linespace", "lsp", P_NUM|P_VI_DEF|P_RCLR, #ifdef FEAT_GUI (char_u *)&p_linespace, PV_NONE, @@ -1815,14 +1815,14 @@ static struct vimoption options[] = #else {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"lisp", NULL, P_BOOL|P_VI_DEF, #ifdef FEAT_LISP (char_u *)&p_lisp, PV_LISP, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"lispwords", "lw", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, #ifdef FEAT_LISP (char_u *)&p_lispwords, PV_LW, @@ -1831,16 +1831,16 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)"", (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"list", NULL, P_BOOL|P_VI_DEF|P_RWIN, (char_u *)VAR_WIN, PV_LIST, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"listchars", "lcs", P_STRING|P_VI_DEF|P_RALL|P_ONECOMMA|P_NODUP, (char_u *)&p_lcs, PV_NONE, - {(char_u *)"eol:$", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"eol:$", (char_u *)0L} SCTX_INIT}, {"loadplugins", "lpl", P_BOOL|P_VI_DEF, (char_u *)&p_lpl, PV_NONE, - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"luadll", NULL, P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, #if defined(DYNAMIC_LUA) (char_u *)&p_luadll, PV_NONE, @@ -1849,7 +1849,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)"", (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"macatsui", NULL, P_BOOL|P_VI_DEF|P_RCLR, #ifdef FEAT_GUI_MAC (char_u *)&p_macatsui, PV_NONE, @@ -1858,10 +1858,10 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)"", (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"magic", NULL, P_BOOL|P_VI_DEF, (char_u *)&p_magic, PV_NONE, - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"makeef", "mef", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, #ifdef FEAT_QUICKFIX (char_u *)&p_mef, PV_NONE, @@ -1870,7 +1870,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"makeencoding","menc", P_STRING|P_VI_DEF, #ifdef FEAT_MBYTE (char_u *)&p_menc, PV_MENC, @@ -1879,7 +1879,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"makeprg", "mp", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, #ifdef FEAT_QUICKFIX (char_u *)&p_mp, PV_MP, @@ -1892,52 +1892,52 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"matchpairs", "mps", P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP, (char_u *)&p_mps, PV_MPS, {(char_u *)"(:),{:},[:]", (char_u *)0L} - SCRIPTID_INIT}, + SCTX_INIT}, {"matchtime", "mat", P_NUM|P_VI_DEF, (char_u *)&p_mat, PV_NONE, - {(char_u *)5L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)5L, (char_u *)0L} SCTX_INIT}, {"maxcombine", "mco", P_NUM|P_VI_DEF|P_CURSWANT, #ifdef FEAT_MBYTE (char_u *)&p_mco, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)2, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)2, (char_u *)0L} SCTX_INIT}, {"maxfuncdepth", "mfd", P_NUM|P_VI_DEF, #ifdef FEAT_EVAL (char_u *)&p_mfd, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)100L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)100L, (char_u *)0L} SCTX_INIT}, {"maxmapdepth", "mmd", P_NUM|P_VI_DEF, (char_u *)&p_mmd, PV_NONE, - {(char_u *)1000L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)1000L, (char_u *)0L} SCTX_INIT}, {"maxmem", "mm", P_NUM|P_VI_DEF, (char_u *)&p_mm, PV_NONE, {(char_u *)DFLT_MAXMEM, (char_u *)0L} - SCRIPTID_INIT}, + SCTX_INIT}, {"maxmempattern","mmp", P_NUM|P_VI_DEF, (char_u *)&p_mmp, PV_NONE, - {(char_u *)1000L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)1000L, (char_u *)0L} SCTX_INIT}, {"maxmemtot", "mmt", P_NUM|P_VI_DEF, (char_u *)&p_mmt, PV_NONE, {(char_u *)DFLT_MAXMEMTOT, (char_u *)0L} - SCRIPTID_INIT}, + SCTX_INIT}, {"menuitems", "mis", P_NUM|P_VI_DEF, #ifdef FEAT_MENU (char_u *)&p_mis, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)25L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)25L, (char_u *)0L} SCTX_INIT}, {"mesg", NULL, P_BOOL|P_VI_DEF, (char_u *)NULL, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"mkspellmem", "msm", P_STRING|P_VI_DEF|P_EXPAND|P_SECURE, #ifdef FEAT_SPELL (char_u *)&p_msm, PV_NONE, @@ -1946,22 +1946,22 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"modeline", "ml", P_BOOL|P_VIM, (char_u *)&p_ml, PV_ML, - {(char_u *)FALSE, (char_u *)TRUE} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)TRUE} SCTX_INIT}, {"modelines", "mls", P_NUM|P_VI_DEF, (char_u *)&p_mls, PV_NONE, - {(char_u *)5L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)5L, (char_u *)0L} SCTX_INIT}, {"modifiable", "ma", P_BOOL|P_VI_DEF|P_NOGLOB, (char_u *)&p_ma, PV_MA, - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"modified", "mod", P_BOOL|P_NO_MKRC|P_VI_DEF|P_RSTAT, (char_u *)&p_mod, PV_MOD, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"more", NULL, P_BOOL|P_VIM, (char_u *)&p_more, PV_NONE, - {(char_u *)FALSE, (char_u *)TRUE} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)TRUE} SCTX_INIT}, {"mouse", NULL, P_STRING|P_VI_DEF|P_FLAGLIST, (char_u *)&p_mouse, PV_NONE, { @@ -1970,21 +1970,21 @@ static struct vimoption options[] = #else (char_u *)"", #endif - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"mousefocus", "mousef", P_BOOL|P_VI_DEF, #ifdef FEAT_GUI (char_u *)&p_mousef, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"mousehide", "mh", P_BOOL|P_VI_DEF, #ifdef FEAT_GUI (char_u *)&p_mh, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"mousemodel", "mousem", P_STRING|P_VI_DEF, (char_u *)&p_mousem, PV_NONE, { @@ -1997,7 +1997,7 @@ static struct vimoption options[] = (char_u *)"extend", # endif #endif - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"mouseshape", "mouses", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, #ifdef FEAT_MOUSESHAPE (char_u *)&p_mouseshape, PV_NONE, @@ -2006,10 +2006,10 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"mousetime", "mouset", P_NUM|P_VI_DEF, (char_u *)&p_mouset, PV_NONE, - {(char_u *)500L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)500L, (char_u *)0L} SCTX_INIT}, {"mzschemedll", NULL, P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, #if defined(DYNAMIC_MZSCHEME) (char_u *)&p_mzschemedll, PV_NONE, @@ -2018,7 +2018,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)"", (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"mzschemegcdll", NULL, P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, #if defined(DYNAMIC_MZSCHEME) (char_u *)&p_mzschemegcdll, PV_NONE, @@ -2027,31 +2027,31 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)"", (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"mzquantum", "mzq", P_NUM, #ifdef FEAT_MZSCHEME (char_u *)&p_mzq, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)100L, (char_u *)100L} SCRIPTID_INIT}, + {(char_u *)100L, (char_u *)100L} SCTX_INIT}, {"novice", NULL, P_BOOL|P_VI_DEF, (char_u *)NULL, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"nrformats", "nf", P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP, (char_u *)&p_nf, PV_NF, {(char_u *)"bin,octal,hex", (char_u *)0L} - SCRIPTID_INIT}, + SCTX_INIT}, {"number", "nu", P_BOOL|P_VI_DEF|P_RWIN, (char_u *)VAR_WIN, PV_NU, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"numberwidth", "nuw", P_NUM|P_RWIN|P_VIM, #ifdef FEAT_LINEBREAK (char_u *)VAR_WIN, PV_NUW, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)8L, (char_u *)4L} SCRIPTID_INIT}, + {(char_u *)8L, (char_u *)4L} SCTX_INIT}, {"omnifunc", "ofu", P_STRING|P_ALLOCED|P_VI_DEF|P_SECURE, #ifdef FEAT_COMPL_FUNC (char_u *)&p_ofu, PV_OFU, @@ -2060,10 +2060,10 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"open", NULL, P_BOOL|P_VI_DEF, (char_u *)NULL, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"opendevice", "odev", P_BOOL|P_VI_DEF, #if defined(MSWIN) (char_u *)&p_odev, PV_NONE, @@ -2071,31 +2071,31 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, #endif {(char_u *)FALSE, (char_u *)FALSE} - SCRIPTID_INIT}, + SCTX_INIT}, {"operatorfunc", "opfunc", P_STRING|P_VI_DEF|P_SECURE, (char_u *)&p_opfunc, PV_NONE, - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"optimize", "opt", P_BOOL|P_VI_DEF, (char_u *)NULL, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"osfiletype", "oft", P_STRING|P_ALLOCED|P_VI_DEF, (char_u *)NULL, PV_NONE, - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"packpath", "pp", P_STRING|P_VI_DEF|P_EXPAND|P_ONECOMMA|P_NODUP |P_SECURE, (char_u *)&p_pp, PV_NONE, {(char_u *)DFLT_RUNTIMEPATH, (char_u *)0L} - SCRIPTID_INIT}, + SCTX_INIT}, {"paragraphs", "para", P_STRING|P_VI_DEF, (char_u *)&p_para, PV_NONE, {(char_u *)"IPLPPPQPP TPHPLIPpLpItpplpipbp", - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"paste", NULL, P_BOOL|P_VI_DEF|P_PRI_MKRC, (char_u *)&p_paste, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"pastetoggle", "pt", P_STRING|P_VI_DEF, (char_u *)&p_pt, PV_NONE, - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"patchexpr", "pex", P_STRING|P_VI_DEF|P_SECURE, #if defined(FEAT_DIFF) && defined(FEAT_EVAL) (char_u *)&p_pex, PV_NONE, @@ -2104,10 +2104,10 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"patchmode", "pm", P_STRING|P_VI_DEF|P_NFNAME, (char_u *)&p_pm, PV_NONE, - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"path", "pa", P_STRING|P_EXPAND|P_VI_DEF|P_COMMA|P_NODUP, (char_u *)&p_path, PV_PATH, { @@ -2116,7 +2116,7 @@ static struct vimoption options[] = #else (char_u *)".,/usr/include,,", #endif - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"perldll", NULL, P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, #if defined(DYNAMIC_PERL) (char_u *)&p_perldll, PV_NONE, @@ -2125,24 +2125,24 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"preserveindent", "pi", P_BOOL|P_VI_DEF|P_VIM, (char_u *)&p_pi, PV_PI, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"previewheight", "pvh", P_NUM|P_VI_DEF, #if defined(FEAT_QUICKFIX) (char_u *)&p_pvh, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)12L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)12L, (char_u *)0L} SCTX_INIT}, {"previewwindow", "pvw", P_BOOL|P_VI_DEF|P_RSTAT|P_NOGLOB, #if defined(FEAT_QUICKFIX) (char_u *)VAR_WIN, PV_PVW, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"printdevice", "pdev", P_STRING|P_VI_DEF|P_SECURE, #ifdef FEAT_PRINTER (char_u *)&p_pdev, PV_NONE, @@ -2151,7 +2151,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"printencoding", "penc", P_STRING|P_VI_DEF, #ifdef FEAT_POSTSCRIPT (char_u *)&p_penc, PV_NONE, @@ -2160,7 +2160,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"printexpr", "pexpr", P_STRING|P_VI_DEF|P_SECURE, #ifdef FEAT_POSTSCRIPT (char_u *)&p_pexpr, PV_NONE, @@ -2169,7 +2169,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"printfont", "pfn", P_STRING|P_VI_DEF, #ifdef FEAT_PRINTER (char_u *)&p_pfn, PV_NONE, @@ -2184,7 +2184,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"printheader", "pheader", P_STRING|P_VI_DEF|P_GETTEXT, #ifdef FEAT_PRINTER (char_u *)&p_header, PV_NONE, @@ -2195,7 +2195,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"printmbcharset", "pmbcs", P_STRING|P_VI_DEF, #if defined(FEAT_POSTSCRIPT) && defined(FEAT_MBYTE) (char_u *)&p_pmcs, PV_NONE, @@ -2204,7 +2204,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"printmbfont", "pmbfn", P_STRING|P_VI_DEF, #if defined(FEAT_POSTSCRIPT) && defined(FEAT_MBYTE) (char_u *)&p_pmfn, PV_NONE, @@ -2213,7 +2213,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"printoptions", "popt", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, #ifdef FEAT_PRINTER (char_u *)&p_popt, PV_NONE, @@ -2222,24 +2222,24 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"prompt", NULL, P_BOOL|P_VI_DEF, (char_u *)&p_prompt, PV_NONE, - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"pumheight", "ph", P_NUM|P_VI_DEF, #ifdef FEAT_INS_EXPAND (char_u *)&p_ph, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"pumwidth", "pw", P_NUM|P_VI_DEF, #ifdef FEAT_INS_EXPAND (char_u *)&p_pw, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)15L, (char_u *)15L} SCRIPTID_INIT}, + {(char_u *)15L, (char_u *)15L} SCTX_INIT}, {"pythonthreedll", NULL, P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, #if defined(DYNAMIC_PYTHON3) (char_u *)&p_py3dll, PV_NONE, @@ -2248,7 +2248,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"pythonthreehome", NULL, P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, #if defined(FEAT_PYTHON3) (char_u *)&p_py3home, PV_NONE, @@ -2257,7 +2257,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"pythondll", NULL, P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, #if defined(DYNAMIC_PYTHON) (char_u *)&p_pydll, PV_NONE, @@ -2266,7 +2266,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"pythonhome", NULL, P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, #if defined(FEAT_PYTHON) (char_u *)&p_pyhome, PV_NONE, @@ -2275,7 +2275,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"pyxversion", "pyx", P_NUM|P_VI_DEF|P_SECURE, #if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) (char_u *)&p_pyx, PV_NONE, @@ -2283,7 +2283,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, #endif {(char_u *)DEFAULT_PYTHON_VER, (char_u *)0L} - SCRIPTID_INIT}, + SCTX_INIT}, {"quoteescape", "qe", P_STRING|P_ALLOCED|P_VI_DEF, #ifdef FEAT_TEXTOBJ (char_u *)&p_qe, PV_QE, @@ -2292,29 +2292,29 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"readonly", "ro", P_BOOL|P_VI_DEF|P_RSTAT|P_NOGLOB, (char_u *)&p_ro, PV_RO, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"redraw", NULL, P_BOOL|P_VI_DEF, (char_u *)NULL, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"redrawtime", "rdt", P_NUM|P_VI_DEF, #ifdef FEAT_RELTIME (char_u *)&p_rdt, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)2000L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)2000L, (char_u *)0L} SCTX_INIT}, {"regexpengine", "re", P_NUM|P_VI_DEF, (char_u *)&p_re, PV_NONE, - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"relativenumber", "rnu", P_BOOL|P_VI_DEF|P_RWIN, (char_u *)VAR_WIN, PV_RNU, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"remap", NULL, P_BOOL|P_VI_DEF, (char_u *)&p_remap, PV_NONE, - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"renderoptions", "rop", P_STRING|P_ONECOMMA|P_RCLR|P_VI_DEF, #ifdef FEAT_RENDER_OPTIONS (char_u *)&p_rop, PV_NONE, @@ -2323,31 +2323,31 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"report", NULL, P_NUM|P_VI_DEF, (char_u *)&p_report, PV_NONE, - {(char_u *)2L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)2L, (char_u *)0L} SCTX_INIT}, {"restorescreen", "rs", P_BOOL|P_VI_DEF, #ifdef WIN3264 (char_u *)&p_rs, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"revins", "ri", P_BOOL|P_VI_DEF|P_VIM, #ifdef FEAT_RIGHTLEFT (char_u *)&p_ri, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"rightleft", "rl", P_BOOL|P_VI_DEF|P_RWIN, #ifdef FEAT_RIGHTLEFT (char_u *)VAR_WIN, PV_RL, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"rightleftcmd", "rlc", P_STRING|P_ALLOCED|P_VI_DEF|P_RWIN, #ifdef FEAT_RIGHTLEFT (char_u *)VAR_WIN, PV_RLC, @@ -2356,7 +2356,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"rubydll", NULL, P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, #if defined(DYNAMIC_RUBY) (char_u *)&p_rubydll, PV_NONE, @@ -2365,56 +2365,56 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"ruler", "ru", P_BOOL|P_VI_DEF|P_VIM|P_RSTAT, #ifdef FEAT_CMDL_INFO (char_u *)&p_ru, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"rulerformat", "ruf", P_STRING|P_VI_DEF|P_ALLOCED|P_RSTAT, #ifdef FEAT_STL_OPT (char_u *)&p_ruf, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"runtimepath", "rtp", P_STRING|P_VI_DEF|P_EXPAND|P_ONECOMMA|P_NODUP |P_SECURE, (char_u *)&p_rtp, PV_NONE, {(char_u *)DFLT_RUNTIMEPATH, (char_u *)0L} - SCRIPTID_INIT}, + SCTX_INIT}, {"scroll", "scr", P_NUM|P_NO_MKRC|P_VI_DEF, (char_u *)VAR_WIN, PV_SCROLL, - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"scrollbind", "scb", P_BOOL|P_VI_DEF, (char_u *)VAR_WIN, PV_SCBIND, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"scrolljump", "sj", P_NUM|P_VI_DEF|P_VIM, (char_u *)&p_sj, PV_NONE, - {(char_u *)1L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)1L, (char_u *)0L} SCTX_INIT}, {"scrolloff", "so", P_NUM|P_VI_DEF|P_VIM|P_RALL, (char_u *)&p_so, PV_NONE, - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"scrollopt", "sbo", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, (char_u *)&p_sbo, PV_NONE, {(char_u *)"ver,jump", (char_u *)0L} - SCRIPTID_INIT}, + SCTX_INIT}, {"sections", "sect", P_STRING|P_VI_DEF, (char_u *)&p_sections, PV_NONE, {(char_u *)"SHNHH HUnhsh", (char_u *)0L} - SCRIPTID_INIT}, + SCTX_INIT}, {"secure", NULL, P_BOOL|P_VI_DEF|P_SECURE, (char_u *)&p_secure, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"selection", "sel", P_STRING|P_VI_DEF, (char_u *)&p_sel, PV_NONE, {(char_u *)"inclusive", (char_u *)0L} - SCRIPTID_INIT}, + SCTX_INIT}, {"selectmode", "slm", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, (char_u *)&p_slm, PV_NONE, - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"sessionoptions", "ssop", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, #ifdef FEAT_SESSION (char_u *)&p_ssop, PV_NONE, @@ -2424,7 +2424,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"shell", "sh", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, (char_u *)&p_sh, PV_NONE, { @@ -2437,7 +2437,7 @@ static struct vimoption options[] = (char_u *)"sh", # endif #endif /* VMS */ - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"shellcmdflag","shcf", P_STRING|P_VI_DEF|P_SECURE, (char_u *)&p_shcf, PV_NONE, { @@ -2446,7 +2446,7 @@ static struct vimoption options[] = #else (char_u *)"-c", #endif - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"shellpipe", "sp", P_STRING|P_VI_DEF|P_SECURE, #ifdef FEAT_QUICKFIX (char_u *)&p_sp, PV_NONE, @@ -2461,30 +2461,30 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"shellquote", "shq", P_STRING|P_VI_DEF|P_SECURE, (char_u *)&p_shq, PV_NONE, - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"shellredir", "srr", P_STRING|P_VI_DEF|P_SECURE, (char_u *)&p_srr, PV_NONE, - {(char_u *)">", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)">", (char_u *)0L} SCTX_INIT}, {"shellslash", "ssl", P_BOOL|P_VI_DEF, #ifdef BACKSLASH_IN_FILENAME (char_u *)&p_ssl, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"shelltemp", "stmp", P_BOOL, (char_u *)&p_stmp, PV_NONE, - {(char_u *)FALSE, (char_u *)TRUE} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)TRUE} SCTX_INIT}, {"shelltype", "st", P_NUM|P_VI_DEF, #ifdef AMIGA (char_u *)&p_st, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"shellxquote", "sxq", P_STRING|P_VI_DEF|P_SECURE, (char_u *)&p_sxq, PV_NONE, { @@ -2493,7 +2493,7 @@ static struct vimoption options[] = #else (char_u *)"", #endif - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"shellxescape", "sxe", P_STRING|P_VI_DEF|P_SECURE, (char_u *)&p_sxe, PV_NONE, { @@ -2502,27 +2502,27 @@ static struct vimoption options[] = #else (char_u *)"", #endif - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"shiftround", "sr", P_BOOL|P_VI_DEF|P_VIM, (char_u *)&p_sr, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"shiftwidth", "sw", P_NUM|P_VI_DEF, (char_u *)&p_sw, PV_SW, - {(char_u *)8L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)8L, (char_u *)0L} SCTX_INIT}, {"shortmess", "shm", P_STRING|P_VIM|P_FLAGLIST, (char_u *)&p_shm, PV_NONE, {(char_u *)"", (char_u *)"filnxtToO"} - SCRIPTID_INIT}, + SCTX_INIT}, {"shortname", "sn", P_BOOL|P_VI_DEF, (char_u *)&p_sn, PV_SN, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"showbreak", "sbr", P_STRING|P_VI_DEF|P_RALL, #ifdef FEAT_LINEBREAK (char_u *)&p_sbr, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"showcmd", "sc", P_BOOL|P_VIM, #ifdef FEAT_CMDL_INFO (char_u *)&p_sc, PV_NONE, @@ -2535,25 +2535,25 @@ static struct vimoption options[] = #else (char_u *)TRUE #endif - } SCRIPTID_INIT}, + } SCTX_INIT}, {"showfulltag", "sft", P_BOOL|P_VI_DEF, (char_u *)&p_sft, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"showmatch", "sm", P_BOOL|P_VI_DEF, (char_u *)&p_sm, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"showmode", "smd", P_BOOL|P_VIM, (char_u *)&p_smd, PV_NONE, - {(char_u *)FALSE, (char_u *)TRUE} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)TRUE} SCTX_INIT}, {"showtabline", "stal", P_NUM|P_VI_DEF|P_RALL, (char_u *)&p_stal, PV_NONE, - {(char_u *)1L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)1L, (char_u *)0L} SCTX_INIT}, {"sidescroll", "ss", P_NUM|P_VI_DEF, (char_u *)&p_ss, PV_NONE, - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"sidescrolloff", "siso", P_NUM|P_VI_DEF|P_VIM|P_RBUF, (char_u *)&p_siso, PV_NONE, - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"signcolumn", "scl", P_STRING|P_ALLOCED|P_VI_DEF|P_RWIN, #ifdef FEAT_SIGNS (char_u *)VAR_WIN, PV_SCL, @@ -2562,36 +2562,36 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"slowopen", "slow", P_BOOL|P_VI_DEF, (char_u *)NULL, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"smartcase", "scs", P_BOOL|P_VI_DEF|P_VIM, (char_u *)&p_scs, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"smartindent", "si", P_BOOL|P_VI_DEF|P_VIM, #ifdef FEAT_SMARTINDENT (char_u *)&p_si, PV_SI, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"smarttab", "sta", P_BOOL|P_VI_DEF|P_VIM, (char_u *)&p_sta, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"softtabstop", "sts", P_NUM|P_VI_DEF|P_VIM, (char_u *)&p_sts, PV_STS, - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"sourceany", NULL, P_BOOL|P_VI_DEF, (char_u *)NULL, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"spell", NULL, P_BOOL|P_VI_DEF|P_RWIN, #ifdef FEAT_SPELL (char_u *)VAR_WIN, PV_SPELL, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"spellcapcheck", "spc", P_STRING|P_ALLOCED|P_VI_DEF|P_RBUF, #ifdef FEAT_SPELL (char_u *)&p_spc, PV_SPC, @@ -2600,7 +2600,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"spellfile", "spf", P_STRING|P_EXPAND|P_ALLOCED|P_VI_DEF|P_SECURE |P_ONECOMMA, #ifdef FEAT_SPELL @@ -2610,7 +2610,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"spelllang", "spl", P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA |P_RBUF|P_EXPAND, #ifdef FEAT_SPELL @@ -2620,7 +2620,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"spellsuggest", "sps", P_STRING|P_VI_DEF|P_EXPAND|P_SECURE|P_ONECOMMA, #ifdef FEAT_SPELL (char_u *)&p_sps, PV_NONE, @@ -2629,27 +2629,27 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"splitbelow", "sb", P_BOOL|P_VI_DEF, (char_u *)&p_sb, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"splitright", "spr", P_BOOL|P_VI_DEF, (char_u *)&p_spr, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"startofline", "sol", P_BOOL|P_VI_DEF|P_VIM, (char_u *)&p_sol, PV_NONE, - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"statusline" ,"stl", P_STRING|P_VI_DEF|P_ALLOCED|P_RSTAT, #ifdef FEAT_STL_OPT (char_u *)&p_stl, PV_STL, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"suffixes", "su", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, (char_u *)&p_su, PV_NONE, {(char_u *)".bak,~,.o,.h,.info,.swp,.obj", - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"suffixesadd", "sua", P_STRING|P_VI_DEF|P_ALLOCED|P_ONECOMMA|P_NODUP, #ifdef FEAT_SEARCHPATH (char_u *)&p_sua, PV_SUA, @@ -2658,16 +2658,16 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"swapfile", "swf", P_BOOL|P_VI_DEF|P_RSTAT, (char_u *)&p_swf, PV_SWF, - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"swapsync", "sws", P_STRING|P_VI_DEF, (char_u *)&p_sws, PV_NONE, - {(char_u *)"fsync", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"fsync", (char_u *)0L} SCTX_INIT}, {"switchbuf", "swb", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, (char_u *)&p_swb, PV_NONE, - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"synmaxcol", "smc", P_NUM|P_VI_DEF|P_RBUF, #ifdef FEAT_SYN_HL (char_u *)&p_smc, PV_SMC, @@ -2676,7 +2676,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"syntax", "syn", P_STRING|P_ALLOCED|P_VI_DEF|P_NOGLOB|P_NFNAME, #ifdef FEAT_SYN_HL (char_u *)&p_syn, PV_SYN, @@ -2685,20 +2685,20 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"tabline", "tal", P_STRING|P_VI_DEF|P_RALL, #ifdef FEAT_STL_OPT (char_u *)&p_tal, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"tabpagemax", "tpm", P_NUM|P_VI_DEF, (char_u *)&p_tpm, PV_NONE, - {(char_u *)10L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)10L, (char_u *)0L} SCTX_INIT}, {"tabstop", "ts", P_NUM|P_VI_DEF|P_RBUF, (char_u *)&p_ts, PV_TS, - {(char_u *)8L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)8L, (char_u *)0L} SCTX_INIT}, {"tagbsearch", "tbs", P_BOOL|P_VI_DEF, (char_u *)&p_tbs, PV_NONE, #ifdef VMS /* binary searching doesn't appear to work on VMS */ @@ -2706,16 +2706,16 @@ static struct vimoption options[] = #else {(char_u *)TRUE, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"tagcase", "tc", P_STRING|P_VIM, (char_u *)&p_tc, PV_TC, - {(char_u *)"followic", (char_u *)"followic"} SCRIPTID_INIT}, + {(char_u *)"followic", (char_u *)"followic"} SCTX_INIT}, {"taglength", "tl", P_NUM|P_VI_DEF, (char_u *)&p_tl, PV_NONE, - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"tagrelative", "tr", P_BOOL|P_VIM, (char_u *)&p_tr, PV_NONE, - {(char_u *)FALSE, (char_u *)TRUE} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)TRUE} SCTX_INIT}, {"tags", "tag", P_STRING|P_EXPAND|P_VI_DEF|P_ONECOMMA|P_NODUP, (char_u *)&p_tags, PV_TAGS, { @@ -2724,10 +2724,10 @@ static struct vimoption options[] = #else (char_u *)"./tags,tags", #endif - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"tagstack", "tgst", P_BOOL|P_VI_DEF, (char_u *)&p_tgst, PV_NONE, - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"tcldll", NULL, P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, #if defined(DYNAMIC_TCL) (char_u *)&p_tcldll, PV_NONE, @@ -2736,17 +2736,17 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"term", NULL, P_STRING|P_EXPAND|P_NODEFAULT|P_NO_MKRC|P_VI_DEF|P_RALL, (char_u *)&T_NAME, PV_NONE, - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"termbidi", "tbidi", P_BOOL|P_VI_DEF, #ifdef FEAT_ARABIC (char_u *)&p_tbidi, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"termencoding", "tenc", P_STRING|P_VI_DEF|P_RCLR, #ifdef FEAT_MBYTE (char_u *)&p_tenc, PV_NONE, @@ -2755,7 +2755,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"termguicolors", "tgc", P_BOOL|P_VI_DEF|P_VIM|P_RCLR, #ifdef FEAT_TERMGUICOLORS (char_u *)&p_tgc, PV_NONE, @@ -2764,7 +2764,7 @@ static struct vimoption options[] = (char_u*)NULL, PV_NONE, {(char_u *)FALSE, (char_u *)FALSE} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"termwinkey", "twk", P_STRING|P_ALLOCED|P_RWIN|P_VI_DEF, #ifdef FEAT_TERMINAL (char_u *)VAR_WIN, PV_TWK, @@ -2773,7 +2773,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"termwinscroll", "twsl", P_NUM|P_VI_DEF|P_VIM|P_RBUF, #ifdef FEAT_TERMINAL (char_u *)&p_twsl, PV_TWSL, @@ -2782,7 +2782,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"termwinsize", "tws", P_STRING|P_ALLOCED|P_RWIN|P_VI_DEF, #ifdef FEAT_TERMINAL (char_u *)VAR_WIN, PV_TWS, @@ -2791,14 +2791,14 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"terse", NULL, P_BOOL|P_VI_DEF, (char_u *)&p_terse, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"textauto", "ta", P_BOOL|P_VIM, (char_u *)&p_ta, PV_NONE, {(char_u *)DFLT_TEXTAUTO, (char_u *)TRUE} - SCRIPTID_INIT}, + SCTX_INIT}, {"textmode", "tx", P_BOOL|P_VI_DEF|P_NO_MKRC, (char_u *)&p_tx, PV_TX, { @@ -2807,40 +2807,40 @@ static struct vimoption options[] = #else (char_u *)FALSE, #endif - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"textwidth", "tw", P_NUM|P_VI_DEF|P_VIM|P_RBUF, (char_u *)&p_tw, PV_TW, - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"thesaurus", "tsr", P_STRING|P_EXPAND|P_VI_DEF|P_ONECOMMA|P_NODUP|P_NDNAME, #ifdef FEAT_INS_EXPAND (char_u *)&p_tsr, PV_TSR, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"tildeop", "top", P_BOOL|P_VI_DEF|P_VIM, (char_u *)&p_to, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"timeout", "to", P_BOOL|P_VI_DEF, (char_u *)&p_timeout, PV_NONE, - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"timeoutlen", "tm", P_NUM|P_VI_DEF, (char_u *)&p_tm, PV_NONE, - {(char_u *)1000L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)1000L, (char_u *)0L} SCTX_INIT}, {"title", NULL, P_BOOL|P_VI_DEF, #ifdef FEAT_TITLE (char_u *)&p_title, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"titlelen", NULL, P_NUM|P_VI_DEF, #ifdef FEAT_TITLE (char_u *)&p_titlelen, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)85L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)85L, (char_u *)0L} SCTX_INIT}, {"titleold", NULL, P_STRING|P_VI_DEF|P_GETTEXT|P_SECURE|P_NO_MKRC, #ifdef FEAT_TITLE (char_u *)&p_titleold, PV_NONE, @@ -2850,14 +2850,14 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"titlestring", NULL, P_STRING|P_VI_DEF, #ifdef FEAT_TITLE (char_u *)&p_titlestring, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"toolbar", "tb", P_STRING|P_ONECOMMA|P_VI_DEF|P_NODUP, #if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_W32) (char_u *)&p_toolbar, PV_NONE, @@ -2866,7 +2866,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"toolbariconsize", "tbis", P_STRING|P_VI_DEF, #if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK) (char_u *)&p_tbis, PV_NONE, @@ -2875,32 +2875,32 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"ttimeout", NULL, P_BOOL|P_VI_DEF|P_VIM, (char_u *)&p_ttimeout, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"ttimeoutlen", "ttm", P_NUM|P_VI_DEF, (char_u *)&p_ttm, PV_NONE, - {(char_u *)-1L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)-1L, (char_u *)0L} SCTX_INIT}, {"ttybuiltin", "tbi", P_BOOL|P_VI_DEF, (char_u *)&p_tbi, PV_NONE, - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"ttyfast", "tf", P_BOOL|P_NO_MKRC|P_VI_DEF, (char_u *)&p_tf, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"ttymouse", "ttym", P_STRING|P_NODEFAULT|P_NO_MKRC|P_VI_DEF, #if defined(FEAT_MOUSE) && (defined(UNIX) || defined(VMS)) (char_u *)&p_ttym, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"ttyscroll", "tsl", P_NUM|P_VI_DEF, (char_u *)&p_ttyscroll, PV_NONE, - {(char_u *)999L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)999L, (char_u *)0L} SCTX_INIT}, {"ttytype", "tty", P_STRING|P_EXPAND|P_NODEFAULT|P_NO_MKRC|P_VI_DEF|P_RALL, (char_u *)&T_NAME, PV_NONE, - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"undodir", "udir", P_STRING|P_EXPAND|P_ONECOMMA|P_NODUP|P_SECURE |P_VI_DEF, #ifdef FEAT_PERSISTENT_UNDO @@ -2910,14 +2910,14 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"undofile", "udf", P_BOOL|P_VI_DEF|P_VIM, #ifdef FEAT_PERSISTENT_UNDO (char_u *)&p_udf, PV_UDF, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"undolevels", "ul", P_NUM|P_VI_DEF, (char_u *)&p_ul, PV_UL, { @@ -2926,16 +2926,16 @@ static struct vimoption options[] = #else (char_u *)100L, #endif - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"undoreload", "ur", P_NUM|P_VI_DEF, (char_u *)&p_ur, PV_NONE, - { (char_u *)10000L, (char_u *)0L} SCRIPTID_INIT}, + { (char_u *)10000L, (char_u *)0L} SCTX_INIT}, {"updatecount", "uc", P_NUM|P_VI_DEF, (char_u *)&p_uc, PV_NONE, - {(char_u *)200L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)200L, (char_u *)0L} SCTX_INIT}, {"updatetime", "ut", P_NUM|P_VI_DEF, (char_u *)&p_ut, PV_NONE, - {(char_u *)4000L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)4000L, (char_u *)0L} SCTX_INIT}, {"varsofttabstop", "vsts", P_STRING|P_VI_DEF|P_VIM|P_COMMA, #ifdef FEAT_VARTABS (char_u *)&p_vsts, PV_VSTS, @@ -2944,7 +2944,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)"", (char_u *)NULL} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"vartabstop", "vts", P_STRING|P_VI_DEF|P_VIM|P_RBUF|P_COMMA, #ifdef FEAT_VARTABS (char_u *)&p_vts, PV_VTS, @@ -2953,13 +2953,13 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)"", (char_u *)NULL} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"verbose", "vbs", P_NUM|P_VI_DEF, (char_u *)&p_verbose, PV_NONE, - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"verbosefile", "vfile", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, (char_u *)&p_vfile, PV_NONE, - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"viewdir", "vdir", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, #ifdef FEAT_SESSION (char_u *)&p_vdir, PV_NONE, @@ -2968,7 +2968,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"viewoptions", "vop", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, #ifdef FEAT_SESSION (char_u *)&p_vop, PV_NONE, @@ -2978,7 +2978,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"viminfo", "vi", P_STRING|P_ONECOMMA|P_NODUP|P_SECURE, #ifdef FEAT_VIMINFO (char_u *)&p_viminfo, PV_NONE, @@ -2996,7 +2996,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"viminfofile", "vif", P_STRING|P_EXPAND|P_ONECOMMA|P_NODUP |P_SECURE|P_VI_DEF, #ifdef FEAT_VIMINFO @@ -3006,7 +3006,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"virtualedit", "ve", P_STRING|P_ONECOMMA|P_NODUP|P_VI_DEF |P_VIM|P_CURSWANT, #ifdef FEAT_VIRTUALEDIT @@ -3016,55 +3016,55 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"visualbell", "vb", P_BOOL|P_VI_DEF, (char_u *)&p_vb, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"w300", NULL, P_NUM|P_VI_DEF, (char_u *)NULL, PV_NONE, - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"w1200", NULL, P_NUM|P_VI_DEF, (char_u *)NULL, PV_NONE, - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"w9600", NULL, P_NUM|P_VI_DEF, (char_u *)NULL, PV_NONE, - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"warn", NULL, P_BOOL|P_VI_DEF, (char_u *)&p_warn, PV_NONE, - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"weirdinvert", "wiv", P_BOOL|P_VI_DEF|P_RCLR, (char_u *)&p_wiv, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"whichwrap", "ww", P_STRING|P_VIM|P_ONECOMMA|P_FLAGLIST, (char_u *)&p_ww, PV_NONE, - {(char_u *)"", (char_u *)"b,s"} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)"b,s"} SCTX_INIT}, {"wildchar", "wc", P_NUM|P_VIM, (char_u *)&p_wc, PV_NONE, {(char_u *)(long)Ctrl_E, (char_u *)(long)TAB} - SCRIPTID_INIT}, + SCTX_INIT}, {"wildcharm", "wcm", P_NUM|P_VI_DEF, (char_u *)&p_wcm, PV_NONE, - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"wildignore", "wig", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, #ifdef FEAT_WILDIGN (char_u *)&p_wig, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"wildignorecase", "wic", P_BOOL|P_VI_DEF, (char_u *)&p_wic, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"wildmenu", "wmnu", P_BOOL|P_VI_DEF, #ifdef FEAT_WILDMENU (char_u *)&p_wmnu, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"wildmode", "wim", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, (char_u *)&p_wim, PV_NONE, - {(char_u *)"full", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"full", (char_u *)0L} SCTX_INIT}, {"wildoptions", "wop", P_STRING|P_VI_DEF, #ifdef FEAT_CMDL_COMPL (char_u *)&p_wop, PV_NONE, @@ -3073,7 +3073,7 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"winaltkeys", "wak", P_STRING|P_VI_DEF, #ifdef FEAT_WAK (char_u *)&p_wak, PV_NONE, @@ -3082,25 +3082,25 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)NULL, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"window", "wi", P_NUM|P_VI_DEF, (char_u *)&p_window, PV_NONE, - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"winheight", "wh", P_NUM|P_VI_DEF, (char_u *)&p_wh, PV_NONE, - {(char_u *)1L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)1L, (char_u *)0L} SCTX_INIT}, {"winfixheight", "wfh", P_BOOL|P_VI_DEF|P_RSTAT, (char_u *)VAR_WIN, PV_WFH, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"winfixwidth", "wfw", P_BOOL|P_VI_DEF|P_RSTAT, (char_u *)VAR_WIN, PV_WFW, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"winminheight", "wmh", P_NUM|P_VI_DEF, (char_u *)&p_wmh, PV_NONE, - {(char_u *)1L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)1L, (char_u *)0L} SCTX_INIT}, {"winminwidth", "wmw", P_NUM|P_VI_DEF, (char_u *)&p_wmw, PV_NONE, - {(char_u *)1L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)1L, (char_u *)0L} SCTX_INIT}, {"winptydll", NULL, P_STRING|P_EXPAND|P_VI_DEF|P_SECURE, #if defined(WIN3264) && defined(FEAT_TERMINAL) (char_u *)&p_winptydll, PV_NONE, { @@ -3114,25 +3114,25 @@ static struct vimoption options[] = (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif - SCRIPTID_INIT}, + SCTX_INIT}, {"winwidth", "wiw", P_NUM|P_VI_DEF, (char_u *)&p_wiw, PV_NONE, - {(char_u *)20L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)20L, (char_u *)0L} SCTX_INIT}, {"wrap", NULL, P_BOOL|P_VI_DEF|P_RWIN, (char_u *)VAR_WIN, PV_WRAP, - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"wrapmargin", "wm", P_NUM|P_VI_DEF, (char_u *)&p_wm, PV_WM, - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"wrapscan", "ws", P_BOOL|P_VI_DEF, (char_u *)&p_ws, PV_NONE, - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"write", NULL, P_BOOL|P_VI_DEF, (char_u *)&p_write, PV_NONE, - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {"writeany", "wa", P_BOOL|P_VI_DEF, (char_u *)&p_wa, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {"writebackup", "wb", P_BOOL|P_VI_DEF|P_VIM, (char_u *)&p_wb, PV_NONE, { @@ -3141,15 +3141,15 @@ static struct vimoption options[] = #else (char_u *)FALSE, #endif - (char_u *)0L} SCRIPTID_INIT}, + (char_u *)0L} SCTX_INIT}, {"writedelay", "wd", P_NUM|P_VI_DEF, (char_u *)&p_wd, PV_NONE, - {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCTX_INIT}, /* terminal output codes */ #define p_term(sss, vvv) {sss, NULL, P_STRING|P_VI_DEF|P_RALL|P_SECURE, \ (char_u *)&vvv, PV_NONE, \ - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {(char_u *)"", (char_u *)0L} SCTX_INIT}, p_term("t_AB", T_CAB) p_term("t_AF", T_CAF) @@ -3233,7 +3233,7 @@ static struct vimoption options[] = /* terminal key codes are not in here */ /* end marker */ - {NULL, NULL, 0, NULL, PV_NONE, {NULL, NULL} SCRIPTID_INIT} + {NULL, NULL, 0, NULL, PV_NONE, {NULL, NULL} SCTX_INIT} }; #define PARAM_COUNT (sizeof(options) / sizeof(struct vimoption)) @@ -3314,7 +3314,7 @@ static char_u *did_set_spell_option(int is_spellfile); static char_u *compile_cap_prog(synblock_T *synblock); #endif #ifdef FEAT_EVAL -static void set_option_scriptID_idx(int opt_idx, int opt_flags, int id); +static void set_option_sctx_idx(int opt_idx, int opt_flags, sctx_T script_ctx); #endif static char_u *set_bool_option(int opt_idx, char_u *varp, int value, int opt_flags); static char_u *set_num_option(int opt_idx, char_u *varp, long value, char_u *errbuf, size_t errbuflen, int opt_flags); @@ -3854,7 +3854,7 @@ set_option_default( } #ifdef FEAT_EVAL - set_option_scriptID_idx(opt_idx, opt_flags, current_SID); + set_option_sctx_idx(opt_idx, opt_flags, current_sctx); #endif } @@ -4679,12 +4679,12 @@ do_set( { /* Mention where the option was last set. */ if (varp == options[opt_idx].var) - last_set_msg(options[opt_idx].scriptID); + last_set_msg(options[opt_idx].script_ctx); else if ((int)options[opt_idx].indir & PV_WIN) - last_set_msg(curwin->w_p_scriptID[ + last_set_msg(curwin->w_p_script_ctx[ (int)options[opt_idx].indir & PV_MASK]); else if ((int)options[opt_idx].indir & PV_BUF) - last_set_msg(curbuf->b_p_scriptID[ + last_set_msg(curbuf->b_p_script_ctx[ (int)options[opt_idx].indir & PV_MASK]); } #endif @@ -5889,8 +5889,9 @@ static void redraw_titles(void) * Set a string option to a new value (without checking the effect). * The string is copied into allocated memory. * if ("opt_idx" == -1) "name" is used, otherwise "opt_idx" is used. - * When "set_sid" is zero set the scriptID to current_SID. When "set_sid" is - * SID_NONE don't set the scriptID. Otherwise set the scriptID to "set_sid". + * When "set_sid" is zero set the scriptID to current_sctx.sc_sid. When + * "set_sid" is SID_NONE don't set the scriptID. Otherwise set the scriptID to + * "set_sid". */ void set_string_option_direct( @@ -5943,8 +5944,18 @@ set_string_option_direct( } # ifdef FEAT_EVAL if (set_sid != SID_NONE) - set_option_scriptID_idx(idx, opt_flags, - set_sid == 0 ? current_SID : set_sid); + { + sctx_T script_ctx; + + if (set_sid == 0) + script_ctx = current_sctx; + else + { + script_ctx.sc_sid = set_sid; + script_ctx.sc_lnum = 0; + } + set_option_sctx_idx(idx, opt_flags, script_ctx); + } # endif } } @@ -7656,7 +7667,7 @@ did_set_string_option( { #ifdef FEAT_EVAL /* Remember where the option was set. */ - set_option_scriptID_idx(opt_idx, opt_flags, current_SID); + set_option_sctx_idx(opt_idx, opt_flags, current_sctx); #endif /* * Free string options that are in allocated memory. @@ -8215,25 +8226,28 @@ compile_cap_prog(synblock_T *synblock) #if defined(FEAT_EVAL) || defined(PROTO) /* - * Set the scriptID for an option, taking care of setting the buffer- or + * Set the script_ctx for an option, taking care of setting the buffer- or * window-local value. */ static void -set_option_scriptID_idx(int opt_idx, int opt_flags, int id) +set_option_sctx_idx(int opt_idx, int opt_flags, sctx_T script_ctx) { int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0; int indir = (int)options[opt_idx].indir; + sctx_T new_script_ctx = script_ctx; + + new_script_ctx.sc_lnum += sourcing_lnum; /* Remember where the option was set. For local options need to do that * in the buffer or window structure. */ if (both || (opt_flags & OPT_GLOBAL) || (indir & (PV_BUF|PV_WIN)) == 0) - options[opt_idx].scriptID = id; + options[opt_idx].script_ctx = new_script_ctx; if (both || (opt_flags & OPT_LOCAL)) { if (indir & PV_BUF) - curbuf->b_p_scriptID[indir & PV_MASK] = id; + curbuf->b_p_script_ctx[indir & PV_MASK] = new_script_ctx; else if (indir & PV_WIN) - curwin->w_p_scriptID[indir & PV_MASK] = id; + curwin->w_p_script_ctx[indir & PV_MASK] = new_script_ctx; } } #endif @@ -8262,7 +8276,7 @@ set_bool_option( *(int *)varp = value; /* set the new value */ #ifdef FEAT_EVAL /* Remember where the option was set. */ - set_option_scriptID_idx(opt_idx, opt_flags, current_SID); + set_option_sctx_idx(opt_idx, opt_flags, current_sctx); #endif #ifdef FEAT_GUI @@ -8898,7 +8912,7 @@ set_num_option( *pp = value; #ifdef FEAT_EVAL /* Remember where the option was set. */ - set_option_scriptID_idx(opt_idx, opt_flags, current_SID); + set_option_sctx_idx(opt_idx, opt_flags, current_sctx); #endif #ifdef FEAT_GUI need_mouse_correct = TRUE; diff --git a/src/proto/eval.pro b/src/proto/eval.pro index 537b6490ad..37170a2f07 100644 --- a/src/proto/eval.pro +++ b/src/proto/eval.pro @@ -119,7 +119,7 @@ int script_autoload(char_u *name, int reload); int read_viminfo_varlist(vir_T *virp, int writing); void write_viminfo_varlist(FILE *fp); int store_session_globals(FILE *fd); -void last_set_msg(scid_T scriptID); +void last_set_msg(sctx_T script_ctx); void reset_v_option_vars(void); void prepare_assert_error(garray_T *gap); void assert_error(garray_T *gap); diff --git a/src/structs.h b/src/structs.h index ee56bd3e40..f978f61b79 100644 --- a/src/structs.h +++ b/src/structs.h @@ -74,6 +74,19 @@ typedef struct terminal_S term_T; typedef struct VimMenu vimmenu_T; #endif +/* + * SCript ConteXt (SCTX): identifies a script script line. + * When sourcing a script "sc_lnum" is zero, "sourcing_lnum" is the current + * line number. When executing a user function "sc_lnum" is the line where the + * function was defined, "sourcing_lnum" is the line number inside the + * function. When stored with a function, mapping, option, etc. "sc_lnum" is + * the line number in the script "sc_sid". + */ +typedef struct { + scid_T sc_sid; // script ID + linenr_T sc_lnum; // line number +} sctx_T; + /* * Reference to a buffer that stores the value of buf_free_count. * bufref_valid() only needs to check "buf" when the count differs. @@ -278,8 +291,8 @@ typedef struct #endif #ifdef FEAT_EVAL - int wo_scriptID[WV_COUNT]; /* SIDs for window-local options */ -# define w_p_scriptID w_onebuf_opt.wo_scriptID + sctx_T wo_script_ctx[WV_COUNT]; /* SCTXs for window-local options */ +# define w_p_script_ctx w_onebuf_opt.wo_script_ctx #endif } winopt_T; @@ -541,7 +554,7 @@ typedef struct expand int xp_pattern_len; /* bytes in xp_pattern before cursor */ #if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL) char_u *xp_arg; /* completion function */ - int xp_scriptID; /* SID for completion function */ + sctx_T xp_script_ctx; /* SCTX for completion function */ #endif int xp_backslash; /* one of the XP_BS_ values */ #ifndef BACKSLASH_IN_FILENAME @@ -1071,7 +1084,7 @@ struct mapblock char m_nowait; /* used */ #ifdef FEAT_EVAL char m_expr; /* used, m_str is an expression */ - scid_T m_script_ID; /* ID of script where map was defined */ + sctx_T m_script_ctx; /* SCTX where map was defined */ #endif }; @@ -1361,7 +1374,7 @@ typedef struct int uf_tml_idx; /* index of line being timed; -1 if none */ int uf_tml_execed; /* line being timed was executed */ #endif - scid_T uf_script_ID; /* ID of script where function was defined, + sctx_T uf_script_ctx; /* SCTX where function was defined, used for s: variables */ int uf_refcount; /* reference count, see func_name_refcount() */ funccall_T *uf_scoped; /* l: local variables for closure */ @@ -2123,7 +2136,7 @@ struct file_buffer int b_p_initialized; /* set when options initialized */ #ifdef FEAT_EVAL - int b_p_scriptID[BV_COUNT]; /* SIDs for buffer-local options */ + sctx_T b_p_script_ctx[BV_COUNT]; /* SCTXs for buffer-local options */ #endif int b_p_ai; /* 'autoindent' */ diff --git a/src/syntax.c b/src/syntax.c index 3c46a0e0e6..8fb4e20e50 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -58,7 +58,7 @@ struct hl_group int sg_link; /* link to this highlight group ID */ int sg_set; /* combination of SG_* flags */ #ifdef FEAT_EVAL - scid_T sg_scriptID; /* script in which the group was last set */ + sctx_T sg_script_ctx; /* script in which the group was last set */ #endif }; @@ -7507,7 +7507,8 @@ do_highlight( } else if (HL_TABLE()[from_id - 1].sg_link != to_id #ifdef FEAT_EVAL - || HL_TABLE()[from_id - 1].sg_scriptID != current_SID + || HL_TABLE()[from_id - 1].sg_script_ctx.sc_sid + != current_sctx.sc_sid #endif || HL_TABLE()[from_id - 1].sg_cleared) { @@ -7515,7 +7516,8 @@ do_highlight( HL_TABLE()[from_id - 1].sg_set |= SG_LINK; HL_TABLE()[from_id - 1].sg_link = to_id; #ifdef FEAT_EVAL - HL_TABLE()[from_id - 1].sg_scriptID = current_SID; + HL_TABLE()[from_id - 1].sg_script_ctx = current_sctx; + HL_TABLE()[from_id - 1].sg_script_ctx.sc_lnum += sourcing_lnum; #endif HL_TABLE()[from_id - 1].sg_cleared = FALSE; redraw_all_later(SOME_VALID); @@ -8277,7 +8279,8 @@ do_highlight( else set_hl_attr(idx); #ifdef FEAT_EVAL - HL_TABLE()[idx].sg_scriptID = current_SID; + HL_TABLE()[idx].sg_script_ctx = current_sctx; + HL_TABLE()[idx].sg_script_ctx.sc_lnum += sourcing_lnum; #endif } @@ -8404,7 +8407,10 @@ highlight_clear(int idx) /* Clear the script ID only when there is no link, since that is not * cleared. */ if (HL_TABLE()[idx].sg_link == 0) - HL_TABLE()[idx].sg_scriptID = 0; + { + HL_TABLE()[idx].sg_script_ctx.sc_sid = 0; + HL_TABLE()[idx].sg_script_ctx.sc_lnum = 0; + } #endif } @@ -9272,7 +9278,7 @@ highlight_list_one(int id) highlight_list_arg(id, didh, LIST_STRING, 0, (char_u *)"cleared", ""); #ifdef FEAT_EVAL if (p_verbose > 0) - last_set_msg(sgp->sg_scriptID); + last_set_msg(sgp->sg_script_ctx); #endif } diff --git a/src/term.c b/src/term.c index cede4b8949..b2e2b0381c 100644 --- a/src/term.c +++ b/src/term.c @@ -6128,7 +6128,7 @@ replace_termcodes( */ if (STRNICMP(src, "", 5) == 0) { - if (current_SID <= 0) + if (current_sctx.sc_sid <= 0) EMSG(_(e_usingsid)); else { @@ -6136,7 +6136,8 @@ replace_termcodes( result[dlen++] = K_SPECIAL; result[dlen++] = (int)KS_EXTRA; result[dlen++] = (int)KE_SNR; - sprintf((char *)result + dlen, "%ld", (long)current_SID); + sprintf((char *)result + dlen, "%ld", + (long)current_sctx.sc_sid); dlen += (int)STRLEN(result + dlen); result[dlen++] = '_'; continue; diff --git a/src/testdir/test_alot.vim b/src/testdir/test_alot.vim index 16a3f7f8ac..7d300a4dac 100644 --- a/src/testdir/test_alot.vim +++ b/src/testdir/test_alot.vim @@ -14,6 +14,7 @@ source test_ex_z.vim source test_execute_func.vim source test_expand.vim source test_expand_dllpath.vim +source test_expand_func.vim source test_expr.vim source test_feedkeys.vim source test_file_perm.vim diff --git a/src/testdir/test_expand_func.vim b/src/testdir/test_expand_func.vim new file mode 100644 index 0000000000..fb29c3eb7a --- /dev/null +++ b/src/testdir/test_expand_func.vim @@ -0,0 +1,66 @@ +" Tests for expand() + +let s:sfile = expand('') +let s:slnum = str2nr(expand('')) +let s:sflnum = str2nr(expand('')) + +func s:expand_sfile() + return expand('') +endfunc + +func s:expand_slnum() + return str2nr(expand('')) +endfunc + +func s:expand_sflnum() + return str2nr(expand('')) +endfunc + +func Test_expand_sfile() + call assert_match('test_expand_func\.vim$', s:sfile) + call assert_match('^function .*\.\.Test_expand_sfile$', expand('')) + + " Call in script-local function + call assert_match('^function .*\.\.Test_expand_sfile\[5\]\.\.\d\+_expand_sfile$', s:expand_sfile()) + + " Call in command + command Sfile echo expand('') + call assert_match('^function .*\.\.Test_expand_sfile$', trim(execute('Sfile'))) + delcommand Sfile +endfunc + +func Test_expand_slnum() + call assert_equal(4, s:slnum) + call assert_equal(2, str2nr(expand(''))) + + " Line-continuation + call assert_equal( + \ 5, + \ str2nr(expand(''))) + + " Call in script-local function + call assert_equal(1, s:expand_slnum()) + + " Call in command + command Slnum echo expand('') + call assert_equal(14, str2nr(trim(execute('Slnum')))) + delcommand Slnum +endfunc + +func Test_expand_sflnum() + call assert_equal(5, s:sflnum) + call assert_equal(52, str2nr(expand(''))) + + " Line-continuation + call assert_equal( + \ 55, + \ str2nr(expand(''))) + + " Call in script-local function + call assert_equal(16, s:expand_sflnum()) + + " Call in command + command Flnum echo expand('') + call assert_equal(64, str2nr(trim(execute('Flnum')))) + delcommand Flnum +endfunc diff --git a/src/testdir/test_maparg.vim b/src/testdir/test_maparg.vim index 0fb878b04a..c9e440edc0 100644 --- a/src/testdir/test_maparg.vim +++ b/src/testdir/test_maparg.vim @@ -13,19 +13,24 @@ function Test_maparg() set cpo-=< set encoding=utf8 " Test maparg() with a string result + let sid = s:SID() + let lnum = expand('') map foo isfoo vnoremap