aboutsummaryrefslogtreecommitdiffstats
path: root/readline.c
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@google.com>2009-09-14 14:32:27 -0700
committerDavid 'Digit' Turner <digit@google.com>2009-09-14 14:32:27 -0700
commit5d8f37ad78fc66901af50c762029a501561f3b23 (patch)
tree206790f8f21000850a98c4f9590a79e779106278 /readline.c
parentcd059b15f2c7df69f4a087bd66900eb172e41d1c (diff)
downloadexternal_qemu-5d8f37ad78fc66901af50c762029a501561f3b23.zip
external_qemu-5d8f37ad78fc66901af50c762029a501561f3b23.tar.gz
external_qemu-5d8f37ad78fc66901af50c762029a501561f3b23.tar.bz2
Merge upstream QEMU 10.0.50 into the Android source tree.
This change integrates many changes from the upstream QEMU sources. Its main purpose is to enable correct ARMv6 and ARMv7 support to the Android emulator. Due to the nature of the upstream code base, this unfortunately also required changes to many other parts of the source. Note that to ensure easier integrations in the future, some source files and directories that have heavy Android-specific customization have been renamed with an -android suffix. The original files are still there for easier integration tracking, but *never* compiled. For example: net.c net-android.c qemu-char.c qemu-char-android.c slirp/ slirp-android/ etc... Tested on linux-x86, darwin-x86 and windows host machines.
Diffstat (limited to 'readline.c')
-rw-r--r--readline.c411
1 files changed, 199 insertions, 212 deletions
diff --git a/readline.c b/readline.c
index 81bc491..7834af0 100644
--- a/readline.c
+++ b/readline.c
@@ -21,12 +21,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#include "qemu-common.h"
-#include "console.h"
-
-#define TERM_CMD_BUF_SIZE 4095
-#define TERM_MAX_CMDS 64
-#define NB_COMPLETIONS_MAX 256
+#include "readline.h"
+#include "monitor.h"
#define IS_NORM 0
#define IS_ESC 1
@@ -34,142 +30,112 @@
#define printf do_not_use_printf
-static char term_cmd_buf[TERM_CMD_BUF_SIZE + 1];
-static int term_cmd_buf_index;
-static int term_cmd_buf_size;
-
-static char term_last_cmd_buf[TERM_CMD_BUF_SIZE + 1];
-static int term_last_cmd_buf_index;
-static int term_last_cmd_buf_size;
-
-static int term_esc_state;
-static int term_esc_param;
-
-static char *term_history[TERM_MAX_CMDS];
-static int term_hist_entry = -1;
-
-static int nb_completions;
-int completion_index;
-static char *completions[NB_COMPLETIONS_MAX];
-
-static ReadLineFunc *term_readline_func;
-static int term_is_password;
-static char term_prompt[256];
-static void *term_readline_opaque;
-
-static void term_show_prompt2(void)
+void readline_show_prompt(ReadLineState *rs)
{
- term_printf("%s", term_prompt);
- term_flush();
- term_last_cmd_buf_index = 0;
- term_last_cmd_buf_size = 0;
- term_esc_state = IS_NORM;
-}
-
-static void term_show_prompt(void)
-{
- term_show_prompt2();
- term_cmd_buf_index = 0;
- term_cmd_buf_size = 0;
+ monitor_printf(rs->mon, "%s", rs->prompt);
+ monitor_flush(rs->mon);
+ rs->last_cmd_buf_index = 0;
+ rs->last_cmd_buf_size = 0;
+ rs->esc_state = IS_NORM;
}
/* update the displayed command line */
-static void term_update(void)
+static void readline_update(ReadLineState *rs)
{
int i, delta, len;
- if (term_cmd_buf_size != term_last_cmd_buf_size ||
- memcmp(term_cmd_buf, term_last_cmd_buf, term_cmd_buf_size) != 0) {
- for(i = 0; i < term_last_cmd_buf_index; i++) {
- term_printf("\033[D");
+ if (rs->cmd_buf_size != rs->last_cmd_buf_size ||
+ memcmp(rs->cmd_buf, rs->last_cmd_buf, rs->cmd_buf_size) != 0) {
+ for(i = 0; i < rs->last_cmd_buf_index; i++) {
+ monitor_printf(rs->mon, "\033[D");
}
- term_cmd_buf[term_cmd_buf_size] = '\0';
- if (term_is_password) {
- len = strlen(term_cmd_buf);
+ rs->cmd_buf[rs->cmd_buf_size] = '\0';
+ if (rs->read_password) {
+ len = strlen(rs->cmd_buf);
for(i = 0; i < len; i++)
- term_printf("*");
+ monitor_printf(rs->mon, "*");
} else {
- term_printf("%s", term_cmd_buf);
+ monitor_printf(rs->mon, "%s", rs->cmd_buf);
}
- term_printf("\033[K");
- memcpy(term_last_cmd_buf, term_cmd_buf, term_cmd_buf_size);
- term_last_cmd_buf_size = term_cmd_buf_size;
- term_last_cmd_buf_index = term_cmd_buf_size;
+ monitor_printf(rs->mon, "\033[K");
+ memcpy(rs->last_cmd_buf, rs->cmd_buf, rs->cmd_buf_size);
+ rs->last_cmd_buf_size = rs->cmd_buf_size;
+ rs->last_cmd_buf_index = rs->cmd_buf_size;
}
- if (term_cmd_buf_index != term_last_cmd_buf_index) {
- delta = term_cmd_buf_index - term_last_cmd_buf_index;
+ if (rs->cmd_buf_index != rs->last_cmd_buf_index) {
+ delta = rs->cmd_buf_index - rs->last_cmd_buf_index;
if (delta > 0) {
for(i = 0;i < delta; i++) {
- term_printf("\033[C");
+ monitor_printf(rs->mon, "\033[C");
}
} else {
delta = -delta;
for(i = 0;i < delta; i++) {
- term_printf("\033[D");
+ monitor_printf(rs->mon, "\033[D");
}
}
- term_last_cmd_buf_index = term_cmd_buf_index;
+ rs->last_cmd_buf_index = rs->cmd_buf_index;
}
- term_flush();
+ monitor_flush(rs->mon);
}
-static void term_insert_char(int ch)
+static void readline_insert_char(ReadLineState *rs, int ch)
{
- if (term_cmd_buf_index < TERM_CMD_BUF_SIZE) {
- memmove(term_cmd_buf + term_cmd_buf_index + 1,
- term_cmd_buf + term_cmd_buf_index,
- term_cmd_buf_size - term_cmd_buf_index);
- term_cmd_buf[term_cmd_buf_index] = ch;
- term_cmd_buf_size++;
- term_cmd_buf_index++;
+ if (rs->cmd_buf_index < READLINE_CMD_BUF_SIZE) {
+ memmove(rs->cmd_buf + rs->cmd_buf_index + 1,
+ rs->cmd_buf + rs->cmd_buf_index,
+ rs->cmd_buf_size - rs->cmd_buf_index);
+ rs->cmd_buf[rs->cmd_buf_index] = ch;
+ rs->cmd_buf_size++;
+ rs->cmd_buf_index++;
}
}
-static void term_backward_char(void)
+static void readline_backward_char(ReadLineState *rs)
{
- if (term_cmd_buf_index > 0) {
- term_cmd_buf_index--;
+ if (rs->cmd_buf_index > 0) {
+ rs->cmd_buf_index--;
}
}
-static void term_forward_char(void)
+static void readline_forward_char(ReadLineState *rs)
{
- if (term_cmd_buf_index < term_cmd_buf_size) {
- term_cmd_buf_index++;
+ if (rs->cmd_buf_index < rs->cmd_buf_size) {
+ rs->cmd_buf_index++;
}
}
-static void term_delete_char(void)
+static void readline_delete_char(ReadLineState *rs)
{
- if (term_cmd_buf_index < term_cmd_buf_size) {
- memmove(term_cmd_buf + term_cmd_buf_index,
- term_cmd_buf + term_cmd_buf_index + 1,
- term_cmd_buf_size - term_cmd_buf_index - 1);
- term_cmd_buf_size--;
+ if (rs->cmd_buf_index < rs->cmd_buf_size) {
+ memmove(rs->cmd_buf + rs->cmd_buf_index,
+ rs->cmd_buf + rs->cmd_buf_index + 1,
+ rs->cmd_buf_size - rs->cmd_buf_index - 1);
+ rs->cmd_buf_size--;
}
}
-static void term_backspace(void)
+static void readline_backspace(ReadLineState *rs)
{
- if (term_cmd_buf_index > 0) {
- term_backward_char();
- term_delete_char();
+ if (rs->cmd_buf_index > 0) {
+ readline_backward_char(rs);
+ readline_delete_char(rs);
}
}
-static void term_backword(void)
+static void readline_backword(ReadLineState *rs)
{
int start;
- if (term_cmd_buf_index == 0 || term_cmd_buf_index > term_cmd_buf_size) {
+ if (rs->cmd_buf_index == 0 || rs->cmd_buf_index > rs->cmd_buf_size) {
return;
}
- start = term_cmd_buf_index - 1;
+ start = rs->cmd_buf_index - 1;
/* find first word (backwards) */
while (start > 0) {
- if (!isspace(term_cmd_buf[start])) {
+ if (!qemu_isspace(rs->cmd_buf[start])) {
break;
}
@@ -178,7 +144,7 @@ static void term_backword(void)
/* find first space (backwards) */
while (start > 0) {
- if (isspace(term_cmd_buf[start])) {
+ if (qemu_isspace(rs->cmd_buf[start])) {
++start;
break;
}
@@ -187,61 +153,63 @@ static void term_backword(void)
}
/* remove word */
- if (start < term_cmd_buf_index) {
- memmove(term_cmd_buf + start,
- term_cmd_buf + term_cmd_buf_index,
- term_cmd_buf_size - term_cmd_buf_index);
- term_cmd_buf_size -= term_cmd_buf_index - start;
- term_cmd_buf_index = start;
+ if (start < rs->cmd_buf_index) {
+ memmove(rs->cmd_buf + start,
+ rs->cmd_buf + rs->cmd_buf_index,
+ rs->cmd_buf_size - rs->cmd_buf_index);
+ rs->cmd_buf_size -= rs->cmd_buf_index - start;
+ rs->cmd_buf_index = start;
}
}
-static void term_bol(void)
+static void readline_bol(ReadLineState *rs)
{
- term_cmd_buf_index = 0;
+ rs->cmd_buf_index = 0;
}
-static void term_eol(void)
+static void readline_eol(ReadLineState *rs)
{
- term_cmd_buf_index = term_cmd_buf_size;
+ rs->cmd_buf_index = rs->cmd_buf_size;
}
-static void term_up_char(void)
+static void readline_up_char(ReadLineState *rs)
{
int idx;
- if (term_hist_entry == 0)
+ if (rs->hist_entry == 0)
return;
- if (term_hist_entry == -1) {
+ if (rs->hist_entry == -1) {
/* Find latest entry */
- for (idx = 0; idx < TERM_MAX_CMDS; idx++) {
- if (term_history[idx] == NULL)
+ for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
+ if (rs->history[idx] == NULL)
break;
}
- term_hist_entry = idx;
+ rs->hist_entry = idx;
}
- term_hist_entry--;
- if (term_hist_entry >= 0) {
- pstrcpy(term_cmd_buf, sizeof(term_cmd_buf),
- term_history[term_hist_entry]);
- term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf);
+ rs->hist_entry--;
+ if (rs->hist_entry >= 0) {
+ pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
+ rs->history[rs->hist_entry]);
+ rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
}
}
-static void term_down_char(void)
+static void readline_down_char(ReadLineState *rs)
{
- if (term_hist_entry == TERM_MAX_CMDS - 1 || term_hist_entry == -1)
- return;
- if (term_history[++term_hist_entry] != NULL) {
- pstrcpy(term_cmd_buf, sizeof(term_cmd_buf),
- term_history[term_hist_entry]);
+ if (rs->hist_entry == -1)
+ return;
+ if (rs->hist_entry < READLINE_MAX_CMDS - 1 &&
+ rs->history[++rs->hist_entry] != NULL) {
+ pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
+ rs->history[rs->hist_entry]);
} else {
- term_hist_entry = -1;
+ rs->cmd_buf[0] = 0;
+ rs->hist_entry = -1;
}
- term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf);
+ rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
}
-static void term_hist_add(const char *cmdline)
+static void readline_hist_add(ReadLineState *rs, const char *cmdline)
{
char *hist_entry, *new_entry;
int idx;
@@ -249,95 +217,99 @@ static void term_hist_add(const char *cmdline)
if (cmdline[0] == '\0')
return;
new_entry = NULL;
- if (term_hist_entry != -1) {
+ if (rs->hist_entry != -1) {
/* We were editing an existing history entry: replace it */
- hist_entry = term_history[term_hist_entry];
- idx = term_hist_entry;
+ hist_entry = rs->history[rs->hist_entry];
+ idx = rs->hist_entry;
if (strcmp(hist_entry, cmdline) == 0) {
goto same_entry;
}
}
/* Search cmdline in history buffers */
- for (idx = 0; idx < TERM_MAX_CMDS; idx++) {
- hist_entry = term_history[idx];
+ for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
+ hist_entry = rs->history[idx];
if (hist_entry == NULL)
break;
if (strcmp(hist_entry, cmdline) == 0) {
same_entry:
new_entry = hist_entry;
/* Put this entry at the end of history */
- memmove(&term_history[idx], &term_history[idx + 1],
- (TERM_MAX_CMDS - idx + 1) * sizeof(char *));
- term_history[TERM_MAX_CMDS - 1] = NULL;
- for (; idx < TERM_MAX_CMDS; idx++) {
- if (term_history[idx] == NULL)
+ memmove(&rs->history[idx], &rs->history[idx + 1],
+ (READLINE_MAX_CMDS - idx + 1) * sizeof(char *));
+ rs->history[READLINE_MAX_CMDS - 1] = NULL;
+ for (; idx < READLINE_MAX_CMDS; idx++) {
+ if (rs->history[idx] == NULL)
break;
}
break;
}
}
- if (idx == TERM_MAX_CMDS) {
+ if (idx == READLINE_MAX_CMDS) {
/* Need to get one free slot */
- free(term_history[0]);
- memcpy(term_history, &term_history[1],
- (TERM_MAX_CMDS - 1) * sizeof(char *));
- term_history[TERM_MAX_CMDS - 1] = NULL;
- idx = TERM_MAX_CMDS - 1;
+ free(rs->history[0]);
+ memcpy(rs->history, &rs->history[1],
+ (READLINE_MAX_CMDS - 1) * sizeof(char *));
+ rs->history[READLINE_MAX_CMDS - 1] = NULL;
+ idx = READLINE_MAX_CMDS - 1;
}
if (new_entry == NULL)
new_entry = strdup(cmdline);
- term_history[idx] = new_entry;
- term_hist_entry = -1;
+ rs->history[idx] = new_entry;
+ rs->hist_entry = -1;
}
/* completion support */
-void add_completion(const char *str)
+void readline_add_completion(ReadLineState *rs, const char *str)
{
- if (nb_completions < NB_COMPLETIONS_MAX) {
- completions[nb_completions++] = qemu_strdup(str);
+ if (rs->nb_completions < READLINE_MAX_COMPLETIONS) {
+ rs->completions[rs->nb_completions++] = qemu_strdup(str);
}
}
-static void term_completion(void)
+void readline_set_completion_index(ReadLineState *rs, int index)
+{
+ rs->completion_index = index;
+}
+
+static void readline_completion(ReadLineState *rs)
{
+ Monitor *mon = cur_mon;
int len, i, j, max_width, nb_cols, max_prefix;
char *cmdline;
- nb_completions = 0;
+ rs->nb_completions = 0;
- cmdline = qemu_malloc(term_cmd_buf_index + 1);
- if (!cmdline)
- return;
- memcpy(cmdline, term_cmd_buf, term_cmd_buf_index);
- cmdline[term_cmd_buf_index] = '\0';
- readline_find_completion(cmdline);
+ cmdline = qemu_malloc(rs->cmd_buf_index + 1);
+ memcpy(cmdline, rs->cmd_buf, rs->cmd_buf_index);
+ cmdline[rs->cmd_buf_index] = '\0';
+ rs->completion_finder(cmdline);
qemu_free(cmdline);
/* no completion found */
- if (nb_completions <= 0)
+ if (rs->nb_completions <= 0)
return;
- if (nb_completions == 1) {
- len = strlen(completions[0]);
- for(i = completion_index; i < len; i++) {
- term_insert_char(completions[0][i]);
+ if (rs->nb_completions == 1) {
+ len = strlen(rs->completions[0]);
+ for(i = rs->completion_index; i < len; i++) {
+ readline_insert_char(rs, rs->completions[0][i]);
}
/* extra space for next argument. XXX: make it more generic */
- if (len > 0 && completions[0][len - 1] != '/')
- term_insert_char(' ');
+ if (len > 0 && rs->completions[0][len - 1] != '/')
+ readline_insert_char(rs, ' ');
} else {
- term_printf("\n");
+ monitor_printf(mon, "\n");
max_width = 0;
max_prefix = 0;
- for(i = 0; i < nb_completions; i++) {
- len = strlen(completions[i]);
+ for(i = 0; i < rs->nb_completions; i++) {
+ len = strlen(rs->completions[i]);
if (i==0) {
max_prefix = len;
} else {
if (len < max_prefix)
max_prefix = len;
for(j=0; j<max_prefix; j++) {
- if (completions[i][j] != completions[0][j])
+ if (rs->completions[i][j] != rs->completions[0][j])
max_prefix = j;
}
}
@@ -345,8 +317,8 @@ static void term_completion(void)
max_width = len;
}
if (max_prefix > 0)
- for(i = completion_index; i < max_prefix; i++) {
- term_insert_char(completions[0][i]);
+ for(i = rs->completion_index; i < max_prefix; i++) {
+ readline_insert_char(rs, rs->completions[0][i]);
}
max_width += 2;
if (max_width < 10)
@@ -355,134 +327,149 @@ static void term_completion(void)
max_width = 80;
nb_cols = 80 / max_width;
j = 0;
- for(i = 0; i < nb_completions; i++) {
- term_printf("%-*s", max_width, completions[i]);
- if (++j == nb_cols || i == (nb_completions - 1)) {
- term_printf("\n");
+ for(i = 0; i < rs->nb_completions; i++) {
+ monitor_printf(rs->mon, "%-*s", max_width, rs->completions[i]);
+ if (++j == nb_cols || i == (rs->nb_completions - 1)) {
+ monitor_printf(rs->mon, "\n");
j = 0;
}
}
- term_show_prompt2();
+ readline_show_prompt(rs);
}
}
/* return true if command handled */
-void readline_handle_byte(int ch)
+void readline_handle_byte(ReadLineState *rs, int ch)
{
- switch(term_esc_state) {
+ switch(rs->esc_state) {
case IS_NORM:
switch(ch) {
case 1:
- term_bol();
+ readline_bol(rs);
break;
case 4:
- term_delete_char();
+ readline_delete_char(rs);
break;
case 5:
- term_eol();
+ readline_eol(rs);
break;
case 9:
- term_completion();
+ readline_completion(rs);
break;
case 10:
case 13:
- term_cmd_buf[term_cmd_buf_size] = '\0';
- if (!term_is_password)
- term_hist_add(term_cmd_buf);
- term_printf("\n");
- term_cmd_buf_index = 0;
- term_cmd_buf_size = 0;
- term_last_cmd_buf_index = 0;
- term_last_cmd_buf_size = 0;
- /* NOTE: readline_start can be called here */
- term_readline_func(term_readline_opaque, term_cmd_buf);
+ rs->cmd_buf[rs->cmd_buf_size] = '\0';
+ if (!rs->read_password)
+ readline_hist_add(rs, rs->cmd_buf);
+ monitor_printf(rs->mon, "\n");
+ rs->cmd_buf_index = 0;
+ rs->cmd_buf_size = 0;
+ rs->last_cmd_buf_index = 0;
+ rs->last_cmd_buf_size = 0;
+ rs->readline_func(rs->mon, rs->cmd_buf, rs->readline_opaque);
break;
case 23:
/* ^W */
- term_backword();
+ readline_backword(rs);
break;
case 27:
- term_esc_state = IS_ESC;
+ rs->esc_state = IS_ESC;
break;
case 127:
case 8:
- term_backspace();
+ readline_backspace(rs);
break;
case 155:
- term_esc_state = IS_CSI;
+ rs->esc_state = IS_CSI;
break;
default:
if (ch >= 32) {
- term_insert_char(ch);
+ readline_insert_char(rs, ch);
}
break;
}
break;
case IS_ESC:
if (ch == '[') {
- term_esc_state = IS_CSI;
- term_esc_param = 0;
+ rs->esc_state = IS_CSI;
+ rs->esc_param = 0;
} else {
- term_esc_state = IS_NORM;
+ rs->esc_state = IS_NORM;
}
break;
case IS_CSI:
switch(ch) {
case 'A':
case 'F':
- term_up_char();
+ readline_up_char(rs);
break;
case 'B':
case 'E':
- term_down_char();
+ readline_down_char(rs);
break;
case 'D':
- term_backward_char();
+ readline_backward_char(rs);
break;
case 'C':
- term_forward_char();
+ readline_forward_char(rs);
break;
case '0' ... '9':
- term_esc_param = term_esc_param * 10 + (ch - '0');
+ rs->esc_param = rs->esc_param * 10 + (ch - '0');
goto the_end;
case '~':
- switch(term_esc_param) {
+ switch(rs->esc_param) {
case 1:
- term_bol();
+ readline_bol(rs);
break;
case 3:
- term_delete_char();
+ readline_delete_char(rs);
break;
case 4:
- term_eol();
+ readline_eol(rs);
break;
}
break;
default:
break;
}
- term_esc_state = IS_NORM;
+ rs->esc_state = IS_NORM;
the_end:
break;
}
- term_update();
+ readline_update(rs);
}
-void readline_start(const char *prompt, int is_password,
+void readline_start(ReadLineState *rs, const char *prompt, int read_password,
ReadLineFunc *readline_func, void *opaque)
{
- pstrcpy(term_prompt, sizeof(term_prompt), prompt);
- term_readline_func = readline_func;
- term_readline_opaque = opaque;
- term_is_password = is_password;
- term_show_prompt();
+ pstrcpy(rs->prompt, sizeof(rs->prompt), prompt);
+ rs->readline_func = readline_func;
+ rs->readline_opaque = opaque;
+ rs->read_password = read_password;
+ readline_restart(rs);
}
-const char *readline_get_history(unsigned int index)
+void readline_restart(ReadLineState *rs)
{
- if (index >= TERM_MAX_CMDS)
+ rs->cmd_buf_index = 0;
+ rs->cmd_buf_size = 0;
+}
+
+const char *readline_get_history(ReadLineState *rs, unsigned int index)
+{
+ if (index >= READLINE_MAX_CMDS)
return NULL;
- return term_history[index];
+ return rs->history[index];
}
+ReadLineState *readline_init(Monitor *mon,
+ ReadLineCompletionFunc *completion_finder)
+{
+ ReadLineState *rs = qemu_mallocz(sizeof(*rs));
+ rs->hist_entry = -1;
+ rs->mon = mon;
+ rs->completion_finder = completion_finder;
+
+ return rs;
+}