summaryrefslogtreecommitdiffstats
path: root/src/charset.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-01-02 17:56:35 +0100
committerBram Moolenaar <Bram@vim.org>2016-01-02 17:56:35 +0100
commit887c1fea4a114e7170091942d0446c8882701b5b (patch)
tree23173526918b54763e5eed1b26a7bdad3ac7884a /src/charset.c
parentacf92d27c94811e3bd6b84cfd54246e91d44c355 (diff)
patch 7.4.1027v7.4.1027
Problem: No support for binary numbers. Solution: Add "bin" to nrformats. (Jason Schulz)
Diffstat (limited to 'src/charset.c')
-rw-r--r--src/charset.c118
1 files changed, 90 insertions, 28 deletions
diff --git a/src/charset.c b/src/charset.c
index a74bf0d5bf..1000692cc1 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -1570,6 +1570,20 @@ skipdigits(q)
#if defined(FEAT_SYN_HL) || defined(FEAT_SPELL) || defined(PROTO)
/*
+ * skip over binary digits
+ */
+ char_u *
+skipbin(q)
+ char_u *q;
+{
+ char_u *p = q;
+
+ while (vim_isbdigit(*p)) /* skip to next non-digit */
+ ++p;
+ return p;
+}
+
+/*
* skip over digits and hex characters
*/
char_u *
@@ -1586,6 +1600,20 @@ skiphex(q)
#if defined(FEAT_EX_EXTRA) || defined(PROTO)
/*
+ * skip to bin digit (or NUL after the string)
+ */
+ char_u *
+skiptobin(q)
+ char_u *q;
+{
+ char_u *p = q;
+
+ while (*p != NUL && !vim_isbdigit(*p)) /* skip to next digit */
+ ++p;
+ return p;
+}
+
+/*
* skip to digit (or NUL after the string)
*/
char_u *
@@ -1641,6 +1669,17 @@ vim_isxdigit(c)
|| (c >= 'A' && c <= 'F');
}
+/*
+ * Corollary of vim_isdigit and vim_isxdigit() that can handle
+ * characters > 0x100.
+ */
+ int
+vim_isbdigit(c)
+ int c;
+{
+ return (c == '0' || c == '1');
+}
+
#if defined(FEAT_MBYTE) || defined(PROTO)
/*
* Vim's own character class functions. These exist because many library
@@ -1822,35 +1861,37 @@ vim_isblankline(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 "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.
+ * If "what" contains STR2NR_BIN recognize binary numbers
+ * If "what" contains STR2NR_OCT recognize octal numbers
+ * If "what" contains STR2NR_HEX recognize hex numbers
+ * If "what" contains STR2NR_FORCE always assume bin/oct/hex.
* If maxlen > 0, check at a maximum maxlen chars
*/
void
-vim_str2nr(start, hexp, len, dooct, dohex, nptr, unptr, maxlen)
+vim_str2nr(start, prep, len, what, nptr, unptr, maxlen)
char_u *start;
- int *hexp; /* return: type of number 0 = decimal, 'x'
- or 'X' is hex, '0' = octal */
+ int *prep; /* return: type of number 0 = decimal, 'x'
+ or 'X' is hex, '0' = octal, 'b' or 'B'
+ is bin */
int *len; /* return: detected length of number */
- int dooct; /* recognize octal number */
- int dohex; /* recognize hex number */
+ int what; /* what numbers to recognize */
long *nptr; /* return: signed result */
unsigned long *unptr; /* return: unsigned result */
int maxlen; /* max length of string to check */
{
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;
@@ -1861,29 +1902,37 @@ vim_str2nr(start, hexp, len, dooct, dohex, nptr, unptr, maxlen)
++ptr;
}
- /* Recognize hex and octal. */
+ /* Recognize hex, octal, and bin. */
if (ptr[0] == '0' && ptr[1] != '8' && ptr[1] != '9'
&& (maxlen == 0 || maxlen > 1))
{
- hex = ptr[1];
- if (dohex && (hex == 'X' || hex == 'x') && vim_isxdigit(ptr[2])
- && (maxlen == 0 || maxlen > 2))
- ptr += 2; /* hexadecimal */
+ pre = ptr[1];
+ if ((what & STR2NR_HEX)
+ && (pre == 'X' || pre == 'x') && vim_isxdigit(ptr[2])
+ && (maxlen == 0 || maxlen > 2))
+ /* hexadecimal */
+ ptr += 2;
+ else if ((what & STR2NR_BIN)
+ && (pre == 'B' || pre == 'b') && vim_isbdigit(ptr[2])
+ && (maxlen == 0 || maxlen > 2))
+ /* binary */
+ ptr += 2;
else
{
- hex = 0; /* default is decimal */
- if (dooct)
+ /* decimal or octal, default is decimal */
+ pre = 0;
+ if (what & STR2NR_OCT)
{
/* Don't interpret "0", "08" or "0129" as octal. */
for (n = 1; VIM_ISDIGIT(ptr[n]); ++n)
{
if (ptr[n] > '7')
{
- hex = 0; /* can't be octal */
+ pre = 0; /* can't be octal */
break;
}
if (ptr[n] >= '0')
- hex = '0'; /* assume octal */
+ pre = '0'; /* assume octal */
if (n == maxlen)
break;
}
@@ -1892,10 +1941,23 @@ vim_str2nr(start, hexp, len, dooct, dohex, nptr, unptr, maxlen)
}
/*
- * Do the string-to-numeric conversion "manually" to avoid sscanf quirks.
- */
+ * Do the string-to-numeric conversion "manually" to avoid sscanf quirks.
+ */
n = 1;
- if (hex == '0' || dooct > 1)
+ if (pre == 'B' || pre == 'b' || what == STR2NR_BIN + STR2NR_FORCE)
+ {
+ /* bin */
+ if (pre != 0)
+ n += 2; /* skip over "0b" */
+ while ('0' <= *ptr && *ptr <= '1')
+ {
+ un = 2 * un + (unsigned long)(*ptr - '0');
+ ++ptr;
+ if (n++ == maxlen)
+ break;
+ }
+ }
+ else if (pre == '0' || what == STR2NR_OCT + STR2NR_FORCE)
{
/* octal */
while ('0' <= *ptr && *ptr <= '7')
@@ -1906,10 +1968,10 @@ vim_str2nr(start, hexp, len, dooct, dohex, nptr, unptr, maxlen)
break;
}
}
- else if (hex != 0 || dohex > 1)
+ else if (pre != 0 || what == STR2NR_HEX + STR2NR_FORCE)
{
/* hex */
- if (hex != 0)
+ if (pre != 0)
n += 2; /* skip over "0x" */
while (vim_isxdigit(*ptr))
{
@@ -1931,8 +1993,8 @@ vim_str2nr(start, hexp, len, dooct, dohex, nptr, unptr, maxlen)
}
}
- if (hexp != NULL)
- *hexp = hex;
+ if (prep != NULL)
+ *prep = pre;
if (len != NULL)
*len = (int)(ptr - start);
if (nptr != NULL)