aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Luke <chrisy@flirble.org>2016-05-10 10:45:10 -0400
committerChris Luke <chrisy@flirble.org>2016-05-10 13:37:03 -0400
commit93dcd1d743db3c0a131ecb0eddfe9c6cb1a7e441 (patch)
treeffa3222f98890078d12d4984f62032f9ec0965dd
parent716d9593497388c48593f818748faf705ac7169e (diff)
VPP-46 Fix cut-and-paste in the debug CLI
Since the move to line-mode the debug CLI was eating everything in the input_vector but only processing upto the first newline. Cut-and-paste type operations generally send a large block of input with multiple newlines and thus all but the very first line were simply ignored. This patch fixes that and also cleans up the difference between input_vector and current_command which in turn removes a lot of cruft from the keystroke parser. Previously current_command was just the character accumulator inside the char-by-char keystroke parser; complete commands were copied back to input_vector (overwriting anything already in there). Now, in char-by-char mode: - input_vector is the stream of incoming bytes yet to be processed - current_command is the accumulated characters of the next command to be executed; once newline is found, it is the complete command to be executed. In line mode: - input_vector and current_command are the same thing. Change-Id: I72d21f0f3508b413879071ab186a71cef1124a2b Signed-off-by: Chris Luke <chrisy@flirble.org>
-rw-r--r--vlib/vlib/unix/cli.c84
1 files changed, 46 insertions, 38 deletions
diff --git a/vlib/vlib/unix/cli.c b/vlib/vlib/unix/cli.c
index dc9ac2aeea5..b0c950cbd8f 100644
--- a/vlib/vlib/unix/cli.c
+++ b/vlib/vlib/unix/cli.c
@@ -1400,15 +1400,8 @@ static int unix_cli_line_process_one(unix_cli_main_t * cm,
case UNIX_CLI_PARSE_ACTION_CRLF:
crlf:
- vec_add1 (cf->current_command, '\r');
- vec_add1 (cf->current_command, '\n');
unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\n", 1);
- vec_validate (cf->input_vector, vec_len(cf->current_command)-1);
- clib_memcpy (cf->input_vector, cf->current_command,
- vec_len(cf->current_command));
- _vec_len(cf->input_vector) = _vec_len (cf->current_command);
-
if (cf->has_history && cf->history_limit)
{
if (cf->command_history && vec_len(cf->command_history) >= cf->history_limit)
@@ -1417,29 +1410,25 @@ static int unix_cli_line_process_one(unix_cli_main_t * cm,
vec_delete (cf->command_history, 1, 0);
}
/* Don't add blank lines to the cmd history */
- if (vec_len (cf->current_command) > 2)
+ if (vec_len (cf->current_command))
{
/* Don't duplicate the previous command */
- _vec_len (cf->current_command) -= 2;
j = vec_len(cf->command_history);
if (j == 0 ||
(vec_len (cf->current_command) != vec_len (cf->command_history[j - 1]) ||
memcmp(cf->current_command, cf->command_history[j - 1],
vec_len (cf->current_command)) != 0))
{
- vec_add1 (cf->command_history, cf->current_command);
- cf->current_command = 0;
+ /* copy the command to the history */
+ u8 * c = 0;
+ vec_append(c, cf->current_command);
+ vec_add1 (cf->command_history, c);
cf->command_number ++;
}
- else
- vec_reset_length (cf->current_command);
}
- else
- vec_reset_length (cf->current_command);
cf->excursion = vec_len (cf->command_history);
}
- else /* history disabled */
- vec_reset_length (cf->current_command);
+
cf->search_mode = 0;
vec_reset_length (cf->search_key);
cf->cursor = 0;
@@ -1491,9 +1480,9 @@ static int unix_cli_line_process_one(unix_cli_main_t * cm,
unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\b \b", 3);
vec_validate (cf->current_command, vec_len(item)-1);
-
clib_memcpy (cf->current_command, item, vec_len(item));
_vec_len (cf->current_command) = vec_len(item);
+
unix_vlib_cli_output_cooked (cf, uf, cf->current_command,
vec_len (cf->current_command));
cf->cursor = vec_len (cf->current_command);
@@ -1567,13 +1556,13 @@ static int unix_cli_line_edit (unix_cli_main_t * cm,
for (i = 0; i < vec_len (cf->input_vector); i++)
{
unix_cli_parse_action_t action;
- /* See if the input buffer is some sort of control code */
i32 matched = 0;
unix_cli_parse_actions_t *a;
/* If we're in the pager mode, search the pager actions */
a = cf->pager_lines ? unix_cli_parse_pager : unix_cli_parse_strings;
+ /* See if the input buffer is some sort of control code */
action = unix_cli_match_action(a, &cf->input_vector[i],
vec_len (cf->input_vector) - i, &matched);
@@ -1585,11 +1574,9 @@ static int unix_cli_line_edit (unix_cli_main_t * cm,
/* There was a partial match which means we need more bytes
* than the input buffer currently has.
* Since the bytes before here have been processed, shift
- * the current contents to the start of the input buffer.
+ * the remaining contents to the start of the input buffer.
*/
- int j = vec_len (cf->input_vector) - i;
- memmove(cf->input_vector, cf->input_vector + i, j);
- _vec_len(cf->input_vector) = j;
+ vec_delete (cf->input_vector, i, 0);
}
return 1; /* wait for more */
@@ -1604,11 +1591,9 @@ static int unix_cli_line_edit (unix_cli_main_t * cm,
/* There was a partial match which means we need more bytes
* than the input buffer currently has.
* Since the bytes before here have been processed, shift
- * the current contents to the start of the input buffer.
+ * the remaining contents to the start of the input buffer.
*/
- int j = vec_len (cf->input_vector) - i;
- memmove(cf->input_vector, cf->input_vector + i, j);
- _vec_len(cf->input_vector) = j;
+ vec_delete (cf->input_vector, i, 0);
}
return 1; /* wait for more */
}
@@ -1618,7 +1603,12 @@ static int unix_cli_line_edit (unix_cli_main_t * cm,
/* process the action */
if (!unix_cli_line_process_one(cm, um, cf, uf,
cf->input_vector[i], action))
- return 0; /* CRLF found */
+ {
+ /* CRLF found. Consume the bytes from the input_vector */
+ vec_delete (cf->input_vector, i + matched, 0);
+ /* And tell our caller to execute cf->input_command */
+ return 0;
+ }
}
i += matched;
@@ -1638,13 +1628,23 @@ static void unix_cli_process_input (unix_cli_main_t * cm,
unformat_input_t input;
int vlib_parse_eval (u8 *);
+more:
/* Try vlibplex first. Someday... */
if (0 && vlib_parse_eval (cf->input_vector) == 0)
goto done;
- /* Line edit, echo, etc. */
- if (!cf->line_mode && unix_cli_line_edit (cm, um, cf))
- return;
+ if (cf->line_mode)
+ {
+ /* just treat whatever we got as a complete line of input */
+ cf->current_command = cf->input_vector;
+ }
+ else
+ {
+ /* Line edit, echo, etc. */
+ if (unix_cli_line_edit (cm, um, cf))
+ /* want more input */
+ return;
+ }
if (um->log_fd)
{
@@ -1662,7 +1662,8 @@ static void unix_cli_process_input (unix_cli_main_t * cm,
}
}
- unformat_init_vector (&input, cf->input_vector);
+ /* Copy our input command to a new string */
+ unformat_init_vector (&input, cf->current_command);
/* Remove leading white space from input. */
(void) unformat (&input, "");
@@ -1674,18 +1675,21 @@ static void unix_cli_process_input (unix_cli_main_t * cm,
if (unformat_check_input (&input) != UNFORMAT_END_OF_INPUT)
vlib_cli_input (um->vlib_main, &input, unix_vlib_cli_output, cli_file_index);
- /* Re-fetch pointer since pool may have moved. */
- cf = pool_elt_at_index (cm->cli_file_pool, cli_file_index);
- uf = pool_elt_at_index (um->file_pool, cf->unix_file_index);
-
/* Zero buffer since otherwise unformat_free will call vec_free on it. */
input.buffer = 0;
unformat_free (&input);
- /* Re-use input vector. */
+ /* Re-fetch pointer since pool may have moved. */
+ cf = pool_elt_at_index (cm->cli_file_pool, cli_file_index);
+ uf = pool_elt_at_index (um->file_pool, cf->unix_file_index);
+
done:
- _vec_len (cf->input_vector) = 0;
+ /* reset vector; we'll re-use it later */
+ if (cf->line_mode)
+ vec_reset_length (cf->input_vector);
+ else
+ vec_reset_length (cf->current_command);
if (cf->no_pager == 2)
{
@@ -1707,6 +1711,10 @@ done:
/* Display the pager prompt */
unix_cli_pager_prompt(cf, uf);
}
+
+ /* Any residual data in the input vector? */
+ if (vec_len (cf->input_vector))
+ goto more;
}
static void unix_cli_kill (unix_cli_main_t * cm, uword cli_file_index)