1
0
forked from aniani/vim

patch 8.2.0886: cannot use octal numbers in scriptversion 4

Problem:    Cannot use octal numbers in scriptversion 4.
Solution:   Add the "0o" notation. (Ken Takata, closes #5304)
This commit is contained in:
Bram Moolenaar 2020-06-02 21:38:22 +02:00
parent 3ac498c8a1
commit c17e66c5c0
7 changed files with 48 additions and 20 deletions

View File

@ -95,15 +95,17 @@ the Number. Examples:
Number -1 --> String "-1" ~ Number -1 --> String "-1" ~
*octal* *octal*
Conversion from a String to a Number is done by converting the first digits to 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 a number. Hexadecimal "0xf9", Octal "017" or "0o17", and Binary "0b10"
recognized (NOTE: when using |scriptversion-4| octal is not recognized). If numbers are recognized (NOTE: when using |scriptversion-4| octal with a
the String doesn't start with digits, the result is zero. leading "0" is not recognized). If the String doesn't start with digits, the
result is zero.
Examples: Examples:
String "456" --> Number 456 ~ String "456" --> Number 456 ~
String "6bar" --> Number 6 ~ String "6bar" --> Number 6 ~
String "foo" --> Number 0 ~ String "foo" --> Number 0 ~
String "0xf1" --> Number 241 ~ String "0xf1" --> Number 241 ~
String "0100" --> Number 64 ~ String "0100" --> Number 64 ~
String "0o100" --> Number 64 ~
String "0b101" --> Number 5 ~ String "0b101" --> Number 5 ~
String "-8" --> Number -8 ~ String "-8" --> Number -8 ~
String "+8" --> Number 0 ~ String "+8" --> Number 0 ~
@ -1264,7 +1266,7 @@ number number constant *expr-number*
*hex-number* *octal-number* *binary-number* *hex-number* *octal-number* *binary-number*
Decimal, Hexadecimal (starting with 0x or 0X), Binary (starting with 0b or 0B) Decimal, Hexadecimal (starting with 0x or 0X), Binary (starting with 0b or 0B)
and Octal (starting with 0). and Octal (starting with 0, 0o or 0O).
*floating-point-format* *floating-point-format*
Floating point numbers can be written in two forms: Floating point numbers can be written in two forms:
@ -9642,8 +9644,8 @@ str2nr({expr} [, {base} [, {quoted}]]) *str2nr()*
< <
When {base} is 16 a leading "0x" or "0X" is ignored. With a When {base} is 16 a leading "0x" or "0X" is ignored. With a
different base the result will be zero. Similarly, when different base the result will be zero. Similarly, when
{base} is 8 a leading "0" is ignored, and when {base} is 2 a {base} is 8 a leading "0", "0o" or "0O" is ignored, and when
leading "0b" or "0B" is ignored. {base} is 2 a leading "0b" or "0B" is ignored.
Text after the number is silently ignored. Text after the number is silently ignored.
Can also be used as a |method|: > Can also be used as a |method|: >
@ -13593,13 +13595,16 @@ instead of failing in mysterious ways.
< <
*scriptversion-4* > *scriptversion-4* >
:scriptversion 4 :scriptversion 4
< Numbers with a leading zero are not recognized as octal. With the < Numbers with a leading zero are not recognized as octal. "0o" or "0O"
is still recognized as octal. With the
previous version you get: > previous version you get: >
echo 017 " displays 15 echo 017 " displays 15 (octal)
echo 018 " displays 18 echo 0o17 " displays 15 (octal)
echo 018 " displays 18 (decimal)
< with script version 4: > < with script version 4: >
echo 017 " displays 17 echo 017 " displays 17 (decimal)
echo 018 " displays 18 echo 0o17 " displays 15 (octal)
echo 018 " displays 18 (decimal)
< Also, it is possible to use single quotes inside numbers to make them < Also, it is possible to use single quotes inside numbers to make them
easier to read: > easier to read: >
echo 1'000'000 echo 1'000'000

View File

@ -1764,6 +1764,8 @@ vim_isblankline(char_u *lbuf)
* If "prep" is not NULL, returns a flag to indicate the type of the number: * If "prep" is not NULL, returns a flag to indicate the type of the number:
* 0 decimal * 0 decimal
* '0' octal * '0' octal
* 'O' octal
* 'o' octal
* 'B' bin * 'B' bin
* 'b' bin * 'b' bin
* 'X' hex * 'X' hex
@ -1783,8 +1785,8 @@ vim_isblankline(char_u *lbuf)
vim_str2nr( vim_str2nr(
char_u *start, char_u *start,
int *prep, // return: type of number 0 = decimal, 'x' int *prep, // return: type of number 0 = decimal, 'x'
// or 'X' is hex, '0' = octal, 'b' or 'B' // or 'X' is hex, '0', 'o' or 'O' is octal,
// is bin // 'b' or 'B' is bin
int *len, // return: detected length of number int *len, // return: detected length of number
int what, // what numbers to recognize int what, // what numbers to recognize
varnumber_T *nptr, // return: signed result varnumber_T *nptr, // return: signed result
@ -1822,6 +1824,11 @@ vim_str2nr(
&& (maxlen == 0 || maxlen > 2)) && (maxlen == 0 || maxlen > 2))
// binary // binary
ptr += 2; ptr += 2;
else if ((what & STR2NR_OOCT)
&& (pre == 'O' || pre == 'o') && vim_isbdigit(ptr[2])
&& (maxlen == 0 || maxlen > 2))
// octal with prefix "0o"
ptr += 2;
else else
{ {
// decimal or octal, default is decimal // decimal or octal, default is decimal
@ -1869,9 +1876,12 @@ vim_str2nr(
} }
} }
} }
else if (pre == '0' || ((what & STR2NR_OCT) && (what & STR2NR_FORCE))) else if (pre == 'O' || pre == 'o' ||
pre == '0' || ((what & STR2NR_OCT) && (what & STR2NR_FORCE)))
{ {
// octal // octal
if (pre != 0 && pre != '0')
n += 2; // skip over "0o"
while ('0' <= *ptr && *ptr <= '7') while ('0' <= *ptr && *ptr <= '7')
{ {
// avoid ubsan error for overflow // avoid ubsan error for overflow

View File

@ -7737,7 +7737,7 @@ f_str2nr(typval_T *argvars, typval_T *rettv)
switch (base) switch (base)
{ {
case 2: what |= STR2NR_BIN + STR2NR_FORCE; break; case 2: what |= STR2NR_BIN + STR2NR_FORCE; break;
case 8: what |= STR2NR_OCT + STR2NR_FORCE; break; case 8: what |= STR2NR_OCT + STR2NR_OOCT + STR2NR_FORCE; break;
case 16: what |= STR2NR_HEX + STR2NR_FORCE; break; case 16: what |= STR2NR_HEX + STR2NR_FORCE; break;
} }
vim_str2nr(p, NULL, NULL, what, &n, NULL, 0, FALSE); vim_str2nr(p, NULL, NULL, what, &n, NULL, 0, FALSE);

View File

@ -199,9 +199,12 @@ scriptversion 4
func Test_vvar_scriptversion4() func Test_vvar_scriptversion4()
call assert_true(has('vimscript-4')) call assert_true(has('vimscript-4'))
call assert_equal(17, 017) call assert_equal(17, 017)
call assert_equal(15, 0o17)
call assert_equal(15, 0O17)
call assert_equal(18, 018) call assert_equal(18, 018)
call assert_equal(64, 0b1'00'00'00) call assert_equal(64, 0b1'00'00'00)
call assert_equal(1048576, 0x10'00'00) call assert_equal(1048576, 0x10'00'00)
call assert_equal(32768, 0o10'00'00)
call assert_equal(1000000, 1'000'000) call assert_equal(1000000, 1'000'000)
call assert_equal("1234", execute("echo 1'234")->trim()) call assert_equal("1234", execute("echo 1'234")->trim())
call assert_equal('1 234', execute("echo 1''234")->trim()) call assert_equal('1 234', execute("echo 1''234")->trim())
@ -211,6 +214,8 @@ endfunc
scriptversion 1 scriptversion 1
func Test_vvar_scriptversion1() func Test_vvar_scriptversion1()
call assert_equal(15, 017) call assert_equal(15, 017)
call assert_equal(15, 0o17)
call assert_equal(15, 0O17)
call assert_equal(18, 018) call assert_equal(18, 018)
endfunc endfunc

View File

@ -189,6 +189,10 @@ func Test_str2nr()
call assert_equal(65, str2nr('0101', 8)) call assert_equal(65, str2nr('0101', 8))
call assert_equal(-65, str2nr('-101', 8)) call assert_equal(-65, str2nr('-101', 8))
call assert_equal(-65, str2nr('-0101', 8)) call assert_equal(-65, str2nr('-0101', 8))
call assert_equal(65, str2nr('0o101', 8))
call assert_equal(65, str2nr('0O0101', 8))
call assert_equal(-65, str2nr('-0O101', 8))
call assert_equal(-65, str2nr('-0o0101', 8))
call assert_equal(11259375, str2nr('abcdef', 16)) call assert_equal(11259375, str2nr('abcdef', 16))
call assert_equal(11259375, str2nr('ABCDEF', 16)) call assert_equal(11259375, str2nr('ABCDEF', 16))
@ -207,6 +211,7 @@ func Test_str2nr()
call assert_equal(0, str2nr('0x10')) call assert_equal(0, str2nr('0x10'))
call assert_equal(0, str2nr('0b10')) call assert_equal(0, str2nr('0b10'))
call assert_equal(0, str2nr('0o10'))
call assert_equal(1, str2nr('12', 2)) call assert_equal(1, str2nr('12', 2))
call assert_equal(1, str2nr('18', 8)) call assert_equal(1, str2nr('18', 8))
call assert_equal(1, str2nr('1g', 16)) call assert_equal(1, str2nr('1g', 16))

View File

@ -746,6 +746,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
886,
/**/ /**/
885, 885,
/**/ /**/

View File

@ -312,11 +312,12 @@
#define NUMBUFLEN 65 #define NUMBUFLEN 65
// flags for vim_str2nr() // flags for vim_str2nr()
#define STR2NR_BIN 0x01 #define STR2NR_BIN 0x01
#define STR2NR_OCT 0x02 #define STR2NR_OCT 0x02
#define STR2NR_HEX 0x04 #define STR2NR_HEX 0x04
#define STR2NR_ALL (STR2NR_BIN + STR2NR_OCT + STR2NR_HEX) #define STR2NR_OOCT 0x08 // Octal with prefix "0o": 0o777
#define STR2NR_NO_OCT (STR2NR_BIN + STR2NR_HEX) #define STR2NR_ALL (STR2NR_BIN + STR2NR_OCT + STR2NR_HEX + STR2NR_OOCT)
#define STR2NR_NO_OCT (STR2NR_BIN + STR2NR_HEX + STR2NR_OOCT)
#define STR2NR_FORCE 0x80 // only when ONE of the above is used #define STR2NR_FORCE 0x80 // only when ONE of the above is used