aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2012-01-31 14:10:26 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2012-01-31 14:10:26 +0100
commit800a9a056a3703b4001bf55ebc30b1c14cf55acc (patch)
tree9dd00a98842ae463b8d976d7a3a483eccff080c9
parent7eaa03709b337b586b11c4b9b53c9675f4de690c (diff)
downloadbusybox-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.c64
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