diff options
author | Denys Vlasenko | 2012-01-31 14:10:26 +0100 |
---|---|---|
committer | Denys Vlasenko | 2012-01-31 14:10:26 +0100 |
commit | 800a9a056a3703b4001bf55ebc30b1c14cf55acc (patch) | |
tree | 9dd00a98842ae463b8d976d7a3a483eccff080c9 /editors/vi.c | |
parent | 7eaa03709b337b586b11c4b9b53c9675f4de690c (diff) | |
download | busybox-800a9a056a3703b4001bf55ebc30b1c14cf55acc.zip busybox-800a9a056a3703b4001bf55ebc30b1c14cf55acc.tar.gz |
vi: move mark[i] pointers if text[] moves after realloc
While at it, optimized :s/find/repl/ a bit
function old new delta
text_hole_make 120 150 +30
colon 2848 2844 -4
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'editors/vi.c')
-rw-r--r-- | editors/vi.c | 64 |
1 files changed, 37 insertions, 27 deletions
diff --git a/editors/vi.c b/editors/vi.c index 4a2d5d4..f7b9f38 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -1040,13 +1040,13 @@ static void colon(char *buf) goto ret; #if ENABLE_FEATURE_VI_YANKMARK - if (Ureg >= 0 && Ureg < 28 && reg[Ureg] != 0) { + if (Ureg >= 0 && Ureg < 28) { free(reg[Ureg]); // free orig line reg- for 'U' - reg[Ureg]= 0; + reg[Ureg] = NULL; } - if (YDreg >= 0 && YDreg < 28 && reg[YDreg] != 0) { + if (YDreg >= 0 && YDreg < 28) { free(reg[YDreg]); // free default yank/delete register - reg[YDreg]= 0; + reg[YDreg] = NULL; } #endif // how many lines in text[]? @@ -1225,51 +1225,53 @@ static void colon(char *buf) #endif /* FEATURE_VI_SET */ #if ENABLE_FEATURE_VI_SEARCH } else if (cmd[0] == 's') { // substitute a pattern with a replacement pattern - char *ls, *F, *R; - int gflag; + char *F, *R, *flags; + size_t len_F, len_R; + int gflag; // global replace flag // F points to the "find" pattern // R points to the "replace" pattern - // replace the cmd line delimiters "/" with NULLs - gflag = 0; // global replace flag + // replace the cmd line delimiters "/" with NULs c = orig_buf[1]; // what is the delimiter F = orig_buf + 2; // start of "find" R = strchr(F, c); // middle delimiter if (!R) goto colon_s_fail; + len_F = R - F; *R++ = '\0'; // terminate "find" - buf1 = strchr(R, c); - if (!buf1) + flags = strchr(R, c); + if (!flags) goto colon_s_fail; - *buf1++ = '\0'; // terminate "replace" - if (*buf1 == 'g') { // :s/foo/bar/g - buf1++; - gflag++; // turn on gflag - } + len_R = flags - R; + *flags++ = '\0'; // terminate "replace" + gflag = *flags; + q = begin_line(q); if (b < 0) { // maybe :s/foo/bar/ - q = begin_line(dot); // start with cur line - b = count_lines(text, q); // cur line number + q = begin_line(dot); // start with cur line + b = count_lines(text, q); // cur line number } if (e < 0) e = b; // maybe :.s/foo/bar/ + for (i = b; i <= e; i++) { // so, :20,23 s \0 find \0 replace \0 - ls = q; // orig line start + char *ls = q; // orig line start + char *found; vc4: - buf1 = char_search(q, F, FORWARD, LIMITED); // search cur line only for "find" - if (buf1) { + found = char_search(q, F, FORWARD, LIMITED); // search cur line only for "find" + if (found) { uintptr_t bias; // we found the "find" pattern - delete it - text_hole_delete(buf1, buf1 + strlen(F) - 1); + text_hole_delete(found, found + len_F - 1); // inset the "replace" patern - bias = string_insert(buf1, R); // insert the string - buf1 += bias; + bias = string_insert(found, R); // insert the string + found += bias; ls += bias; /*q += bias; - recalculated anyway */ // check for "global" :s/foo/bar/g - if (gflag == 1) { - if ((buf1 + strlen(R)) < end_line(ls)) { - q = buf1 + strlen(R); + if (gflag == 'g') { + if ((found + len_R) < end_line(ls)) { + q = found + len_R; goto vc4; // don't let q move past cur line } } @@ -2073,6 +2075,14 @@ static uintptr_t text_hole_make(char *p, int size) // at "p", make a 'size' byte dot += bias; end += bias; p += bias; +#if ENABLE_FEATURE_VI_YANKMARK + { + int i; + for (i = 0; i < ARRAY_SIZE(mark); i++) + if (mark[i]) + mark[i] += bias; + } +#endif text = new_text; } memmove(p + size, p, end - size - p); @@ -3305,7 +3315,7 @@ static void do_cmd(int c) end_cmd_q(); // stop adding to q break; case 'U': // U- Undo; replace current line with original version - if (reg[Ureg] != 0) { + if (reg[Ureg] != NULL) { p = begin_line(dot); q = end_line(dot); p = text_hole_delete(p, q); // delete cur line |