diff src/ops.c @ 7447:ad432f8f68fb v7.4.1027

commit https://github.com/vim/vim/commit/887c1fea4a114e7170091942d0446c8882701b5b Author: Bram Moolenaar <Bram@vim.org> Date: Sat Jan 2 17:56:35 2016 +0100 patch 7.4.1027 Problem: No support for binary numbers. Solution: Add "bin" to nrformats. (Jason Schulz)
author Christian Brabandt <cb@256bit.org>
date Sat, 02 Jan 2016 18:00:05 +0100
parents 4c5f53a60543
children a49163681559
line wrap: on
line diff
--- a/src/ops.c
+++ b/src/ops.c
@@ -5379,7 +5379,7 @@ do_addsub(command, Prenum1, g_cmd)
     int		col;
     char_u	*buf1;
     char_u	buf2[NUMBUFLEN];
-    int		hex;		/* 'X' or 'x': hex; '0': octal */
+    int		pre;		/* 'X'/'x': hex; '0': octal; 'B'/'b': bin */
     static int	hexupper = FALSE;	/* 0xABC */
     unsigned long n;
     unsigned long offset = 0;		/* line offset for Ctrl_V mode */
@@ -5390,6 +5390,7 @@ do_addsub(command, Prenum1, g_cmd)
     int		todel;
     int		dohex;
     int		dooct;
+    int		dobin;
     int		doalp;
     int		firstdigit;
     int		subtract;
@@ -5403,9 +5404,13 @@ do_addsub(command, Prenum1, g_cmd)
     int		did_change = FALSE;
     pos_T	t = curwin->w_cursor;
     int		maxlen = 0;
+    int		pos = 0;
+    int		bit = 0;
+    int		bits = sizeof(unsigned long) * 8;
 
     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" */
 
     /*
@@ -5454,17 +5459,45 @@ do_addsub(command, Prenum1, g_cmd)
 	ptr = ml_get_curline();
 	RLADDSUBFIX(ptr);
 
+	if (dobin)
+	    while (col > 0 && vim_isbdigit(ptr[col]))
+		--col;
+
 	if (dohex)
 	    while (col > 0 && vim_isxdigit(ptr[col]))
 		--col;
-	if (       dohex
+
+	if (       dobin
+		&& dohex
+		&& ! ((col > 0
+		    && (ptr[col] == 'X'
+			|| ptr[col] == 'x')
+		    && ptr[col - 1] == '0'
+		    && vim_isxdigit(ptr[col + 1]))))
+	{
+
+	    /* In case of binary/hexadecimal pattern overlap match, rescan */
+
+	    col = curwin->w_cursor.col;
+
+	    while (col > 0 && vim_isdigit(ptr[col]))
+		col--;
+	}
+
+	if ((       dohex
 		&& col > 0
 		&& (ptr[col] == 'X'
 		    || ptr[col] == 'x')
 		&& ptr[col - 1] == '0'
-		&& vim_isxdigit(ptr[col + 1]))
+		&& vim_isxdigit(ptr[col + 1])) ||
+	    (       dobin
+		&& col > 0
+		&& (ptr[col] == 'B'
+		    || ptr[col] == 'b')
+		&& ptr[col - 1] == '0'
+		&& vim_isbdigit(ptr[col + 1])))
 	{
-	    /* Found hexadecimal number, move to its start. */
+	    /* Found hexadecimal or binary number, move to its start. */
 	    --col;
 	}
 	else
@@ -5609,11 +5642,14 @@ do_addsub(command, Prenum1, g_cmd)
 					: curwin->w_cursor.col - col + 1);
 	    }
 
-	    vim_str2nr(ptr + col, &hex, &length, dooct, dohex, NULL, &n,
-								      maxlen);
-
-	    /* ignore leading '-' for hex and octal numbers */
-	    if (hex && negative)
+	    vim_str2nr(ptr + col, &pre, &length,
+		    0 + (dobin ? STR2NR_BIN : 0)
+		      + (dooct ? STR2NR_OCT : 0)
+		      + (dohex ? STR2NR_HEX : 0),
+		    NULL, &n, maxlen);
+
+	    /* ignore leading '-' for hex and octal and bin numbers */
+	    if (pre && negative)
 	    {
 		++col;
 		--length;
@@ -5634,7 +5670,7 @@ do_addsub(command, Prenum1, g_cmd)
 		n += (unsigned long)Prenum1;
 
 	    /* handle wraparound for decimal numbers */
-	    if (!hex)
+	    if (!pre)
 	    {
 		if (subtract)
 		{
@@ -5706,25 +5742,37 @@ do_addsub(command, Prenum1, g_cmd)
 	    {
 		*ptr++ = '-';
 	    }
-	    if (hex)
+	    if (pre)
 	    {
 		*ptr++ = '0';
 		--length;
 	    }
-	    if (hex == 'x' || hex == 'X')
+	    if (pre == 'b' || pre == 'B' || 
+		pre == 'x' || pre == 'X')
 	    {
-		*ptr++ = hex;
+		*ptr++ = pre;
 		--length;
 	    }
 
 	    /*
 	     * Put the number characters in buf2[].
 	     */
-	    if (hex == 0)
+	    if (pre == 'b' || pre == 'B')
+	    {
+		/* leading zeros */
+		for (bit = bits; bit > 0; bit--)
+		    if ((n >> (bit - 1)) & 0x1) break;
+
+		for (pos = 0; bit > 0; bit--)
+		    buf2[pos++] = ((n >> (bit - 1)) & 0x1) ? '1' : '0';
+
+		buf2[pos] = '\0';
+	    }
+	    else if (pre == 0)
 		sprintf((char *)buf2, "%lu", n);
-	    else if (hex == '0')
+	    else if (pre == '0')
 		sprintf((char *)buf2, "%lo", n);
-	    else if (hex && hexupper)
+	    else if (pre && hexupper)
 		sprintf((char *)buf2, "%lX", n);
 	    else
 		sprintf((char *)buf2, "%lx", n);
@@ -5736,7 +5784,7 @@ do_addsub(command, Prenum1, g_cmd)
 	     * 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;
@@ -6359,7 +6407,7 @@ get_reg_type(regname, reglen)
 #endif
 
     if (regname != NUL && !valid_yank_reg(regname, FALSE))
-        return MAUTO;
+	return MAUTO;
 
     get_yank_register(regname, FALSE);