From 887c1fea4a114e7170091942d0446c8882701b5b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 2 Jan 2016 17:56:35 +0100 Subject: patch 7.4.1027 Problem: No support for binary numbers. Solution: Add "bin" to nrformats. (Jason Schulz) --- src/charset.c | 118 ++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 90 insertions(+), 28 deletions(-) (limited to 'src/charset.c') diff --git a/src/charset.c b/src/charset.c index a74bf0d5bf..1000692cc1 100644 --- a/src/charset.c +++ b/src/charset.c @@ -1569,6 +1569,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 */ @@ -1585,6 +1599,20 @@ skiphex(q) #endif #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) */ @@ -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) -- cgit v1.2.3