diff options
Diffstat (limited to 'src/nvim/charset.c')
-rw-r--r-- | src/nvim/charset.c | 85 |
1 files changed, 66 insertions, 19 deletions
diff --git a/src/nvim/charset.c b/src/nvim/charset.c index b93eafbf60..48046c9f17 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -1454,6 +1454,20 @@ char_u* skipdigits(char_u *q) return p; } +/// skip over binary digits +/// +/// @param q +/// +/// @return Pointer to the character after the skipped digits. +char_u* skipbin(char_u *q) +{ + char_u *p = q; + + while (ascii_isbdigit(*p)) /* skip to next non-digit */ + ++p; + return p; +} + /// skip over digits and hex characters /// /// @param q @@ -1485,6 +1499,20 @@ char_u* skiptodigit(char_u *q) return p; } +/// skip to binary character (or NUL after the string) +/// +/// @param q +/// +/// @return Pointer to the binary character or (NUL after the string). +char_u* skiptobin(char_u *q) +{ + char_u *p = q; + + while (*p != NUL && !ascii_isbdigit(*p)) /* skip to next digit */ + ++p; + return p; +} + /// skip to hex character (or NUL after the string) /// /// @param q @@ -1720,33 +1748,38 @@ int vim_isblankline(char_u *lbuf) } /// Convert a string into a long and/or unsigned long, taking care of -/// hexadecimal and octal numbers. Accepts a '-' sign. -/// If "hexp" is not NULL, returns a flag to indicate the type of the number: +/// hexadecimal, octal and binary numbers. Accepts a '-' sign. +/// If "prep" is not NULL, returns a flag to indicate the type of the number: /// 0 decimal /// '0' octal +/// 'B' bin +/// 'b' bin /// 'X' hex /// 'x' hex /// If "len" is not NULL, the length of the number in characters is returned. /// If "nptr" is not NULL, the signed result is returned in it. /// If "unptr" is not NULL, the unsigned result is returned in it. +/// If "dobin" is non-zero recognize binary numbers, when > 1 always assume +/// binary number. /// If "dooct" is non-zero recognize octal numbers, when > 1 always assume /// octal number. /// If "dohex" is non-zero recognize hex numbers, when > 1 always assume /// hex number. /// /// @param start -/// @param hexp Returns type of number 0 = decimal, 'x' or 'X' is hex, -// '0' = octal +/// @param prep Returns type of number 0 = decimal, 'x' or 'X' is hex, +// '0' = octal, 'b' or 'B' is bin /// @param len Returns the detected length of number. +/// @param dobin recognize binary number /// @param dooct recognize octal number /// @param dohex recognize hex number /// @param nptr Returns the signed result. /// @param unptr Returns the unsigned result. -void vim_str2nr(char_u *start, int *hexp, int *len, int dooct, int dohex, +void vim_str2nr(char_u *start, int *prep, int *len, int dobin, int dooct, int dohex, long *nptr, unsigned long *unptr) { char_u *ptr = start; - int hex = 0; // default is decimal + int pre = 0; // default is decimal int negative = FALSE; unsigned long un = 0; int n; @@ -1756,31 +1789,35 @@ void vim_str2nr(char_u *start, int *hexp, int *len, int dooct, int dohex, ++ptr; } - // Recognize hex and octal. + // Recognize hex, octal, and bin. if ((ptr[0] == '0') && (ptr[1] != '8') && (ptr[1] != '9')) { - hex = ptr[1]; + pre = ptr[1]; if (dohex - && ((hex == 'X') || (hex == 'x')) + && ((pre == 'X') || (pre == 'x')) && ascii_isxdigit(ptr[2])) { // hexadecimal ptr += 2; + } else if (dobin + && ((pre == 'B') || (pre == 'b')) + && ascii_isbdigit(ptr[2])) { + // binary + ptr += 2; } else { // default is decimal - hex = 0; + pre = 0; if (dooct) { // Don't interpret "0", "08" or "0129" as octal. for (n = 1; ascii_isdigit(ptr[n]); ++n) { if (ptr[n] > '7') { // can't be octal - hex = 0; + pre = 0; break; } - if (ptr[n] >= '0') { // assume octal - hex = '0'; + pre = '0'; } } } @@ -1788,28 +1825,38 @@ void vim_str2nr(char_u *start, int *hexp, int *len, int dooct, int dohex, } // Do the string-to-numeric conversion "manually" to avoid sscanf quirks. - if ((hex == '0') || (dooct > 1)) { + if ((pre == 'B') || (pre == 'b') || (dobin > 1)) { + // bin + if (pre != 0) + n += 2; // skip over "0b" + while ('0' <= *ptr && *ptr <= '1') { + un = 2 * un + (unsigned long)(*ptr - '0'); + ++ptr; + } + } else if ((pre == '0') || (dooct > 1)) { // octal while ('0' <= *ptr && *ptr <= '7') { un = 8 * un + (unsigned long)(*ptr - '0'); ptr++; } - } else if ((hex != 0) || (dohex > 1)) { + } else if (pre != 0 || dohex > 1) { // hex + if (pre != 0) + n += 2; // skip over "0x" while (ascii_isxdigit(*ptr)) { un = 16 * un + (unsigned long)hex2nr(*ptr); - ptr++; + ++ptr; } } else { // decimal while (ascii_isdigit(*ptr)) { un = 10 * un + (unsigned long)(*ptr - '0'); - ptr++; + ++ptr; } } - if (hexp != NULL) { - *hexp = hex; + if (prep != NULL) { + *prep = pre; } if (len != NULL) { |