summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-09-15 14:33:22 +0200
committerBram Moolenaar <Bram@vim.org>2019-09-15 14:33:22 +0200
commit60a8de28d11595f4df0419ece8afa7d6accc9fbd (patch)
tree0dc410fcff779f8f9f7769f775f7e41d924a0da7
parent50bf7ce0c9f8c3ede2d1a02c734beba9d5a0504e (diff)
downloadvim-git-60a8de28d11595f4df0419ece8afa7d6accc9fbd.tar.gz
patch 8.1.2035: recognizing octal numbers is confusingv8.1.2035
Problem: Recognizing octal numbers is confusing. Solution: Introduce scriptversion 4: do not use octal and allow for single quote inside numbers.
-rw-r--r--runtime/doc/eval.txt29
-rw-r--r--src/eval.c4
-rw-r--r--src/evalfunc.c13
-rw-r--r--src/scriptfile.c2
-rw-r--r--src/testdir/test_eval_stuff.vim37
-rw-r--r--src/testdir/test_functions.vim6
-rw-r--r--src/version.c2
-rw-r--r--src/vim.h12
8 files changed, 78 insertions, 27 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 8cb2af1e6..a81731759 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1,4 +1,4 @@
-*eval.txt* For Vim version 8.1. Last change: 2019 Sep 10
+*eval.txt* For Vim version 8.1. Last change: 2019 Sep 15
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -92,7 +92,8 @@ the Number. Examples:
*octal*
Conversion from a String to a Number is done by converting the first digits to
a number. Hexadecimal "0xf9", Octal "017", and Binary "0b10" numbers are
-recognized. If the String doesn't start with digits, the result is zero.
+recognized (NOTE: when using |scriptversion-4| octal is not recognized). If
+the String doesn't start with digits, the result is zero.
Examples:
String "456" --> Number 456 ~
String "6bar" --> Number 6 ~
@@ -2757,7 +2758,8 @@ sqrt({expr}) Float square root of {expr}
str2float({expr}) Float convert String to Float
str2list({expr} [, {utf8}]) List convert each character of {expr} to
ASCII/UTF8 value
-str2nr({expr} [, {base}]) Number convert String to Number
+str2nr({expr} [, {base} [, {quoted}]])
+ Number convert String to Number
strchars({expr} [, {skipcc}]) Number character length of the String {expr}
strcharpart({str}, {start} [, {len}])
String {len} characters of {str} at {start}
@@ -9075,9 +9077,11 @@ str2list({expr} [, {utf8}]) *str2list()*
GetString()->str2list()
-str2nr({expr} [, {base}]) *str2nr()*
+str2nr({expr} [, {base} [, {quoted}]]) *str2nr()*
Convert string {expr} to a number.
{base} is the conversion base, it can be 2, 8, 10 or 16.
+ When {quoted} is present and non-zero then embedded single
+ quotes are ignored, thus "1'000'000" is a million.
When {base} is omitted base 10 is used. This also means that
a leading zero doesn't cause octal conversion to be used, as
@@ -12937,6 +12941,23 @@ instead of failing in mysterious ways.
Test for support with: >
has('vimscript-3')
+<
+ *scriptversion-4* >
+ :scriptversion 4
+< Numbers with a leading zero are not recognized as octal. With the
+ previous version you get: >
+ echo 017 " displays 15
+ echo 018 " displays 18
+< with script version 4: >
+ echo 017 " displays 17
+ echo 018 " displays 18
+< Also, it is possible to use single quotes inside numbers to make them
+ easier to read: >
+ echo 1'000'000
+< The quotes must be surrounded by digits.
+
+ Test for support with: >
+ has('vimscript-4')
==============================================================================
11. No +eval feature *no-eval-feature*
diff --git a/src/eval.c b/src/eval.c
index acdfac3a3..680ca1af7 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -2617,7 +2617,9 @@ eval7(
else
{
// decimal, hex or octal number
- vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0, TRUE);
+ vim_str2nr(*arg, NULL, &len, current_sctx.sc_version >= 4
+ ? STR2NR_NO_OCT + STR2NR_QUOTE
+ : STR2NR_ALL, &n, NULL, 0, TRUE);
if (len == 0)
{
semsg(_(e_invexpr2), *arg);
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 438aac8ea..67726923d 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -728,7 +728,7 @@ static funcentry_T global_functions[] =
{"str2float", 1, 1, FEARG_1, f_str2float},
#endif
{"str2list", 1, 2, FEARG_1, f_str2list},
- {"str2nr", 1, 2, FEARG_1, f_str2nr},
+ {"str2nr", 1, 3, FEARG_1, f_str2nr},
{"strcharpart", 2, 3, FEARG_1, f_strcharpart},
{"strchars", 1, 2, FEARG_1, f_strchars},
{"strdisplaywidth", 1, 2, FEARG_1, f_strdisplaywidth},
@@ -7323,7 +7323,7 @@ f_str2nr(typval_T *argvars, typval_T *rettv)
int base = 10;
char_u *p;
varnumber_T n;
- int what;
+ int what = 0;
int isneg;
if (argvars[1].v_type != VAR_UNKNOWN)
@@ -7334,6 +7334,8 @@ f_str2nr(typval_T *argvars, typval_T *rettv)
emsg(_(e_invarg));
return;
}
+ if (argvars[2].v_type != VAR_UNKNOWN && tv_get_number(&argvars[2]))
+ what |= STR2NR_QUOTE;
}
p = skipwhite(tv_get_string(&argvars[0]));
@@ -7342,10 +7344,9 @@ f_str2nr(typval_T *argvars, typval_T *rettv)
p = skipwhite(p + 1);
switch (base)
{
- case 2: what = STR2NR_BIN + STR2NR_FORCE; break;
- case 8: what = STR2NR_OCT + STR2NR_FORCE; break;
- case 16: what = STR2NR_HEX + STR2NR_FORCE; break;
- default: what = 0;
+ case 2: what |= STR2NR_BIN + STR2NR_FORCE; break;
+ case 8: what |= STR2NR_OCT + STR2NR_FORCE; break;
+ case 16: what |= STR2NR_HEX + STR2NR_FORCE; break;
}
vim_str2nr(p, NULL, NULL, what, &n, NULL, 0, FALSE);
// Text after the number is silently ignored.
diff --git a/src/scriptfile.c b/src/scriptfile.c
index d46b1e0b7..92db59c2d 100644
--- a/src/scriptfile.c
+++ b/src/scriptfile.c
@@ -1659,7 +1659,7 @@ ex_scriptversion(exarg_T *eap UNUSED)
nr = getdigits(&eap->arg);
if (nr == 0 || *eap->arg != NUL)
emsg(_(e_invarg));
- else if (nr > 3)
+ else if (nr > 4)
semsg(_("E999: scriptversion not supported: %d"), nr);
else
current_sctx.sc_version = nr;
diff --git a/src/testdir/test_eval_stuff.vim b/src/testdir/test_eval_stuff.vim
index b518f5ae6..720f3094e 100644
--- a/src/testdir/test_eval_stuff.vim
+++ b/src/testdir/test_eval_stuff.vim
@@ -74,7 +74,7 @@ func Test_readfile_binary()
new
call setline(1, ['one', 'two', 'three'])
setlocal ff=dos
- write XReadfile
+ silent write XReadfile
let lines = 'XReadfile'->readfile()
call assert_equal(['one', 'two', 'three'], lines)
let lines = readfile('XReadfile', '', 2)
@@ -124,6 +124,15 @@ func Test_string_concatenation()
call assert_equal('ab', a)
endfunc
+" Test fix for issue #4507
+func Test_skip_after_throw()
+ try
+ throw 'something'
+ let x = wincol() || &ts
+ catch /something/
+ endtry
+endfunc
+
scriptversion 2
func Test_string_concat_scriptversion2()
call assert_true(has('vimscript-2'))
@@ -183,17 +192,23 @@ func Test_dict_access_scriptversion2()
call assert_true(1 && l:x.foo)
endfunc
-func Test_scriptversion()
+scriptversion 4
+func Test_vvar_scriptversion4()
+ call assert_equal(17, 017)
+ call assert_equal(18, 018)
+ call assert_equal(64, 0b1'00'00'00)
+ call assert_equal(1048576, 0x10'00'00)
+ call assert_equal(1000000, 1'000'000)
+endfunc
+
+scriptversion 1
+func Test_vvar_scriptversion1()
+ call assert_equal(15, 017)
+ call assert_equal(18, 018)
+endfunc
+
+func Test_scriptversion_fail()
call writefile(['scriptversion 9'], 'Xversionscript')
call assert_fails('source Xversionscript', 'E999:')
call delete('Xversionscript')
endfunc
-
-" Test fix for issue #4507
-func Test_skip_after_throw()
- try
- throw 'something'
- let x = wincol() || &ts
- catch /something/
- endtry
-endfunc
diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim
index 2e051bb26..e78206188 100644
--- a/src/testdir/test_functions.vim
+++ b/src/testdir/test_functions.vim
@@ -157,6 +157,12 @@ func Test_str2nr()
call assert_equal(11259375, str2nr('0XABCDEF', 16))
call assert_equal(-11259375, str2nr('-0xABCDEF', 16))
+ call assert_equal(1, str2nr("1'000'000", 10, 0))
+ call assert_equal(256, str2nr("1'0000'0000", 2, 1))
+ call assert_equal(262144, str2nr("1'000'000", 8, 1))
+ call assert_equal(1000000, str2nr("1'000'000", 10, 1))
+ call assert_equal(65536, str2nr("1'00'00", 16, 1))
+
call assert_equal(0, str2nr('0x10'))
call assert_equal(0, str2nr('0b10'))
call assert_equal(1, str2nr('12', 2))
diff --git a/src/version.c b/src/version.c
index 69c77d81d..09baa5324 100644
--- a/src/version.c
+++ b/src/version.c
@@ -758,6 +758,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2035,
+/**/
2034,
/**/
2033,
diff --git a/src/vim.h b/src/vim.h
index 46ca6930d..8afa93352 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -307,11 +307,15 @@
#define NUMBUFLEN 65
// flags for vim_str2nr()
-#define STR2NR_BIN 1
-#define STR2NR_OCT 2
-#define STR2NR_HEX 4
+#define STR2NR_BIN 0x01
+#define STR2NR_OCT 0x02
+#define STR2NR_HEX 0x04
#define STR2NR_ALL (STR2NR_BIN + STR2NR_OCT + STR2NR_HEX)
-#define STR2NR_FORCE 8 // only when ONE of the above is used
+#define STR2NR_NO_OCT (STR2NR_BIN + STR2NR_HEX)
+
+#define STR2NR_FORCE 0x80 // only when ONE of the above is used
+
+#define STR2NR_QUOTE 0x10 // ignore embedded single quotes
/*
* Shorthand for unsigned variables. Many systems, but not all, have u_char