aboutsummaryrefslogtreecommitdiff
path: root/editors
diff options
context:
space:
mode:
Diffstat (limited to 'editors')
-rw-r--r--editors/sed.c38
-rw-r--r--editors/vi.c97
2 files changed, 82 insertions, 53 deletions
diff --git a/editors/sed.c b/editors/sed.c
index c8bb503ea..4e9babb9d 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -282,7 +282,7 @@ static int index_of_next_unescaped_regexp_delim(int delimiter, const char *str)
282static int parse_regex_delim(const char *cmdstr, char **match, char **replace) 282static int parse_regex_delim(const char *cmdstr, char **match, char **replace)
283{ 283{
284 const char *cmdstr_ptr = cmdstr; 284 const char *cmdstr_ptr = cmdstr;
285 char delimiter; 285 unsigned char delimiter;
286 int idx = 0; 286 int idx = 0;
287 287
288 /* verify that the 's' or 'y' is followed by something. That something 288 /* verify that the 's' or 'y' is followed by something. That something
@@ -297,7 +297,7 @@ static int parse_regex_delim(const char *cmdstr, char **match, char **replace)
297 297
298 /* save the replacement string */ 298 /* save the replacement string */
299 cmdstr_ptr += idx + 1; 299 cmdstr_ptr += idx + 1;
300 idx = index_of_next_unescaped_regexp_delim(-delimiter, cmdstr_ptr); 300 idx = index_of_next_unescaped_regexp_delim(- (int)delimiter, cmdstr_ptr);
301 *replace = copy_parsing_escapes(cmdstr_ptr, idx); 301 *replace = copy_parsing_escapes(cmdstr_ptr, idx);
302 302
303 return ((cmdstr_ptr - cmdstr) + idx); 303 return ((cmdstr_ptr - cmdstr) + idx);
@@ -322,10 +322,11 @@ static int get_address(const char *my_str, int *linenum, regex_t ** regex)
322 char *temp; 322 char *temp;
323 323
324 delimiter = '/'; 324 delimiter = '/';
325 if (*my_str == '\\') delimiter = *++pos; 325 if (*my_str == '\\')
326 delimiter = *++pos;
326 next = index_of_next_unescaped_regexp_delim(delimiter, ++pos); 327 next = index_of_next_unescaped_regexp_delim(delimiter, ++pos);
327 temp = copy_parsing_escapes(pos, next); 328 temp = copy_parsing_escapes(pos, next);
328 *regex = xmalloc(sizeof(regex_t)); 329 *regex = xzalloc(sizeof(regex_t));
329 xregcomp(*regex, temp, G.regex_type|REG_NEWLINE); 330 xregcomp(*regex, temp, G.regex_type|REG_NEWLINE);
330 free(temp); 331 free(temp);
331 /* Move position to next character after last delimiter */ 332 /* Move position to next character after last delimiter */
@@ -434,8 +435,10 @@ static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr)
434 /* compile the match string into a regex */ 435 /* compile the match string into a regex */
435 if (*match != '\0') { 436 if (*match != '\0') {
436 /* If match is empty, we use last regex used at runtime */ 437 /* If match is empty, we use last regex used at runtime */
437 sed_cmd->sub_match = xmalloc(sizeof(regex_t)); 438 sed_cmd->sub_match = xzalloc(sizeof(regex_t));
439 dbg("xregcomp('%s',%x)", match, cflags);
438 xregcomp(sed_cmd->sub_match, match, cflags); 440 xregcomp(sed_cmd->sub_match, match, cflags);
441 dbg("regcomp ok");
439 } 442 }
440 free(match); 443 free(match);
441 444
@@ -717,8 +720,12 @@ static int do_subst_command(sed_cmd_t *sed_cmd, char **line_p)
717 G.previous_regex_ptr = current_regex; 720 G.previous_regex_ptr = current_regex;
718 721
719 /* Find the first match */ 722 /* Find the first match */
720 if (REG_NOMATCH == regexec(current_regex, line, 10, G.regmatch, 0)) 723 dbg("matching '%s'", line);
724 if (REG_NOMATCH == regexec(current_regex, line, 10, G.regmatch, 0)) {
725 dbg("no match");
721 return 0; 726 return 0;
727 }
728 dbg("match");
722 729
723 /* Initialize temporary output buffer. */ 730 /* Initialize temporary output buffer. */
724 G.pipeline.buf = xmalloc(PIPE_GROW); 731 G.pipeline.buf = xmalloc(PIPE_GROW);
@@ -730,9 +737,10 @@ static int do_subst_command(sed_cmd_t *sed_cmd, char **line_p)
730 int i; 737 int i;
731 738
732 /* Work around bug in glibc regexec, demonstrated by: 739 /* Work around bug in glibc regexec, demonstrated by:
733 echo " a.b" | busybox sed 's [^ .]* x g' 740 * echo " a.b" | busybox sed 's [^ .]* x g'
734 The match_count check is so not to break 741 * The match_count check is so not to break
735 echo "hi" | busybox sed 's/^/!/g' */ 742 * echo "hi" | busybox sed 's/^/!/g'
743 */
736 if (!G.regmatch[0].rm_so && !G.regmatch[0].rm_eo && match_count) { 744 if (!G.regmatch[0].rm_so && !G.regmatch[0].rm_eo && match_count) {
737 pipe_putc(*line++); 745 pipe_putc(*line++);
738 continue; 746 continue;
@@ -763,11 +771,14 @@ static int do_subst_command(sed_cmd_t *sed_cmd, char **line_p)
763 altered++; 771 altered++;
764 772
765 /* if we're not doing this globally, get out now */ 773 /* if we're not doing this globally, get out now */
766 if (sed_cmd->which_match) 774 if (sed_cmd->which_match != 0)
775 break;
776
777 if (*line == '\0')
767 break; 778 break;
768 779
769//maybe (G.regmatch[0].rm_eo ? REG_NOTBOL : 0) instead of unconditional REG_NOTBOL? 780//maybe (G.regmatch[0].rm_eo ? REG_NOTBOL : 0) instead of unconditional REG_NOTBOL?
770 } while (*line && regexec(current_regex, line, 10, G.regmatch, REG_NOTBOL) != REG_NOMATCH); 781 } while (regexec(current_regex, line, 10, G.regmatch, REG_NOTBOL) != REG_NOMATCH);
771 782
772 /* Copy rest of string into output pipeline */ 783 /* Copy rest of string into output pipeline */
773 while (1) { 784 while (1) {
@@ -1067,8 +1078,8 @@ static void process_files(void)
1067 } 1078 }
1068 1079
1069 /* actual sedding */ 1080 /* actual sedding */
1070 //bb_error_msg("pattern_space:'%s' next_line:'%s' cmd:%c", 1081 dbg("pattern_space:'%s' next_line:'%s' cmd:%c",
1071 //pattern_space, next_line, sed_cmd->cmd); 1082 pattern_space, next_line, sed_cmd->cmd);
1072 switch (sed_cmd->cmd) { 1083 switch (sed_cmd->cmd) {
1073 1084
1074 /* Print line number */ 1085 /* Print line number */
@@ -1115,6 +1126,7 @@ static void process_files(void)
1115 case 's': 1126 case 's':
1116 if (!do_subst_command(sed_cmd, &pattern_space)) 1127 if (!do_subst_command(sed_cmd, &pattern_space))
1117 break; 1128 break;
1129 dbg("do_subst_command succeeeded:'%s'", pattern_space);
1118 substituted |= 1; 1130 substituted |= 1;
1119 1131
1120 /* handle p option */ 1132 /* handle p option */
diff --git a/editors/vi.c b/editors/vi.c
index d6d926e35..6fae221ac 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -278,7 +278,6 @@ struct globals {
278 smallint cmd_mode; // 0=command 1=insert 2=replace 278 smallint cmd_mode; // 0=command 1=insert 2=replace
279 int file_modified; // buffer contents changed (counter, not flag!) 279 int file_modified; // buffer contents changed (counter, not flag!)
280 int last_file_modified; // = -1; 280 int last_file_modified; // = -1;
281 int fn_start; // index of first cmd line file name
282 int save_argc; // how many file names on cmd line 281 int save_argc; // how many file names on cmd line
283 int cmdcnt; // repetition count 282 int cmdcnt; // repetition count
284 unsigned rows, columns; // the terminal screen is this size 283 unsigned rows, columns; // the terminal screen is this size
@@ -363,7 +362,6 @@ struct globals {
363#define cmd_mode (G.cmd_mode ) 362#define cmd_mode (G.cmd_mode )
364#define file_modified (G.file_modified ) 363#define file_modified (G.file_modified )
365#define last_file_modified (G.last_file_modified ) 364#define last_file_modified (G.last_file_modified )
366#define fn_start (G.fn_start )
367#define save_argc (G.save_argc ) 365#define save_argc (G.save_argc )
368#define cmdcnt (G.cmdcnt ) 366#define cmdcnt (G.cmdcnt )
369#define rows (G.rows ) 367#define rows (G.rows )
@@ -599,9 +597,10 @@ int vi_main(int argc, char **argv)
599 } 597 }
600 598
601 // The argv array can be used by the ":next" and ":rewind" commands 599 // The argv array can be used by the ":next" and ":rewind" commands
602 // save optind. 600 argv += optind;
603 fn_start = optind; // remember first file name for :next and :rew 601 argc -= optind;
604 save_argc = argc; 602 save_argc = argc;
603 optind = 0;
605 604
606 //----- This is the main file handling loop -------------- 605 //----- This is the main file handling loop --------------
607 while (1) { 606 while (1) {
@@ -1021,7 +1020,7 @@ static void colon(char *buf)
1021 } else if (strncmp(cmd, "edit", i) == 0) { // Edit a file 1020 } else if (strncmp(cmd, "edit", i) == 0) { // Edit a file
1022 // don't edit, if the current file has been modified 1021 // don't edit, if the current file has been modified
1023 if (file_modified && !useforce) { 1022 if (file_modified && !useforce) {
1024 status_line_bold("No write since last change (:edit! overrides)"); 1023 status_line_bold("No write since last change (:%s! overrides)", cmd);
1025 goto ret; 1024 goto ret;
1026 } 1025 }
1027 if (args[0]) { 1026 if (args[0]) {
@@ -1040,13 +1039,13 @@ static void colon(char *buf)
1040 goto ret; 1039 goto ret;
1041 1040
1042#if ENABLE_FEATURE_VI_YANKMARK 1041#if ENABLE_FEATURE_VI_YANKMARK
1043 if (Ureg >= 0 && Ureg < 28 && reg[Ureg] != 0) { 1042 if (Ureg >= 0 && Ureg < 28) {
1044 free(reg[Ureg]); // free orig line reg- for 'U' 1043 free(reg[Ureg]); // free orig line reg- for 'U'
1045 reg[Ureg]= 0; 1044 reg[Ureg] = NULL;
1046 } 1045 }
1047 if (YDreg >= 0 && YDreg < 28 && reg[YDreg] != 0) { 1046 if (YDreg >= 0 && YDreg < 28) {
1048 free(reg[YDreg]); // free default yank/delete register 1047 free(reg[YDreg]); // free default yank/delete register
1049 reg[YDreg]= 0; 1048 reg[YDreg] = NULL;
1050 } 1049 }
1051#endif 1050#endif
1052 // how many lines in text[]? 1051 // how many lines in text[]?
@@ -1111,11 +1110,12 @@ static void colon(char *buf)
1111 Hit_Return(); 1110 Hit_Return();
1112 } else if (strncmp(cmd, "quit", i) == 0 // quit 1111 } else if (strncmp(cmd, "quit", i) == 0 // quit
1113 || strncmp(cmd, "next", i) == 0 // edit next file 1112 || strncmp(cmd, "next", i) == 0 // edit next file
1113 || strncmp(cmd, "prev", i) == 0 // edit previous file
1114 ) { 1114 ) {
1115 int n; 1115 int n;
1116 if (useforce) { 1116 if (useforce) {
1117 // force end of argv list
1118 if (*cmd == 'q') { 1117 if (*cmd == 'q') {
1118 // force end of argv list
1119 optind = save_argc; 1119 optind = save_argc;
1120 } 1120 }
1121 editing = 0; 1121 editing = 0;
@@ -1123,8 +1123,7 @@ static void colon(char *buf)
1123 } 1123 }
1124 // don't exit if the file been modified 1124 // don't exit if the file been modified
1125 if (file_modified) { 1125 if (file_modified) {
1126 status_line_bold("No write since last change (:%s! overrides)", 1126 status_line_bold("No write since last change (:%s! overrides)", cmd);
1127 (*cmd == 'q' ? "quit" : "next"));
1128 goto ret; 1127 goto ret;
1129 } 1128 }
1130 // are there other file to edit 1129 // are there other file to edit
@@ -1137,6 +1136,14 @@ static void colon(char *buf)
1137 status_line_bold("No more files to edit"); 1136 status_line_bold("No more files to edit");
1138 goto ret; 1137 goto ret;
1139 } 1138 }
1139 if (*cmd == 'p') {
1140 // are there previous files to edit
1141 if (optind < 1) {
1142 status_line_bold("No previous files to edit");
1143 goto ret;
1144 }
1145 optind -= 2;
1146 }
1140 editing = 0; 1147 editing = 0;
1141 } else if (strncmp(cmd, "read", i) == 0) { // read file into text[] 1148 } else if (strncmp(cmd, "read", i) == 0) { // read file into text[]
1142 fn = args; 1149 fn = args;
@@ -1172,10 +1179,10 @@ static void colon(char *buf)
1172 } 1179 }
1173 } else if (strncmp(cmd, "rewind", i) == 0) { // rewind cmd line args 1180 } else if (strncmp(cmd, "rewind", i) == 0) { // rewind cmd line args
1174 if (file_modified && !useforce) { 1181 if (file_modified && !useforce) {
1175 status_line_bold("No write since last change (:rewind! overrides)"); 1182 status_line_bold("No write since last change (:%s! overrides)", cmd);
1176 } else { 1183 } else {
1177 // reset the filenames to edit 1184 // reset the filenames to edit
1178 optind = fn_start - 1; 1185 optind = -1; /* start from 0th file */
1179 editing = 0; 1186 editing = 0;
1180 } 1187 }
1181#if ENABLE_FEATURE_VI_SET 1188#if ENABLE_FEATURE_VI_SET
@@ -1225,51 +1232,53 @@ static void colon(char *buf)
1225#endif /* FEATURE_VI_SET */ 1232#endif /* FEATURE_VI_SET */
1226#if ENABLE_FEATURE_VI_SEARCH 1233#if ENABLE_FEATURE_VI_SEARCH
1227 } else if (cmd[0] == 's') { // substitute a pattern with a replacement pattern 1234 } else if (cmd[0] == 's') { // substitute a pattern with a replacement pattern
1228 char *ls, *F, *R; 1235 char *F, *R, *flags;
1229 int gflag; 1236 size_t len_F, len_R;
1237 int gflag; // global replace flag
1230 1238
1231 // F points to the "find" pattern 1239 // F points to the "find" pattern
1232 // R points to the "replace" pattern 1240 // R points to the "replace" pattern
1233 // replace the cmd line delimiters "/" with NULLs 1241 // replace the cmd line delimiters "/" with NULs
1234 gflag = 0; // global replace flag
1235 c = orig_buf[1]; // what is the delimiter 1242 c = orig_buf[1]; // what is the delimiter
1236 F = orig_buf + 2; // start of "find" 1243 F = orig_buf + 2; // start of "find"
1237 R = strchr(F, c); // middle delimiter 1244 R = strchr(F, c); // middle delimiter
1238 if (!R) 1245 if (!R)
1239 goto colon_s_fail; 1246 goto colon_s_fail;
1247 len_F = R - F;
1240 *R++ = '\0'; // terminate "find" 1248 *R++ = '\0'; // terminate "find"
1241 buf1 = strchr(R, c); 1249 flags = strchr(R, c);
1242 if (!buf1) 1250 if (!flags)
1243 goto colon_s_fail; 1251 goto colon_s_fail;
1244 *buf1++ = '\0'; // terminate "replace" 1252 len_R = flags - R;
1245 if (*buf1 == 'g') { // :s/foo/bar/g 1253 *flags++ = '\0'; // terminate "replace"
1246 buf1++; 1254 gflag = *flags;
1247 gflag++; // turn on gflag 1255
1248 }
1249 q = begin_line(q); 1256 q = begin_line(q);
1250 if (b < 0) { // maybe :s/foo/bar/ 1257 if (b < 0) { // maybe :s/foo/bar/
1251 q = begin_line(dot); // start with cur line 1258 q = begin_line(dot); // start with cur line
1252 b = count_lines(text, q); // cur line number 1259 b = count_lines(text, q); // cur line number
1253 } 1260 }
1254 if (e < 0) 1261 if (e < 0)
1255 e = b; // maybe :.s/foo/bar/ 1262 e = b; // maybe :.s/foo/bar/
1263
1256 for (i = b; i <= e; i++) { // so, :20,23 s \0 find \0 replace \0 1264 for (i = b; i <= e; i++) { // so, :20,23 s \0 find \0 replace \0
1257 ls = q; // orig line start 1265 char *ls = q; // orig line start
1266 char *found;
1258 vc4: 1267 vc4:
1259 buf1 = char_search(q, F, FORWARD, LIMITED); // search cur line only for "find" 1268 found = char_search(q, F, FORWARD, LIMITED); // search cur line only for "find"
1260 if (buf1) { 1269 if (found) {
1261 uintptr_t bias; 1270 uintptr_t bias;
1262 // we found the "find" pattern - delete it 1271 // we found the "find" pattern - delete it
1263 text_hole_delete(buf1, buf1 + strlen(F) - 1); 1272 text_hole_delete(found, found + len_F - 1);
1264 // inset the "replace" patern 1273 // inset the "replace" patern
1265 bias = string_insert(buf1, R); // insert the string 1274 bias = string_insert(found, R); // insert the string
1266 buf1 += bias; 1275 found += bias;
1267 ls += bias; 1276 ls += bias;
1268 /*q += bias; - recalculated anyway */ 1277 /*q += bias; - recalculated anyway */
1269 // check for "global" :s/foo/bar/g 1278 // check for "global" :s/foo/bar/g
1270 if (gflag == 1) { 1279 if (gflag == 'g') {
1271 if ((buf1 + strlen(R)) < end_line(ls)) { 1280 if ((found + len_R) < end_line(ls)) {
1272 q = buf1 + strlen(R); 1281 q = found + len_R;
1273 goto vc4; // don't let q move past cur line 1282 goto vc4; // don't let q move past cur line
1274 } 1283 }
1275 } 1284 }
@@ -2073,6 +2082,14 @@ static uintptr_t text_hole_make(char *p, int size) // at "p", make a 'size' byte
2073 dot += bias; 2082 dot += bias;
2074 end += bias; 2083 end += bias;
2075 p += bias; 2084 p += bias;
2085#if ENABLE_FEATURE_VI_YANKMARK
2086 {
2087 int i;
2088 for (i = 0; i < ARRAY_SIZE(mark); i++)
2089 if (mark[i])
2090 mark[i] += bias;
2091 }
2092#endif
2076 text = new_text; 2093 text = new_text;
2077 } 2094 }
2078 memmove(p + size, p, end - size - p); 2095 memmove(p + size, p, end - size - p);
@@ -2304,7 +2321,7 @@ static void rawmode(void)
2304{ 2321{
2305 tcgetattr(0, &term_orig); 2322 tcgetattr(0, &term_orig);
2306 term_vi = term_orig; 2323 term_vi = term_orig;
2307 term_vi.c_lflag &= (~ICANON & ~ECHO); // leave ISIG ON- allow intr's 2324 term_vi.c_lflag &= (~ICANON & ~ECHO); // leave ISIG on - allow intr's
2308 term_vi.c_iflag &= (~IXON & ~ICRNL); 2325 term_vi.c_iflag &= (~IXON & ~ICRNL);
2309 term_vi.c_oflag &= (~ONLCR); 2326 term_vi.c_oflag &= (~ONLCR);
2310 term_vi.c_cc[VMIN] = 1; 2327 term_vi.c_cc[VMIN] = 1;
@@ -3314,7 +3331,7 @@ static void do_cmd(int c)
3314 end_cmd_q(); // stop adding to q 3331 end_cmd_q(); // stop adding to q
3315 break; 3332 break;
3316 case 'U': // U- Undo; replace current line with original version 3333 case 'U': // U- Undo; replace current line with original version
3317 if (reg[Ureg] != 0) { 3334 if (reg[Ureg] != NULL) {
3318 p = begin_line(dot); 3335 p = begin_line(dot);
3319 q = end_line(dot); 3336 q = end_line(dot);
3320 p = text_hole_delete(p, q); // delete cur line 3337 p = text_hole_delete(p, q); // delete cur line
@@ -3328,7 +3345,7 @@ static void do_cmd(int c)
3328 case KEYCODE_END: // Cursor Key End 3345 case KEYCODE_END: // Cursor Key End
3329 for (;;) { 3346 for (;;) {
3330 dot = end_line(dot); 3347 dot = end_line(dot);
3331 if (--cmdcnt > 0) 3348 if (--cmdcnt <= 0)
3332 break; 3349 break;
3333 dot_next(); 3350 dot_next();
3334 } 3351 }
@@ -3506,7 +3523,7 @@ static void do_cmd(int c)
3506 || strncmp(p, "q!", cnt) == 0 // delete lines 3523 || strncmp(p, "q!", cnt) == 0 // delete lines
3507 ) { 3524 ) {
3508 if (file_modified && p[1] != '!') { 3525 if (file_modified && p[1] != '!') {
3509 status_line_bold("No write since last change (:quit! overrides)"); 3526 status_line_bold("No write since last change (:%s! overrides)", p);
3510 } else { 3527 } else {
3511 editing = 0; 3528 editing = 0;
3512 } 3529 }