diff options
Diffstat (limited to 'src')
-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 |
4 files changed, 41 insertions, 12 deletions
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)) |