aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/charset.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/charset.c')
-rw-r--r--src/nvim/charset.c85
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) {