Busybox 1.20.0 squashed commit for ICS
diff --git a/editors/vi.c b/editors/vi.c
index 96a0c8d..b4ad12e 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -278,7 +278,6 @@
smallint cmd_mode; // 0=command 1=insert 2=replace
int file_modified; // buffer contents changed (counter, not flag!)
int last_file_modified; // = -1;
- int fn_start; // index of first cmd line file name
int save_argc; // how many file names on cmd line
int cmdcnt; // repetition count
unsigned rows, columns; // the terminal screen is this size
@@ -363,7 +362,6 @@
#define cmd_mode (G.cmd_mode )
#define file_modified (G.file_modified )
#define last_file_modified (G.last_file_modified )
-#define fn_start (G.fn_start )
#define save_argc (G.save_argc )
#define cmdcnt (G.cmdcnt )
#define rows (G.rows )
@@ -599,9 +597,10 @@
}
// The argv array can be used by the ":next" and ":rewind" commands
- // save optind.
- fn_start = optind; // remember first file name for :next and :rew
+ argv += optind;
+ argc -= optind;
save_argc = argc;
+ optind = 0;
//----- This is the main file handling loop --------------
while (1) {
@@ -1021,7 +1020,7 @@
} else if (strncmp(cmd, "edit", i) == 0) { // Edit a file
// don't edit, if the current file has been modified
if (file_modified && !useforce) {
- status_line_bold("No write since last change (:edit! overrides)");
+ status_line_bold("No write since last change (:%s! overrides)", cmd);
goto ret;
}
if (args[0]) {
@@ -1040,13 +1039,13 @@
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[]?
@@ -1111,11 +1110,12 @@
Hit_Return();
} else if (strncmp(cmd, "quit", i) == 0 // quit
|| strncmp(cmd, "next", i) == 0 // edit next file
+ || strncmp(cmd, "prev", i) == 0 // edit previous file
) {
int n;
if (useforce) {
- // force end of argv list
if (*cmd == 'q') {
+ // force end of argv list
optind = save_argc;
}
editing = 0;
@@ -1123,8 +1123,7 @@
}
// don't exit if the file been modified
if (file_modified) {
- status_line_bold("No write since last change (:%s! overrides)",
- (*cmd == 'q' ? "quit" : "next"));
+ status_line_bold("No write since last change (:%s! overrides)", cmd);
goto ret;
}
// are there other file to edit
@@ -1137,6 +1136,14 @@
status_line_bold("No more files to edit");
goto ret;
}
+ if (*cmd == 'p') {
+ // are there previous files to edit
+ if (optind < 1) {
+ status_line_bold("No previous files to edit");
+ goto ret;
+ }
+ optind -= 2;
+ }
editing = 0;
} else if (strncmp(cmd, "read", i) == 0) { // read file into text[]
fn = args;
@@ -1172,10 +1179,10 @@
}
} else if (strncmp(cmd, "rewind", i) == 0) { // rewind cmd line args
if (file_modified && !useforce) {
- status_line_bold("No write since last change (:rewind! overrides)");
+ status_line_bold("No write since last change (:%s! overrides)", cmd);
} else {
// reset the filenames to edit
- optind = fn_start - 1;
+ optind = -1; /* start from 0th file */
editing = 0;
}
#if ENABLE_FEATURE_VI_SET
@@ -1225,51 +1232,53 @@
#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 +2082,14 @@
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);
@@ -2304,7 +2321,7 @@
{
tcgetattr(0, &term_orig);
term_vi = term_orig;
- term_vi.c_lflag &= (~ICANON & ~ECHO); // leave ISIG ON- allow intr's
+ term_vi.c_lflag &= (~ICANON & ~ECHO); // leave ISIG on - allow intr's
term_vi.c_iflag &= (~IXON & ~ICRNL);
term_vi.c_oflag &= (~ONLCR);
term_vi.c_cc[VMIN] = 1;
@@ -3063,7 +3080,6 @@
//----- Execute a Vi Command -----------------------------------
static void do_cmd(int c)
{
- const char *msg = msg; // for compiler
char *p, *q, *save_dot;
char buf[12];
int dir;
@@ -3072,8 +3088,8 @@
// c1 = c; // quiet the compiler
// cnt = yf = 0; // quiet the compiler
-// msg = p = q = save_dot = buf; // quiet the compiler
- memset(buf, '\0', 12);
+// p = q = save_dot = buf; // quiet the compiler
+ memset(buf, '\0', sizeof(buf));
show_status_line();
@@ -3189,19 +3205,18 @@
case KEYCODE_LEFT: // cursor key Left
case 8: // ctrl-H- move left (This may be ERASE char)
case 0x7f: // DEL- move left (This may be ERASE char)
- if (--cmdcnt > 0) {
- do_cmd(c);
- }
- dot_left();
+ do {
+ dot_left();
+ } while (--cmdcnt > 0);
break;
case 10: // Newline ^J
case 'j': // j- goto next line, same col
case KEYCODE_DOWN: // cursor key Down
- if (--cmdcnt > 0) {
- do_cmd(c);
- }
- dot_next(); // go to next B-o-l
- dot = move_to_col(dot, ccol + offset); // try stay in same col
+ do {
+ dot_next(); // go to next B-o-l
+ // try stay in same col
+ dot = move_to_col(dot, ccol + offset);
+ } while (--cmdcnt > 0);
break;
case 12: // ctrl-L force redraw whole screen
case 18: // ctrl-R force redraw
@@ -3214,11 +3229,10 @@
break;
case 13: // Carriage Return ^M
case '+': // +- goto next line
- if (--cmdcnt > 0) {
- do_cmd(c);
- }
- dot_next();
- dot_skip_over_ws();
+ do {
+ dot_next();
+ dot_skip_over_ws();
+ } while (--cmdcnt > 0);
break;
case 21: // ctrl-U scroll up half screen
dot_scroll((rows - 2) / 2, -1);
@@ -3236,10 +3250,9 @@
case ' ': // move right
case 'l': // move right
case KEYCODE_RIGHT: // Cursor Key Right
- if (--cmdcnt > 0) {
- do_cmd(c);
- }
- dot_right();
+ do {
+ dot_right();
+ } while (--cmdcnt > 0);
break;
#if ENABLE_FEATURE_VI_YANKMARK
case '"': // "- name a register to use for Delete/Yank
@@ -3309,7 +3322,7 @@
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
@@ -3321,11 +3334,12 @@
#endif /* FEATURE_VI_YANKMARK */
case '$': // $- goto end of line
case KEYCODE_END: // Cursor Key End
- if (--cmdcnt > 0) {
+ for (;;) {
+ dot = end_line(dot);
+ if (--cmdcnt <= 0)
+ break;
dot_next();
- do_cmd(c);
}
- dot = end_line(dot);
break;
case '%': // %- find matching char of pair () [] {}
for (q = dot; q < end && *q != '\n'; q++) {
@@ -3350,38 +3364,35 @@
//
//**** fall through to ... ';'
case ';': // ;- look at rest of line for last forward char
- if (--cmdcnt > 0) {
- do_cmd(';');
- }
- if (last_forward_char == 0)
- break;
- q = dot + 1;
- while (q < end - 1 && *q != '\n' && *q != last_forward_char) {
- q++;
- }
- if (*q == last_forward_char)
- dot = q;
+ do {
+ if (last_forward_char == 0)
+ break;
+ q = dot + 1;
+ while (q < end - 1 && *q != '\n' && *q != last_forward_char) {
+ q++;
+ }
+ if (*q == last_forward_char)
+ dot = q;
+ } while (--cmdcnt > 0);
break;
case ',': // repeat latest 'f' in opposite direction
- if (--cmdcnt > 0) {
- do_cmd(',');
- }
if (last_forward_char == 0)
break;
- q = dot - 1;
- while (q >= text && *q != '\n' && *q != last_forward_char) {
- q--;
- }
- if (q >= text && *q == last_forward_char)
- dot = q;
+ do {
+ q = dot - 1;
+ while (q >= text && *q != '\n' && *q != last_forward_char) {
+ q--;
+ }
+ if (q >= text && *q == last_forward_char)
+ dot = q;
+ } while (--cmdcnt > 0);
break;
case '-': // -- goto prev line
- if (--cmdcnt > 0) {
- do_cmd(c);
- }
- dot_prev();
- dot_skip_over_ws();
+ do {
+ dot_prev();
+ dot_skip_over_ws();
+ } while (--cmdcnt > 0);
break;
#if ENABLE_FEATURE_VI_DOT_CMD
case '.': // .- repeat the last modifying command
@@ -3413,9 +3424,6 @@
// user changed mind and erased the "/"- do nothing
break;
case 'N': // N- backward search for last pattern
- if (--cmdcnt > 0) {
- do_cmd(c);
- }
dir = BACK; // assume BACKWARD search
p = dot - 1;
if (last_search_pattern[0] == '?') {
@@ -3427,41 +3435,41 @@
case 'n': // n- repeat search for last pattern
// search rest of text[] starting at next char
// if search fails return orignal "p" not the "p+1" address
- if (--cmdcnt > 0) {
- do_cmd(c);
- }
+ do {
+ const char *msg;
dc3:
- dir = FORWARD; // assume FORWARD search
- p = dot + 1;
- if (last_search_pattern[0] == '?') {
- dir = BACK;
- p = dot - 1;
- }
- dc4:
- q = char_search(p, last_search_pattern + 1, dir, FULL);
- if (q != NULL) {
- dot = q; // good search, update "dot"
- msg = "";
- goto dc2;
- }
- // no pattern found between "dot" and "end"- continue at top
- p = text;
- if (dir == BACK) {
- p = end - 1;
- }
- q = char_search(p, last_search_pattern + 1, dir, FULL);
- if (q != NULL) { // found something
- dot = q; // found new pattern- goto it
- msg = "search hit BOTTOM, continuing at TOP";
- if (dir == BACK) {
- msg = "search hit TOP, continuing at BOTTOM";
+ dir = FORWARD; // assume FORWARD search
+ p = dot + 1;
+ if (last_search_pattern[0] == '?') {
+ dir = BACK;
+ p = dot - 1;
}
- } else {
- msg = "Pattern not found";
- }
+ dc4:
+ q = char_search(p, last_search_pattern + 1, dir, FULL);
+ if (q != NULL) {
+ dot = q; // good search, update "dot"
+ msg = NULL;
+ goto dc2;
+ }
+ // no pattern found between "dot" and "end"- continue at top
+ p = text;
+ if (dir == BACK) {
+ p = end - 1;
+ }
+ q = char_search(p, last_search_pattern + 1, dir, FULL);
+ if (q != NULL) { // found something
+ dot = q; // found new pattern- goto it
+ msg = "search hit BOTTOM, continuing at TOP";
+ if (dir == BACK) {
+ msg = "search hit TOP, continuing at BOTTOM";
+ }
+ } else {
+ msg = "Pattern not found";
+ }
dc2:
- if (*msg)
- status_line_bold("%s", msg);
+ if (msg)
+ status_line_bold("%s", msg);
+ } while (--cmdcnt > 0);
break;
case '{': // {- move backward paragraph
q = char_search(dot, "\n\n", BACK, FULL);
@@ -3506,7 +3514,7 @@
|| strncmp(p, "q!", cnt) == 0 // delete lines
) {
if (file_modified && p[1] != '!') {
- status_line_bold("No write since last change (:quit! overrides)");
+ status_line_bold("No write since last change (:%s! overrides)", p);
} else {
editing = 0;
}
@@ -3580,18 +3588,17 @@
case 'B': // B- back a blank-delimited Word
case 'E': // E- end of a blank-delimited word
case 'W': // W- forward a blank-delimited word
- if (--cmdcnt > 0) {
- do_cmd(c);
- }
dir = FORWARD;
if (c == 'B')
dir = BACK;
- if (c == 'W' || isspace(dot[dir])) {
- dot = skip_thing(dot, 1, dir, S_TO_WS);
- dot = skip_thing(dot, 2, dir, S_OVER_WS);
- }
- if (c != 'W')
- dot = skip_thing(dot, 1, dir, S_BEFORE_WS);
+ do {
+ if (c == 'W' || isspace(dot[dir])) {
+ dot = skip_thing(dot, 1, dir, S_TO_WS);
+ dot = skip_thing(dot, 2, dir, S_OVER_WS);
+ }
+ if (c != 'W')
+ dot = skip_thing(dot, 1, dir, S_BEFORE_WS);
+ } while (--cmdcnt > 0);
break;
case 'C': // C- Change to e-o-l
case 'D': // D- delete to e-o-l
@@ -3642,20 +3649,19 @@
case 'i': // i- insert before current char
case KEYCODE_INSERT: // Cursor Key Insert
dc_i:
- cmd_mode = 1; // start insrting
+ cmd_mode = 1; // start inserting
break;
case 'J': // J- join current and next lines together
- if (--cmdcnt > 1) {
- do_cmd(c);
- }
- dot_end(); // move to NL
- if (dot < end - 1) { // make sure not last char in text[]
- *dot++ = ' '; // replace NL with space
- file_modified++;
- while (isblank(*dot)) { // delete leading WS
- dot_delete();
+ do {
+ dot_end(); // move to NL
+ if (dot < end - 1) { // make sure not last char in text[]
+ *dot++ = ' '; // replace NL with space
+ file_modified++;
+ while (isblank(*dot)) { // delete leading WS
+ dot_delete();
+ }
}
- }
+ } while (--cmdcnt > 0);
end_cmd_q(); // stop adding to q
break;
case 'L': // L- goto bottom line on screen
@@ -3699,20 +3705,19 @@
case 'X': // X- delete char before dot
case 'x': // x- delete the current char
case 's': // s- substitute the current char
- if (--cmdcnt > 0) {
- do_cmd(c);
- }
dir = 0;
if (c == 'X')
dir = -1;
- if (dot[dir] != '\n') {
- if (c == 'X')
- dot--; // delete prev char
- dot = yank_delete(dot, dot, 0, YANKDEL); // delete char
- }
- if (c == 's')
- goto dc_i; // start insrting
+ do {
+ if (dot[dir] != '\n') {
+ if (c == 'X')
+ dot--; // delete prev char
+ dot = yank_delete(dot, dot, 0, YANKDEL); // delete char
+ }
+ } while (--cmdcnt > 0);
end_cmd_q(); // stop adding to q
+ if (c == 's')
+ goto dc_i; // start inserting
break;
case 'Z': // Z- if modified, {write}; exit
// ZZ means to save file (if necessary), then exit
@@ -3743,23 +3748,22 @@
break;
case 'b': // b- back a word
case 'e': // e- end of word
- if (--cmdcnt > 0) {
- do_cmd(c);
- }
dir = FORWARD;
if (c == 'b')
dir = BACK;
- if ((dot + dir) < text || (dot + dir) > end - 1)
- break;
- dot += dir;
- if (isspace(*dot)) {
- dot = skip_thing(dot, (c == 'e') ? 2 : 1, dir, S_OVER_WS);
- }
- if (isalnum(*dot) || *dot == '_') {
- dot = skip_thing(dot, 1, dir, S_END_ALNUM);
- } else if (ispunct(*dot)) {
- dot = skip_thing(dot, 1, dir, S_END_PUNCT);
- }
+ do {
+ if ((dot + dir) < text || (dot + dir) > end - 1)
+ break;
+ dot += dir;
+ if (isspace(*dot)) {
+ dot = skip_thing(dot, (c == 'e') ? 2 : 1, dir, S_OVER_WS);
+ }
+ if (isalnum(*dot) || *dot == '_') {
+ dot = skip_thing(dot, 1, dir, S_END_ALNUM);
+ } else if (ispunct(*dot)) {
+ dot = skip_thing(dot, 1, dir, S_END_PUNCT);
+ }
+ } while (--cmdcnt > 0);
break;
case 'c': // c- change something
case 'd': // d- delete something
@@ -3844,11 +3848,10 @@
}
case 'k': // k- goto prev line, same col
case KEYCODE_UP: // cursor key Up
- if (--cmdcnt > 0) {
- do_cmd(c);
- }
- dot_prev();
- dot = move_to_col(dot, ccol + offset); // try stay in same col
+ do {
+ dot_prev();
+ dot = move_to_col(dot, ccol + offset); // try stay in same col
+ } while (--cmdcnt > 0);
break;
case 'r': // r- replace the current char with user input
c1 = get_one_char(); // get the replacement char
@@ -3866,19 +3869,18 @@
last_forward_char = 0;
break;
case 'w': // w- forward a word
- if (--cmdcnt > 0) {
- do_cmd(c);
- }
- if (isalnum(*dot) || *dot == '_') { // we are on ALNUM
- dot = skip_thing(dot, 1, FORWARD, S_END_ALNUM);
- } else if (ispunct(*dot)) { // we are on PUNCT
- dot = skip_thing(dot, 1, FORWARD, S_END_PUNCT);
- }
- if (dot < end - 1)
- dot++; // move over word
- if (isspace(*dot)) {
- dot = skip_thing(dot, 2, FORWARD, S_OVER_WS);
- }
+ do {
+ if (isalnum(*dot) || *dot == '_') { // we are on ALNUM
+ dot = skip_thing(dot, 1, FORWARD, S_END_ALNUM);
+ } else if (ispunct(*dot)) { // we are on PUNCT
+ dot = skip_thing(dot, 1, FORWARD, S_END_PUNCT);
+ }
+ if (dot < end - 1)
+ dot++; // move over word
+ if (isspace(*dot)) {
+ dot = skip_thing(dot, 2, FORWARD, S_OVER_WS);
+ }
+ } while (--cmdcnt > 0);
break;
case 'z': // z-
c1 = get_one_char(); // get the replacement char
@@ -3894,17 +3896,16 @@
dot = move_to_col(dot, cmdcnt - 1); // try to move to column
break;
case '~': // ~- flip the case of letters a-z -> A-Z
- if (--cmdcnt > 0) {
- do_cmd(c);
- }
- if (islower(*dot)) {
- *dot = toupper(*dot);
- file_modified++;
- } else if (isupper(*dot)) {
- *dot = tolower(*dot);
- file_modified++;
- }
- dot_right();
+ do {
+ if (islower(*dot)) {
+ *dot = toupper(*dot);
+ file_modified++;
+ } else if (isupper(*dot)) {
+ *dot = tolower(*dot);
+ file_modified++;
+ }
+ dot_right();
+ } while (--cmdcnt > 0);
end_cmd_q(); // stop adding to q
break;
//----- The Cursor and Function Keys -----------------------------