diff options
author | Sean Dewar <seandewar@users.noreply.github.com> | 2021-06-03 01:55:18 +0100 |
---|---|---|
committer | Sean Dewar <seandewar@users.noreply.github.com> | 2021-09-11 15:36:03 +0100 |
commit | 90a4cf92d21b730fea7099fb3e12a9ef791a1a57 (patch) | |
tree | c342ec4595fd613430bff9e7a6924c7ee3291c71 | |
parent | 10018958d860780c3766f4e785710201c07f3684 (diff) | |
download | rneovim-90a4cf92d21b730fea7099fb3e12a9ef791a1a57.tar.gz rneovim-90a4cf92d21b730fea7099fb3e12a9ef791a1a57.tar.bz2 rneovim-90a4cf92d21b730fea7099fb3e12a9ef791a1a57.zip |
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 vim/vim#5304)
https://github.com/vim/vim/commit/c17e66c5c0acd5038f1eb3d7b3049b64bb6ea30b
:scriptversion is N/A.
Cherry-pick latest str2nr() doc changes from v8.1.2035.
Cherry-pick various mentions of the 0o prefix from:
- v8.2.2324
- https://github.com/vim/vim/commit/2346a6378483c9871016f9fc821ec5cbea638f13
- https://github.com/vim/vim/commit/11e3c5ba820325b69cb56f70e13c21d7b8808d33
- https://github.com/vim/vim/commit/82be4849eed0b8fbee45bc8da99b685ec89af59a
Patch used ascii_isbdigit() by mistake, which was fixed in v8.2.2309.
Make STR2NR_OOCT work the same as STR2NR_OCT when forcing.
In Vim, STR2NR_FORCE | STR2NR_OOCT isn't handled, and doesn't actually
force anything. Rather than abort(), make it work as STR2NR_OCT.
This means STR2NR_FORCE | STR2NR_OCT works the same as
STR2NR_FORCE | STR2NR_OOCT and STR2NR_FORCE | STR2NR_OCT | STR2NR_OOCT.
-rw-r--r-- | runtime/doc/eval.txt | 23 | ||||
-rw-r--r-- | runtime/doc/usr_41.txt | 9 | ||||
-rw-r--r-- | src/nvim/charset.c | 37 | ||||
-rw-r--r-- | src/nvim/charset.h | 9 | ||||
-rw-r--r-- | src/nvim/eval/funcs.c | 2 | ||||
-rw-r--r-- | src/nvim/testdir/test_functions.vim | 5 | ||||
-rw-r--r-- | test/unit/charset/vim_str2nr_spec.lua | 103 |
7 files changed, 160 insertions, 28 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index cd449a5d34..d2e476b83b 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -20,7 +20,7 @@ There are six types of variables: *Number* *Integer* Number A 32 or 64 bit signed number. |expr-number| The number of bits is available in |v:numbersize|. - Examples: -123 0x10 0177 0b1011 + Examples: -123 0x10 0177 0o177 0b1011 Float A floating point number. |floating-point-format| *Float* Examples: 123.456 1.15e-6 -1.1e3 @@ -54,14 +54,15 @@ the Number. Examples: Number -1 --> String "-1" ~ *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. -Examples: +a number. Hexadecimal "0xf9", Octal "017" or "0o17", and Binary "0b10" +numbers are recognized. If the String doesn't start with digits, the result +is zero. Examples: String "456" --> Number 456 ~ String "6bar" --> Number 6 ~ String "foo" --> Number 0 ~ String "0xf1" --> Number 241 ~ String "0100" --> Number 64 ~ + String "0o100" --> Number 64 ~ String "0b101" --> Number 5 ~ String "-8" --> Number -8 ~ String "+8" --> Number 0 ~ @@ -1085,7 +1086,7 @@ number number constant *expr-number* *hex-number* *octal-number* *binary-number* 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 numbers can be written in two forms: @@ -6554,9 +6555,9 @@ mkdir({name} [, {path} [, {prot}]]) If {path} is "p" then intermediate directories are created as necessary. Otherwise it must be "". If {prot} is given it is used to set the protection bits of - the new directory. The default is 0755 (rwxr-xr-x: r/w for - the user readable for others). Use 0700 to make it unreadable - for others. + the new directory. The default is 0o755 (rwxr-xr-x: r/w for + the user, readable for others). Use 0o700 to make it + unreadable for others. {prot} is applied for all parts of {name}. Thus if you create /tmp/foo/bar then /tmp/foo will be created with 0700. Example: > @@ -8650,9 +8651,9 @@ str2nr({expr} [, {base} [, {quoted}]]) *str2nr()* let nr = str2nr('123') < When {base} is 16 a leading "0x" or "0X" is ignored. With a - different base the result will be zero. Similarly, when {base} - is 8 a leading "0" is ignored, and when {base} is 2 a leading - "0b" or "0B" is ignored. + different base the result will be zero. Similarly, when + {base} is 8 a leading "0", "0o" or "0O" is ignored, and when + {base} is 2 a leading "0b" or "0B" is ignored. Text after the number is silently ignored. diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index a190bf2f27..c9321e8736 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -118,7 +118,8 @@ Numbers can be decimal, hexadecimal, octal or binary. A hexadecimal number starts with "0x" or "0X". For example "0x1f" is decimal 31. -An octal number starts with a zero and another digit. "017" is decimal 15. +An octal number starts with "0o", "0O" or a zero and another digit. "0o17" is +decimal 15. A binary number starts with "0b" or "0B". For example "0b101" is decimal 5. @@ -127,14 +128,14 @@ number, it will be interpreted as an octal number! The ":echo" command always prints decimal numbers. Example: > - :echo 0x7f 036 + :echo 0x7f 0o36 < 127 30 ~ A number is made negative with a minus sign. This also works for hexadecimal, octal and binary numbers. A minus sign is also used for subtraction. Compare this with the previous example: > - :echo 0x7f -036 + :echo 0x7f -0o36 < 97 ~ White space in an expression is ignored. However, it's recommended to use it @@ -142,7 +143,7 @@ for separating items, to make the expression easier to read. For example, to avoid the confusion with a negative number above, put a space between the minus sign and the following number: > - :echo 0x7f - 036 + :echo 0x7f - 0o36 ============================================================================== *41.2* Variables diff --git a/src/nvim/charset.c b/src/nvim/charset.c index 7b08488925..94b6b7a8d7 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -1385,6 +1385,8 @@ bool vim_isblankline(char_u *lbuf) /// If "prep" is not NULL, returns a flag to indicate the type of the number: /// 0 decimal /// '0' octal +/// 'O' octal +/// 'o' octal /// 'B' bin /// 'b' bin /// 'X' hex @@ -1402,8 +1404,8 @@ bool vim_isblankline(char_u *lbuf) /// /// @param start /// @param prep Returns guessed type of number 0 = decimal, 'x' or 'X' is -/// hexadecimal, '0' = octal, 'b' or 'B' is binary. When using -/// STR2NR_FORCE is always zero. +/// hexadecimal, '0', 'o' or 'O' is octal, 'b' or 'B' is binary. +/// When using STR2NR_FORCE is always zero. /// @param len Returns the detected length of number. /// @param what Recognizes what number passed, @see ChStr2NrFlags. /// @param nptr Returns the signed result. @@ -1433,8 +1435,8 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len, } if (what & STR2NR_FORCE) { - // When forcing main consideration is skipping the prefix. Octal and decimal - // numbers have no prefixes to skip. pre is not set. + // When forcing main consideration is skipping the prefix. Decimal numbers + // have no prefixes to skip. pre is not set. switch (what & ~(STR2NR_FORCE | STR2NR_QUOTE)) { case STR2NR_HEX: { if (!STRING_ENDED(ptr + 2) @@ -1454,7 +1456,16 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len, } goto vim_str2nr_bin; } - case STR2NR_OCT: { + // Make STR2NR_OOCT work the same as STR2NR_OCT when forcing. + case STR2NR_OCT: + case STR2NR_OOCT: + case STR2NR_OCT | STR2NR_OOCT: { + if (!STRING_ENDED(ptr + 2) + && ptr[0] == '0' + && (ptr[1] == 'o' || ptr[1] == 'O') + && ascii_isbdigit(ptr[2])) { + ptr += 2; + } goto vim_str2nr_oct; } case 0: { @@ -1464,9 +1475,9 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len, abort(); } } - } else if ((what & (STR2NR_HEX|STR2NR_OCT|STR2NR_BIN)) - && !STRING_ENDED(ptr + 1) - && ptr[0] == '0' && ptr[1] != '8' && ptr[1] != '9') { + } else if ((what & (STR2NR_HEX | STR2NR_OCT | STR2NR_OOCT | STR2NR_BIN)) + && !STRING_ENDED(ptr + 1) && ptr[0] == '0' && ptr[1] != '8' + && ptr[1] != '9') { pre = ptr[1]; // Detect hexadecimal: 0x or 0X followed by hex digit. if ((what & STR2NR_HEX) @@ -1484,7 +1495,15 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len, ptr += 2; goto vim_str2nr_bin; } - // Detect octal number: zero followed by octal digits without '8' or '9'. + // Detect octal: 0o or 0O followed by octal digits (without '8' or '9'). + if ((what & STR2NR_OOCT) + && !STRING_ENDED(ptr + 2) + && (pre == 'O' || pre == 'o') + && ascii_isbdigit(ptr[2])) { + ptr += 2; + goto vim_str2nr_oct; + } + // Detect old octal format: 0 followed by octal digits. pre = 0; if (!(what & STR2NR_OCT) || !('0' <= ptr[1] && ptr[1] <= '7')) { diff --git a/src/nvim/charset.h b/src/nvim/charset.h index b5f1f8506b..2fef4d78a2 100644 --- a/src/nvim/charset.h +++ b/src/nvim/charset.h @@ -23,14 +23,19 @@ typedef enum { STR2NR_BIN = (1 << 0), ///< Allow binary numbers. STR2NR_OCT = (1 << 1), ///< Allow octal numbers. STR2NR_HEX = (1 << 2), ///< Allow hexadecimal numbers. + STR2NR_OOCT = (1 << 3), ///< Octal with prefix "0o": 0o777 /// Force one of the above variants. /// /// STR2NR_FORCE|STR2NR_DEC is actually not different from supplying zero /// as flags, but still present for completeness. + /// + /// STR2NR_FORCE|STR2NR_OCT|STR2NR_OOCT is the same as STR2NR_FORCE|STR2NR_OCT + /// or STR2NR_FORCE|STR2NR_OOCT. STR2NR_FORCE = (1 << 7), /// Recognize all formats vim_str2nr() can recognize. - STR2NR_ALL = STR2NR_BIN | STR2NR_OCT | STR2NR_HEX, - STR2NR_NO_OCT = STR2NR_BIN | STR2NR_HEX, ///< Disallow octal numbers. + STR2NR_ALL = STR2NR_BIN | STR2NR_OCT | STR2NR_HEX | STR2NR_OOCT, + /// Disallow octals numbers without the 0o prefix. + STR2NR_NO_OCT = STR2NR_BIN | STR2NR_HEX | STR2NR_OOCT, STR2NR_QUOTE = (1 << 4), ///< Ignore embedded single quotes. } ChStr2NrFlags; diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 61f535e32e..801b0f9d1c 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -10022,7 +10022,7 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) break; } case 8: { - what |= STR2NR_OCT | STR2NR_FORCE; + what |= STR2NR_OCT | STR2NR_OOCT | STR2NR_FORCE; break; } case 16: { diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim index 2e838f73b6..ed46730cbb 100644 --- a/src/nvim/testdir/test_functions.vim +++ b/src/nvim/testdir/test_functions.vim @@ -152,6 +152,10 @@ func Test_str2nr() call assert_equal(65, str2nr('0101', 8)) call assert_equal(-65, str2nr('-101', 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)) @@ -170,6 +174,7 @@ func Test_str2nr() call assert_equal(0, str2nr('0x10')) call assert_equal(0, str2nr('0b10')) + call assert_equal(0, str2nr('0o10')) call assert_equal(1, str2nr('12', 2)) call assert_equal(1, str2nr('18', 8)) call assert_equal(1, str2nr('1g', 16)) diff --git a/test/unit/charset/vim_str2nr_spec.lua b/test/unit/charset/vim_str2nr_spec.lua index ebcceca7ae..5fc3b83a13 100644 --- a/test/unit/charset/vim_str2nr_spec.lua +++ b/test/unit/charset/vim_str2nr_spec.lua @@ -86,10 +86,13 @@ describe('vim_str2nr()', function() test_vim_str2nr('', lib.STR2NR_ALL, {len = 0, num = 0, unum = 0, pre = 0}, 0) test_vim_str2nr('', lib.STR2NR_BIN, {len = 0, num = 0, unum = 0, pre = 0}, 0) test_vim_str2nr('', lib.STR2NR_OCT, {len = 0, num = 0, unum = 0, pre = 0}, 0) + test_vim_str2nr('', lib.STR2NR_OOCT, {len = 0, num = 0, unum = 0, pre = 0}, 0) test_vim_str2nr('', lib.STR2NR_HEX, {len = 0, num = 0, unum = 0, pre = 0}, 0) test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_DEC, {len = 0, num = 0, unum = 0, pre = 0}, 0) test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_BIN, {len = 0, num = 0, unum = 0, pre = 0}, 0) test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_OCT, {len = 0, num = 0, unum = 0, pre = 0}, 0) + test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_OOCT, {len = 0, num = 0, unum = 0, pre = 0}, 0) + test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_OCT + lib.STR2NR_OOCT, {len = 0, num = 0, unum = 0, pre = 0}, 0) test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_HEX, {len = 0, num = 0, unum = 0, pre = 0}, 0) end) itp('works with decimal numbers', function() @@ -98,9 +101,11 @@ describe('vim_str2nr()', function() lib.STR2NR_BIN, lib.STR2NR_OCT, lib.STR2NR_HEX, + lib.STR2NR_OOCT, lib.STR2NR_BIN + lib.STR2NR_OCT, lib.STR2NR_BIN + lib.STR2NR_HEX, lib.STR2NR_OCT + lib.STR2NR_HEX, + lib.STR2NR_OOCT + lib.STR2NR_HEX, lib.STR2NR_ALL, lib.STR2NR_FORCE + lib.STR2NR_DEC, }) do @@ -212,13 +217,16 @@ describe('vim_str2nr()', function() end end end) - itp('works with octal numbers', function() + itp('works with octal numbers (0 prefix)', function() for _, flags in ipairs({ lib.STR2NR_OCT, lib.STR2NR_OCT + lib.STR2NR_BIN, lib.STR2NR_OCT + lib.STR2NR_HEX, + lib.STR2NR_OCT + lib.STR2NR_OOCT, lib.STR2NR_ALL, lib.STR2NR_FORCE + lib.STR2NR_OCT, + lib.STR2NR_FORCE + lib.STR2NR_OOCT, + lib.STR2NR_FORCE + lib.STR2NR_OCT + lib.STR2NR_OOCT, }) do local oct if flags > lib.STR2NR_FORCE then @@ -267,6 +275,99 @@ describe('vim_str2nr()', function() end end end) + itp('works with octal numbers (0o or 0O prefix)', function() + for _, flags in ipairs({ + lib.STR2NR_OOCT, + lib.STR2NR_OOCT + lib.STR2NR_BIN, + lib.STR2NR_OOCT + lib.STR2NR_HEX, + lib.STR2NR_OCT + lib.STR2NR_OOCT, + lib.STR2NR_OCT + lib.STR2NR_OOCT + lib.STR2NR_BIN, + lib.STR2NR_OCT + lib.STR2NR_OOCT + lib.STR2NR_HEX, + lib.STR2NR_ALL, + lib.STR2NR_FORCE + lib.STR2NR_OCT, + lib.STR2NR_FORCE + lib.STR2NR_OOCT, + lib.STR2NR_FORCE + lib.STR2NR_OCT + lib.STR2NR_OOCT, + }) do + local oct + local OCT + if flags > lib.STR2NR_FORCE then + oct = 0 + OCT = 0 + else + oct = ('o'):byte() + OCT = ('O'):byte() + end + + test_vim_str2nr( '0o054', flags, {len = 5, num = 44, unum = 44, pre = oct}, 0) + test_vim_str2nr( '0o054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1) + test_vim_str2nr( '0o054', flags, {len = 0}, 2) + test_vim_str2nr( '0o054', flags, {len = 3, num = 0, unum = 0, pre = oct}, 3) + test_vim_str2nr( '0o054', flags, {len = 4, num = 5, unum = 5, pre = oct}, 4) + test_vim_str2nr( '0o054', flags, {len = 5, num = 44, unum = 44, pre = oct}, 5) + test_vim_str2nr( '0o0548', flags, {len = 5, num = 44, unum = 44, pre = oct}, 5) + test_vim_str2nr( '0o054', flags, {len = 5, num = 44, unum = 44, pre = oct}, 6) + + test_vim_str2nr( '0o054x', flags, {len = 0}, 6) + test_vim_str2nr( '0o054x', flags, {len = 0}, 0) + test_vim_str2nr( '0o054x', flags, {len = 5, num = 44, unum = 44, pre = oct}, 6, false) + test_vim_str2nr( '0o054x', flags, {len = 5, num = 44, unum = 44, pre = oct}, 0, false) + + test_vim_str2nr('-0o054', flags, {len = 6, num = -44, unum = 44, pre = oct}, 0) + test_vim_str2nr('-0o054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1) + test_vim_str2nr('-0o054', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2) + test_vim_str2nr('-0o054', flags, {len = 0}, 3) + test_vim_str2nr('-0o054', flags, {len = 4, num = 0, unum = 0, pre = oct}, 4) + test_vim_str2nr('-0o054', flags, {len = 5, num = -5, unum = 5, pre = oct}, 5) + test_vim_str2nr('-0o054', flags, {len = 6, num = -44, unum = 44, pre = oct}, 6) + test_vim_str2nr('-0o0548', flags, {len = 6, num = -44, unum = 44, pre = oct}, 6) + test_vim_str2nr('-0o054', flags, {len = 6, num = -44, unum = 44, pre = oct}, 7) + + test_vim_str2nr('-0o054x', flags, {len = 0}, 7) + test_vim_str2nr('-0o054x', flags, {len = 0}, 0) + test_vim_str2nr('-0o054x', flags, {len = 6, num = -44, unum = 44, pre = oct}, 7, false) + test_vim_str2nr('-0o054x', flags, {len = 6, num = -44, unum = 44, pre = oct}, 0, false) + + test_vim_str2nr( '0O054', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 0) + test_vim_str2nr( '0O054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1) + test_vim_str2nr( '0O054', flags, {len = 0}, 2) + test_vim_str2nr( '0O054', flags, {len = 3, num = 0, unum = 0, pre = OCT}, 3) + test_vim_str2nr( '0O054', flags, {len = 4, num = 5, unum = 5, pre = OCT}, 4) + test_vim_str2nr( '0O054', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 5) + test_vim_str2nr( '0O0548', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 5) + test_vim_str2nr( '0O054', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 6) + + test_vim_str2nr( '0O054x', flags, {len = 0}, 6) + test_vim_str2nr( '0O054x', flags, {len = 0}, 0) + test_vim_str2nr( '0O054x', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 6, false) + test_vim_str2nr( '0O054x', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 0, false) + + test_vim_str2nr('-0O054', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 0) + test_vim_str2nr('-0O054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1) + test_vim_str2nr('-0O054', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2) + test_vim_str2nr('-0O054', flags, {len = 0}, 3) + test_vim_str2nr('-0O054', flags, {len = 4, num = 0, unum = 0, pre = OCT}, 4) + test_vim_str2nr('-0O054', flags, {len = 5, num = -5, unum = 5, pre = OCT}, 5) + test_vim_str2nr('-0O054', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 6) + test_vim_str2nr('-0O0548', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 6) + test_vim_str2nr('-0O054', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 7) + + test_vim_str2nr('-0O054x', flags, {len = 0}, 7) + test_vim_str2nr('-0O054x', flags, {len = 0}, 0) + test_vim_str2nr('-0O054x', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 7, false) + test_vim_str2nr('-0O054x', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 0, false) + + if flags > lib.STR2NR_FORCE then + test_vim_str2nr('-0548', flags, {len = 0}, 5) + test_vim_str2nr('-0548', flags, {len = 0}, 0) + test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = 0}, 5, false) + test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = 0}, 0, false) + test_vim_str2nr('-055', flags, {len = 4, num = -45, unum = 45, pre = 0}, 0) + else + test_vim_str2nr('-0548', flags, {len = 5, num = -548, unum = 548, pre = 0}, 5) + test_vim_str2nr('-0548', flags, {len = 5, num = -548, unum = 548, pre = 0}, 0) + end + end + end) itp('works with hexadecimal numbers', function() for _, flags in ipairs({ lib.STR2NR_HEX, |