vi: prevent unlimited recursion in do_cmd(). Closes 4153
function old new delta do_cmd 4284 4194 -90 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
289c47b049
commit
12e154f0cf
298
editors/vi.c
298
editors/vi.c
@ -3063,7 +3063,6 @@ static void refresh(int full_screen)
|
|||||||
//----- Execute a Vi Command -----------------------------------
|
//----- Execute a Vi Command -----------------------------------
|
||||||
static void do_cmd(int c)
|
static void do_cmd(int c)
|
||||||
{
|
{
|
||||||
const char *msg = msg; // for compiler
|
|
||||||
char *p, *q, *save_dot;
|
char *p, *q, *save_dot;
|
||||||
char buf[12];
|
char buf[12];
|
||||||
int dir;
|
int dir;
|
||||||
@ -3072,8 +3071,8 @@ static void do_cmd(int c)
|
|||||||
|
|
||||||
// c1 = c; // quiet the compiler
|
// c1 = c; // quiet the compiler
|
||||||
// cnt = yf = 0; // quiet the compiler
|
// cnt = yf = 0; // quiet the compiler
|
||||||
// msg = p = q = save_dot = buf; // quiet the compiler
|
// p = q = save_dot = buf; // quiet the compiler
|
||||||
memset(buf, '\0', 12);
|
memset(buf, '\0', sizeof(buf));
|
||||||
|
|
||||||
show_status_line();
|
show_status_line();
|
||||||
|
|
||||||
@ -3189,19 +3188,18 @@ static void do_cmd(int c)
|
|||||||
case KEYCODE_LEFT: // cursor key Left
|
case KEYCODE_LEFT: // cursor key Left
|
||||||
case 8: // ctrl-H- move left (This may be ERASE char)
|
case 8: // ctrl-H- move left (This may be ERASE char)
|
||||||
case 0x7f: // DEL- move left (This may be ERASE char)
|
case 0x7f: // DEL- move left (This may be ERASE char)
|
||||||
if (--cmdcnt > 0) {
|
do {
|
||||||
do_cmd(c);
|
dot_left();
|
||||||
}
|
} while (--cmdcnt > 0);
|
||||||
dot_left();
|
|
||||||
break;
|
break;
|
||||||
case 10: // Newline ^J
|
case 10: // Newline ^J
|
||||||
case 'j': // j- goto next line, same col
|
case 'j': // j- goto next line, same col
|
||||||
case KEYCODE_DOWN: // cursor key Down
|
case KEYCODE_DOWN: // cursor key Down
|
||||||
if (--cmdcnt > 0) {
|
do {
|
||||||
do_cmd(c);
|
dot_next(); // go to next B-o-l
|
||||||
}
|
// try stay in same col
|
||||||
dot_next(); // go to next B-o-l
|
dot = move_to_col(dot, ccol + offset);
|
||||||
dot = move_to_col(dot, ccol + offset); // try stay in same col
|
} while (--cmdcnt > 0);
|
||||||
break;
|
break;
|
||||||
case 12: // ctrl-L force redraw whole screen
|
case 12: // ctrl-L force redraw whole screen
|
||||||
case 18: // ctrl-R force redraw
|
case 18: // ctrl-R force redraw
|
||||||
@ -3214,11 +3212,10 @@ static void do_cmd(int c)
|
|||||||
break;
|
break;
|
||||||
case 13: // Carriage Return ^M
|
case 13: // Carriage Return ^M
|
||||||
case '+': // +- goto next line
|
case '+': // +- goto next line
|
||||||
if (--cmdcnt > 0) {
|
do {
|
||||||
do_cmd(c);
|
dot_next();
|
||||||
}
|
dot_skip_over_ws();
|
||||||
dot_next();
|
} while (--cmdcnt > 0);
|
||||||
dot_skip_over_ws();
|
|
||||||
break;
|
break;
|
||||||
case 21: // ctrl-U scroll up half screen
|
case 21: // ctrl-U scroll up half screen
|
||||||
dot_scroll((rows - 2) / 2, -1);
|
dot_scroll((rows - 2) / 2, -1);
|
||||||
@ -3236,10 +3233,9 @@ static void do_cmd(int c)
|
|||||||
case ' ': // move right
|
case ' ': // move right
|
||||||
case 'l': // move right
|
case 'l': // move right
|
||||||
case KEYCODE_RIGHT: // Cursor Key Right
|
case KEYCODE_RIGHT: // Cursor Key Right
|
||||||
if (--cmdcnt > 0) {
|
do {
|
||||||
do_cmd(c);
|
dot_right();
|
||||||
}
|
} while (--cmdcnt > 0);
|
||||||
dot_right();
|
|
||||||
break;
|
break;
|
||||||
#if ENABLE_FEATURE_VI_YANKMARK
|
#if ENABLE_FEATURE_VI_YANKMARK
|
||||||
case '"': // "- name a register to use for Delete/Yank
|
case '"': // "- name a register to use for Delete/Yank
|
||||||
@ -3321,11 +3317,12 @@ static void do_cmd(int c)
|
|||||||
#endif /* FEATURE_VI_YANKMARK */
|
#endif /* FEATURE_VI_YANKMARK */
|
||||||
case '$': // $- goto end of line
|
case '$': // $- goto end of line
|
||||||
case KEYCODE_END: // Cursor Key End
|
case KEYCODE_END: // Cursor Key End
|
||||||
if (--cmdcnt > 0) {
|
for (;;) {
|
||||||
|
dot = end_line(dot);
|
||||||
|
if (--cmdcnt > 0)
|
||||||
|
break;
|
||||||
dot_next();
|
dot_next();
|
||||||
do_cmd(c);
|
|
||||||
}
|
}
|
||||||
dot = end_line(dot);
|
|
||||||
break;
|
break;
|
||||||
case '%': // %- find matching char of pair () [] {}
|
case '%': // %- find matching char of pair () [] {}
|
||||||
for (q = dot; q < end && *q != '\n'; q++) {
|
for (q = dot; q < end && *q != '\n'; q++) {
|
||||||
@ -3350,38 +3347,35 @@ static void do_cmd(int c)
|
|||||||
//
|
//
|
||||||
//**** fall through to ... ';'
|
//**** fall through to ... ';'
|
||||||
case ';': // ;- look at rest of line for last forward char
|
case ';': // ;- look at rest of line for last forward char
|
||||||
if (--cmdcnt > 0) {
|
do {
|
||||||
do_cmd(';');
|
if (last_forward_char == 0)
|
||||||
}
|
break;
|
||||||
if (last_forward_char == 0)
|
q = dot + 1;
|
||||||
break;
|
while (q < end - 1 && *q != '\n' && *q != last_forward_char) {
|
||||||
q = dot + 1;
|
q++;
|
||||||
while (q < end - 1 && *q != '\n' && *q != last_forward_char) {
|
}
|
||||||
q++;
|
if (*q == last_forward_char)
|
||||||
}
|
dot = q;
|
||||||
if (*q == last_forward_char)
|
} while (--cmdcnt > 0);
|
||||||
dot = q;
|
|
||||||
break;
|
break;
|
||||||
case ',': // repeat latest 'f' in opposite direction
|
case ',': // repeat latest 'f' in opposite direction
|
||||||
if (--cmdcnt > 0) {
|
|
||||||
do_cmd(',');
|
|
||||||
}
|
|
||||||
if (last_forward_char == 0)
|
if (last_forward_char == 0)
|
||||||
break;
|
break;
|
||||||
q = dot - 1;
|
do {
|
||||||
while (q >= text && *q != '\n' && *q != last_forward_char) {
|
q = dot - 1;
|
||||||
q--;
|
while (q >= text && *q != '\n' && *q != last_forward_char) {
|
||||||
}
|
q--;
|
||||||
if (q >= text && *q == last_forward_char)
|
}
|
||||||
dot = q;
|
if (q >= text && *q == last_forward_char)
|
||||||
|
dot = q;
|
||||||
|
} while (--cmdcnt > 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '-': // -- goto prev line
|
case '-': // -- goto prev line
|
||||||
if (--cmdcnt > 0) {
|
do {
|
||||||
do_cmd(c);
|
dot_prev();
|
||||||
}
|
dot_skip_over_ws();
|
||||||
dot_prev();
|
} while (--cmdcnt > 0);
|
||||||
dot_skip_over_ws();
|
|
||||||
break;
|
break;
|
||||||
#if ENABLE_FEATURE_VI_DOT_CMD
|
#if ENABLE_FEATURE_VI_DOT_CMD
|
||||||
case '.': // .- repeat the last modifying command
|
case '.': // .- repeat the last modifying command
|
||||||
@ -3413,9 +3407,6 @@ static void do_cmd(int c)
|
|||||||
// user changed mind and erased the "/"- do nothing
|
// user changed mind and erased the "/"- do nothing
|
||||||
break;
|
break;
|
||||||
case 'N': // N- backward search for last pattern
|
case 'N': // N- backward search for last pattern
|
||||||
if (--cmdcnt > 0) {
|
|
||||||
do_cmd(c);
|
|
||||||
}
|
|
||||||
dir = BACK; // assume BACKWARD search
|
dir = BACK; // assume BACKWARD search
|
||||||
p = dot - 1;
|
p = dot - 1;
|
||||||
if (last_search_pattern[0] == '?') {
|
if (last_search_pattern[0] == '?') {
|
||||||
@ -3427,41 +3418,41 @@ static void do_cmd(int c)
|
|||||||
case 'n': // n- repeat search for last pattern
|
case 'n': // n- repeat search for last pattern
|
||||||
// search rest of text[] starting at next char
|
// search rest of text[] starting at next char
|
||||||
// if search fails return orignal "p" not the "p+1" address
|
// if search fails return orignal "p" not the "p+1" address
|
||||||
if (--cmdcnt > 0) {
|
do {
|
||||||
do_cmd(c);
|
const char *msg;
|
||||||
}
|
|
||||||
dc3:
|
dc3:
|
||||||
dir = FORWARD; // assume FORWARD search
|
dir = FORWARD; // assume FORWARD search
|
||||||
p = dot + 1;
|
p = dot + 1;
|
||||||
if (last_search_pattern[0] == '?') {
|
if (last_search_pattern[0] == '?') {
|
||||||
dir = BACK;
|
dir = BACK;
|
||||||
p = dot - 1;
|
p = dot - 1;
|
||||||
}
|
}
|
||||||
dc4:
|
dc4:
|
||||||
q = char_search(p, last_search_pattern + 1, dir, FULL);
|
q = char_search(p, last_search_pattern + 1, dir, FULL);
|
||||||
if (q != NULL) {
|
if (q != NULL) {
|
||||||
dot = q; // good search, update "dot"
|
dot = q; // good search, update "dot"
|
||||||
msg = "";
|
msg = NULL;
|
||||||
goto dc2;
|
goto dc2;
|
||||||
}
|
}
|
||||||
// no pattern found between "dot" and "end"- continue at top
|
// no pattern found between "dot" and "end"- continue at top
|
||||||
p = text;
|
p = text;
|
||||||
if (dir == BACK) {
|
if (dir == BACK) {
|
||||||
p = end - 1;
|
p = end - 1;
|
||||||
}
|
}
|
||||||
q = char_search(p, last_search_pattern + 1, dir, FULL);
|
q = char_search(p, last_search_pattern + 1, dir, FULL);
|
||||||
if (q != NULL) { // found something
|
if (q != NULL) { // found something
|
||||||
dot = q; // found new pattern- goto it
|
dot = q; // found new pattern- goto it
|
||||||
msg = "search hit BOTTOM, continuing at TOP";
|
msg = "search hit BOTTOM, continuing at TOP";
|
||||||
if (dir == BACK) {
|
if (dir == BACK) {
|
||||||
msg = "search hit TOP, continuing at BOTTOM";
|
msg = "search hit TOP, continuing at BOTTOM";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
msg = "Pattern not found";
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
msg = "Pattern not found";
|
|
||||||
}
|
|
||||||
dc2:
|
dc2:
|
||||||
if (*msg)
|
if (msg)
|
||||||
status_line_bold("%s", msg);
|
status_line_bold("%s", msg);
|
||||||
|
} while (--cmdcnt > 0);
|
||||||
break;
|
break;
|
||||||
case '{': // {- move backward paragraph
|
case '{': // {- move backward paragraph
|
||||||
q = char_search(dot, "\n\n", BACK, FULL);
|
q = char_search(dot, "\n\n", BACK, FULL);
|
||||||
@ -3580,18 +3571,17 @@ static void do_cmd(int c)
|
|||||||
case 'B': // B- back a blank-delimited Word
|
case 'B': // B- back a blank-delimited Word
|
||||||
case 'E': // E- end of a blank-delimited word
|
case 'E': // E- end of a blank-delimited word
|
||||||
case 'W': // W- forward a blank-delimited word
|
case 'W': // W- forward a blank-delimited word
|
||||||
if (--cmdcnt > 0) {
|
|
||||||
do_cmd(c);
|
|
||||||
}
|
|
||||||
dir = FORWARD;
|
dir = FORWARD;
|
||||||
if (c == 'B')
|
if (c == 'B')
|
||||||
dir = BACK;
|
dir = BACK;
|
||||||
if (c == 'W' || isspace(dot[dir])) {
|
do {
|
||||||
dot = skip_thing(dot, 1, dir, S_TO_WS);
|
if (c == 'W' || isspace(dot[dir])) {
|
||||||
dot = skip_thing(dot, 2, dir, S_OVER_WS);
|
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);
|
if (c != 'W')
|
||||||
|
dot = skip_thing(dot, 1, dir, S_BEFORE_WS);
|
||||||
|
} while (--cmdcnt > 0);
|
||||||
break;
|
break;
|
||||||
case 'C': // C- Change to e-o-l
|
case 'C': // C- Change to e-o-l
|
||||||
case 'D': // D- delete to e-o-l
|
case 'D': // D- delete to e-o-l
|
||||||
@ -3642,20 +3632,19 @@ static void do_cmd(int c)
|
|||||||
case 'i': // i- insert before current char
|
case 'i': // i- insert before current char
|
||||||
case KEYCODE_INSERT: // Cursor Key Insert
|
case KEYCODE_INSERT: // Cursor Key Insert
|
||||||
dc_i:
|
dc_i:
|
||||||
cmd_mode = 1; // start insrting
|
cmd_mode = 1; // start inserting
|
||||||
break;
|
break;
|
||||||
case 'J': // J- join current and next lines together
|
case 'J': // J- join current and next lines together
|
||||||
if (--cmdcnt > 1) {
|
do {
|
||||||
do_cmd(c);
|
dot_end(); // move to NL
|
||||||
}
|
if (dot < end - 1) { // make sure not last char in text[]
|
||||||
dot_end(); // move to NL
|
*dot++ = ' '; // replace NL with space
|
||||||
if (dot < end - 1) { // make sure not last char in text[]
|
file_modified++;
|
||||||
*dot++ = ' '; // replace NL with space
|
while (isblank(*dot)) { // delete leading WS
|
||||||
file_modified++;
|
dot_delete();
|
||||||
while (isblank(*dot)) { // delete leading WS
|
}
|
||||||
dot_delete();
|
|
||||||
}
|
}
|
||||||
}
|
} while (--cmdcnt > 0);
|
||||||
end_cmd_q(); // stop adding to q
|
end_cmd_q(); // stop adding to q
|
||||||
break;
|
break;
|
||||||
case 'L': // L- goto bottom line on screen
|
case 'L': // L- goto bottom line on screen
|
||||||
@ -3699,20 +3688,19 @@ static void do_cmd(int c)
|
|||||||
case 'X': // X- delete char before dot
|
case 'X': // X- delete char before dot
|
||||||
case 'x': // x- delete the current char
|
case 'x': // x- delete the current char
|
||||||
case 's': // s- substitute the current char
|
case 's': // s- substitute the current char
|
||||||
if (--cmdcnt > 0) {
|
|
||||||
do_cmd(c);
|
|
||||||
}
|
|
||||||
dir = 0;
|
dir = 0;
|
||||||
if (c == 'X')
|
if (c == 'X')
|
||||||
dir = -1;
|
dir = -1;
|
||||||
if (dot[dir] != '\n') {
|
do {
|
||||||
if (c == 'X')
|
if (dot[dir] != '\n') {
|
||||||
dot--; // delete prev char
|
if (c == 'X')
|
||||||
dot = yank_delete(dot, dot, 0, YANKDEL); // delete char
|
dot--; // delete prev char
|
||||||
}
|
dot = yank_delete(dot, dot, 0, YANKDEL); // delete char
|
||||||
if (c == 's')
|
}
|
||||||
goto dc_i; // start insrting
|
} while (--cmdcnt > 0);
|
||||||
end_cmd_q(); // stop adding to q
|
end_cmd_q(); // stop adding to q
|
||||||
|
if (c == 's')
|
||||||
|
goto dc_i; // start inserting
|
||||||
break;
|
break;
|
||||||
case 'Z': // Z- if modified, {write}; exit
|
case 'Z': // Z- if modified, {write}; exit
|
||||||
// ZZ means to save file (if necessary), then exit
|
// ZZ means to save file (if necessary), then exit
|
||||||
@ -3743,23 +3731,22 @@ static void do_cmd(int c)
|
|||||||
break;
|
break;
|
||||||
case 'b': // b- back a word
|
case 'b': // b- back a word
|
||||||
case 'e': // e- end of word
|
case 'e': // e- end of word
|
||||||
if (--cmdcnt > 0) {
|
|
||||||
do_cmd(c);
|
|
||||||
}
|
|
||||||
dir = FORWARD;
|
dir = FORWARD;
|
||||||
if (c == 'b')
|
if (c == 'b')
|
||||||
dir = BACK;
|
dir = BACK;
|
||||||
if ((dot + dir) < text || (dot + dir) > end - 1)
|
do {
|
||||||
break;
|
if ((dot + dir) < text || (dot + dir) > end - 1)
|
||||||
dot += dir;
|
break;
|
||||||
if (isspace(*dot)) {
|
dot += dir;
|
||||||
dot = skip_thing(dot, (c == 'e') ? 2 : 1, dir, S_OVER_WS);
|
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);
|
if (isalnum(*dot) || *dot == '_') {
|
||||||
} else if (ispunct(*dot)) {
|
dot = skip_thing(dot, 1, dir, S_END_ALNUM);
|
||||||
dot = skip_thing(dot, 1, dir, S_END_PUNCT);
|
} else if (ispunct(*dot)) {
|
||||||
}
|
dot = skip_thing(dot, 1, dir, S_END_PUNCT);
|
||||||
|
}
|
||||||
|
} while (--cmdcnt > 0);
|
||||||
break;
|
break;
|
||||||
case 'c': // c- change something
|
case 'c': // c- change something
|
||||||
case 'd': // d- delete something
|
case 'd': // d- delete something
|
||||||
@ -3844,11 +3831,10 @@ static void do_cmd(int c)
|
|||||||
}
|
}
|
||||||
case 'k': // k- goto prev line, same col
|
case 'k': // k- goto prev line, same col
|
||||||
case KEYCODE_UP: // cursor key Up
|
case KEYCODE_UP: // cursor key Up
|
||||||
if (--cmdcnt > 0) {
|
do {
|
||||||
do_cmd(c);
|
dot_prev();
|
||||||
}
|
dot = move_to_col(dot, ccol + offset); // try stay in same col
|
||||||
dot_prev();
|
} while (--cmdcnt > 0);
|
||||||
dot = move_to_col(dot, ccol + offset); // try stay in same col
|
|
||||||
break;
|
break;
|
||||||
case 'r': // r- replace the current char with user input
|
case 'r': // r- replace the current char with user input
|
||||||
c1 = get_one_char(); // get the replacement char
|
c1 = get_one_char(); // get the replacement char
|
||||||
@ -3866,19 +3852,18 @@ static void do_cmd(int c)
|
|||||||
last_forward_char = 0;
|
last_forward_char = 0;
|
||||||
break;
|
break;
|
||||||
case 'w': // w- forward a word
|
case 'w': // w- forward a word
|
||||||
if (--cmdcnt > 0) {
|
do {
|
||||||
do_cmd(c);
|
if (isalnum(*dot) || *dot == '_') { // we are on ALNUM
|
||||||
}
|
dot = skip_thing(dot, 1, FORWARD, S_END_ALNUM);
|
||||||
if (isalnum(*dot) || *dot == '_') { // we are on ALNUM
|
} else if (ispunct(*dot)) { // we are on PUNCT
|
||||||
dot = skip_thing(dot, 1, FORWARD, S_END_ALNUM);
|
dot = skip_thing(dot, 1, FORWARD, S_END_PUNCT);
|
||||||
} 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 (dot < end - 1)
|
if (isspace(*dot)) {
|
||||||
dot++; // move over word
|
dot = skip_thing(dot, 2, FORWARD, S_OVER_WS);
|
||||||
if (isspace(*dot)) {
|
}
|
||||||
dot = skip_thing(dot, 2, FORWARD, S_OVER_WS);
|
} while (--cmdcnt > 0);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'z': // z-
|
case 'z': // z-
|
||||||
c1 = get_one_char(); // get the replacement char
|
c1 = get_one_char(); // get the replacement char
|
||||||
@ -3894,17 +3879,16 @@ static void do_cmd(int c)
|
|||||||
dot = move_to_col(dot, cmdcnt - 1); // try to move to column
|
dot = move_to_col(dot, cmdcnt - 1); // try to move to column
|
||||||
break;
|
break;
|
||||||
case '~': // ~- flip the case of letters a-z -> A-Z
|
case '~': // ~- flip the case of letters a-z -> A-Z
|
||||||
if (--cmdcnt > 0) {
|
do {
|
||||||
do_cmd(c);
|
if (islower(*dot)) {
|
||||||
}
|
*dot = toupper(*dot);
|
||||||
if (islower(*dot)) {
|
file_modified++;
|
||||||
*dot = toupper(*dot);
|
} else if (isupper(*dot)) {
|
||||||
file_modified++;
|
*dot = tolower(*dot);
|
||||||
} else if (isupper(*dot)) {
|
file_modified++;
|
||||||
*dot = tolower(*dot);
|
}
|
||||||
file_modified++;
|
dot_right();
|
||||||
}
|
} while (--cmdcnt > 0);
|
||||||
dot_right();
|
|
||||||
end_cmd_q(); // stop adding to q
|
end_cmd_q(); // stop adding to q
|
||||||
break;
|
break;
|
||||||
//----- The Cursor and Function Keys -----------------------------
|
//----- The Cursor and Function Keys -----------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user