aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/ops.c
diff options
context:
space:
mode:
authorJason Schulz <jason@schulz.name>2015-12-29 15:17:16 -0800
committerJason Schulz <jason@schulz.name>2016-01-15 18:21:06 -0800
commit7ad3f077dc68a83b2cdfb7b1d04de9266d7978a9 (patch)
treeaaa485d0853be6b46865cf2d87064ec0299f0cde /src/nvim/ops.c
parentdddbf9c5fa061cb03d6b6240ac6610b68b9304f5 (diff)
downloadrneovim-7ad3f077dc68a83b2cdfb7b1d04de9266d7978a9.tar.gz
rneovim-7ad3f077dc68a83b2cdfb7b1d04de9266d7978a9.tar.bz2
rneovim-7ad3f077dc68a83b2cdfb7b1d04de9266d7978a9.zip
Add support for binary numbers
Diffstat (limited to 'src/nvim/ops.c')
-rw-r--r--src/nvim/ops.c80
1 files changed, 61 insertions, 19 deletions
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index c3d968ca51..ee86f8fe7a 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -4197,7 +4197,7 @@ int do_addsub(int command, linenr_T Prenum1)
int col;
char_u *buf1;
char_u buf2[NUMBUFLEN];
- int hex; /* 'X' or 'x': hex; '0': octal */
+ int pre; /* 'X' or 'x': hex; '0': octal; 'B' or 'b': bin */
static int hexupper = FALSE; /* 0xABC */
unsigned long n, oldn;
char_u *ptr;
@@ -4206,6 +4206,7 @@ int do_addsub(int command, linenr_T Prenum1)
int todel;
int dohex;
int dooct;
+ int dobin;
int doalp;
int firstdigit;
int negative;
@@ -4213,6 +4214,7 @@ int do_addsub(int command, linenr_T Prenum1)
dohex = (vim_strchr(curbuf->b_p_nf, 'x') != NULL); /* "heX" */
dooct = (vim_strchr(curbuf->b_p_nf, 'o') != NULL); /* "Octal" */
+ dobin = (vim_strchr(curbuf->b_p_nf, 'b') != NULL); /* "Bin" */
doalp = (vim_strchr(curbuf->b_p_nf, 'p') != NULL); /* "alPha" */
ptr = get_cursor_line_ptr();
@@ -4222,19 +4224,44 @@ int do_addsub(int command, linenr_T Prenum1)
* First check if we are on a hexadecimal number, after the "0x".
*/
col = curwin->w_cursor.col;
+
+ if (dobin)
+ while (col > 0 && ascii_isbdigit(ptr[col]))
+ --col;
+
if (dohex)
while (col > 0 && ascii_isxdigit(ptr[col]))
--col;
- if ( dohex
- && col > 0
+ if ( dobin
+ && dohex
+ && ! ((col > 0
&& (ptr[col] == 'X'
|| ptr[col] == 'x')
&& ptr[col - 1] == '0'
- && ascii_isxdigit(ptr[col + 1])) {
- /*
- * Found hexadecimal number, move to its start.
- */
- --col;
+ && ascii_isxdigit(ptr[col + 1])))) {
+
+ /* In case of binary/hexadecimal pattern overlap match, rescan */
+
+ col = curwin->w_cursor.col;
+
+ while (col > 0 && ascii_isdigit(ptr[col]))
+ col--;
+ }
+
+ if (( dohex
+ && col > 0
+ && (ptr[col] == 'X'
+ || ptr[col] == 'x')
+ && ptr[col - 1] == '0'
+ && ascii_isxdigit(ptr[col + 1])) ||
+ ( dobin
+ && col > 0
+ && (ptr[col] == 'B'
+ || ptr[col] == 'b')
+ && ptr[col - 1] == '0'
+ && ascii_isbdigit(ptr[col + 1]))) {
+ /* Found hexadecimal or binary number, move to its start. */
+ --col;
} else {
/*
* Search forward and then backward to find the start of number.
@@ -4297,10 +4324,10 @@ int do_addsub(int command, linenr_T Prenum1)
}
/* get the number value (unsigned) */
- vim_str2nr(ptr + col, &hex, &length, dooct, dohex, NULL, &n);
+ vim_str2nr(ptr + col, &pre, &length, dobin, dooct, dohex, NULL, &n);
- /* ignore leading '-' for hex and octal numbers */
- if (hex && negative) {
+ /* ignore leading '-' for hex, octal and bin numbers */
+ if (pre && negative) {
++col;
--length;
negative = FALSE;
@@ -4320,7 +4347,7 @@ int do_addsub(int command, linenr_T Prenum1)
n += (unsigned long)Prenum1;
/* handle wraparound for decimal numbers */
- if (!hex) {
+ if (!pre) {
if (subtract) {
if (n > oldn) {
n = 1 + (n ^ (unsigned long)-1);
@@ -4370,23 +4397,38 @@ int do_addsub(int command, linenr_T Prenum1)
if (negative) {
*ptr++ = '-';
}
- if (hex) {
+ if (pre) {
*ptr++ = '0';
--length;
}
- if (hex == 'x' || hex == 'X') {
- *ptr++ = hex;
+ if (pre == 'b' || pre == 'B'
+ || pre == 'x' || pre == 'X') {
+ *ptr++ = pre;
--length;
}
/*
* Put the number characters in buf2[].
*/
- if (hex == 0)
+ if (pre == 'b' || pre == 'B') {
+
+ size_t bits = 0;
+ size_t pos = 0;
+
+ /* leading zeros */
+ for (bits = 8 * sizeof(unsigned long); bits > 0; bits--)
+ if ((n >> (bits - 1)) & 0x1) break;
+
+ while (bits > 0)
+ buf2[pos++] = ((n >> --bits) & 0x1) ? '1' : '0';
+
+ buf2[pos] = '\0';
+
+ } else if (pre == 0)
sprintf((char *)buf2, "%" PRIu64, (uint64_t)n);
- else if (hex == '0')
+ else if (pre == '0')
sprintf((char *)buf2, "%" PRIo64, (uint64_t)n);
- else if (hex && hexupper)
+ else if (pre && hexupper)
sprintf((char *)buf2, "%" PRIX64, (uint64_t)n);
else
sprintf((char *)buf2, "%" PRIx64, (uint64_t)n);
@@ -4398,7 +4440,7 @@ int do_addsub(int command, linenr_T Prenum1)
* Don't do this when
* the result may look like an octal number.
*/
- if (firstdigit == '0' && !(dooct && hex == 0))
+ if (firstdigit == '0' && !(dooct && pre == 0))
while (length-- > 0)
*ptr++ = '0';
*ptr = NUL;