# HG changeset patch # User Christian Brabandt # Date 1451754005 -3600 # Node ID ad432f8f68fb5ec6696579516df5978238847a79 # Parent a67ee44e58488de05fef4309b2ae3a6ef69128e4 commit https://github.com/vim/vim/commit/887c1fea4a114e7170091942d0446c8882701b5b Author: Bram Moolenaar 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) diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -416,9 +416,14 @@ CTRL-X Subtract [count] from the numbe additional [count] (so effectively creating a [count] decrementing sequence). {not in Vi} -The CTRL-A and CTRL-X commands work for (signed) decimal numbers, unsigned -octal and hexadecimal numbers and alphabetic characters. This depends on the -'nrformats' option. +The CTRL-A and CTRL-X commands can work for: +- signed and unsigned decimal numbers +- unsigned binary, octal and hexadecimal numbers +- alphabetic characters + +This depends on the 'nrformats' option: +- When 'nrformats' includes "bin", Vim assumes numbers starting with '0b' or + '0B' are binary. - When 'nrformats' includes "octal", Vim considers numbers starting with a '0' to be octal, unless the number includes a '8' or '9'. Other numbers are decimal and may have a preceding minus sign. @@ -447,6 +452,10 @@ octal number. Note that when 'nrformats' includes "octal", decimal numbers with leading zeros cause mistakes, because they can be confused with octal numbers. +Note similarly, when 'nrformats' includes "bin", binary numbers with a leading +'0x' or '0X' can be interpreted as hexadecimal rather than binary since '0b' +are valid hexadecimal digits. + The CTRL-A command is very useful in a macro. Example: Use the following steps to make a numbered list. @@ -1736,7 +1745,7 @@ Vim has a sorting function and a sorting found here: |sort()|, |uniq()|. *:sor* *:sort* -:[range]sor[t][!] [i][u][r][n][x][o] [/{pattern}/] +:[range]sor[t][!] [i][u][r][n][x][o][b] [/{pattern}/] Sort lines in [range]. When no range is given all lines are sorted. @@ -1756,6 +1765,9 @@ found here: |sort()|, |uniq()|. With [o] sorting is done on the first octal number in the line (after or inside a {pattern} match). + With [b] sorting is done on the first binary number in + the line (after or inside a {pattern} match). + With [u] only keep the first of a sequence of identical lines (ignoring case when [i] is used). Without this flag, a sequence of identical lines diff --git a/runtime/doc/version7.txt b/runtime/doc/version7.txt --- a/runtime/doc/version7.txt +++ b/runtime/doc/version7.txt @@ -931,7 +931,7 @@ New and extended functions: ~ |spellbadword()| get a badly spelled word |spellsuggest()| get suggestions for correct spelling |split()| split a String into a List -|str2nr()| convert a string to a number, base 8, 10 or 16 +|str2nr()| convert a string to a number, base 2, 8, 10 or 16 |stridx()| extra argument: start position |strridx()| extra argument: start position |string()| string representation of a List or Dictionary diff --git a/src/charset.c b/src/charset.c --- 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) diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -1625,7 +1625,7 @@ call_vim_function(func, argc, argv, safe len = 0; else /* Recognize a number argument, the others must be strings. */ - vim_str2nr(argv[i], NULL, &len, TRUE, TRUE, &n, NULL, 0); + vim_str2nr(argv[i], NULL, &len, STR2NR_ALL, &n, NULL, 0); if (len != 0 && len == (int)STRLEN(argv[i])) { argvars[i].v_type = VAR_NUMBER; @@ -5139,7 +5139,7 @@ eval7(arg, rettv, evaluate, want_string) else #endif { - vim_str2nr(*arg, NULL, &len, TRUE, TRUE, &n, NULL, 0); + vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0); *arg += len; if (evaluate) { @@ -18529,11 +18529,12 @@ f_str2nr(argvars, rettv) int base = 10; char_u *p; long n; + int what; if (argvars[1].v_type != VAR_UNKNOWN) { base = get_tv_number(&argvars[1]); - if (base != 8 && base != 10 && base != 16) + if (base != 2 && base != 8 && base != 10 && base != 16) { EMSG(_(e_invarg)); return; @@ -18543,7 +18544,14 @@ f_str2nr(argvars, rettv) p = skipwhite(get_tv_string(&argvars[0])); if (*p == '+') p = skipwhite(p + 1); - vim_str2nr(p, NULL, NULL, base == 8 ? 2 : 0, base == 16 ? 2 : 0, &n, NULL, 0); + switch (base) + { + case 2: what = STR2NR_BIN + STR2NR_FORCE; break; + case 8: what = STR2NR_OCT + STR2NR_FORCE; break; + case 16: what = STR2NR_HEX + STR2NR_FORCE; break; + default: what = 0; + } + vim_str2nr(p, NULL, NULL, what, &n, NULL, 0); rettv->vval.v_number = n; } @@ -21349,7 +21357,7 @@ get_tv_number_chk(varp, denote) case VAR_STRING: if (varp->vval.v_string != NULL) vim_str2nr(varp->vval.v_string, NULL, NULL, - TRUE, TRUE, &n, NULL, 0); + STR2NR_ALL, &n, NULL, 0); return n; case VAR_LIST: EMSG(_("E745: Using a List as a Number")); diff --git a/src/ex_cmds.c b/src/ex_cmds.c --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -365,8 +365,8 @@ ex_sort(eap) long deleted; colnr_T start_col; colnr_T end_col; - int sort_oct; /* sort on octal number */ - int sort_hex; /* sort on hex number */ + int sort_what = 0; + int format_found = 0; /* Sorting one line is really quick! */ if (count <= 1) @@ -381,7 +381,7 @@ ex_sort(eap) if (nrs == NULL) goto sortend; - sort_abort = sort_ic = sort_rx = sort_nr = sort_oct = sort_hex = 0; + sort_abort = sort_ic = sort_rx = sort_nr = 0; for (p = eap->arg; *p != NUL; ++p) { @@ -392,11 +392,25 @@ ex_sort(eap) else if (*p == 'r') sort_rx = TRUE; else if (*p == 'n') + { sort_nr = 2; + ++format_found; + } + else if (*p == 'b') + { + sort_what = STR2NR_BIN + STR2NR_FORCE; + ++format_found; + } else if (*p == 'o') - sort_oct = 2; + { + sort_what = STR2NR_OCT + STR2NR_FORCE; + ++format_found; + } else if (*p == 'x') - sort_hex = 2; + { + sort_what = STR2NR_HEX + STR2NR_FORCE; + ++format_found; + } else if (*p == 'u') unique = TRUE; else if (*p == '"') /* comment start */ @@ -439,15 +453,15 @@ ex_sort(eap) } } - /* Can only have one of 'n', 'o' and 'x'. */ - if (sort_nr + sort_oct + sort_hex > 2) + /* Can only have one of 'n', 'b', 'o' and 'x'. */ + if (format_found > 1) { EMSG(_(e_invarg)); goto sortend; } /* From here on "sort_nr" is used as a flag for any number sorting. */ - sort_nr += sort_oct + sort_hex; + sort_nr += sort_what; /* * Make an array with all line numbers. This avoids having to copy all @@ -489,8 +503,10 @@ ex_sort(eap) *s2 = NUL; /* Sorting on number: Store the number itself. */ p = s + start_col; - if (sort_hex) + if (sort_what & STR2NR_HEX) s = skiptohex(p); + else if (sort_what & STR2NR_BIN) + s = skiptobin(p); else s = skiptodigit(p); if (s > p && s[-1] == '-') @@ -499,8 +515,8 @@ ex_sort(eap) /* empty line should sort before any number */ nrs[lnum - eap->line1].start_col_nr = -MAXLNUM; else - vim_str2nr(s, NULL, NULL, sort_oct, sort_hex, - &nrs[lnum - eap->line1].start_col_nr, NULL, 0); + vim_str2nr(s, NULL, NULL, sort_what, + &nrs[lnum - eap->line1].start_col_nr, NULL, 0); *s2 = c; } else diff --git a/src/ex_getln.c b/src/ex_getln.c --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -5935,7 +5935,7 @@ get_list_range(str, num1, num2) *str = skipwhite(*str); if (**str == '-' || vim_isdigit(**str)) /* parse "from" part of range */ { - vim_str2nr(*str, NULL, &len, FALSE, FALSE, &num, NULL, 0); + vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0); *str += len; *num1 = (int)num; first = TRUE; @@ -5944,7 +5944,7 @@ get_list_range(str, num1, num2) if (**str == ',') /* parse "to" part of range */ { *str = skipwhite(*str + 1); - vim_str2nr(*str, NULL, &len, FALSE, FALSE, &num, NULL, 0); + vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0); if (len > 0) { *num2 = (int)num; diff --git a/src/misc2.c b/src/misc2.c --- a/src/misc2.c +++ b/src/misc2.c @@ -2780,7 +2780,7 @@ find_special_key(srcp, modp, keycode, ke bp += 3; /* skip t_xx, xx may be '-' or '>' */ else if (STRNICMP(bp, "char-", 5) == 0) { - vim_str2nr(bp + 5, NULL, &l, TRUE, TRUE, NULL, NULL, 0); + vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0); bp += l + 5; break; } @@ -2812,7 +2812,7 @@ find_special_key(srcp, modp, keycode, ke && VIM_ISDIGIT(last_dash[6])) { /* or or */ - vim_str2nr(last_dash + 6, NULL, NULL, TRUE, TRUE, NULL, &n, 0); + vim_str2nr(last_dash + 6, NULL, NULL, STR2NR_ALL, NULL, &n, 0); key = (int)n; } else diff --git a/src/ops.c b/src/ops.c --- 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); diff --git a/src/option.c b/src/option.c --- a/src/option.c +++ b/src/option.c @@ -1940,7 +1940,7 @@ static struct vimoption {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, {"nrformats", "nf", P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP, (char_u *)&p_nf, PV_NF, - {(char_u *)"octal,hex", (char_u *)0L} + {(char_u *)"bin,octal,hex", (char_u *)0L} SCRIPTID_INIT}, {"number", "nu", P_BOOL|P_VI_DEF|P_RWIN, (char_u *)VAR_WIN, PV_NU, @@ -3031,7 +3031,7 @@ static struct vimoption static char *(p_ambw_values[]) = {"single", "double", NULL}; #endif static char *(p_bg_values[]) = {"light", "dark", NULL}; -static char *(p_nf_values[]) = {"octal", "hex", "alpha", NULL}; +static char *(p_nf_values[]) = {"bin", "octal", "hex", "alpha", NULL}; static char *(p_ff_values[]) = {FF_UNIX, FF_DOS, FF_MAC, NULL}; #ifdef FEAT_CRYPT static char *(p_cm_values[]) = {"zip", "blowfish", "blowfish2", NULL}; @@ -4579,7 +4579,8 @@ do_set(arg, opt_flags) { /* Allow negative (for 'undolevels'), octal and * hex numbers. */ - vim_str2nr(arg, NULL, &i, TRUE, TRUE, &value, NULL, 0); + vim_str2nr(arg, NULL, &i, STR2NR_ALL, + &value, NULL, 0); if (arg[i] != NUL && !vim_iswhite(arg[i])) { errmsg = e_invarg; diff --git a/src/proto/charset.pro b/src/proto/charset.pro --- a/src/proto/charset.pro +++ b/src/proto/charset.pro @@ -36,11 +36,14 @@ void getvvcol __ARGS((win_T *wp, pos_T * void getvcols __ARGS((win_T *wp, pos_T *pos1, pos_T *pos2, colnr_T *left, colnr_T *right)); char_u *skipwhite __ARGS((char_u *q)); char_u *skipdigits __ARGS((char_u *q)); +char_u *skipbin __ARGS((char_u *q)); char_u *skiphex __ARGS((char_u *q)); +char_u *skiptobin __ARGS((char_u *q)); char_u *skiptodigit __ARGS((char_u *q)); char_u *skiptohex __ARGS((char_u *q)); int vim_isdigit __ARGS((int c)); int vim_isxdigit __ARGS((int c)); +int vim_isbdigit __ARGS((int c)); int vim_islower __ARGS((int c)); int vim_isupper __ARGS((int c)); int vim_toupper __ARGS((int c)); @@ -49,7 +52,7 @@ char_u *skiptowhite __ARGS((char_u *p)); char_u *skiptowhite_esc __ARGS((char_u *p)); long getdigits __ARGS((char_u **pp)); int vim_isblankline __ARGS((char_u *lbuf)); -void vim_str2nr __ARGS((char_u *start, int *hexp, int *len, int dooct, int dohex, long *nptr, unsigned long *unptr, int strlen)); +void vim_str2nr __ARGS((char_u *start, int *prep, int *len, int what, long *nptr, unsigned long *unptr, int maxlen)); int hex2nr __ARGS((int c)); int hexhex2nr __ARGS((char_u *p)); int rem_backslash __ARGS((char_u *str)); diff --git a/src/spell.c b/src/spell.c --- a/src/spell.c +++ b/src/spell.c @@ -1047,7 +1047,9 @@ spell_check(wp, ptr, attrp, capcol, doco * julifeest". */ if (*ptr >= '0' && *ptr <= '9') { - if (*ptr == '0' && (ptr[1] == 'x' || ptr[1] == 'X')) + if (*ptr == '0' && (ptr[1] == 'b' || ptr[1] == 'B')) + mi.mi_end = skipbin(ptr + 2); + else if (*ptr == '0' && (ptr[1] == 'x' || ptr[1] == 'X')) mi.mi_end = skiphex(ptr + 2); else mi.mi_end = skipdigits(ptr); @@ -15612,7 +15614,7 @@ ex_spelldump(eap) /* enable spelling locally in the new window */ set_option_value((char_u*)"spell", TRUE, (char_u*)"", OPT_LOCAL); - set_option_value((char_u*)"spl", dummy, spl, OPT_LOCAL); + set_option_value((char_u*)"spl", dummy, spl, OPT_LOCAL); vim_free(spl); if (!bufempty() || !buf_valid(curbuf)) diff --git a/src/testdir/test57.in b/src/testdir/test57.in --- a/src/testdir/test57.in +++ b/src/testdir/test57.in @@ -30,6 +30,8 @@ STARTTEST :/^t25:/+1,/^t26/-1sort/\d\d/rn :/^t26:/+1,/^t27/-1sort/\d\d/rx :/^t27:/+1,/^t28/-1sort no +:/^t28:/+1,/^t29/-1sort b +:/^t29:/+1,/^t30/-1sort b :/^t01:/,$wq! test.out ENDTEST @@ -494,7 +496,38 @@ c321d b322b b321 b321b +t28: binary -t28: done +0b111000 +0b101100 +0b101001 +0b101001 +0b101000 +0b000000 +0b001000 +0b010000 +0b101000 +0b100000 +0b101010 +0b100010 +0b100100 +0b100010 +t29: binary with leading characters + +0b100010 +0b010000 + 0b101001 +b0b101100 +0b100010 + 0b100100 +a0b001000 +0b101000 +0b101000 +a0b101001 +ab0b100000 +0b101010 +0b000000 +b0b111000 +t30: done diff --git a/src/testdir/test57.ok b/src/testdir/test57.ok --- a/src/testdir/test57.ok +++ b/src/testdir/test57.ok @@ -453,7 +453,38 @@ c321d b322b b321 b321b +t28: binary -t28: done +0b000000 +0b001000 +0b010000 +0b100000 +0b100010 +0b100010 +0b100100 +0b101000 +0b101000 +0b101001 +0b101001 +0b101010 +0b101100 +0b111000 +t29: binary with leading characters + +0b000000 +a0b001000 +0b010000 +ab0b100000 +0b100010 +0b100010 + 0b100100 +0b101000 +0b101000 + 0b101001 +a0b101001 +0b101010 +b0b101100 +b0b111000 +t30: done diff --git a/src/testdir/test58.in b/src/testdir/test58.in --- a/src/testdir/test58.in +++ b/src/testdir/test58.in @@ -104,6 +104,8 @@ gg:/^addstart/+1,/^addend/-1w! Xtest.lat :" :" NOSLITSUGS :call TestOne('8', '8') +:" Numbers +:call TestOne('9', '9') :" :" clean up for valgrind :delfunc TestOne @@ -636,4 +638,19 @@ bad: foobar barfoo badend +Test Numbers + +9affstart +9affend + +9dicstart +1234 +foo +bar +9dicend + +9good: 0b1011 0777 1234 0x01ff +badend + + test output: diff --git a/src/testdir/test58.ok b/src/testdir/test58.ok --- a/src/testdir/test58.ok +++ b/src/testdir/test58.ok @@ -281,3 +281,9 @@ foobar ['faabar', 'foo bar', 'bar'] barfoo ['bar foo', 'bar', 'foo'] + +test 9-9 +# file: Xtest.latin1.spl +bar +foo +------- diff --git a/src/testdir/test_increment.in b/src/testdir/test_increment.in --- a/src/testdir/test_increment.in +++ b/src/testdir/test_increment.in @@ -286,6 +286,49 @@ 0x123456 1) Ctrl-V f3 0x124456 +22) Block increment on 0b0 +Text: +0b1 +0b1 + Expected: + 1) Ctrl-A on visually block selected region (cursor at beginning): + 0b10 + 0b10 + 2) Ctrl-A on visually block selected region (cursor at end) + 0b10 + 0b10 + +23) block-wise increment on part of binary +Text: +0b1001 + + Expected: + 1) Ctrl-V 5l +0b1011 + +24) increment hexadecimal +Text: +0x0b1001 + + Expected: + 1) +0x0b1002 + +25) increment binary with nrformats including alpha +Text: +0b1001a + + Expected: + 1) +0b1010a + +26) increment binary with 64 bits +Text: +0b1111111111111111111111111111111111111111111111111111111111111110 + + Expected: + 1) +0b1111111111111111111111111111111111111111111111111111111111111111 STARTTEST @@ -415,6 +458,38 @@ V3kg.. :set nrformats&vim f3 +:" Test 22 +:/^S22=/+,/^E22=/-y a +:/^E22=/+put a +kj$j:.+put a +k$+ + +:" Test 23 +:/^S23=/+,/^E23=/-y a +:/^E23=/+put a +:set nrformats&vim +4l + +:" Test 24 +:/^S24=/+,/^E24=/-y a +:/^E24=/+put a +:set nrformats&vim +$ + +:" Test 25 +:set nrformats+=alpha +:/^S25=/+,/^E25=/-y a +:/^E25=/+put a +k$ +:set nrformats&vim + +:" Test 26 +:set nrformats+=alpha +:/^S26=/+,/^E26=/-y a +:/^E26=/+put a +k$ +:set nrformats&vim + :" Save the report :/^# Test 1/,$w! test.out :qa! @@ -615,6 +690,45 @@ E21==== +# Test 22 +S22==== +0b1 +0b1 +E22==== + + + + +# Test 23 +S23==== +0b1001 +E23==== + + + + +# Test 24 +S24==== +0x0b1001 +E24==== + + + + +# Test 25 +S25==== +0b1001a +E25==== + + + + +# Test 26 +S26==== +0b1111111111111111111111111111111111111111111111111111111111111110 +E26==== + + ENDTEST diff --git a/src/testdir/test_increment.ok b/src/testdir/test_increment.ok --- a/src/testdir/test_increment.ok +++ b/src/testdir/test_increment.ok @@ -288,6 +288,53 @@ E21==== 0x124456 +# Test 22 +S22==== +0b1 +0b1 +E22==== + +0b10 +0b10 + +0b10 +0b10 + + +# Test 23 +S23==== +0b1001 +E23==== + +0b1011 + + + +# Test 24 +S24==== +0x0b1001 +E24==== + +0x0b1002 + + + +# Test 25 +S25==== +0b1001a +E25==== + +0b1010a + + + +# Test 26 +S26==== +0b1111111111111111111111111111111111111111111111111111111111111110 +E26==== + +0b1111111111111111111111111111111111111111111111111111111111111111 + ENDTEST diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1027, +/**/ 1026, /**/ 1025, diff --git a/src/vim.h b/src/vim.h --- a/src/vim.h +++ b/src/vim.h @@ -392,7 +392,15 @@ # endif #endif -#define NUMBUFLEN 30 /* length of a buffer to store a number in ASCII */ +/* length of a buffer to store a number in ASCII (64 bits binary + NUL) */ +#define NUMBUFLEN 65 + +/* flags for vim_str2nr() */ +#define STR2NR_BIN 1 +#define STR2NR_OCT 2 +#define STR2NR_HEX 4 +#define STR2NR_ALL (STR2NR_BIN + STR2NR_OCT + STR2NR_HEX) +#define STR2NR_FORCE 8 /* only when ONE of the above is used */ /* * Shorthand for unsigned variables. Many systems, but not all, have u_char