From 22e421549d54147d003f6444de007cb1d73f1d27 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 3 Apr 2016 14:02:02 +0200 Subject: [PATCH 1/8] patch 7.4.1700 Problem: Equivalence classes are not properly tested. Solution: Add tests for multi-byte and latin1. Fix an error. (Owen Leibman) --- src/regexp.c | 4 ++-- src/testdir/Make_all.mak | 2 ++ src/testdir/test_alot_latin.vim | 7 +++++++ src/testdir/test_alot_utf8.vim | 7 +++++++ src/testdir/test_regexp_latin.vim | 32 ++++++++++++++++++++++++++++ src/testdir/test_regexp_utf8.vim | 35 +++++++++++++++++++++++++++++++ src/version.c | 2 ++ 7 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 src/testdir/test_alot_latin.vim create mode 100644 src/testdir/test_alot_utf8.vim create mode 100644 src/testdir/test_regexp_latin.vim create mode 100644 src/testdir/test_regexp_utf8.vim diff --git a/src/regexp.c b/src/regexp.c index cd7dc3f228..b20e9c5ec5 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -791,7 +791,7 @@ char *EQUIVAL_CLASS_C[16] = { "E\x71\x72\x73\x74", "I\x75\x76\x77\x78", "N\x69", - "O\xEB\xEC\xED\xEE\xEF", + "O\xEB\xEC\xED\xEE\xEF\x80", "U\xFB\xFC\xFD\xFE", "Y\xBA", "a\x42\x43\x44\x45\x46\x47", @@ -799,7 +799,7 @@ char *EQUIVAL_CLASS_C[16] = { "e\x51\x52\x53\x54", "i\x55\x56\x57\x58", "n\x49", - "o\xCB\xCC\xCD\xCE\xCF", + "o\xCB\xCC\xCD\xCE\xCF\x70", "u\xDB\xDC\xDD\xDE", "y\x8D\xDF", }; diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index 98cf98562f..2540abfbf0 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -183,6 +183,8 @@ NEW_TESTS = test_arglist.res \ test_viml.res \ test_visual.res \ test_window_id.res \ + test_alot_latin.res \ + test_alot_utf8.res \ test_alot.res diff --git a/src/testdir/test_alot_latin.vim b/src/testdir/test_alot_latin.vim new file mode 100644 index 0000000000..23a404cac1 --- /dev/null +++ b/src/testdir/test_alot_latin.vim @@ -0,0 +1,7 @@ +" A series of tests that can run in one Vim invocation. +" This makes testing go faster, since Vim doesn't need to restart. + +" These tests use latin1 'encoding'. Setting 'encoding' is in the individual +" files, so that they can be run by themselves. + +source test_regexp_latin.vim diff --git a/src/testdir/test_alot_utf8.vim b/src/testdir/test_alot_utf8.vim new file mode 100644 index 0000000000..20d919c323 --- /dev/null +++ b/src/testdir/test_alot_utf8.vim @@ -0,0 +1,7 @@ +" A series of tests that can run in one Vim invocation. +" This makes testing go faster, since Vim doesn't need to restart. + +" These tests use utf8 'encoding'. Setting 'encoding' is in the individual +" files, so that they can be run by themselves. + +source test_regexp_utf8.vim diff --git a/src/testdir/test_regexp_latin.vim b/src/testdir/test_regexp_latin.vim new file mode 100644 index 0000000000..8528412806 --- /dev/null +++ b/src/testdir/test_regexp_latin.vim @@ -0,0 +1,32 @@ +" Tests for regexp in latin1 encoding +set encoding=latin1 +scriptencoding latin1 + +func s:equivalence_test() + let str = "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z" + let groups = split(str) + for group1 in groups + for c in split(group1, '\zs') + " next statement confirms that equivalence class matches every + " character in group + call assert_match('^[[=' . c . '=]]*$', group1) + for group2 in groups + if group2 != group1 + " next statement converts that equivalence class doesn't match + " a character in any other group + call assert_equal(-1, match(group2, '[[=' . c . '=]]')) + endif + endfor + endfor + endfor +endfunc + +func Test_equivalence_re1() + set re=1 + call s:equivalence_test() +endfunc + +func Test_equivalence_re2() + set re=2 + call s:equivalence_test() +endfunc diff --git a/src/testdir/test_regexp_utf8.vim b/src/testdir/test_regexp_utf8.vim new file mode 100644 index 0000000000..f5d7ec946d --- /dev/null +++ b/src/testdir/test_regexp_utf8.vim @@ -0,0 +1,35 @@ +" Tests for regexp in utf8 encoding +if !has('multi_byte') + finish +endif +set encoding=utf-8 +scriptencoding utf-8 + +func s:equivalence_test() + let str = "AÀÁÂÃÄÅĀĂĄǍǞǠẢ BḂḆ CÇĆĈĊČ DĎĐḊḎḐ EÈÉÊËĒĔĖĘĚẺẼ FḞ GĜĞĠĢǤǦǴḠ HĤĦḢḦḨ IÌÍÎÏĨĪĬĮİǏỈ JĴ KĶǨḰḴ LĹĻĽĿŁḺ MḾṀ NÑŃŅŇṄṈ OÒÓÔÕÖØŌŎŐƠǑǪǬỎ PṔṖ Q RŔŖŘṘṞ SŚŜŞŠṠ TŢŤŦṪṮ UÙÚÛÜŨŪŬŮŰŲƯǓỦ VṼ WŴẀẂẄẆ XẊẌ YÝŶŸẎỲỶỸ ZŹŻŽƵẐẔ aàáâãäåāăąǎǟǡả bḃḇ cçćĉċč dďđḋḏḑ eèéêëēĕėęěẻẽ fḟ gĝğġģǥǧǵḡ hĥħḣḧḩẖ iìíîïĩīĭįǐỉ jĵǰ kķǩḱḵ lĺļľŀłḻ mḿṁ nñńņňʼnṅṉ oòóôõöøōŏőơǒǫǭỏ pṕṗ q rŕŗřṙṟ sśŝşšṡ tţťŧṫṯẗ uùúûüũūŭůűųưǔủ vṽ wŵẁẃẅẇẘ xẋẍ yýÿŷẏẙỳỷỹ zźżžƶẑẕ" + let groups = split(str) + for group1 in groups + for c in split(group1, '\zs') + " next statement confirms that equivalence class matches every + " character in group + call assert_match('^[[=' . c . '=]]*$', group1) + for group2 in groups + if group2 != group1 + " next statement converts that equivalence class doesn't match + " character in any other group + call assert_equal(-1, match(group2, '[[=' . c . '=]]')) + endif + endfor + endfor + endfor +endfunc + +func Test_equivalence_re1() + set re=1 + call s:equivalence_test() +endfunc + +func Test_equivalence_re2() + set re=2 + call s:equivalence_test() +endfunc diff --git a/src/version.c b/src/version.c index 23d4acb833..5ecf9e0841 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1700, /**/ 1699, /**/ From f9f22dbe4f90673ecce601a9dee4bb750ce3cd8f Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 3 Apr 2016 14:09:59 +0200 Subject: [PATCH 2/8] patch 7.4.1701 Problem: Equivalence classes still tested in old style tests. Solution: Remove the duplicate. --- src/testdir/test44.in | 6 ------ src/testdir/test44.ok | 2 -- src/testdir/test99.in | 4 ---- src/testdir/test99.ok | 2 -- src/version.c | 2 ++ 5 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/testdir/test44.in b/src/testdir/test44.in index 44c3ea7114..7126392377 100644 --- a/src/testdir/test44.in +++ b/src/testdir/test44.in @@ -34,10 +34,6 @@ x:" f /[\U1234abcd\u1234\uabcd] x:" g /\%d21879b -x:" h -/ [[=A=]]* [[=B=]]* [[=C=]]* [[=D=]]* [[=E=]]* [[=F=]]* [[=G=]]* [[=H=]]* [[=I=]]* [[=J=]]* [[=K=]]* [[=L=]]* [[=M=]]* [[=N=]]* [[=O=]]* [[=P=]]* [[=Q=]]* [[=R=]]* [[=S=]]* [[=T=]]* [[=U=]]* [[=V=]]* [[=W=]]* [[=X=]]* [[=Y=]]* [[=Z=]]*/e -x:" i -/ [[=a=]]* [[=b=]]* [[=c=]]* [[=d=]]* [[=e=]]* [[=f=]]* [[=g=]]* [[=h=]]* [[=i=]]* [[=j=]]* [[=k=]]* [[=l=]]* [[=m=]]* [[=n=]]* [[=o=]]* [[=p=]]* [[=q=]]* [[=r=]]* [[=s=]]* [[=t=]]* [[=u=]]* [[=v=]]* [[=w=]]* [[=x=]]* [[=y=]]* [[=z=]]*/e x:" j Test backwards search from a multi-byte char /x x?. @@ -80,8 +76,6 @@ d 天使x e y f z g a啷bb -h AÀÁÂÃÄÅĀĂĄǍǞǠẢ BḂḆ CÇĆĈĊČ DĎĐḊḎḐ EÈÉÊËĒĔĖĘĚẺẼ FḞ GĜĞĠĢǤǦǴḠ HĤĦḢḦḨ IÌÍÎÏĨĪĬĮİǏỈ JĴ KĶǨḰḴ LĹĻĽĿŁḺ MḾṀ NÑŃŅŇṄṈ OÒÓÔÕÖØŌŎŐƠǑǪǬỎ PṔṖ Q RŔŖŘṘṞ SŚŜŞŠṠ TŢŤŦṪṮ UÙÚÛÜŨŪŬŮŰŲƯǓỦ VṼ WŴẀẂẄẆ XẊẌ YÝŶŸẎỲỶỸ ZŹŻŽƵẐẔ -i aàáâãäåāăąǎǟǡả bḃḇ cçćĉċč dďđḋḏḑ eèéêëēĕėęěẻẽ fḟ gĝğġģǥǧǵḡ hĥħḣḧḩẖ iìíîïĩīĭįǐỉ jĵǰ kķǩḱḵ lĺļľŀłḻ mḿṁ nñńņňʼnṅṉ oòóôõöøōŏőơǒǫǭỏ pṕṗ q rŕŗřṙṟ sśŝşšṡ tţťŧṫṯẗ uùúûüũūŭůűųưǔủ vṽ wŵẁẃẅẇẘ xẋẍ yýÿŷẏẙỳỷỹ zźżžƶẑẕ j 0123❤x k combinations l äö üᾱ̆́ diff --git a/src/testdir/test44.ok b/src/testdir/test44.ok index 42b46e9122..45774d7cbb 100644 --- a/src/testdir/test44.ok +++ b/src/testdir/test44.ok @@ -14,8 +14,6 @@ d 使x e y f z g abb -h AÀÁÂÃÄÅĀĂĄǍǞǠẢ BḂḆ CÇĆĈĊČ DĎĐḊḎḐ EÈÉÊËĒĔĖĘĚẺẼ FḞ GĜĞĠĢǤǦǴḠ HĤĦḢḦḨ IÌÍÎÏĨĪĬĮİǏỈ JĴ KĶǨḰḴ LĹĻĽĿŁḺ MḾṀ NÑŃŅŇṄṈ OÒÓÔÕÖØŌŎŐƠǑǪǬỎ PṔṖ Q RŔŖŘṘṞ SŚŜŞŠṠ TŢŤŦṪṮ UÙÚÛÜŨŪŬŮŰŲƯǓỦ VṼ WŴẀẂẄẆ XẊẌ YÝŶŸẎỲỶỸ ZŹŻŽƵẐ -i aàáâãäåāăąǎǟǡả bḃḇ cçćĉċč dďđḋḏḑ eèéêëēĕėęěẻẽ fḟ gĝğġģǥǧǵḡ hĥħḣḧḩẖ iìíîïĩīĭįǐỉ jĵǰ kķǩḱḵ lĺļľŀłḻ mḿṁ nñńņňʼnṅṉ oòóôõöøōŏőơǒǫǭỏ pṕṗ q rŕŗřṙṟ sśŝşšṡ tţťŧṫṯẗ uùúûüũūŭůűųưǔủ vṽ wŵẁẃẅẇẘ xẋẍ yýÿŷẏẙỳỷỹ zźżžƶẑ j 012❤ k œ̄ṣ́m̥̄ᾱ̆́ l ä ö ü ᾱ̆́ diff --git a/src/testdir/test99.in b/src/testdir/test99.in index d992d4d6fa..3961244c79 100644 --- a/src/testdir/test99.in +++ b/src/testdir/test99.in @@ -29,8 +29,6 @@ x/[\u4f7f\u5929]\+ x/\%U12345678 x/[\U1234abcd\u1234\uabcd] x/\%d21879b -x/ [[=A=]]* [[=B=]]* [[=C=]]* [[=D=]]* [[=E=]]* [[=F=]]* [[=G=]]* [[=H=]]* [[=I=]]* [[=J=]]* [[=K=]]* [[=L=]]* [[=M=]]* [[=N=]]* [[=O=]]* [[=P=]]* [[=Q=]]* [[=R=]]* [[=S=]]* [[=T=]]* [[=U=]]* [[=V=]]* [[=W=]]* [[=X=]]* [[=Y=]]* [[=Z=]]*/e -x/ [[=a=]]* [[=b=]]* [[=c=]]* [[=d=]]* [[=e=]]* [[=f=]]* [[=g=]]* [[=h=]]* [[=i=]]* [[=j=]]* [[=k=]]* [[=l=]]* [[=m=]]* [[=n=]]* [[=o=]]* [[=p=]]* [[=q=]]* [[=r=]]* [[=s=]]* [[=t=]]* [[=u=]]* [[=v=]]* [[=w=]]* [[=x=]]* [[=y=]]* [[=z=]]*/e x:" Test backwards search from a multi-byte char /x x?. @@ -66,8 +64,6 @@ d 天使x e y f z g a啷bb -h AÀÁÂÃÄÅĀĂĄǍǞǠẢ BḂḆ CÇĆĈĊČ DĎĐḊḎḐ EÈÉÊËĒĔĖĘĚẺẼ FḞ GĜĞĠĢǤǦǴḠ HĤĦḢḦḨ IÌÍÎÏĨĪĬĮİǏỈ JĴ KĶǨḰḴ LĹĻĽĿŁḺ MḾṀ NÑŃŅŇṄṈ OÒÓÔÕÖØŌŎŐƠǑǪǬỎ PṔṖ Q RŔŖŘṘṞ SŚŜŞŠṠ TŢŤŦṪṮ UÙÚÛÜŨŪŬŮŰŲƯǓỦ VṼ WŴẀẂẄẆ XẊẌ YÝŶŸẎỲỶỸ ZŹŻŽƵẐẔ -i aàáâãäåāăąǎǟǡả bḃḇ cçćĉċč dďđḋḏḑ eèéêëēĕėęěẻẽ fḟ gĝğġģǥǧǵḡ hĥħḣḧḩẖ iìíîïĩīĭįǐỉ jĵǰ kķǩḱḵ lĺļľŀłḻ mḿṁ nñńņňʼnṅṉ oòóôõöøōŏőơǒǫǭỏ pṕṗ q rŕŗřṙṟ sśŝşšṡ tţťŧṫṯẗ uùúûüũūŭůűųưǔủ vṽ wŵẁẃẅẇẘ xẋẍ yýÿŷẏẙỳỷỹ zźżžƶẑẕ j 0123❤x k combinations l äö üᾱ̆́ diff --git a/src/testdir/test99.ok b/src/testdir/test99.ok index 330f4550c7..dea3665cf6 100644 --- a/src/testdir/test99.ok +++ b/src/testdir/test99.ok @@ -14,8 +14,6 @@ d 使x e y f z g abb -h AÀÁÂÃÄÅĀĂĄǍǞǠẢ BḂḆ CÇĆĈĊČ DĎĐḊḎḐ EÈÉÊËĒĔĖĘĚẺẼ FḞ GĜĞĠĢǤǦǴḠ HĤĦḢḦḨ IÌÍÎÏĨĪĬĮİǏỈ JĴ KĶǨḰḴ LĹĻĽĿŁḺ MḾṀ NÑŃŅŇṄṈ OÒÓÔÕÖØŌŎŐƠǑǪǬỎ PṔṖ Q RŔŖŘṘṞ SŚŜŞŠṠ TŢŤŦṪṮ UÙÚÛÜŨŪŬŮŰŲƯǓỦ VṼ WŴẀẂẄẆ XẊẌ YÝŶŸẎỲỶỸ ZŹŻŽƵẐ -i aàáâãäåāăąǎǟǡả bḃḇ cçćĉċč dďđḋḏḑ eèéêëēĕėęěẻẽ fḟ gĝğġģǥǧǵḡ hĥħḣḧḩẖ iìíîïĩīĭįǐỉ jĵǰ kķǩḱḵ lĺļľŀłḻ mḿṁ nñńņňʼnṅṉ oòóôõöøōŏőơǒǫǭỏ pṕṗ q rŕŗřṙṟ sśŝşšṡ tţťŧṫṯẗ uùúûüũūŭůűųưǔủ vṽ wŵẁẃẅẇẘ xẋẍ yýÿŷẏẙỳỷỹ zźżžƶẑ j 012❤ k œ̄ṣ́m̥̄ᾱ̆́ l ä ö ü ᾱ̆́ diff --git a/src/version.c b/src/version.c index 5ecf9e0841..9d6deb6710 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1701, /**/ 1700, /**/ From 4afc7c5d4a73340831077a02bfe1f74935e7f4a1 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 3 Apr 2016 14:56:52 +0200 Subject: [PATCH 3/8] patch 7.4.1702 Problem: Using freed memory when parsing 'printoptions' fails. Solution: Save the old options and restore them in case of an error. (Dominique) --- src/hardcopy.c | 35 ++++++++++++++++++++++++++++++----- src/testdir/test_hardcopy.vim | 4 ++++ src/version.c | 2 ++ 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/hardcopy.c b/src/hardcopy.c index 74fee2e214..f65a6dd40a 100644 --- a/src/hardcopy.c +++ b/src/hardcopy.c @@ -189,6 +189,8 @@ parse_list_options( option_table_T *table, int table_size) { + option_table_T *old_opts; + char_u *ret = NULL; char_u *stringp; char_u *colonp; char_u *commap; @@ -196,8 +198,16 @@ parse_list_options( int idx = 0; /* init for GCC */ int len; + /* Save the old values, so that they can be restored in case of an error. */ + old_opts = (option_table_T *)alloc(sizeof(option_table_T) * table_size); + if (old_opts == NULL) + return NULL; + for (idx = 0; idx < table_size; ++idx) + { + old_opts[idx] = table[idx]; table[idx].present = FALSE; + } /* * Repeat for all comma separated parts. @@ -207,7 +217,10 @@ parse_list_options( { colonp = vim_strchr(stringp, ':'); if (colonp == NULL) - return (char_u *)N_("E550: Missing colon"); + { + ret = (char_u *)N_("E550: Missing colon"); + break; + } commap = vim_strchr(stringp, ','); if (commap == NULL) commap = option_str + STRLEN(option_str); @@ -219,15 +232,20 @@ parse_list_options( break; if (idx == table_size) - return (char_u *)N_("E551: Illegal component"); - + { + ret = (char_u *)N_("E551: Illegal component"); + break; + } p = colonp + 1; table[idx].present = TRUE; if (table[idx].hasnum) { if (!VIM_ISDIGIT(*p)) - return (char_u *)N_("E552: digit expected"); + { + ret = (char_u *)N_("E552: digit expected"); + break; + } table[idx].number = getdigits(&p); /*advances p*/ } @@ -240,7 +258,14 @@ parse_list_options( ++stringp; } - return NULL; + if (ret != NULL) + { + /* Restore old options in case of error */ + for (idx = 0; idx < table_size; ++idx) + table[idx] = old_opts[idx]; + } + vim_free(old_opts); + return ret; } diff --git a/src/testdir/test_hardcopy.vim b/src/testdir/test_hardcopy.vim index 4629d17dd2..ea9790d134 100644 --- a/src/testdir/test_hardcopy.vim +++ b/src/testdir/test_hardcopy.vim @@ -23,6 +23,10 @@ func Test_printoptions_parsing() set printoptions=formfeed:y set printoptions= set printoptions& + + call assert_fails('set printoptions=paper', 'E550:') + call assert_fails('set printoptions=shredder:on', 'E551:') + call assert_fails('set printoptions=left:no', 'E552:') endfunc func Test_printmbfont_parsing() diff --git a/src/version.c b/src/version.c index 9d6deb6710..569446610c 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1702, /**/ 1701, /**/ From b50e5f56861deb867478997397f7c784a7043233 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 3 Apr 2016 20:57:20 +0200 Subject: [PATCH 4/8] patch 7.4.1703 Problem: Can't assert for not equal and not matching. Solution: Add assert_notmatch() and assert_notequal(). --- runtime/doc/eval.txt | 14 +++++- src/eval.c | 92 ++++++++++++++++++++++++++++--------- src/testdir/test_assert.vim | 25 ++++++++++ src/version.c | 2 + 4 files changed, 110 insertions(+), 23 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index f1425bae36..b0b847953e 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1801,11 +1801,13 @@ arglistid( [{winnr} [, {tabnr}]]) Number argument list id argv( {nr}) String {nr} entry of the argument list argv() List the argument list -assert_equal( {exp}, {act} [, {msg}]) none assert {exp} equals {act} +assert_equal( {exp}, {act} [, {msg}]) none assert {exp} is equal to {act} assert_exception( {error} [, {msg}]) none assert {error} is in v:exception assert_fails( {cmd} [, {error}]) none assert {cmd} fails assert_false( {actual} [, {msg}]) none assert {actual} is false assert_match( {pat}, {text} [, {msg}]) none assert {pat} matches {text} +assert_notequal( {exp}, {act} [, {msg}]) none assert {exp} is not equal {act} +assert_notmatch( {pat}, {text} [, {msg}]) none assert {pat} not matches {text} assert_true( {actual} [, {msg}]) none assert {actual} is true asin( {expr}) Float arc sine of {expr} atan( {expr}) Float arc tangent of {expr} @@ -2338,6 +2340,16 @@ assert_match({pattern}, {actual} [, {msg}]) < Will result in a string to be added to |v:errors|: test.vim line 12: Pattern '^f.*o$' does not match 'foobar' ~ + *assert_notequal()* +assert_notequal({expected}, {actual} [, {msg}]) + The opposite of `assert_equal()`: add an error message to + |v:errors| when {expected} and {actual} are equal. + + *assert_notmatch()* +assert_notmatch({pattern}, {actual} [, {msg}]) + The opposite of `assert_match()`: add an error message to + |v:errors| when {pattern} matches {actual}. + assert_true({actual} [, {msg}]) *assert_true()* When {actual} is not true an error message is added to |v:errors|, like with |assert_equal()|. diff --git a/src/eval.c b/src/eval.c index e1d69d00de..ab006b113c 100644 --- a/src/eval.c +++ b/src/eval.c @@ -476,6 +476,8 @@ static void f_assert_exception(typval_T *argvars, typval_T *rettv); static void f_assert_fails(typval_T *argvars, typval_T *rettv); static void f_assert_false(typval_T *argvars, typval_T *rettv); static void f_assert_match(typval_T *argvars, typval_T *rettv); +static void f_assert_notequal(typval_T *argvars, typval_T *rettv); +static void f_assert_notmatch(typval_T *argvars, typval_T *rettv); static void f_assert_true(typval_T *argvars, typval_T *rettv); #ifdef FEAT_FLOAT static void f_asin(typval_T *argvars, typval_T *rettv); @@ -8182,6 +8184,8 @@ static struct fst {"assert_fails", 1, 2, f_assert_fails}, {"assert_false", 1, 2, f_assert_false}, {"assert_match", 2, 3, f_assert_match}, + {"assert_notequal", 2, 3, f_assert_notequal}, + {"assert_notmatch", 2, 3, f_assert_notmatch}, {"assert_true", 1, 2, f_assert_true}, #ifdef FEAT_FLOAT {"atan", 1, 1, f_atan}, @@ -9323,8 +9327,17 @@ f_argv(typval_T *argvars, typval_T *rettv) alist_name(&ARGLIST[idx]), -1); } +typedef enum +{ + ASSERT_EQUAL, + ASSERT_NOTEQUAL, + ASSERT_MATCH, + ASSERT_NOTMATCH, + ASSERT_OTHER, +} assert_type_T; + static void prepare_assert_error(garray_T*gap); -static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_str, typval_T *exp_tv, typval_T *got_tv, int is_match); +static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_str, typval_T *exp_tv, typval_T *got_tv, assert_type_T is_match); static void assert_error(garray_T *gap); static void assert_bool(typval_T *argvars, int isTrue); @@ -9400,7 +9413,7 @@ fill_assert_error( char_u *exp_str, typval_T *exp_tv, typval_T *got_tv, - int is_match) + assert_type_T atype) { char_u numbuf[NUMBUFLEN]; char_u *tofree; @@ -9412,7 +9425,7 @@ fill_assert_error( } else { - if (is_match) + if (atype == ASSERT_MATCH || atype == ASSERT_NOTMATCH) ga_concat(gap, (char_u *)"Pattern "); else ga_concat(gap, (char_u *)"Expected "); @@ -9423,8 +9436,12 @@ fill_assert_error( } else ga_concat_esc(gap, exp_str); - if (is_match) + if (atype == ASSERT_MATCH) ga_concat(gap, (char_u *)" does not match "); + else if (atype == ASSERT_NOTMATCH) + ga_concat(gap, (char_u *)" does match "); + else if (atype == ASSERT_NOTEQUAL) + ga_concat(gap, (char_u *)" differs from "); else ga_concat(gap, (char_u *)" but got "); ga_concat_esc(gap, tv2string(got_tv, &tofree, numbuf, 0)); @@ -9446,22 +9463,38 @@ assert_error(garray_T *gap) list_append_string(vimvars[VV_ERRORS].vv_list, gap->ga_data, gap->ga_len); } + static void +assert_equal_common(typval_T *argvars, assert_type_T atype) +{ + garray_T ga; + + if (tv_equal(&argvars[0], &argvars[1], FALSE, FALSE) + != (atype == ASSERT_EQUAL)) + { + prepare_assert_error(&ga); + fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1], + atype); + assert_error(&ga); + ga_clear(&ga); + } +} + /* * "assert_equal(expected, actual[, msg])" function */ static void f_assert_equal(typval_T *argvars, typval_T *rettv UNUSED) { - garray_T ga; + assert_equal_common(argvars, ASSERT_EQUAL); +} - if (!tv_equal(&argvars[0], &argvars[1], FALSE, FALSE)) - { - prepare_assert_error(&ga); - fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1], - FALSE); - assert_error(&ga); - ga_clear(&ga); - } +/* + * "assert_notequal(expected, actual[, msg])" function + */ + static void +f_assert_notequal(typval_T *argvars, typval_T *rettv UNUSED) +{ + assert_equal_common(argvars, ASSERT_NOTEQUAL); } /* @@ -9486,7 +9519,7 @@ f_assert_exception(typval_T *argvars, typval_T *rettv UNUSED) { prepare_assert_error(&ga); fill_assert_error(&ga, &argvars[1], NULL, &argvars[0], - &vimvars[VV_EXCEPTION].vv_tv, FALSE); + &vimvars[VV_EXCEPTION].vv_tv, ASSERT_OTHER); assert_error(&ga); ga_clear(&ga); } @@ -9523,7 +9556,7 @@ f_assert_fails(typval_T *argvars, typval_T *rettv UNUSED) { prepare_assert_error(&ga); fill_assert_error(&ga, &argvars[2], NULL, &argvars[1], - &vimvars[VV_ERRMSG].vv_tv, FALSE); + &vimvars[VV_ERRMSG].vv_tv, ASSERT_OTHER); assert_error(&ga); ga_clear(&ga); } @@ -9555,7 +9588,7 @@ assert_bool(typval_T *argvars, int isTrue) prepare_assert_error(&ga); fill_assert_error(&ga, &argvars[1], (char_u *)(isTrue ? "True" : "False"), - NULL, &argvars[0], FALSE); + NULL, &argvars[0], ASSERT_OTHER); assert_error(&ga); ga_clear(&ga); } @@ -9570,11 +9603,8 @@ f_assert_false(typval_T *argvars, typval_T *rettv UNUSED) assert_bool(argvars, FALSE); } -/* - * "assert_match(pattern, actual[, msg])" function - */ static void -f_assert_match(typval_T *argvars, typval_T *rettv UNUSED) +assert_match_common(typval_T *argvars, assert_type_T atype) { garray_T ga; char_u buf1[NUMBUFLEN]; @@ -9584,16 +9614,34 @@ f_assert_match(typval_T *argvars, typval_T *rettv UNUSED) if (pat == NULL || text == NULL) EMSG(_(e_invarg)); - else if (!pattern_match(pat, text, FALSE)) + else if (pattern_match(pat, text, FALSE) != (atype == ASSERT_MATCH)) { prepare_assert_error(&ga); fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1], - TRUE); + atype); assert_error(&ga); ga_clear(&ga); } } +/* + * "assert_match(pattern, actual[, msg])" function + */ + static void +f_assert_match(typval_T *argvars, typval_T *rettv UNUSED) +{ + assert_match_common(argvars, ASSERT_MATCH); +} + +/* + * "assert_notmatch(pattern, actual[, msg])" function + */ + static void +f_assert_notmatch(typval_T *argvars, typval_T *rettv UNUSED) +{ + assert_match_common(argvars, ASSERT_NOTMATCH); +} + /* * "assert_true(actual[, msg])" function */ diff --git a/src/testdir/test_assert.vim b/src/testdir/test_assert.vim index bc025b4c43..d7fb6385f9 100644 --- a/src/testdir/test_assert.vim +++ b/src/testdir/test_assert.vim @@ -18,6 +18,22 @@ func Test_assert_equal() call assert_equal(4, n) let l = [1, 2, 3] call assert_equal([1, 2, 3], l) + + let s = 'foo' + call assert_equal('bar', s) + call assert_match("Expected 'bar' but got 'foo'", v:errors[0]) + call remove(v:errors, 0) +endfunc + +func Test_assert_notequal() + let n = 4 + call assert_notequal('foo', n) + let s = 'foo' + call assert_notequal([1, 2, 3], s) + + call assert_notequal('foo', s) + call assert_match("Expected 'foo' differs from 'foo'", v:errors[0]) + call remove(v:errors, 0) endfunc func Test_assert_exception() @@ -74,6 +90,15 @@ func Test_match() call remove(v:errors, 0) endfunc +func Test_notmatch() + call assert_notmatch('foo', 'bar') + call assert_notmatch('^foobar$', 'foobars') + + call assert_notmatch('foo', 'foobar') + call assert_match("Pattern 'foo' does match 'foobar'", v:errors[0]) + call remove(v:errors, 0) +endfunc + func Test_assert_fail_fails() call assert_fails('xxx', {}) call assert_match("Expected {} but got 'E731:", v:errors[0]) diff --git a/src/version.c b/src/version.c index 569446610c..ea6d1c37e2 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1703, /**/ 1702, /**/ From 3dda7db4e1f7c4a8110a1f83001ec36b46693d27 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 3 Apr 2016 21:22:58 +0200 Subject: [PATCH 5/8] patch 7.4.1704 Problem: Using freed memory with "wincmd p". (Dominique Pelle) Solution: Also clear "prevwin" in other tab pages. --- src/version.c | 2 ++ src/window.c | 13 ++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/version.c b/src/version.c index ea6d1c37e2..58377a49ef 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1704, /**/ 1703, /**/ diff --git a/src/window.c b/src/window.c index c7905aec57..bbd0a527c0 100644 --- a/src/window.c +++ b/src/window.c @@ -340,7 +340,7 @@ newwindow: /* cursor to last accessed (previous) window */ case 'p': case Ctrl_P: - if (prevwin == NULL) + if (!win_valid(prevwin)) beep_flush(); else win_goto(prevwin); @@ -4577,8 +4577,15 @@ win_free( unref_var_dict(wp->w_vars); #endif - if (prevwin == wp) - prevwin = NULL; + { + tabpage_T *ttp; + + if (prevwin == wp) + prevwin = NULL; + for (ttp = first_tabpage; ttp != NULL; ttp = ttp->tp_next) + if (ttp->tp_prevwin == wp) + ttp->tp_prevwin = NULL; + } win_free_lsize(wp); for (i = 0; i < wp->w_tagstacklen; ++i) From 7c1c6dbb6817640fd3956a0d5417da23fde336d8 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 3 Apr 2016 22:08:05 +0200 Subject: [PATCH 6/8] patch 7.4.1705 Problem: The 'guifont' option does not allow for a quality setting. Solution: Add the "q" item, supported on MS-Windows. (Yasuhiro Matsumoto) --- runtime/doc/options.txt | 10 +++++-- src/gui_w32.c | 8 ++++++ src/os_mswin.c | 62 +++++++++++++++++++++++++++++++++++++++++ src/proto/os_mswin.pro | 1 + src/version.c | 2 ++ 5 files changed, 80 insertions(+), 3 deletions(-) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index f71c4ad2dc..6ddf07673a 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 7.4. Last change: 2016 Mar 24 +*options.txt* For Vim version 7.4. Last change: 2016 Apr 03 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1070,7 +1070,7 @@ A jump table for the options with a short description can be found at |Q_op|. Note that environment variables are not expanded. If you want to use $HOME you must expand it explicitly, e.g.: > - :let backupskip = escape(expand('$HOME'), '\') . '/tmp/*' + :let &backupskip = escape(expand('$HOME'), '\') . '/tmp/*' < Note that the default also makes sure that "crontab -e" works (when a backup would be made by renaming the original file crontab won't see @@ -1245,7 +1245,7 @@ A jump table for the options with a short description can be found at |Q_op|. break if 'linebreak' is on. Only works for ASCII and also for 8-bit characters when 'encoding' is an 8-bit encoding. - *'breakindent'* *'bri'* *'nobreakindent'* *'nobri'* + *'breakindent'* *'bri'* *'nobreakindent'* *'nobri'* 'breakindent' 'bri' boolean (default off) local to window {not in Vi} @@ -3634,6 +3634,10 @@ A jump table for the options with a short description can be found at |Q_op|. HANGEUL, HEBREW, JOHAB, MAC, OEM, RUSSIAN, SHIFTJIS, SYMBOL, THAI, TURKISH, VIETNAMESE ANSI and BALTIC. Normally you would use "cDEFAULT". + qXX - quality XX. Valid charsets are: PROOF, DRAFT, + ANTIALIASED, UNANTIALIASED, CLEARTYPE, DEFAULT. + Normally you would use "qDEFAULT". + Some quality values isn't supported in legacy OSs. Use a ':' to separate the options. - A '_' can be used in the place of a space, so you don't need to use diff --git a/src/gui_w32.c b/src/gui_w32.c index 0679ed222b..543d5d5a12 100644 --- a/src/gui_w32.c +++ b/src/gui_w32.c @@ -3291,6 +3291,7 @@ logfont2name(LOGFONT lf) char *p; char *res; char *charset_name; + char *quality_name; char *font_name = lf.lfFaceName; charset_name = charset_id2name((int)lf.lfCharSet); @@ -3304,6 +3305,8 @@ logfont2name(LOGFONT lf) (char_u **)&font_name, &len); } #endif + quality_name = quality_id2name((int)lf.lfQuality); + res = (char *)alloc((unsigned)(strlen(font_name) + 20 + (charset_name == NULL ? 0 : strlen(charset_name) + 2))); if (res != NULL) @@ -3331,6 +3334,11 @@ logfont2name(LOGFONT lf) STRCAT(p, ":c"); STRCAT(p, charset_name); } + if (quality_name != NULL) + { + STRCAT(p, ":q"); + STRCAT(p, quality_name); + } } #ifdef FEAT_MBYTE diff --git a/src/os_mswin.c b/src/os_mswin.c index 607fd6a51f..77582cc479 100644 --- a/src/os_mswin.c +++ b/src/os_mswin.c @@ -2689,6 +2689,33 @@ charset_pairs[] = {NULL, 0} }; +struct quality_pair +{ + char *name; + DWORD quality; +}; + +static struct quality_pair +quality_pairs[] = { +#ifdef CLEARTYPE_QUALITY + {"CLEARTYPE", CLEARTYPE_QUALITY}, +#endif +#ifdef ANTIALIASED_QUALITY + {"ANTIALIASED", ANTIALIASED_QUALITY}, +#endif +#ifdef NOANTIALIASED_QUALITY + {"NOANTIALIASED", NOANTIALIASED_QUALITY}, +#endif +#ifdef PROOF_QUALITY + {"PROOF", PROOF_QUALITY}, +#endif +#ifdef PROOF_QUALITY + {"DRAFT", DRAFT_QUALITY}, +#endif + {"DEFAULT", DEFAULT_QUALITY}, + {NULL, 0} +}; + /* * Convert a charset ID to a name. * Return NULL when not recognized. @@ -2704,6 +2731,21 @@ charset_id2name(int id) return cp->name; } +/* + * Convert a quality ID to a name. + * Return NULL when not recognized. + */ + char * +quality_id2name(DWORD id) +{ + struct quality_pair *qp; + + for (qp = quality_pairs; qp->name != NULL; ++qp) + if (id == qp->quality) + break; + return qp->name; +} + static const LOGFONT s_lfDefault = { -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, @@ -2985,6 +3027,26 @@ get_logfont( } break; } + case 'q': + { + struct quality_pair *qp; + + for (qp = quality_pairs; qp->name != NULL; ++qp) + if (STRNCMP(p, qp->name, strlen(qp->name)) == 0) + { + lf->lfQuality = qp->quality; + p += strlen(qp->name); + break; + } + if (qp->name == NULL && verbose) + { + vim_snprintf((char *)IObuff, IOSIZE, + _("E244: Illegal quality name \"%s\" in font name \"%s\""), p, name); + EMSG(IObuff); + break; + } + break; + } default: if (verbose) { diff --git a/src/proto/os_mswin.pro b/src/proto/os_mswin.pro index 333ba76c53..fb2da93714 100644 --- a/src/proto/os_mswin.pro +++ b/src/proto/os_mswin.pro @@ -49,6 +49,7 @@ void serverForeground(char_u *name); char_u *serverGetReply(HWND server, int *expr_res, int remove, int wait); void serverProcessPendingMessages(void); char *charset_id2name(int id); +char *quality_id2name __ARGS((DWORD id)); int get_logfont(LOGFONT *lf, char_u *name, HDC printer_dc, int verbose); void channel_init_winsock(void); /* vim: set ft=c : */ diff --git a/src/version.c b/src/version.c index 58377a49ef..aefcfae155 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1705, /**/ 1704, /**/ From e185c1efba3cb2611ac303c39a08e908497cbac4 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 3 Apr 2016 22:22:30 +0200 Subject: [PATCH 7/8] patch 7.4.1706 Problem: Old style function declaration breaks build. Solution: Remove __ARGS(). --- src/proto/os_mswin.pro | 2 +- src/version.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/proto/os_mswin.pro b/src/proto/os_mswin.pro index fb2da93714..d25c17404b 100644 --- a/src/proto/os_mswin.pro +++ b/src/proto/os_mswin.pro @@ -49,7 +49,7 @@ void serverForeground(char_u *name); char_u *serverGetReply(HWND server, int *expr_res, int remove, int wait); void serverProcessPendingMessages(void); char *charset_id2name(int id); -char *quality_id2name __ARGS((DWORD id)); +char *quality_id2name(DWORD id); int get_logfont(LOGFONT *lf, char_u *name, HDC printer_dc, int verbose); void channel_init_winsock(void); /* vim: set ft=c : */ diff --git a/src/version.c b/src/version.c index aefcfae155..4502f7fdf3 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1706, /**/ 1705, /**/ From 0921ecff1c5a74541bad6c073e8ade32247403d8 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 3 Apr 2016 22:44:36 +0200 Subject: [PATCH 8/8] patch 7.4.1707 Problem: Cannot use empty dictionary key, even though it can be useful. Solution: Allow using an empty dictionary key. --- src/eval.c | 16 +++++----------- src/hashtab.c | 3 +-- src/testdir/test_expr.vim | 14 ++++++++++++++ src/version.c | 2 ++ 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/eval.c b/src/eval.c index ab006b113c..070485f19e 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2782,11 +2782,9 @@ get_lval( if (len == -1) { /* "[key]": get key from "var1" */ - key = get_tv_string(&var1); /* is number or string */ - if (*key == NUL) + key = get_tv_string_chk(&var1); /* is number or string */ + if (key == NULL) { - if (!quiet) - EMSG(_(e_emptykey)); clear_tv(&var1); return NULL; } @@ -5623,11 +5621,9 @@ eval_index( if (len == -1) { - key = get_tv_string(&var1); - if (*key == NUL) + key = get_tv_string_chk(&var1); + if (key == NULL) { - if (verbose) - EMSG(_(e_emptykey)); clear_tv(&var1); return FAIL; } @@ -7754,11 +7750,9 @@ get_dict_tv(char_u **arg, typval_T *rettv, int evaluate) if (evaluate) { key = get_tv_string_buf_chk(&tvkey, buf); - if (key == NULL || *key == NUL) + if (key == NULL) { /* "key" is NULL when get_tv_string_buf_chk() gave an errmsg */ - if (key != NULL) - EMSG(_(e_emptykey)); clear_tv(&tvkey); goto failret; } diff --git a/src/hashtab.c b/src/hashtab.c index d1ba2c9528..f9c7c27994 100644 --- a/src/hashtab.c +++ b/src/hashtab.c @@ -468,8 +468,7 @@ hash_hash(char_u *key) char_u *p; if ((hash = *key) == 0) - return (hash_T)0; /* Empty keys are not allowed, but we don't - want to crash if we get one. */ + return (hash_T)0; p = key + 1; /* A simplistic algorithm that appears to do very well. diff --git a/src/testdir/test_expr.vim b/src/testdir/test_expr.vim index f5c9e26c0c..33115c7f1f 100644 --- a/src/testdir/test_expr.vim +++ b/src/testdir/test_expr.vim @@ -36,3 +36,17 @@ func Test_version() call assert_false(has('patch-9.1.0')) call assert_false(has('patch-9.9.1')) endfunc + +func Test_dict() + let d = {'': 'empty', 'a': 'a', 0: 'zero'} + call assert_equal('empty', d['']) + call assert_equal('a', d['a']) + call assert_equal('zero', d[0]) + call assert_true(has_key(d, '')) + call assert_true(has_key(d, 'a')) + + let d[''] = 'none' + let d['a'] = 'aaa' + call assert_equal('none', d['']) + call assert_equal('aaa', d['a']) +endfunc diff --git a/src/version.c b/src/version.c index 4502f7fdf3..2f1e01b1a9 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1707, /**/ 1706, /**/