Merge #14611 from seandewar/vim-8.1.1116

vim-patch:8.1.{1116,1188,1190,1355,1722,2035,2036,2038,2043},8.2.{0886,2309}
This commit is contained in:
Justin M. Keyes 2021-09-11 12:12:59 -07:00 committed by GitHub
commit 413e86869e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 406 additions and 127 deletions

View File

@ -20,7 +20,7 @@ There are six types of variables:
*Number* *Integer* *Number* *Integer*
Number A 32 or 64 bit signed number. |expr-number| Number A 32 or 64 bit signed number. |expr-number|
The number of bits is available in |v:numbersize|. 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* Float A floating point number. |floating-point-format| *Float*
Examples: 123.456 1.15e-6 -1.1e3 Examples: 123.456 1.15e-6 -1.1e3
@ -54,14 +54,15 @@ 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. If the String doesn't start with digits, the result is zero. numbers are recognized. If the String doesn't start with digits, the result
Examples: is zero. 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 ~
@ -1085,7 +1086,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:
@ -2519,7 +2520,8 @@ stdpath({what}) String/List returns the standard path(s) for {w
str2float({expr}) Float convert String to Float str2float({expr}) Float convert String to Float
str2list({expr} [, {utf8}]) List convert each character of {expr} to str2list({expr} [, {utf8}]) List convert each character of {expr} to
ASCII/UTF8 value 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} strchars({expr} [, {skipcc}]) Number character length of the String {expr}
strcharpart({str}, {start} [, {len}]) strcharpart({str}, {start} [, {len}])
String {len} characters of {str} at String {len} characters of {str} at
@ -6572,9 +6574,9 @@ mkdir({name} [, {path} [, {prot}]])
If {path} is "p" then intermediate directories are created as If {path} is "p" then intermediate directories are created as
necessary. Otherwise it must be "". necessary. Otherwise it must be "".
If {prot} is given it is used to set the protection bits of 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 new directory. The default is 0o755 (rwxr-xr-x: r/w for
the user readable for others). Use 0700 to make it unreadable the user, readable for others). Use 0o700 to make it
for others. unreadable for others.
{prot} is applied for all parts of {name}. Thus if you create {prot} is applied for all parts of {name}. Thus if you create
/tmp/foo/bar then /tmp/foo will be created with 0700. Example: > /tmp/foo/bar then /tmp/foo will be created with 0700. Example: >
@ -8664,9 +8666,11 @@ str2list({expr} [, {utf8}]) *str2list()*
< Can also be used as a |method|: > < Can also be used as a |method|: >
GetString()->str2list() GetString()->str2list()
str2nr({expr} [, {base}]) *str2nr()* str2nr({expr} [, {base} [, {quoted}]]) *str2nr()*
Convert string {expr} to a number. Convert string {expr} to a number.
{base} is the conversion base, it can be 2, 8, 10 or 16. {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 When {base} is omitted base 10 is used. This also means that
a leading zero doesn't cause octal conversion to be used, as a leading zero doesn't cause octal conversion to be used, as
@ -8674,9 +8678,9 @@ str2nr({expr} [, {base}]) *str2nr()*
let nr = str2nr('123') let nr = str2nr('123')
< <
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 {base} different base the result will be zero. Similarly, when
is 8 a leading "0" is ignored, and when {base} is 2 a leading {base} is 8 a leading "0", "0o" or "0O" is ignored, and when
"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.
@ -10433,14 +10437,15 @@ This does NOT work: >
When the selected range of items is partly past the When the selected range of items is partly past the
end of the list, items will be added. end of the list, items will be added.
*:let+=* *:let-=* *:letstar=* *:let+=* *:let-=* *:letstar=*
*:let/=* *:let%=* *:let.=* *E734* *:let/=* *:let%=* *:let.=* *:let..=* *E734*
:let {var} += {expr1} Like ":let {var} = {var} + {expr1}". :let {var} += {expr1} Like ":let {var} = {var} + {expr1}".
:let {var} -= {expr1} Like ":let {var} = {var} - {expr1}". :let {var} -= {expr1} Like ":let {var} = {var} - {expr1}".
:let {var} *= {expr1} Like ":let {var} = {var} * {expr1}". :let {var} *= {expr1} Like ":let {var} = {var} * {expr1}".
:let {var} /= {expr1} Like ":let {var} = {var} / {expr1}". :let {var} /= {expr1} Like ":let {var} = {var} / {expr1}".
:let {var} %= {expr1} Like ":let {var} = {var} % {expr1}". :let {var} %= {expr1} Like ":let {var} = {var} % {expr1}".
:let {var} .= {expr1} Like ":let {var} = {var} . {expr1}". :let {var} .= {expr1} Like ":let {var} = {var} . {expr1}".
:let {var} ..= {expr1} Like ":let {var} = {var} .. {expr1}".
These fail if {var} was not set yet and when the type These fail if {var} was not set yet and when the type
of {var} and {expr1} don't fit the operator. of {var} and {expr1} don't fit the operator.

View File

@ -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 A hexadecimal number starts with "0x" or "0X". For example "0x1f" is decimal
31. 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. 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: > The ":echo" command always prints decimal numbers. Example: >
:echo 0x7f 036 :echo 0x7f 0o36
< 127 30 ~ < 127 30 ~
A number is made negative with a minus sign. This also works for hexadecimal, 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 octal and binary numbers. A minus sign is also used for subtraction. Compare
this with the previous example: > this with the previous example: >
:echo 0x7f -036 :echo 0x7f -0o36
< 97 ~ < 97 ~
White space in an expression is ignored. However, it's recommended to use it 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 avoid the confusion with a negative number above, put a space between the
minus sign and the following number: > minus sign and the following number: >
:echo 0x7f - 036 :echo 0x7f - 0o36
============================================================================== ==============================================================================
*41.2* Variables *41.2* Variables

View File

@ -460,6 +460,7 @@ Commands:
:Print :Print
:promptfind :promptfind
:promptrepl :promptrepl
:scriptversion (always version 1)
:shell :shell
:sleep! (does not hide the cursor; same as :sleep) :sleep! (does not hide the cursor; same as :sleep)
:smile :smile

View File

@ -169,6 +169,14 @@ static inline bool ascii_isbdigit(int c)
return (c == '0' || c == '1'); return (c == '0' || c == '1');
} }
/// Checks if `c` is an octal digit, that is, 0-7.
///
/// @see {ascii_isdigit}
static inline bool ascii_isodigit(int c)
{
return (c >= '0' && c <= '7');
}
/// Checks if `c` is a white-space character, that is, /// Checks if `c` is a white-space character, that is,
/// one of \f, \n, \r, \t, \v. /// one of \f, \n, \r, \t, \v.
/// ///

View File

@ -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: /// 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
@ -1396,20 +1398,25 @@ bool vim_isblankline(char_u *lbuf)
/// If "what" contains STR2NR_OCT recognize octal numbers. /// If "what" contains STR2NR_OCT recognize octal numbers.
/// If "what" contains STR2NR_HEX recognize hex numbers. /// If "what" contains STR2NR_HEX recognize hex numbers.
/// If "what" contains STR2NR_FORCE always assume bin/oct/hex. /// If "what" contains STR2NR_FORCE always assume bin/oct/hex.
/// If "what" contains STR2NR_QUOTE ignore embedded single quotes
/// If maxlen > 0, check at a maximum maxlen chars. /// If maxlen > 0, check at a maximum maxlen chars.
/// If strict is true, check the number strictly. return *len = 0 if fail.
/// ///
/// @param start /// @param start
/// @param prep Returns guessed type of number 0 = decimal, 'x' or 'X' is /// @param prep Returns guessed type of number 0 = decimal, 'x' or 'X' is
/// hexadecimal, '0' = octal, 'b' or 'B' is binary. When using /// hexadecimal, '0', 'o' or 'O' is octal, 'b' or 'B' is binary.
/// STR2NR_FORCE is always zero. /// When using STR2NR_FORCE is always zero.
/// @param len Returns the detected length of number. /// @param len Returns the detected length of number.
/// @param what Recognizes what number passed, @see ChStr2NrFlags. /// @param what Recognizes what number passed, @see ChStr2NrFlags.
/// @param nptr Returns the signed result. /// @param nptr Returns the signed result.
/// @param unptr Returns the unsigned result. /// @param unptr Returns the unsigned result.
/// @param maxlen Max length of string to check. /// @param maxlen Max length of string to check.
/// @param strict If true, fail if the number has unexpected trailing
/// alpha-numeric chars: *len is set to 0 and nothing else is
/// returned.
void vim_str2nr(const char_u *const start, int *const prep, int *const len, void vim_str2nr(const char_u *const start, int *const prep, int *const len,
const int what, varnumber_T *const nptr, const int what, varnumber_T *const nptr,
uvarnumber_T *const unptr, const int maxlen) uvarnumber_T *const unptr, const int maxlen, const bool strict)
FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_NONNULL_ARG(1)
{ {
const char *ptr = (const char *)start; const char *ptr = (const char *)start;
@ -1419,14 +1426,18 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len,
const bool negative = (ptr[0] == '-'); const bool negative = (ptr[0] == '-');
uvarnumber_T un = 0; uvarnumber_T un = 0;
if (len != NULL) {
*len = 0;
}
if (negative) { if (negative) {
ptr++; ptr++;
} }
if (what & STR2NR_FORCE) { if (what & STR2NR_FORCE) {
// When forcing main consideration is skipping the prefix. Octal and decimal // When forcing main consideration is skipping the prefix. Decimal numbers
// numbers have no prefixes to skip. pre is not set. // have no prefixes to skip. pre is not set.
switch ((unsigned)what & (~(unsigned)STR2NR_FORCE)) { switch (what & ~(STR2NR_FORCE | STR2NR_QUOTE)) {
case STR2NR_HEX: { case STR2NR_HEX: {
if (!STRING_ENDED(ptr + 2) if (!STRING_ENDED(ptr + 2)
&& ptr[0] == '0' && ptr[0] == '0'
@ -1445,7 +1456,16 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len,
} }
goto vim_str2nr_bin; 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_isodigit(ptr[2])) {
ptr += 2;
}
goto vim_str2nr_oct; goto vim_str2nr_oct;
} }
case 0: { case 0: {
@ -1455,9 +1475,9 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len,
abort(); abort();
} }
} }
} else if ((what & (STR2NR_HEX|STR2NR_OCT|STR2NR_BIN)) } else if ((what & (STR2NR_HEX | STR2NR_OCT | STR2NR_OOCT | STR2NR_BIN))
&& !STRING_ENDED(ptr + 1) && !STRING_ENDED(ptr + 1) && ptr[0] == '0' && ptr[1] != '8'
&& ptr[0] == '0' && ptr[1] != '8' && ptr[1] != '9') { && ptr[1] != '9') {
pre = ptr[1]; pre = ptr[1];
// Detect hexadecimal: 0x or 0X followed by hex digit. // Detect hexadecimal: 0x or 0X followed by hex digit.
if ((what & STR2NR_HEX) if ((what & STR2NR_HEX)
@ -1475,10 +1495,18 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len,
ptr += 2; ptr += 2;
goto vim_str2nr_bin; 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_isodigit(ptr[2])) {
ptr += 2;
goto vim_str2nr_oct;
}
// Detect old octal format: 0 followed by octal digits.
pre = 0; pre = 0;
if (!(what & STR2NR_OCT) if (!(what & STR2NR_OCT)
|| !('0' <= ptr[1] && ptr[1] <= '7')) { || !ascii_isodigit(ptr[1])) {
goto vim_str2nr_dec; goto vim_str2nr_dec;
} }
for (int i = 2; !STRING_ENDED(ptr + i) && ascii_isdigit(ptr[i]); i++) { for (int i = 2; !STRING_ENDED(ptr + i) && ascii_isdigit(ptr[i]); i++) {
@ -1492,11 +1520,22 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len,
goto vim_str2nr_dec; goto vim_str2nr_dec;
} }
// Do the string-to-numeric conversion "manually" to avoid sscanf quirks. // Do the conversion manually to avoid sscanf() quirks.
abort(); // Shouldve used goto earlier. abort(); // Shouldve used goto earlier.
#define PARSE_NUMBER(base, cond, conv) \ #define PARSE_NUMBER(base, cond, conv) \
do { \ do { \
while (!STRING_ENDED(ptr) && (cond)) { \ const char *const after_prefix = ptr; \
while (!STRING_ENDED(ptr)) { \
if ((what & STR2NR_QUOTE) && ptr > after_prefix && *ptr == '\'') { \
ptr++; \
if (!STRING_ENDED(ptr) && (cond)) { \
continue; \
} \
ptr--; \
} \
if (!(cond)) { \
break; \
} \
const uvarnumber_T digit = (uvarnumber_T)(conv); \ const uvarnumber_T digit = (uvarnumber_T)(conv); \
/* avoid ubsan error for overflow */ \ /* avoid ubsan error for overflow */ \
if (un < UVARNUMBER_MAX / base \ if (un < UVARNUMBER_MAX / base \
@ -1513,7 +1552,7 @@ vim_str2nr_bin:
PARSE_NUMBER(2, (*ptr == '0' || *ptr == '1'), (*ptr - '0')); PARSE_NUMBER(2, (*ptr == '0' || *ptr == '1'), (*ptr - '0'));
goto vim_str2nr_proceed; goto vim_str2nr_proceed;
vim_str2nr_oct: vim_str2nr_oct:
PARSE_NUMBER(8, ('0' <= *ptr && *ptr <= '7'), (*ptr - '0')); PARSE_NUMBER(8, (ascii_isodigit(*ptr)), (*ptr - '0'));
goto vim_str2nr_proceed; goto vim_str2nr_proceed;
vim_str2nr_dec: vim_str2nr_dec:
PARSE_NUMBER(10, (ascii_isdigit(*ptr)), (*ptr - '0')); PARSE_NUMBER(10, (ascii_isdigit(*ptr)), (*ptr - '0'));
@ -1524,6 +1563,12 @@ vim_str2nr_hex:
#undef PARSE_NUMBER #undef PARSE_NUMBER
vim_str2nr_proceed: vim_str2nr_proceed:
// Check for an alpha-numeric character immediately following, that is
// most likely a typo.
if (strict && ptr - (const char *)start != maxlen && ASCII_ISALNUM(*ptr)) {
return;
}
if (prep != NULL) { if (prep != NULL) {
*prep = pre; *prep = pre;
} }

View File

@ -23,13 +23,20 @@ typedef enum {
STR2NR_BIN = (1 << 0), ///< Allow binary numbers. STR2NR_BIN = (1 << 0), ///< Allow binary numbers.
STR2NR_OCT = (1 << 1), ///< Allow octal numbers. STR2NR_OCT = (1 << 1), ///< Allow octal numbers.
STR2NR_HEX = (1 << 2), ///< Allow hexadecimal numbers. STR2NR_HEX = (1 << 2), ///< Allow hexadecimal numbers.
STR2NR_OOCT = (1 << 3), ///< Octal with prefix "0o": 0o777
/// Force one of the above variants. /// Force one of the above variants.
/// ///
/// STR2NR_FORCE|STR2NR_DEC is actually not different from supplying zero /// STR2NR_FORCE|STR2NR_DEC is actually not different from supplying zero
/// as flags, but still present for completeness. /// as flags, but still present for completeness.
STR2NR_FORCE = (1 << 3), ///
/// 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. /// Recognize all formats vim_str2nr() can recognize.
STR2NR_ALL = STR2NR_BIN | STR2NR_OCT | STR2NR_HEX, 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; } ChStr2NrFlags;
#ifdef INCLUDE_GENERATED_DECLARATIONS #ifdef INCLUDE_GENERATED_DECLARATIONS

View File

@ -1456,21 +1456,18 @@ static void ex_let_const(exarg_T *eap, const bool is_const)
/* /*
* Assign the typevalue "tv" to the variable or variables at "arg_start". * Assign the typevalue "tv" to the variable or variables at "arg_start".
* Handles both "var" with any type and "[var, var; var]" with a list type. * Handles both "var" with any type and "[var, var; var]" with a list type.
* When "nextchars" is not NULL it points to a string with characters that * When "op" is not NULL it points to a string with characters that
* must appear after the variable(s). Use "+", "-" or "." for add, subtract * must appear after the variable(s). Use "+", "-" or "." for add, subtract
* or concatenate. * or concatenate.
* Returns OK or FAIL; * Returns OK or FAIL;
*/ */
static int static int ex_let_vars(char_u *arg_start,
ex_let_vars( typval_T *tv,
char_u *arg_start, int copy, // copy values from "tv", don't move
typval_T *tv, int semicolon, // from skip_var_list()
int copy, // copy values from "tv", don't move int var_count, // from skip_var_list()
int semicolon, // from skip_var_list() int is_const, // lock variables for :const
int var_count, // from skip_var_list() char_u *op)
int is_const, // lock variables for :const
char_u *nextchars
)
{ {
char_u *arg = arg_start; char_u *arg = arg_start;
typval_T ltv; typval_T ltv;
@ -1479,7 +1476,7 @@ ex_let_vars(
/* /*
* ":let var = expr" or ":for var in list" * ":let var = expr" or ":for var in list"
*/ */
if (ex_let_one(arg, tv, copy, is_const, nextchars, nextchars) == NULL) { if (ex_let_one(arg, tv, copy, is_const, op, op) == NULL) {
return FAIL; return FAIL;
} }
return OK; return OK;
@ -1510,7 +1507,7 @@ ex_let_vars(
while (*arg != ']') { while (*arg != ']') {
arg = skipwhite(arg + 1); arg = skipwhite(arg + 1);
arg = ex_let_one(arg, TV_LIST_ITEM_TV(item), true, is_const, arg = ex_let_one(arg, TV_LIST_ITEM_TV(item), true, is_const,
(const char_u *)",;]", nextchars); (const char_u *)",;]", op);
if (arg == NULL) { if (arg == NULL) {
return FAIL; return FAIL;
} }
@ -1532,8 +1529,8 @@ ex_let_vars(
ltv.vval.v_list = rest_list; ltv.vval.v_list = rest_list;
tv_list_ref(rest_list); tv_list_ref(rest_list);
arg = ex_let_one(skipwhite(arg + 1), &ltv, false, is_const, arg = ex_let_one(skipwhite(arg + 1), &ltv, false, is_const, (char_u *)"]",
(char_u *)"]", nextchars); op);
tv_clear(&ltv); tv_clear(&ltv);
if (arg == NULL) { if (arg == NULL) {
return FAIL; return FAIL;
@ -3950,7 +3947,12 @@ static int eval7(
rettv->vval.v_float = f; rettv->vval.v_float = f;
} }
} else { } else {
vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0); vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0, true);
if (len == 0) {
EMSG2(_(e_invexpr2), *arg);
ret = FAIL;
break;
}
*arg += len; *arg += len;
if (evaluate) { if (evaluate) {
rettv->v_type = VAR_NUMBER; rettv->v_type = VAR_NUMBER;
@ -8670,6 +8672,7 @@ handle_subscript(
} }
} }
// "." is ".name" lookup when we found a dict.
while (ret == OK while (ret == OK
&& (((**arg == '[' || (**arg == '.' && rettv->v_type == VAR_DICT) && (((**arg == '[' || (**arg == '.' && rettv->v_type == VAR_DICT)
|| (**arg == '(' && (!evaluate || tv_is_func(*rettv)))) || (**arg == '(' && (!evaluate || tv_is_func(*rettv))))

View File

@ -344,7 +344,7 @@ return {
stdpath={args=1}, stdpath={args=1},
str2float={args=1, base=1}, str2float={args=1, base=1},
str2list={args={1, 2}, base=1}, str2list={args={1, 2}, base=1},
str2nr={args={1, 2}}, str2nr={args={1, 3}},
strcharpart={args={2, 3}}, strcharpart={args={2, 3}},
strchars={args={1,2}}, strchars={args={1,2}},
strdisplaywidth={args={1, 2}}, strdisplaywidth={args={1, 2}},

View File

@ -437,7 +437,7 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len,
t += 4; t += 4;
uvarnumber_T ch; uvarnumber_T ch;
vim_str2nr((char_u *)ubuf, NULL, NULL, vim_str2nr((char_u *)ubuf, NULL, NULL,
STR2NR_HEX | STR2NR_FORCE, NULL, &ch, 4); STR2NR_HEX | STR2NR_FORCE, NULL, &ch, 4, true);
if (ch == 0) { if (ch == 0) {
hasnul = true; hasnul = true;
} }
@ -611,8 +611,8 @@ parse_json_number_check:
// Convert integer // Convert integer
varnumber_T nr; varnumber_T nr;
int num_len; int num_len;
vim_str2nr((char_u *) s, NULL, &num_len, 0, &nr, NULL, (int) (p - s)); vim_str2nr((char_u *)s, NULL, &num_len, 0, &nr, NULL, (int)(p - s), true);
if ((int) exp_num_len != num_len) { if ((int)exp_num_len != num_len) {
emsgf(_("E685: internal error: while converting number \"%.*s\" " emsgf(_("E685: internal error: while converting number \"%.*s\" "
"to integer vim_str2nr consumed %i bytes in place of %zu"), "to integer vim_str2nr consumed %i bytes in place of %zu"),
(int) exp_num_len, s, num_len, exp_num_len); (int) exp_num_len, s, num_len, exp_num_len);

View File

@ -9998,7 +9998,7 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{ {
int base = 10; int base = 10;
varnumber_T n; varnumber_T n;
int what; int what = 0;
if (argvars[1].v_type != VAR_UNKNOWN) { if (argvars[1].v_type != VAR_UNKNOWN) {
base = tv_get_number(&argvars[1]); base = tv_get_number(&argvars[1]);
@ -10006,6 +10006,9 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
EMSG(_(e_invarg)); EMSG(_(e_invarg));
return; return;
} }
if (argvars[2].v_type != VAR_UNKNOWN && tv_get_number(&argvars[2])) {
what |= STR2NR_QUOTE;
}
} }
char_u *p = skipwhite((const char_u *)tv_get_string(&argvars[0])); char_u *p = skipwhite((const char_u *)tv_get_string(&argvars[0]));
@ -10015,22 +10018,20 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
} }
switch (base) { switch (base) {
case 2: { case 2: {
what = STR2NR_BIN | STR2NR_FORCE; what |= STR2NR_BIN | STR2NR_FORCE;
break; break;
} }
case 8: { case 8: {
what = STR2NR_OCT | STR2NR_FORCE; what |= STR2NR_OCT | STR2NR_OOCT | STR2NR_FORCE;
break; break;
} }
case 16: { case 16: {
what = STR2NR_HEX | STR2NR_FORCE; what |= STR2NR_HEX | STR2NR_FORCE;
break; break;
} }
default: {
what = 0;
}
} }
vim_str2nr(p, NULL, NULL, what, &n, NULL, 0); vim_str2nr(p, NULL, NULL, what, &n, NULL, 0, false);
// Text after the number is silently ignored.
if (isneg) { if (isneg) {
rettv->vval.v_number = -n; rettv->vval.v_number = -n;
} else { } else {

View File

@ -2990,7 +2990,8 @@ varnumber_T tv_get_number_chk(const typval_T *const tv, bool *const ret_error)
case VAR_STRING: { case VAR_STRING: {
varnumber_T n = 0; varnumber_T n = 0;
if (tv->vval.v_string != NULL) { if (tv->vval.v_string != NULL) {
vim_str2nr(tv->vval.v_string, NULL, NULL, STR2NR_ALL, &n, NULL, 0); vim_str2nr(tv->vval.v_string, NULL, NULL, STR2NR_ALL, &n, NULL, 0,
false);
} }
return n; return n;
} }

View File

@ -609,7 +609,7 @@ void ex_sort(exarg_T *eap)
} else { } else {
nrs[lnum - eap->line1].st_u.num.is_number = true; nrs[lnum - eap->line1].st_u.num.is_number = true;
vim_str2nr(s, NULL, NULL, sort_what, vim_str2nr(s, NULL, NULL, sort_what,
&nrs[lnum - eap->line1].st_u.num.value, NULL, 0); &nrs[lnum - eap->line1].st_u.num.value, NULL, 0, false);
} }
} else { } else {
s = skipwhite(p); s = skipwhite(p);

View File

@ -6056,7 +6056,7 @@ int get_list_range(char_u **str, int *num1, int *num2)
*str = skipwhite(*str); *str = skipwhite(*str);
if (**str == '-' || ascii_isdigit(**str)) { // parse "from" part of range if (**str == '-' || ascii_isdigit(**str)) { // parse "from" part of range
vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0); vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, false);
*str += len; *str += len;
*num1 = (int)num; *num1 = (int)num;
first = true; first = true;
@ -6064,7 +6064,7 @@ int get_list_range(char_u **str, int *num1, int *num2)
*str = skipwhite(*str); *str = skipwhite(*str);
if (**str == ',') { // parse "to" part of range if (**str == ',') { // parse "to" part of range
*str = skipwhite(*str + 1); *str = skipwhite(*str + 1);
vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0); vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, false);
if (len > 0) { if (len > 0) {
*num2 = (int)num; *num2 = (int)num;
*str = skipwhite(*str + len); *str = skipwhite(*str + len);

View File

@ -628,7 +628,11 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp,
if (end - bp > 3 && bp[0] == 't' && bp[1] == '_') { if (end - bp > 3 && bp[0] == 't' && bp[1] == '_') {
bp += 3; // skip t_xx, xx may be '-' or '>' bp += 3; // skip t_xx, xx may be '-' or '>'
} else if (end - bp > 4 && STRNICMP(bp, "char-", 5) == 0) { } else if (end - bp > 4 && STRNICMP(bp, "char-", 5) == 0) {
vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0); vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0, true);
if (l == 0) {
EMSG(_(e_invarg));
return 0;
}
bp += l + 5; bp += l + 5;
break; break;
} }
@ -654,7 +658,11 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp,
if (STRNICMP(last_dash + 1, "char-", 5) == 0 if (STRNICMP(last_dash + 1, "char-", 5) == 0
&& ascii_isdigit(last_dash[6])) { && ascii_isdigit(last_dash[6])) {
// <Char-123> or <Char-033> or <Char-0x33> // <Char-123> or <Char-033> or <Char-0x33>
vim_str2nr(last_dash + 6, NULL, NULL, STR2NR_ALL, NULL, &n, 0); vim_str2nr(last_dash + 6, NULL, &l, STR2NR_ALL, NULL, &n, 0, true);
if (l == 0) {
EMSG(_(e_invarg));
return 0;
}
key = (int)n; key = (int)n;
} else { } else {
int off = 1; int off = 1;

View File

@ -5017,7 +5017,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
0 + (do_bin ? STR2NR_BIN : 0) 0 + (do_bin ? STR2NR_BIN : 0)
+ (do_oct ? STR2NR_OCT : 0) + (do_oct ? STR2NR_OCT : 0)
+ (do_hex ? STR2NR_HEX : 0), + (do_hex ? STR2NR_HEX : 0),
NULL, &n, maxlen); NULL, &n, maxlen, false);
// ignore leading '-' for hex, octal and bin numbers // ignore leading '-' for hex, octal and bin numbers
if (pre && negative) { if (pre && negative) {

View File

@ -1276,9 +1276,9 @@ int do_set(
} }
} else if (*arg == '-' || ascii_isdigit(*arg)) { } else if (*arg == '-' || ascii_isdigit(*arg)) {
// Allow negative, octal and hex numbers. // Allow negative, octal and hex numbers.
vim_str2nr(arg, NULL, &i, STR2NR_ALL, &value, NULL, 0); vim_str2nr(arg, NULL, &i, STR2NR_ALL, &value, NULL, 0, true);
if (arg[i] != NUL && !ascii_iswhite(arg[i])) { if (i == 0 || (arg[i] != NUL && !ascii_iswhite(arg[i]))) {
errmsg = e_invarg; errmsg = (char_u *)N_("E521: Number required after =");
goto skip; goto skip;
} }
} else { } else {
@ -7486,7 +7486,7 @@ unsigned int get_bkc_value(buf_T *buf)
/// ///
/// @param win If not NULL, the window to get the local option from; global /// @param win If not NULL, the window to get the local option from; global
/// otherwise. /// otherwise.
char_u *get_showbreak_value(win_T *const win FUNC_ATTR_UNUSED) char_u *get_showbreak_value(win_T *const win)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_WARN_UNUSED_RESULT
{ {
if (win->w_p_sbr == NULL || *win->w_p_sbr == NUL) { if (win->w_p_sbr == NULL || *win->w_p_sbr == NUL) {

View File

@ -33,6 +33,24 @@ func Test_for_invalid()
redraw redraw
endfunc endfunc
func Test_readfile_binary()
new
call setline(1, ['one', 'two', 'three'])
setlocal ff=dos
silent write XReadfile
let lines = readfile('XReadfile')
call assert_equal(['one', 'two', 'three'], lines)
let lines = readfile('XReadfile', '', 2)
call assert_equal(['one', 'two'], lines)
let lines = readfile('XReadfile', 'b')
call assert_equal(["one\r", "two\r", "three\r", ""], lines)
let lines = readfile('XReadfile', 'b', 2)
call assert_equal(["one\r", "two\r"], lines)
bwipe!
call delete('XReadfile')
endfunc
func Test_mkdir_p() func Test_mkdir_p()
call mkdir('Xmkdir/nested', 'p') call mkdir('Xmkdir/nested', 'p')
call assert_true(isdirectory('Xmkdir/nested')) call assert_true(isdirectory('Xmkdir/nested'))
@ -90,6 +108,15 @@ func Test_string_concatenation()
call assert_equal('ab', a) call assert_equal('ab', a)
endfunc endfunc
" Test fix for issue #4507
func Test_skip_after_throw()
try
throw 'something'
let x = wincol() || &ts
catch /something/
endtry
endfunc
func Test_nocatch_restore_silent_emsg() func Test_nocatch_restore_silent_emsg()
silent! try silent! try
throw 1 throw 1
@ -111,15 +138,6 @@ func Test_let_errmsg()
let v:errmsg = '' let v:errmsg = ''
endfunc endfunc
" Test fix for issue #4507
func Test_skip_after_throw()
try
throw 'something'
let x = wincol() || &ts
catch /something/
endtry
endfunc
func Test_number_max_min_size() func Test_number_max_min_size()
" This will fail on systems without 64 bit number support or when not " This will fail on systems without 64 bit number support or when not
" configured correctly. " configured correctly.

View File

@ -502,6 +502,17 @@ func Test_empty_concatenate()
call assert_equal('b', 'b' . 'a'[4:0]) call assert_equal('b', 'b' . 'a'[4:0])
endfunc endfunc
func Test_broken_number()
let X = 'bad'
call assert_fails('echo 1X', 'E15:')
call assert_fails('echo 0b1X', 'E15:')
call assert_fails('echo 0b12', 'E15:')
call assert_fails('echo 0x1X', 'E15:')
call assert_fails('echo 011X', 'E15:')
call assert_equal(2, str2nr('2a'))
call assert_fails('inoremap <Char-0b1z> b', 'E474:')
endfunc
func Test_eval_after_if() func Test_eval_after_if()
let s:val = '' let s:val = ''
func SetVal(x) func SetVal(x)

View File

@ -152,6 +152,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))
@ -161,8 +165,16 @@ func Test_str2nr()
call assert_equal(11259375, str2nr('0XABCDEF', 16)) call assert_equal(11259375, str2nr('0XABCDEF', 16))
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(1000, 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('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

@ -351,7 +351,7 @@ LexExprToken viml_pexpr_next_token(ParserState *const pstate, const int flags)
} }
if (exp_start) { if (exp_start) {
vim_str2nr(pline.data + exp_start, NULL, NULL, 0, NULL, &exp_part, vim_str2nr(pline.data + exp_start, NULL, NULL, 0, NULL, &exp_part,
(int)(ret.len - exp_start)); (int)(ret.len - exp_start), false);
} }
if (exp_negative) { if (exp_negative) {
exp_part += frac_size; exp_part += frac_size;
@ -369,7 +369,7 @@ LexExprToken viml_pexpr_next_token(ParserState *const pstate, const int flags)
int len; int len;
int prep; int prep;
vim_str2nr(pline.data, &prep, &len, STR2NR_ALL, NULL, vim_str2nr(pline.data, &prep, &len, STR2NR_ALL, NULL,
&ret.data.num.val.integer, (int)pline.size); &ret.data.num.val.integer, (int)pline.size, false);
ret.len = (size_t)len; ret.len = (size_t)len;
const uint8_t bases[] = { const uint8_t bases[] = {
[0] = 10, [0] = 10,

View File

@ -43,7 +43,8 @@ local function argreset(arg, args)
end end
end end
local function test_vim_str2nr(s, what, exp, maxlen) local function test_vim_str2nr(s, what, exp, maxlen, strict)
if strict == nil then strict = true end
local bits = {} local bits = {}
for k, _ in pairs(exp) do for k, _ in pairs(exp) do
bits[#bits + 1] = k bits[#bits + 1] = k
@ -62,11 +63,11 @@ local function test_vim_str2nr(s, what, exp, maxlen)
cv[k] = args[k] cv[k] = args[k]
end end
end end
lib.vim_str2nr(s, cv.pre, cv.len, what, cv.num, cv.unum, maxlen) lib.vim_str2nr(s, cv.pre, cv.len, what, cv.num, cv.unum, maxlen, strict)
for cck, ccv in pairs(cv) do for cck, ccv in pairs(cv) do
if exp[cck] ~= tonumber(ccv[0]) then if exp[cck] ~= tonumber(ccv[0]) then
error(('Failed check (%s = %d) in test (s=%s, w=%u, m=%d): %d'):format( error(('Failed check (%s = %d) in test (s=%s, w=%u, m=%d, strict=%s): %d'):format(
cck, exp[cck], s, tonumber(what), maxlen, tonumber(ccv[0]) cck, exp[cck], s, tonumber(what), maxlen, tostring(strict), tonumber(ccv[0])
)) ))
end end
end end
@ -85,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_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_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_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_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_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_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_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) test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_HEX, {len = 0, num = 0, unum = 0, pre = 0}, 0)
end) end)
itp('works with decimal numbers', function() itp('works with decimal numbers', function()
@ -97,31 +101,39 @@ describe('vim_str2nr()', function()
lib.STR2NR_BIN, lib.STR2NR_BIN,
lib.STR2NR_OCT, lib.STR2NR_OCT,
lib.STR2NR_HEX, lib.STR2NR_HEX,
lib.STR2NR_OOCT,
lib.STR2NR_BIN + lib.STR2NR_OCT, lib.STR2NR_BIN + lib.STR2NR_OCT,
lib.STR2NR_BIN + lib.STR2NR_HEX, lib.STR2NR_BIN + lib.STR2NR_HEX,
lib.STR2NR_OCT + lib.STR2NR_HEX, lib.STR2NR_OCT + lib.STR2NR_HEX,
lib.STR2NR_OOCT + lib.STR2NR_HEX,
lib.STR2NR_ALL, lib.STR2NR_ALL,
lib.STR2NR_FORCE + lib.STR2NR_DEC, lib.STR2NR_FORCE + lib.STR2NR_DEC,
}) do }) do
-- Check that all digits are recognized -- Check that all digits are recognized
test_vim_str2nr( '12345', flags, {len = 5, num = 12345, unum = 12345, pre = 0}, 0) test_vim_str2nr( '12345', flags, {len = 5, num = 12345, unum = 12345, pre = 0}, 0)
test_vim_str2nr( '67890', flags, {len = 5, num = 67890, unum = 67890, pre = 0}, 0) test_vim_str2nr( '67890', flags, {len = 5, num = 67890, unum = 67890, pre = 0}, 0)
test_vim_str2nr( '12345A', flags, {len = 5, num = 12345, unum = 12345, pre = 0}, 0) test_vim_str2nr( '12345A', flags, {len = 0}, 0)
test_vim_str2nr( '67890A', flags, {len = 5, num = 67890, unum = 67890, pre = 0}, 0) test_vim_str2nr( '67890A', flags, {len = 0}, 0)
test_vim_str2nr( '12345A', flags, {len = 5, num = 12345, unum = 12345, pre = 0}, 0, false)
test_vim_str2nr( '67890A', flags, {len = 5, num = 67890, unum = 67890, pre = 0}, 0, false)
test_vim_str2nr( '42', flags, {len = 2, num = 42, unum = 42, pre = 0}, 0) test_vim_str2nr( '42', flags, {len = 2, num = 42, unum = 42, pre = 0}, 0)
test_vim_str2nr( '42', flags, {len = 1, num = 4, unum = 4, pre = 0}, 1) test_vim_str2nr( '42', flags, {len = 1, num = 4, unum = 4, pre = 0}, 1)
test_vim_str2nr( '42', flags, {len = 2, num = 42, unum = 42, pre = 0}, 2) test_vim_str2nr( '42', flags, {len = 2, num = 42, unum = 42, pre = 0}, 2)
test_vim_str2nr( '42', flags, {len = 2, num = 42, unum = 42, pre = 0}, 3) -- includes NUL byte in maxlen test_vim_str2nr( '42', flags, {len = 2, num = 42, unum = 42, pre = 0}, 3) -- includes NUL byte in maxlen
test_vim_str2nr( '42x', flags, {len = 2, num = 42, unum = 42, pre = 0}, 0) test_vim_str2nr( '42x', flags, {len = 0}, 0)
test_vim_str2nr( '42x', flags, {len = 2, num = 42, unum = 42, pre = 0}, 3) test_vim_str2nr( '42x', flags, {len = 0}, 3)
test_vim_str2nr( '42x', flags, {len = 2, num = 42, unum = 42, pre = 0}, 0, false)
test_vim_str2nr( '42x', flags, {len = 2, num = 42, unum = 42, pre = 0}, 3, false)
test_vim_str2nr('-42', flags, {len = 3, num = -42, unum = 42, pre = 0}, 3) test_vim_str2nr('-42', flags, {len = 3, num = -42, unum = 42, pre = 0}, 3)
test_vim_str2nr('-42', flags, {len = 1, num = 0, unum = 0, pre = 0}, 1) test_vim_str2nr('-42', flags, {len = 1, num = 0, unum = 0, pre = 0}, 1)
test_vim_str2nr('-42x', flags, {len = 3, num = -42, unum = 42, pre = 0}, 0) test_vim_str2nr('-42x', flags, {len = 0}, 0)
test_vim_str2nr('-42x', flags, {len = 3, num = -42, unum = 42, pre = 0}, 4) test_vim_str2nr('-42x', flags, {len = 0}, 4)
test_vim_str2nr('-42x', flags, {len = 3, num = -42, unum = 42, pre = 0}, 0, false)
test_vim_str2nr('-42x', flags, {len = 3, num = -42, unum = 42, pre = 0}, 4, false)
end end
end) end)
itp('works with binary numbers', function() itp('works with binary numbers', function()
@ -144,62 +156,77 @@ describe('vim_str2nr()', function()
test_vim_str2nr( '0b101', flags, {len = 5, num = 5, unum = 5, pre = bin}, 0) test_vim_str2nr( '0b101', flags, {len = 5, num = 5, unum = 5, pre = bin}, 0)
test_vim_str2nr( '0b101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1) test_vim_str2nr( '0b101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
test_vim_str2nr( '0b101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2) test_vim_str2nr( '0b101', flags, {len = 0}, 2)
test_vim_str2nr( '0b101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
test_vim_str2nr( '0b101', flags, {len = 3, num = 1, unum = 1, pre = bin}, 3) test_vim_str2nr( '0b101', flags, {len = 3, num = 1, unum = 1, pre = bin}, 3)
test_vim_str2nr( '0b101', flags, {len = 4, num = 2, unum = 2, pre = bin}, 4) test_vim_str2nr( '0b101', flags, {len = 4, num = 2, unum = 2, pre = bin}, 4)
test_vim_str2nr( '0b101', flags, {len = 5, num = 5, unum = 5, pre = bin}, 5) test_vim_str2nr( '0b101', flags, {len = 5, num = 5, unum = 5, pre = bin}, 5)
test_vim_str2nr( '0b101', flags, {len = 5, num = 5, unum = 5, pre = bin}, 6) test_vim_str2nr( '0b101', flags, {len = 5, num = 5, unum = 5, pre = bin}, 6)
test_vim_str2nr( '0b1012', flags, {len = 5, num = 5, unum = 5, pre = bin}, 0) test_vim_str2nr( '0b1012', flags, {len = 0}, 0)
test_vim_str2nr( '0b1012', flags, {len = 5, num = 5, unum = 5, pre = bin}, 6) test_vim_str2nr( '0b1012', flags, {len = 0}, 6)
test_vim_str2nr( '0b1012', flags, {len = 5, num = 5, unum = 5, pre = bin}, 0, false)
test_vim_str2nr( '0b1012', flags, {len = 5, num = 5, unum = 5, pre = bin}, 6, false)
test_vim_str2nr('-0b101', flags, {len = 6, num = -5, unum = 5, pre = bin}, 0) test_vim_str2nr('-0b101', flags, {len = 6, num = -5, unum = 5, pre = bin}, 0)
test_vim_str2nr('-0b101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1) test_vim_str2nr('-0b101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
test_vim_str2nr('-0b101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2) test_vim_str2nr('-0b101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
test_vim_str2nr('-0b101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3) test_vim_str2nr('-0b101', flags, {len = 0}, 3)
test_vim_str2nr('-0b101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
test_vim_str2nr('-0b101', flags, {len = 4, num = -1, unum = 1, pre = bin}, 4) test_vim_str2nr('-0b101', flags, {len = 4, num = -1, unum = 1, pre = bin}, 4)
test_vim_str2nr('-0b101', flags, {len = 5, num = -2, unum = 2, pre = bin}, 5) test_vim_str2nr('-0b101', flags, {len = 5, num = -2, unum = 2, pre = bin}, 5)
test_vim_str2nr('-0b101', flags, {len = 6, num = -5, unum = 5, pre = bin}, 6) test_vim_str2nr('-0b101', flags, {len = 6, num = -5, unum = 5, pre = bin}, 6)
test_vim_str2nr('-0b101', flags, {len = 6, num = -5, unum = 5, pre = bin}, 7) test_vim_str2nr('-0b101', flags, {len = 6, num = -5, unum = 5, pre = bin}, 7)
test_vim_str2nr('-0b1012', flags, {len = 6, num = -5, unum = 5, pre = bin}, 0) test_vim_str2nr('-0b1012', flags, {len = 0}, 0)
test_vim_str2nr('-0b1012', flags, {len = 6, num = -5, unum = 5, pre = bin}, 7) test_vim_str2nr('-0b1012', flags, {len = 0}, 7)
test_vim_str2nr('-0b1012', flags, {len = 6, num = -5, unum = 5, pre = bin}, 0, false)
test_vim_str2nr('-0b1012', flags, {len = 6, num = -5, unum = 5, pre = bin}, 7, false)
test_vim_str2nr( '0B101', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 0) test_vim_str2nr( '0B101', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 0)
test_vim_str2nr( '0B101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1) test_vim_str2nr( '0B101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
test_vim_str2nr( '0B101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2) test_vim_str2nr( '0B101', flags, {len = 0}, 2)
test_vim_str2nr( '0B101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
test_vim_str2nr( '0B101', flags, {len = 3, num = 1, unum = 1, pre = BIN}, 3) test_vim_str2nr( '0B101', flags, {len = 3, num = 1, unum = 1, pre = BIN}, 3)
test_vim_str2nr( '0B101', flags, {len = 4, num = 2, unum = 2, pre = BIN}, 4) test_vim_str2nr( '0B101', flags, {len = 4, num = 2, unum = 2, pre = BIN}, 4)
test_vim_str2nr( '0B101', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 5) test_vim_str2nr( '0B101', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 5)
test_vim_str2nr( '0B101', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 6) test_vim_str2nr( '0B101', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 6)
test_vim_str2nr( '0B1012', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 0) test_vim_str2nr( '0B1012', flags, {len = 0}, 0)
test_vim_str2nr( '0B1012', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 6) test_vim_str2nr( '0B1012', flags, {len = 0}, 6)
test_vim_str2nr( '0B1012', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 0, false)
test_vim_str2nr( '0B1012', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 6, false)
test_vim_str2nr('-0B101', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 0) test_vim_str2nr('-0B101', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 0)
test_vim_str2nr('-0B101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1) test_vim_str2nr('-0B101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
test_vim_str2nr('-0B101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2) test_vim_str2nr('-0B101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
test_vim_str2nr('-0B101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3) test_vim_str2nr('-0B101', flags, {len = 0}, 3)
test_vim_str2nr('-0B101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
test_vim_str2nr('-0B101', flags, {len = 4, num = -1, unum = 1, pre = BIN}, 4) test_vim_str2nr('-0B101', flags, {len = 4, num = -1, unum = 1, pre = BIN}, 4)
test_vim_str2nr('-0B101', flags, {len = 5, num = -2, unum = 2, pre = BIN}, 5) test_vim_str2nr('-0B101', flags, {len = 5, num = -2, unum = 2, pre = BIN}, 5)
test_vim_str2nr('-0B101', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 6) test_vim_str2nr('-0B101', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 6)
test_vim_str2nr('-0B101', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 7) test_vim_str2nr('-0B101', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 7)
test_vim_str2nr('-0B1012', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 0) test_vim_str2nr('-0B1012', flags, {len = 0}, 0)
test_vim_str2nr('-0B1012', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 7) test_vim_str2nr('-0B1012', flags, {len = 0}, 7)
test_vim_str2nr('-0B1012', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 0, false)
test_vim_str2nr('-0B1012', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 7, false)
if flags > lib.STR2NR_FORCE then if flags > lib.STR2NR_FORCE then
test_vim_str2nr('-101', flags, {len = 4, num = -5, unum = 5, pre = 0}, 0) test_vim_str2nr('-101', flags, {len = 4, num = -5, unum = 5, pre = 0}, 0)
end end
end end
end) end)
itp('works with octal numbers', function() itp('works with octal numbers (0 prefix)', function()
for _, flags in ipairs({ for _, flags in ipairs({
lib.STR2NR_OCT, lib.STR2NR_OCT,
lib.STR2NR_OCT + lib.STR2NR_BIN, lib.STR2NR_OCT + lib.STR2NR_BIN,
lib.STR2NR_OCT + lib.STR2NR_HEX, lib.STR2NR_OCT + lib.STR2NR_HEX,
lib.STR2NR_OCT + lib.STR2NR_OOCT,
lib.STR2NR_ALL, lib.STR2NR_ALL,
lib.STR2NR_FORCE + lib.STR2NR_OCT, lib.STR2NR_FORCE + lib.STR2NR_OCT,
lib.STR2NR_FORCE + lib.STR2NR_OOCT,
lib.STR2NR_FORCE + lib.STR2NR_OCT + lib.STR2NR_OOCT,
}) do }) do
local oct local oct
if flags > lib.STR2NR_FORCE then if flags > lib.STR2NR_FORCE then
@ -218,8 +245,10 @@ describe('vim_str2nr()', function()
test_vim_str2nr( '0548', flags, {len = 3, num = 44, unum = 44, pre = oct}, 3) test_vim_str2nr( '0548', flags, {len = 3, num = 44, unum = 44, pre = oct}, 3)
test_vim_str2nr( '054', flags, {len = 3, num = 44, unum = 44, pre = oct}, 4) test_vim_str2nr( '054', flags, {len = 3, num = 44, unum = 44, pre = oct}, 4)
test_vim_str2nr( '054x', flags, {len = 3, num = 44, unum = 44, pre = oct}, 4) test_vim_str2nr( '054x', flags, {len = 0}, 4)
test_vim_str2nr( '054x', flags, {len = 3, num = 44, unum = 44, pre = oct}, 0) test_vim_str2nr( '054x', flags, {len = 0}, 0)
test_vim_str2nr( '054x', flags, {len = 3, num = 44, unum = 44, pre = oct}, 4, false)
test_vim_str2nr( '054x', flags, {len = 3, num = 44, unum = 44, pre = oct}, 0, false)
test_vim_str2nr('-054', flags, {len = 4, num = -44, unum = 44, pre = oct}, 0) test_vim_str2nr('-054', flags, {len = 4, num = -44, unum = 44, pre = oct}, 0)
test_vim_str2nr('-054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1) test_vim_str2nr('-054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
@ -229,13 +258,110 @@ describe('vim_str2nr()', function()
test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = oct}, 4) test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = oct}, 4)
test_vim_str2nr('-054', flags, {len = 4, num = -44, unum = 44, pre = oct}, 5) test_vim_str2nr('-054', flags, {len = 4, num = -44, unum = 44, pre = oct}, 5)
test_vim_str2nr('-054x', flags, {len = 4, num = -44, unum = 44, pre = oct}, 5) test_vim_str2nr('-054x', flags, {len = 0}, 5)
test_vim_str2nr('-054x', flags, {len = 4, num = -44, unum = 44, pre = oct}, 0) test_vim_str2nr('-054x', flags, {len = 0}, 0)
test_vim_str2nr('-054x', flags, {len = 4, num = -44, unum = 44, pre = oct}, 5, false)
test_vim_str2nr('-054x', flags, {len = 4, num = -44, unum = 44, pre = oct}, 0, false)
if flags > lib.STR2NR_FORCE then if flags > lib.STR2NR_FORCE then
test_vim_str2nr('-54', flags, {len = 3, num = -44, unum = 44, pre = 0}, 0) test_vim_str2nr('-54', flags, {len = 3, num = -44, unum = 44, pre = 0}, 0)
test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = 0}, 5) test_vim_str2nr('-0548', flags, {len = 0}, 5)
test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = 0}, 0) 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)
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 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 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}, 5)
test_vim_str2nr('-0548', flags, {len = 5, num = -548, unum = 548, pre = 0}, 0) test_vim_str2nr('-0548', flags, {len = 5, num = -548, unum = 548, pre = 0}, 0)
@ -268,53 +394,85 @@ describe('vim_str2nr()', function()
test_vim_str2nr( '0x101', flags, {len = 5, num = 257, unum =257, pre = hex}, 0) test_vim_str2nr( '0x101', flags, {len = 5, num = 257, unum =257, pre = hex}, 0)
test_vim_str2nr( '0x101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1) test_vim_str2nr( '0x101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
test_vim_str2nr( '0x101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2) test_vim_str2nr( '0x101', flags, {len = 0}, 2)
test_vim_str2nr( '0x101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
test_vim_str2nr( '0x101', flags, {len = 3, num = 1, unum = 1, pre = hex}, 3) test_vim_str2nr( '0x101', flags, {len = 3, num = 1, unum = 1, pre = hex}, 3)
test_vim_str2nr( '0x101', flags, {len = 4, num = 16, unum = 16, pre = hex}, 4) test_vim_str2nr( '0x101', flags, {len = 4, num = 16, unum = 16, pre = hex}, 4)
test_vim_str2nr( '0x101', flags, {len = 5, num = 257, unum =257, pre = hex}, 5) test_vim_str2nr( '0x101', flags, {len = 5, num = 257, unum =257, pre = hex}, 5)
test_vim_str2nr( '0x101', flags, {len = 5, num = 257, unum =257, pre = hex}, 6) test_vim_str2nr( '0x101', flags, {len = 5, num = 257, unum =257, pre = hex}, 6)
test_vim_str2nr( '0x101G', flags, {len = 5, num = 257, unum =257, pre = hex}, 0) test_vim_str2nr( '0x101G', flags, {len = 0}, 0)
test_vim_str2nr( '0x101G', flags, {len = 5, num = 257, unum =257, pre = hex}, 6) test_vim_str2nr( '0x101G', flags, {len = 0}, 6)
test_vim_str2nr( '0x101G', flags, {len = 5, num = 257, unum =257, pre = hex}, 0, false)
test_vim_str2nr( '0x101G', flags, {len = 5, num = 257, unum =257, pre = hex}, 6, false)
test_vim_str2nr('-0x101', flags, {len = 6, num =-257, unum =257, pre = hex}, 0) test_vim_str2nr('-0x101', flags, {len = 6, num =-257, unum =257, pre = hex}, 0)
test_vim_str2nr('-0x101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1) test_vim_str2nr('-0x101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
test_vim_str2nr('-0x101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2) test_vim_str2nr('-0x101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
test_vim_str2nr('-0x101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3) test_vim_str2nr('-0x101', flags, {len = 0}, 3)
test_vim_str2nr('-0x101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
test_vim_str2nr('-0x101', flags, {len = 4, num = -1, unum = 1, pre = hex}, 4) test_vim_str2nr('-0x101', flags, {len = 4, num = -1, unum = 1, pre = hex}, 4)
test_vim_str2nr('-0x101', flags, {len = 5, num = -16, unum = 16, pre = hex}, 5) test_vim_str2nr('-0x101', flags, {len = 5, num = -16, unum = 16, pre = hex}, 5)
test_vim_str2nr('-0x101', flags, {len = 6, num =-257, unum =257, pre = hex}, 6) test_vim_str2nr('-0x101', flags, {len = 6, num =-257, unum =257, pre = hex}, 6)
test_vim_str2nr('-0x101', flags, {len = 6, num =-257, unum =257, pre = hex}, 7) test_vim_str2nr('-0x101', flags, {len = 6, num =-257, unum =257, pre = hex}, 7)
test_vim_str2nr('-0x101G', flags, {len = 6, num =-257, unum =257, pre = hex}, 0) test_vim_str2nr('-0x101G', flags, {len = 0}, 0)
test_vim_str2nr('-0x101G', flags, {len = 6, num =-257, unum =257, pre = hex}, 7) test_vim_str2nr('-0x101G', flags, {len = 0}, 7)
test_vim_str2nr('-0x101G', flags, {len = 6, num =-257, unum =257, pre = hex}, 0, false)
test_vim_str2nr('-0x101G', flags, {len = 6, num =-257, unum =257, pre = hex}, 7, false)
test_vim_str2nr( '0X101', flags, {len = 5, num = 257, unum =257, pre = HEX}, 0) test_vim_str2nr( '0X101', flags, {len = 5, num = 257, unum =257, pre = HEX}, 0)
test_vim_str2nr( '0X101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1) test_vim_str2nr( '0X101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
test_vim_str2nr( '0X101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2) test_vim_str2nr( '0X101', flags, {len = 0}, 2)
test_vim_str2nr( '0X101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
test_vim_str2nr( '0X101', flags, {len = 3, num = 1, unum = 1, pre = HEX}, 3) test_vim_str2nr( '0X101', flags, {len = 3, num = 1, unum = 1, pre = HEX}, 3)
test_vim_str2nr( '0X101', flags, {len = 4, num = 16, unum = 16, pre = HEX}, 4) test_vim_str2nr( '0X101', flags, {len = 4, num = 16, unum = 16, pre = HEX}, 4)
test_vim_str2nr( '0X101', flags, {len = 5, num = 257, unum =257, pre = HEX}, 5) test_vim_str2nr( '0X101', flags, {len = 5, num = 257, unum =257, pre = HEX}, 5)
test_vim_str2nr( '0X101', flags, {len = 5, num = 257, unum =257, pre = HEX}, 6) test_vim_str2nr( '0X101', flags, {len = 5, num = 257, unum =257, pre = HEX}, 6)
test_vim_str2nr( '0X101G', flags, {len = 5, num = 257, unum =257, pre = HEX}, 0) test_vim_str2nr( '0X101G', flags, {len = 0}, 0)
test_vim_str2nr( '0X101G', flags, {len = 5, num = 257, unum =257, pre = HEX}, 6) test_vim_str2nr( '0X101G', flags, {len = 0}, 6)
test_vim_str2nr( '0X101G', flags, {len = 5, num = 257, unum =257, pre = HEX}, 0, false)
test_vim_str2nr( '0X101G', flags, {len = 5, num = 257, unum =257, pre = HEX}, 6, false)
test_vim_str2nr('-0X101', flags, {len = 6, num =-257, unum =257, pre = HEX}, 0) test_vim_str2nr('-0X101', flags, {len = 6, num =-257, unum =257, pre = HEX}, 0)
test_vim_str2nr('-0X101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1) test_vim_str2nr('-0X101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
test_vim_str2nr('-0X101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2) test_vim_str2nr('-0X101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
test_vim_str2nr('-0X101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3) test_vim_str2nr('-0X101', flags, {len = 0}, 3)
test_vim_str2nr('-0X101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
test_vim_str2nr('-0X101', flags, {len = 4, num = -1, unum = 1, pre = HEX}, 4) test_vim_str2nr('-0X101', flags, {len = 4, num = -1, unum = 1, pre = HEX}, 4)
test_vim_str2nr('-0X101', flags, {len = 5, num = -16, unum = 16, pre = HEX}, 5) test_vim_str2nr('-0X101', flags, {len = 5, num = -16, unum = 16, pre = HEX}, 5)
test_vim_str2nr('-0X101', flags, {len = 6, num =-257, unum =257, pre = HEX}, 6) test_vim_str2nr('-0X101', flags, {len = 6, num =-257, unum =257, pre = HEX}, 6)
test_vim_str2nr('-0X101', flags, {len = 6, num =-257, unum =257, pre = HEX}, 7) test_vim_str2nr('-0X101', flags, {len = 6, num =-257, unum =257, pre = HEX}, 7)
test_vim_str2nr('-0X101G', flags, {len = 6, num =-257, unum =257, pre = HEX}, 0) test_vim_str2nr('-0X101G', flags, {len = 0}, 0)
test_vim_str2nr('-0X101G', flags, {len = 6, num =-257, unum =257, pre = HEX}, 7) test_vim_str2nr('-0X101G', flags, {len = 0}, 7)
test_vim_str2nr('-0X101G', flags, {len = 6, num =-257, unum =257, pre = HEX}, 0, false)
test_vim_str2nr('-0X101G', flags, {len = 6, num =-257, unum =257, pre = HEX}, 7, false)
if flags > lib.STR2NR_FORCE then if flags > lib.STR2NR_FORCE then
test_vim_str2nr('-101', flags, {len = 4, num = -257, unum = 257, pre = 0}, 0) test_vim_str2nr('-101', flags, {len = 4, num = -257, unum = 257, pre = 0}, 0)
end end
end end
end) end)
-- Test_str2nr() in test_functions.vim already tests normal usage
itp('works with weirdly quoted numbers', function()
local flags = lib.STR2NR_DEC + lib.STR2NR_QUOTE
test_vim_str2nr("'027", flags, {len = 0}, 0)
test_vim_str2nr("'027", flags, {len = 0}, 0, false)
test_vim_str2nr("1'2'3'4", flags, {len = 7, num = 1234, unum = 1234, pre = 0}, 0)
-- counter-intuitive, but like Vim, strict=true should partially accept
-- these: (' and - are not alpha-numeric)
test_vim_str2nr("7''331", flags, {len = 1, num = 7, unum = 7, pre = 0}, 0)
test_vim_str2nr("123'x4", flags, {len = 3, num = 123, unum = 123, pre = 0}, 0)
test_vim_str2nr("1337'", flags, {len = 4, num = 1337, unum = 1337, pre = 0}, 0)
test_vim_str2nr("-'", flags, {len = 1, num = 0, unum = 0, pre = 0}, 0)
flags = lib.STR2NR_HEX + lib.STR2NR_QUOTE
local hex = ('x'):byte()
test_vim_str2nr("0x'abcd", flags, {len = 0}, 0)
test_vim_str2nr("0x'abcd", flags, {len = 1, num = 0, unum = 0, pre = 0}, 0, false)
test_vim_str2nr("0xab''cd", flags, {len = 4, num = 171, unum = 171, pre = hex}, 0)
end)
end) end)