diff src/charset.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 05afb5be93bd
children f04e2b6feea2
line wrap: on
line diff
--- 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, dohe
 	++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, dohe
     }
 
     /*
-     * 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, dohe
 		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, dohe
 	}
     }
 
-    if (hexp != NULL)
-	*hexp = hex;
+    if (prep != NULL)
+	*prep = pre;
     if (len != NULL)
 	*len = (int)(ptr - start);
     if (nptr != NULL)