diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2012-01-31 14:10:26 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2012-01-31 14:10:26 +0100 |
commit | 800a9a056a3703b4001bf55ebc30b1c14cf55acc (patch) | |
tree | 9dd00a98842ae463b8d976d7a3a483eccff080c9 | |
parent | 7eaa03709b337b586b11c4b9b53c9675f4de690c (diff) | |
download | busybox-w32-800a9a056a3703b4001bf55ebc30b1c14cf55acc.tar.gz busybox-w32-800a9a056a3703b4001bf55ebc30b1c14cf55acc.tar.bz2 busybox-w32-800a9a056a3703b4001bf55ebc30b1c14cf55acc.zip |
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>
-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 4a2d5d4f1..f7b9f3873 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -1040,13 +1040,13 @@ static void colon(char *buf) | |||
1040 | goto ret; | 1040 | goto ret; |
1041 | 1041 | ||
1042 | #if ENABLE_FEATURE_VI_YANKMARK | 1042 | #if ENABLE_FEATURE_VI_YANKMARK |
1043 | if (Ureg >= 0 && Ureg < 28 && reg[Ureg] != 0) { | 1043 | if (Ureg >= 0 && Ureg < 28) { |
1044 | free(reg[Ureg]); // free orig line reg- for 'U' | 1044 | free(reg[Ureg]); // free orig line reg- for 'U' |
1045 | reg[Ureg]= 0; | 1045 | reg[Ureg] = NULL; |
1046 | } | 1046 | } |
1047 | if (YDreg >= 0 && YDreg < 28 && reg[YDreg] != 0) { | 1047 | if (YDreg >= 0 && YDreg < 28) { |
1048 | free(reg[YDreg]); // free default yank/delete register | 1048 | free(reg[YDreg]); // free default yank/delete register |
1049 | reg[YDreg]= 0; | 1049 | reg[YDreg] = NULL; |
1050 | } | 1050 | } |
1051 | #endif | 1051 | #endif |
1052 | // how many lines in text[]? | 1052 | // how many lines in text[]? |
@@ -1225,51 +1225,53 @@ static void colon(char *buf) | |||
1225 | #endif /* FEATURE_VI_SET */ | 1225 | #endif /* FEATURE_VI_SET */ |
1226 | #if ENABLE_FEATURE_VI_SEARCH | 1226 | #if ENABLE_FEATURE_VI_SEARCH |
1227 | } else if (cmd[0] == 's') { // substitute a pattern with a replacement pattern | 1227 | } else if (cmd[0] == 's') { // substitute a pattern with a replacement pattern |
1228 | char *ls, *F, *R; | 1228 | char *F, *R, *flags; |
1229 | int gflag; | 1229 | size_t len_F, len_R; |
1230 | int gflag; // global replace flag | ||
1230 | 1231 | ||
1231 | // F points to the "find" pattern | 1232 | // F points to the "find" pattern |
1232 | // R points to the "replace" pattern | 1233 | // R points to the "replace" pattern |
1233 | // replace the cmd line delimiters "/" with NULLs | 1234 | // replace the cmd line delimiters "/" with NULs |
1234 | gflag = 0; // global replace flag | ||
1235 | c = orig_buf[1]; // what is the delimiter | 1235 | c = orig_buf[1]; // what is the delimiter |
1236 | F = orig_buf + 2; // start of "find" | 1236 | F = orig_buf + 2; // start of "find" |
1237 | R = strchr(F, c); // middle delimiter | 1237 | R = strchr(F, c); // middle delimiter |
1238 | if (!R) | 1238 | if (!R) |
1239 | goto colon_s_fail; | 1239 | goto colon_s_fail; |
1240 | len_F = R - F; | ||
1240 | *R++ = '\0'; // terminate "find" | 1241 | *R++ = '\0'; // terminate "find" |
1241 | buf1 = strchr(R, c); | 1242 | flags = strchr(R, c); |
1242 | if (!buf1) | 1243 | if (!flags) |
1243 | goto colon_s_fail; | 1244 | goto colon_s_fail; |
1244 | *buf1++ = '\0'; // terminate "replace" | 1245 | len_R = flags - R; |
1245 | if (*buf1 == 'g') { // :s/foo/bar/g | 1246 | *flags++ = '\0'; // terminate "replace" |
1246 | buf1++; | 1247 | gflag = *flags; |
1247 | gflag++; // turn on gflag | 1248 | |
1248 | } | ||
1249 | q = begin_line(q); | 1249 | q = begin_line(q); |
1250 | if (b < 0) { // maybe :s/foo/bar/ | 1250 | if (b < 0) { // maybe :s/foo/bar/ |
1251 | q = begin_line(dot); // start with cur line | 1251 | q = begin_line(dot); // start with cur line |
1252 | b = count_lines(text, q); // cur line number | 1252 | b = count_lines(text, q); // cur line number |
1253 | } | 1253 | } |
1254 | if (e < 0) | 1254 | if (e < 0) |
1255 | e = b; // maybe :.s/foo/bar/ | 1255 | e = b; // maybe :.s/foo/bar/ |
1256 | |||
1256 | for (i = b; i <= e; i++) { // so, :20,23 s \0 find \0 replace \0 | 1257 | for (i = b; i <= e; i++) { // so, :20,23 s \0 find \0 replace \0 |
1257 | ls = q; // orig line start | 1258 | char *ls = q; // orig line start |
1259 | char *found; | ||
1258 | vc4: | 1260 | vc4: |
1259 | buf1 = char_search(q, F, FORWARD, LIMITED); // search cur line only for "find" | 1261 | found = char_search(q, F, FORWARD, LIMITED); // search cur line only for "find" |
1260 | if (buf1) { | 1262 | if (found) { |
1261 | uintptr_t bias; | 1263 | uintptr_t bias; |
1262 | // we found the "find" pattern - delete it | 1264 | // we found the "find" pattern - delete it |
1263 | text_hole_delete(buf1, buf1 + strlen(F) - 1); | 1265 | text_hole_delete(found, found + len_F - 1); |
1264 | // inset the "replace" patern | 1266 | // inset the "replace" patern |
1265 | bias = string_insert(buf1, R); // insert the string | 1267 | bias = string_insert(found, R); // insert the string |
1266 | buf1 += bias; | 1268 | found += bias; |
1267 | ls += bias; | 1269 | ls += bias; |
1268 | /*q += bias; - recalculated anyway */ | 1270 | /*q += bias; - recalculated anyway */ |
1269 | // check for "global" :s/foo/bar/g | 1271 | // check for "global" :s/foo/bar/g |
1270 | if (gflag == 1) { | 1272 | if (gflag == 'g') { |
1271 | if ((buf1 + strlen(R)) < end_line(ls)) { | 1273 | if ((found + len_R) < end_line(ls)) { |
1272 | q = buf1 + strlen(R); | 1274 | q = found + len_R; |
1273 | goto vc4; // don't let q move past cur line | 1275 | goto vc4; // don't let q move past cur line |
1274 | } | 1276 | } |
1275 | } | 1277 | } |
@@ -2073,6 +2075,14 @@ static uintptr_t text_hole_make(char *p, int size) // at "p", make a 'size' byte | |||
2073 | dot += bias; | 2075 | dot += bias; |
2074 | end += bias; | 2076 | end += bias; |
2075 | p += bias; | 2077 | p += bias; |
2078 | #if ENABLE_FEATURE_VI_YANKMARK | ||
2079 | { | ||
2080 | int i; | ||
2081 | for (i = 0; i < ARRAY_SIZE(mark); i++) | ||
2082 | if (mark[i]) | ||
2083 | mark[i] += bias; | ||
2084 | } | ||
2085 | #endif | ||
2076 | text = new_text; | 2086 | text = new_text; |
2077 | } | 2087 | } |
2078 | memmove(p + size, p, end - size - p); | 2088 | memmove(p + size, p, end - size - p); |
@@ -3305,7 +3315,7 @@ static void do_cmd(int c) | |||
3305 | end_cmd_q(); // stop adding to q | 3315 | end_cmd_q(); // stop adding to q |
3306 | break; | 3316 | break; |
3307 | case 'U': // U- Undo; replace current line with original version | 3317 | case 'U': // U- Undo; replace current line with original version |
3308 | if (reg[Ureg] != 0) { | 3318 | if (reg[Ureg] != NULL) { |
3309 | p = begin_line(dot); | 3319 | p = begin_line(dot); |
3310 | q = end_line(dot); | 3320 | q = end_line(dot); |
3311 | p = text_hole_delete(p, q); // delete cur line | 3321 | p = text_hole_delete(p, q); // delete cur line |