Commit 4c36ba323582773a87e9d277b0ce8febcf2113fd

Authored by aliguori
1 parent bb806047

monitor: Introduce ReadLineState (Jan Kiszka)

As another step towards decoupled monitor terminals encapsulate the
state of the readline processor in a separate data structure called
ReadLineState and adapt all interfaces appropriately. For now the
monitor continues to instantiate just a single readline state.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6714 c046a42c-6fe2-441c-8c8c-71466251a162
monitor.c
@@ -81,6 +81,7 @@ static uint8_t term_outbuf[1024]; @@ -81,6 +81,7 @@ static uint8_t term_outbuf[1024];
81 static int term_outbuf_index; 81 static int term_outbuf_index;
82 static BlockDriverCompletionFunc *password_completion_cb; 82 static BlockDriverCompletionFunc *password_completion_cb;
83 static void *password_opaque; 83 static void *password_opaque;
  84 +ReadLineState *rs;
84 85
85 Monitor *cur_mon = NULL; 86 Monitor *cur_mon = NULL;
86 87
@@ -91,7 +92,7 @@ static CPUState *mon_cpu = NULL; @@ -91,7 +92,7 @@ static CPUState *mon_cpu = NULL;
91 static void monitor_read_password(Monitor *mon, ReadLineFunc *readline_func, 92 static void monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
92 void *opaque) 93 void *opaque)
93 { 94 {
94 - readline_start("Password: ", 1, readline_func, opaque); 95 + readline_start(rs, "Password: ", 1, readline_func, opaque);
95 } 96 }
96 97
97 void monitor_flush(Monitor *mon) 98 void monitor_flush(Monitor *mon)
@@ -366,7 +367,7 @@ static void do_info_history(Monitor *mon) @@ -366,7 +367,7 @@ static void do_info_history(Monitor *mon)
366 367
367 i = 0; 368 i = 0;
368 for(;;) { 369 for(;;) {
369 - str = readline_get_history(i); 370 + str = readline_get_history(rs, i);
370 if (!str) 371 if (!str)
371 break; 372 break;
372 monitor_printf(mon, "%d: '%s'\n", i, str); 373 monitor_printf(mon, "%d: '%s'\n", i, str);
@@ -2687,7 +2688,7 @@ static void cmd_completion(const char *name, const char *list) @@ -2687,7 +2688,7 @@ static void cmd_completion(const char *name, const char *list)
2687 memcpy(cmd, pstart, len); 2688 memcpy(cmd, pstart, len);
2688 cmd[len] = '\0'; 2689 cmd[len] = '\0';
2689 if (name[0] == '\0' || !strncmp(name, cmd, strlen(name))) { 2690 if (name[0] == '\0' || !strncmp(name, cmd, strlen(name))) {
2690 - readline_add_completion(cmd); 2691 + readline_add_completion(rs, cmd);
2691 } 2692 }
2692 if (*p == '\0') 2693 if (*p == '\0')
2693 break; 2694 break;
@@ -2740,7 +2741,7 @@ static void file_completion(const char *input) @@ -2740,7 +2741,7 @@ static void file_completion(const char *input)
2740 stat(file, &sb); 2741 stat(file, &sb);
2741 if(S_ISDIR(sb.st_mode)) 2742 if(S_ISDIR(sb.st_mode))
2742 pstrcat(file, sizeof(file), "/"); 2743 pstrcat(file, sizeof(file), "/");
2743 - readline_add_completion(file); 2744 + readline_add_completion(rs, file);
2744 } 2745 }
2745 } 2746 }
2746 closedir(ffs); 2747 closedir(ffs);
@@ -2753,7 +2754,7 @@ static void block_completion_it(void *opaque, BlockDriverState *bs) @@ -2753,7 +2754,7 @@ static void block_completion_it(void *opaque, BlockDriverState *bs)
2753 2754
2754 if (input[0] == '\0' || 2755 if (input[0] == '\0' ||
2755 !strncmp(name, (char *)input, strlen(input))) { 2756 !strncmp(name, (char *)input, strlen(input))) {
2756 - readline_add_completion(name); 2757 + readline_add_completion(rs, name);
2757 } 2758 }
2758 } 2759 }
2759 2760
@@ -2783,7 +2784,7 @@ static void parse_cmdline(const char *cmdline, @@ -2783,7 +2784,7 @@ static void parse_cmdline(const char *cmdline,
2783 *pnb_args = nb_args; 2784 *pnb_args = nb_args;
2784 } 2785 }
2785 2786
2786 -void readline_find_completion(const char *cmdline) 2787 +static void monitor_find_completion(const char *cmdline)
2787 { 2788 {
2788 const char *cmdname; 2789 const char *cmdname;
2789 char *args[MAX_ARGS]; 2790 char *args[MAX_ARGS];
@@ -2813,7 +2814,7 @@ void readline_find_completion(const char *cmdline) @@ -2813,7 +2814,7 @@ void readline_find_completion(const char *cmdline)
2813 cmdname = ""; 2814 cmdname = "";
2814 else 2815 else
2815 cmdname = args[0]; 2816 cmdname = args[0];
2816 - readline_set_completion_index(strlen(cmdname)); 2817 + readline_set_completion_index(rs, strlen(cmdname));
2817 for(cmd = mon_cmds; cmd->name != NULL; cmd++) { 2818 for(cmd = mon_cmds; cmd->name != NULL; cmd++) {
2818 cmd_completion(cmdname, cmd->name); 2819 cmd_completion(cmdname, cmd->name);
2819 } 2820 }
@@ -2837,23 +2838,23 @@ void readline_find_completion(const char *cmdline) @@ -2837,23 +2838,23 @@ void readline_find_completion(const char *cmdline)
2837 switch(*ptype) { 2838 switch(*ptype) {
2838 case 'F': 2839 case 'F':
2839 /* file completion */ 2840 /* file completion */
2840 - readline_set_completion_index(strlen(str)); 2841 + readline_set_completion_index(rs, strlen(str));
2841 file_completion(str); 2842 file_completion(str);
2842 break; 2843 break;
2843 case 'B': 2844 case 'B':
2844 /* block device name completion */ 2845 /* block device name completion */
2845 - readline_set_completion_index(strlen(str)); 2846 + readline_set_completion_index(rs, strlen(str));
2846 bdrv_iterate(block_completion_it, (void *)str); 2847 bdrv_iterate(block_completion_it, (void *)str);
2847 break; 2848 break;
2848 case 's': 2849 case 's':
2849 /* XXX: more generic ? */ 2850 /* XXX: more generic ? */
2850 if (!strcmp(cmd->name, "info")) { 2851 if (!strcmp(cmd->name, "info")) {
2851 - readline_set_completion_index(strlen(str)); 2852 + readline_set_completion_index(rs, strlen(str));
2852 for(cmd = info_cmds; cmd->name != NULL; cmd++) { 2853 for(cmd = info_cmds; cmd->name != NULL; cmd++) {
2853 cmd_completion(str, cmd->name); 2854 cmd_completion(str, cmd->name);
2854 } 2855 }
2855 } else if (!strcmp(cmd->name, "sendkey")) { 2856 } else if (!strcmp(cmd->name, "sendkey")) {
2856 - readline_set_completion_index(strlen(str)); 2857 + readline_set_completion_index(rs, strlen(str));
2857 for(key = key_defs; key->name != NULL; key++) { 2858 for(key = key_defs; key->name != NULL; key++) {
2858 cmd_completion(str, key->name); 2859 cmd_completion(str, key->name);
2859 } 2860 }
@@ -2876,8 +2877,8 @@ static void term_read(void *opaque, const uint8_t *buf, int size) @@ -2876,8 +2877,8 @@ static void term_read(void *opaque, const uint8_t *buf, int size)
2876 { 2877 {
2877 int i; 2878 int i;
2878 2879
2879 - for (i = 0; i < size; i++)  
2880 - readline_handle_byte(buf[i]); 2880 + for(i = 0; i < size; i++)
  2881 + readline_handle_byte(rs, buf[i]);
2881 } 2882 }
2882 2883
2883 static int monitor_suspended; 2884 static int monitor_suspended;
@@ -2886,7 +2887,7 @@ static void monitor_command_cb(Monitor *mon, const char *cmdline, void *opaque) @@ -2886,7 +2887,7 @@ static void monitor_command_cb(Monitor *mon, const char *cmdline, void *opaque)
2886 { 2887 {
2887 monitor_handle_command(mon, cmdline); 2888 monitor_handle_command(mon, cmdline);
2888 if (!monitor_suspended) 2889 if (!monitor_suspended)
2889 - readline_show_prompt(); 2890 + readline_show_prompt(rs);
2890 else 2891 else
2891 monitor_suspended = 2; 2892 monitor_suspended = 2;
2892 } 2893 }
@@ -2905,8 +2906,8 @@ void monitor_resume(Monitor *mon) @@ -2905,8 +2906,8 @@ void monitor_resume(Monitor *mon)
2905 2906
2906 static void monitor_start_input(void) 2907 static void monitor_start_input(void)
2907 { 2908 {
2908 - readline_start("(qemu) ", 0, monitor_command_cb, NULL);  
2909 - readline_show_prompt(); 2909 + readline_start(rs, "(qemu) ", 0, monitor_command_cb, NULL);
  2910 + readline_show_prompt(rs);
2910 } 2911 }
2911 2912
2912 static void term_event(void *opaque, int event) 2913 static void term_event(void *opaque, int event)
@@ -2935,6 +2936,7 @@ void monitor_init(CharDriverState *chr) @@ -2935,6 +2936,7 @@ void monitor_init(CharDriverState *chr)
2935 mon = qemu_mallocz(sizeof(*mon)); 2936 mon = qemu_mallocz(sizeof(*mon));
2936 2937
2937 mon->chr = chr; 2938 mon->chr = chr;
  2939 + rs = readline_init(mon, monitor_find_completion);
2938 2940
2939 qemu_chr_add_handlers(chr, term_can_read, term_read, term_event, mon); 2941 qemu_chr_add_handlers(chr, term_can_read, term_read, term_event, mon);
2940 2942
@@ -2942,7 +2944,7 @@ void monitor_init(CharDriverState *chr) @@ -2942,7 +2944,7 @@ void monitor_init(CharDriverState *chr)
2942 if (!cur_mon) 2944 if (!cur_mon)
2943 cur_mon = mon; 2945 cur_mon = mon;
2944 2946
2945 - readline_start("", 0, monitor_command_cb, NULL); 2947 + readline_start(rs, "", 0, monitor_command_cb, NULL);
2946 } 2948 }
2947 2949
2948 static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque) 2950 static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque)
readline.c
@@ -24,148 +24,118 @@ @@ -24,148 +24,118 @@
24 #include "readline.h" 24 #include "readline.h"
25 #include "monitor.h" 25 #include "monitor.h"
26 26
27 -#define TERM_CMD_BUF_SIZE 4095  
28 -#define TERM_MAX_CMDS 64  
29 -#define NB_COMPLETIONS_MAX 256  
30 -  
31 #define IS_NORM 0 27 #define IS_NORM 0
32 #define IS_ESC 1 28 #define IS_ESC 1
33 #define IS_CSI 2 29 #define IS_CSI 2
34 30
35 #define printf do_not_use_printf 31 #define printf do_not_use_printf
36 32
37 -static char term_cmd_buf[TERM_CMD_BUF_SIZE + 1];  
38 -static int term_cmd_buf_index;  
39 -static int term_cmd_buf_size;  
40 -  
41 -static char term_last_cmd_buf[TERM_CMD_BUF_SIZE + 1];  
42 -static int term_last_cmd_buf_index;  
43 -static int term_last_cmd_buf_size;  
44 -  
45 -static int term_esc_state;  
46 -static int term_esc_param;  
47 -  
48 -static char *term_history[TERM_MAX_CMDS];  
49 -static int term_hist_entry = -1;  
50 -  
51 -static int nb_completions;  
52 -static int completion_index;  
53 -static char *completions[NB_COMPLETIONS_MAX];  
54 -  
55 -static ReadLineFunc *term_readline_func;  
56 -static int term_is_password;  
57 -static char term_prompt[256];  
58 -static void *term_readline_opaque;  
59 -  
60 -void readline_show_prompt(void) 33 +void readline_show_prompt(ReadLineState *rs)
61 { 34 {
62 - Monitor *mon = cur_mon;  
63 -  
64 - monitor_printf(mon, "%s", term_prompt);  
65 - monitor_flush(mon);  
66 - term_last_cmd_buf_index = 0;  
67 - term_last_cmd_buf_size = 0;  
68 - term_esc_state = IS_NORM; 35 + monitor_printf(rs->mon, "%s", rs->prompt);
  36 + monitor_flush(rs->mon);
  37 + rs->last_cmd_buf_index = 0;
  38 + rs->last_cmd_buf_size = 0;
  39 + rs->esc_state = IS_NORM;
69 } 40 }
70 41
71 /* update the displayed command line */ 42 /* update the displayed command line */
72 -static void term_update(void) 43 +static void readline_update(ReadLineState *rs)
73 { 44 {
74 - Monitor *mon = cur_mon;  
75 int i, delta, len; 45 int i, delta, len;
76 46
77 - if (term_cmd_buf_size != term_last_cmd_buf_size ||  
78 - memcmp(term_cmd_buf, term_last_cmd_buf, term_cmd_buf_size) != 0) {  
79 - for(i = 0; i < term_last_cmd_buf_index; i++) {  
80 - monitor_printf(mon, "\033[D"); 47 + if (rs->cmd_buf_size != rs->last_cmd_buf_size ||
  48 + memcmp(rs->cmd_buf, rs->last_cmd_buf, rs->cmd_buf_size) != 0) {
  49 + for(i = 0; i < rs->last_cmd_buf_index; i++) {
  50 + monitor_printf(rs->mon, "\033[D");
81 } 51 }
82 - term_cmd_buf[term_cmd_buf_size] = '\0';  
83 - if (term_is_password) {  
84 - len = strlen(term_cmd_buf); 52 + rs->cmd_buf[rs->cmd_buf_size] = '\0';
  53 + if (rs->read_password) {
  54 + len = strlen(rs->cmd_buf);
85 for(i = 0; i < len; i++) 55 for(i = 0; i < len; i++)
86 - monitor_printf(mon, "*"); 56 + monitor_printf(rs->mon, "*");
87 } else { 57 } else {
88 - monitor_printf(mon, "%s", term_cmd_buf); 58 + monitor_printf(rs->mon, "%s", rs->cmd_buf);
89 } 59 }
90 - monitor_printf(mon, "\033[K");  
91 - memcpy(term_last_cmd_buf, term_cmd_buf, term_cmd_buf_size);  
92 - term_last_cmd_buf_size = term_cmd_buf_size;  
93 - term_last_cmd_buf_index = term_cmd_buf_size; 60 + monitor_printf(rs->mon, "\033[K");
  61 + memcpy(rs->last_cmd_buf, rs->cmd_buf, rs->cmd_buf_size);
  62 + rs->last_cmd_buf_size = rs->cmd_buf_size;
  63 + rs->last_cmd_buf_index = rs->cmd_buf_size;
94 } 64 }
95 - if (term_cmd_buf_index != term_last_cmd_buf_index) {  
96 - delta = term_cmd_buf_index - term_last_cmd_buf_index; 65 + if (rs->cmd_buf_index != rs->last_cmd_buf_index) {
  66 + delta = rs->cmd_buf_index - rs->last_cmd_buf_index;
97 if (delta > 0) { 67 if (delta > 0) {
98 for(i = 0;i < delta; i++) { 68 for(i = 0;i < delta; i++) {
99 - monitor_printf(mon, "\033[C"); 69 + monitor_printf(rs->mon, "\033[C");
100 } 70 }
101 } else { 71 } else {
102 delta = -delta; 72 delta = -delta;
103 for(i = 0;i < delta; i++) { 73 for(i = 0;i < delta; i++) {
104 - monitor_printf(mon, "\033[D"); 74 + monitor_printf(rs->mon, "\033[D");
105 } 75 }
106 } 76 }
107 - term_last_cmd_buf_index = term_cmd_buf_index; 77 + rs->last_cmd_buf_index = rs->cmd_buf_index;
108 } 78 }
109 - monitor_flush(mon); 79 + monitor_flush(rs->mon);
110 } 80 }
111 81
112 -static void term_insert_char(int ch) 82 +static void readline_insert_char(ReadLineState *rs, int ch)
113 { 83 {
114 - if (term_cmd_buf_index < TERM_CMD_BUF_SIZE) {  
115 - memmove(term_cmd_buf + term_cmd_buf_index + 1,  
116 - term_cmd_buf + term_cmd_buf_index,  
117 - term_cmd_buf_size - term_cmd_buf_index);  
118 - term_cmd_buf[term_cmd_buf_index] = ch;  
119 - term_cmd_buf_size++;  
120 - term_cmd_buf_index++; 84 + if (rs->cmd_buf_index < READLINE_CMD_BUF_SIZE) {
  85 + memmove(rs->cmd_buf + rs->cmd_buf_index + 1,
  86 + rs->cmd_buf + rs->cmd_buf_index,
  87 + rs->cmd_buf_size - rs->cmd_buf_index);
  88 + rs->cmd_buf[rs->cmd_buf_index] = ch;
  89 + rs->cmd_buf_size++;
  90 + rs->cmd_buf_index++;
121 } 91 }
122 } 92 }
123 93
124 -static void term_backward_char(void) 94 +static void readline_backward_char(ReadLineState *rs)
125 { 95 {
126 - if (term_cmd_buf_index > 0) {  
127 - term_cmd_buf_index--; 96 + if (rs->cmd_buf_index > 0) {
  97 + rs->cmd_buf_index--;
128 } 98 }
129 } 99 }
130 100
131 -static void term_forward_char(void) 101 +static void readline_forward_char(ReadLineState *rs)
132 { 102 {
133 - if (term_cmd_buf_index < term_cmd_buf_size) {  
134 - term_cmd_buf_index++; 103 + if (rs->cmd_buf_index < rs->cmd_buf_size) {
  104 + rs->cmd_buf_index++;
135 } 105 }
136 } 106 }
137 107
138 -static void term_delete_char(void) 108 +static void readline_delete_char(ReadLineState *rs)
139 { 109 {
140 - if (term_cmd_buf_index < term_cmd_buf_size) {  
141 - memmove(term_cmd_buf + term_cmd_buf_index,  
142 - term_cmd_buf + term_cmd_buf_index + 1,  
143 - term_cmd_buf_size - term_cmd_buf_index - 1);  
144 - term_cmd_buf_size--; 110 + if (rs->cmd_buf_index < rs->cmd_buf_size) {
  111 + memmove(rs->cmd_buf + rs->cmd_buf_index,
  112 + rs->cmd_buf + rs->cmd_buf_index + 1,
  113 + rs->cmd_buf_size - rs->cmd_buf_index - 1);
  114 + rs->cmd_buf_size--;
145 } 115 }
146 } 116 }
147 117
148 -static void term_backspace(void) 118 +static void readline_backspace(ReadLineState *rs)
149 { 119 {
150 - if (term_cmd_buf_index > 0) {  
151 - term_backward_char();  
152 - term_delete_char(); 120 + if (rs->cmd_buf_index > 0) {
  121 + readline_backward_char(rs);
  122 + readline_delete_char(rs);
153 } 123 }
154 } 124 }
155 125
156 -static void term_backword(void) 126 +static void readline_backword(ReadLineState *rs)
157 { 127 {
158 int start; 128 int start;
159 129
160 - if (term_cmd_buf_index == 0 || term_cmd_buf_index > term_cmd_buf_size) { 130 + if (rs->cmd_buf_index == 0 || rs->cmd_buf_index > rs->cmd_buf_size) {
161 return; 131 return;
162 } 132 }
163 133
164 - start = term_cmd_buf_index - 1; 134 + start = rs->cmd_buf_index - 1;
165 135
166 /* find first word (backwards) */ 136 /* find first word (backwards) */
167 while (start > 0) { 137 while (start > 0) {
168 - if (!qemu_isspace(term_cmd_buf[start])) { 138 + if (!qemu_isspace(rs->cmd_buf[start])) {
169 break; 139 break;
170 } 140 }
171 141
@@ -174,7 +144,7 @@ static void term_backword(void) @@ -174,7 +144,7 @@ static void term_backword(void)
174 144
175 /* find first space (backwards) */ 145 /* find first space (backwards) */
176 while (start > 0) { 146 while (start > 0) {
177 - if (qemu_isspace(term_cmd_buf[start])) { 147 + if (qemu_isspace(rs->cmd_buf[start])) {
178 ++start; 148 ++start;
179 break; 149 break;
180 } 150 }
@@ -183,61 +153,61 @@ static void term_backword(void) @@ -183,61 +153,61 @@ static void term_backword(void)
183 } 153 }
184 154
185 /* remove word */ 155 /* remove word */
186 - if (start < term_cmd_buf_index) {  
187 - memmove(term_cmd_buf + start,  
188 - term_cmd_buf + term_cmd_buf_index,  
189 - term_cmd_buf_size - term_cmd_buf_index);  
190 - term_cmd_buf_size -= term_cmd_buf_index - start;  
191 - term_cmd_buf_index = start; 156 + if (start < rs->cmd_buf_index) {
  157 + memmove(rs->cmd_buf + start,
  158 + rs->cmd_buf + rs->cmd_buf_index,
  159 + rs->cmd_buf_size - rs->cmd_buf_index);
  160 + rs->cmd_buf_size -= rs->cmd_buf_index - start;
  161 + rs->cmd_buf_index = start;
192 } 162 }
193 } 163 }
194 164
195 -static void term_bol(void) 165 +static void readline_bol(ReadLineState *rs)
196 { 166 {
197 - term_cmd_buf_index = 0; 167 + rs->cmd_buf_index = 0;
198 } 168 }
199 169
200 -static void term_eol(void) 170 +static void readline_eol(ReadLineState *rs)
201 { 171 {
202 - term_cmd_buf_index = term_cmd_buf_size; 172 + rs->cmd_buf_index = rs->cmd_buf_size;
203 } 173 }
204 174
205 -static void term_up_char(void) 175 +static void readline_up_char(ReadLineState *rs)
206 { 176 {
207 int idx; 177 int idx;
208 178
209 - if (term_hist_entry == 0) 179 + if (rs->hist_entry == 0)
210 return; 180 return;
211 - if (term_hist_entry == -1) { 181 + if (rs->hist_entry == -1) {
212 /* Find latest entry */ 182 /* Find latest entry */
213 - for (idx = 0; idx < TERM_MAX_CMDS; idx++) {  
214 - if (term_history[idx] == NULL) 183 + for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
  184 + if (rs->history[idx] == NULL)
215 break; 185 break;
216 } 186 }
217 - term_hist_entry = idx; 187 + rs->hist_entry = idx;
218 } 188 }
219 - term_hist_entry--;  
220 - if (term_hist_entry >= 0) {  
221 - pstrcpy(term_cmd_buf, sizeof(term_cmd_buf),  
222 - term_history[term_hist_entry]);  
223 - term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf); 189 + rs->hist_entry--;
  190 + if (rs->hist_entry >= 0) {
  191 + pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
  192 + rs->history[rs->hist_entry]);
  193 + rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
224 } 194 }
225 } 195 }
226 196
227 -static void term_down_char(void) 197 +static void readline_down_char(ReadLineState *rs)
228 { 198 {
229 - if (term_hist_entry == TERM_MAX_CMDS - 1 || term_hist_entry == -1) 199 + if (rs->hist_entry == READLINE_MAX_CMDS - 1 || rs->hist_entry == -1)
230 return; 200 return;
231 - if (term_history[++term_hist_entry] != NULL) {  
232 - pstrcpy(term_cmd_buf, sizeof(term_cmd_buf),  
233 - term_history[term_hist_entry]); 201 + if (rs->history[++rs->hist_entry] != NULL) {
  202 + pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
  203 + rs->history[rs->hist_entry]);
234 } else { 204 } else {
235 - term_hist_entry = -1; 205 + rs->hist_entry = -1;
236 } 206 }
237 - term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf); 207 + rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
238 } 208 }
239 209
240 -static void term_hist_add(const char *cmdline) 210 +static void readline_hist_add(ReadLineState *rs, const char *cmdline)
241 { 211 {
242 char *hist_entry, *new_entry; 212 char *hist_entry, *new_entry;
243 int idx; 213 int idx;
@@ -245,99 +215,99 @@ static void term_hist_add(const char *cmdline) @@ -245,99 +215,99 @@ static void term_hist_add(const char *cmdline)
245 if (cmdline[0] == '\0') 215 if (cmdline[0] == '\0')
246 return; 216 return;
247 new_entry = NULL; 217 new_entry = NULL;
248 - if (term_hist_entry != -1) { 218 + if (rs->hist_entry != -1) {
249 /* We were editing an existing history entry: replace it */ 219 /* We were editing an existing history entry: replace it */
250 - hist_entry = term_history[term_hist_entry];  
251 - idx = term_hist_entry; 220 + hist_entry = rs->history[rs->hist_entry];
  221 + idx = rs->hist_entry;
252 if (strcmp(hist_entry, cmdline) == 0) { 222 if (strcmp(hist_entry, cmdline) == 0) {
253 goto same_entry; 223 goto same_entry;
254 } 224 }
255 } 225 }
256 /* Search cmdline in history buffers */ 226 /* Search cmdline in history buffers */
257 - for (idx = 0; idx < TERM_MAX_CMDS; idx++) {  
258 - hist_entry = term_history[idx]; 227 + for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
  228 + hist_entry = rs->history[idx];
259 if (hist_entry == NULL) 229 if (hist_entry == NULL)
260 break; 230 break;
261 if (strcmp(hist_entry, cmdline) == 0) { 231 if (strcmp(hist_entry, cmdline) == 0) {
262 same_entry: 232 same_entry:
263 new_entry = hist_entry; 233 new_entry = hist_entry;
264 /* Put this entry at the end of history */ 234 /* Put this entry at the end of history */
265 - memmove(&term_history[idx], &term_history[idx + 1],  
266 - (TERM_MAX_CMDS - idx + 1) * sizeof(char *));  
267 - term_history[TERM_MAX_CMDS - 1] = NULL;  
268 - for (; idx < TERM_MAX_CMDS; idx++) {  
269 - if (term_history[idx] == NULL) 235 + memmove(&rs->history[idx], &rs->history[idx + 1],
  236 + (READLINE_MAX_CMDS - idx + 1) * sizeof(char *));
  237 + rs->history[READLINE_MAX_CMDS - 1] = NULL;
  238 + for (; idx < READLINE_MAX_CMDS; idx++) {
  239 + if (rs->history[idx] == NULL)
270 break; 240 break;
271 } 241 }
272 break; 242 break;
273 } 243 }
274 } 244 }
275 - if (idx == TERM_MAX_CMDS) { 245 + if (idx == READLINE_MAX_CMDS) {
276 /* Need to get one free slot */ 246 /* Need to get one free slot */
277 - free(term_history[0]);  
278 - memcpy(term_history, &term_history[1],  
279 - (TERM_MAX_CMDS - 1) * sizeof(char *));  
280 - term_history[TERM_MAX_CMDS - 1] = NULL;  
281 - idx = TERM_MAX_CMDS - 1; 247 + free(rs->history[0]);
  248 + memcpy(rs->history, &rs->history[1],
  249 + (READLINE_MAX_CMDS - 1) * sizeof(char *));
  250 + rs->history[READLINE_MAX_CMDS - 1] = NULL;
  251 + idx = READLINE_MAX_CMDS - 1;
282 } 252 }
283 if (new_entry == NULL) 253 if (new_entry == NULL)
284 new_entry = strdup(cmdline); 254 new_entry = strdup(cmdline);
285 - term_history[idx] = new_entry;  
286 - term_hist_entry = -1; 255 + rs->history[idx] = new_entry;
  256 + rs->hist_entry = -1;
287 } 257 }
288 258
289 /* completion support */ 259 /* completion support */
290 260
291 -void readline_add_completion(const char *str) 261 +void readline_add_completion(ReadLineState *rs, const char *str)
292 { 262 {
293 - if (nb_completions < NB_COMPLETIONS_MAX) {  
294 - completions[nb_completions++] = qemu_strdup(str); 263 + if (rs->nb_completions < READLINE_MAX_COMPLETIONS) {
  264 + rs->completions[rs->nb_completions++] = qemu_strdup(str);
295 } 265 }
296 } 266 }
297 267
298 -void readline_set_completion_index(int index) 268 +void readline_set_completion_index(ReadLineState *rs, int index)
299 { 269 {
300 - completion_index = index; 270 + rs->completion_index = index;
301 } 271 }
302 272
303 -static void term_completion(void) 273 +static void readline_completion(ReadLineState *rs)
304 { 274 {
305 Monitor *mon = cur_mon; 275 Monitor *mon = cur_mon;
306 int len, i, j, max_width, nb_cols, max_prefix; 276 int len, i, j, max_width, nb_cols, max_prefix;
307 char *cmdline; 277 char *cmdline;
308 278
309 - nb_completions = 0; 279 + rs->nb_completions = 0;
310 280
311 - cmdline = qemu_malloc(term_cmd_buf_index + 1);  
312 - memcpy(cmdline, term_cmd_buf, term_cmd_buf_index);  
313 - cmdline[term_cmd_buf_index] = '\0';  
314 - readline_find_completion(cmdline); 281 + cmdline = qemu_malloc(rs->cmd_buf_index + 1);
  282 + memcpy(cmdline, rs->cmd_buf, rs->cmd_buf_index);
  283 + cmdline[rs->cmd_buf_index] = '\0';
  284 + rs->completion_finder(cmdline);
315 qemu_free(cmdline); 285 qemu_free(cmdline);
316 286
317 /* no completion found */ 287 /* no completion found */
318 - if (nb_completions <= 0) 288 + if (rs->nb_completions <= 0)
319 return; 289 return;
320 - if (nb_completions == 1) {  
321 - len = strlen(completions[0]);  
322 - for(i = completion_index; i < len; i++) {  
323 - term_insert_char(completions[0][i]); 290 + if (rs->nb_completions == 1) {
  291 + len = strlen(rs->completions[0]);
  292 + for(i = rs->completion_index; i < len; i++) {
  293 + readline_insert_char(rs, rs->completions[0][i]);
324 } 294 }
325 /* extra space for next argument. XXX: make it more generic */ 295 /* extra space for next argument. XXX: make it more generic */
326 - if (len > 0 && completions[0][len - 1] != '/')  
327 - term_insert_char(' '); 296 + if (len > 0 && rs->completions[0][len - 1] != '/')
  297 + readline_insert_char(rs, ' ');
328 } else { 298 } else {
329 monitor_printf(mon, "\n"); 299 monitor_printf(mon, "\n");
330 max_width = 0; 300 max_width = 0;
331 max_prefix = 0; 301 max_prefix = 0;
332 - for(i = 0; i < nb_completions; i++) {  
333 - len = strlen(completions[i]); 302 + for(i = 0; i < rs->nb_completions; i++) {
  303 + len = strlen(rs->completions[i]);
334 if (i==0) { 304 if (i==0) {
335 max_prefix = len; 305 max_prefix = len;
336 } else { 306 } else {
337 if (len < max_prefix) 307 if (len < max_prefix)
338 max_prefix = len; 308 max_prefix = len;
339 for(j=0; j<max_prefix; j++) { 309 for(j=0; j<max_prefix; j++) {
340 - if (completions[i][j] != completions[0][j]) 310 + if (rs->completions[i][j] != rs->completions[0][j])
341 max_prefix = j; 311 max_prefix = j;
342 } 312 }
343 } 313 }
@@ -345,8 +315,8 @@ static void term_completion(void) @@ -345,8 +315,8 @@ static void term_completion(void)
345 max_width = len; 315 max_width = len;
346 } 316 }
347 if (max_prefix > 0) 317 if (max_prefix > 0)
348 - for(i = completion_index; i < max_prefix; i++) {  
349 - term_insert_char(completions[0][i]); 318 + for(i = rs->completion_index; i < max_prefix; i++) {
  319 + readline_insert_char(rs, rs->completions[0][i]);
350 } 320 }
351 max_width += 2; 321 max_width += 2;
352 if (max_width < 10) 322 if (max_width < 10)
@@ -355,135 +325,147 @@ static void term_completion(void) @@ -355,135 +325,147 @@ static void term_completion(void)
355 max_width = 80; 325 max_width = 80;
356 nb_cols = 80 / max_width; 326 nb_cols = 80 / max_width;
357 j = 0; 327 j = 0;
358 - for(i = 0; i < nb_completions; i++) {  
359 - monitor_printf(mon, "%-*s", max_width, completions[i]);  
360 - if (++j == nb_cols || i == (nb_completions - 1)) {  
361 - monitor_printf(mon, "\n"); 328 + for(i = 0; i < rs->nb_completions; i++) {
  329 + monitor_printf(rs->mon, "%-*s", max_width, rs->completions[i]);
  330 + if (++j == nb_cols || i == (rs->nb_completions - 1)) {
  331 + monitor_printf(rs->mon, "\n");
362 j = 0; 332 j = 0;
363 } 333 }
364 } 334 }
365 - readline_show_prompt(); 335 + readline_show_prompt(rs);
366 } 336 }
367 } 337 }
368 338
369 /* return true if command handled */ 339 /* return true if command handled */
370 -void readline_handle_byte(int ch) 340 +void readline_handle_byte(ReadLineState *rs, int ch)
371 { 341 {
372 - Monitor *mon = cur_mon;  
373 -  
374 - switch(term_esc_state) { 342 + switch(rs->esc_state) {
375 case IS_NORM: 343 case IS_NORM:
376 switch(ch) { 344 switch(ch) {
377 case 1: 345 case 1:
378 - term_bol(); 346 + readline_bol(rs);
379 break; 347 break;
380 case 4: 348 case 4:
381 - term_delete_char(); 349 + readline_delete_char(rs);
382 break; 350 break;
383 case 5: 351 case 5:
384 - term_eol(); 352 + readline_eol(rs);
385 break; 353 break;
386 case 9: 354 case 9:
387 - term_completion(); 355 + readline_completion(rs);
388 break; 356 break;
389 case 10: 357 case 10:
390 case 13: 358 case 13:
391 - term_cmd_buf[term_cmd_buf_size] = '\0';  
392 - if (!term_is_password)  
393 - term_hist_add(term_cmd_buf);  
394 - monitor_printf(mon, "\n");  
395 - term_cmd_buf_index = 0;  
396 - term_cmd_buf_size = 0;  
397 - term_last_cmd_buf_index = 0;  
398 - term_last_cmd_buf_size = 0;  
399 - /* NOTE: readline_start can be called here */  
400 - term_readline_func(mon, term_cmd_buf, term_readline_opaque); 359 + rs->cmd_buf[rs->cmd_buf_size] = '\0';
  360 + if (!rs->read_password)
  361 + readline_hist_add(rs, rs->cmd_buf);
  362 + monitor_printf(rs->mon, "\n");
  363 + rs->cmd_buf_index = 0;
  364 + rs->cmd_buf_size = 0;
  365 + rs->last_cmd_buf_index = 0;
  366 + rs->last_cmd_buf_size = 0;
  367 + rs->readline_func(rs->mon, rs->cmd_buf, rs->readline_opaque);
401 break; 368 break;
402 case 23: 369 case 23:
403 /* ^W */ 370 /* ^W */
404 - term_backword(); 371 + readline_backword(rs);
405 break; 372 break;
406 case 27: 373 case 27:
407 - term_esc_state = IS_ESC; 374 + rs->esc_state = IS_ESC;
408 break; 375 break;
409 case 127: 376 case 127:
410 case 8: 377 case 8:
411 - term_backspace(); 378 + readline_backspace(rs);
412 break; 379 break;
413 case 155: 380 case 155:
414 - term_esc_state = IS_CSI; 381 + rs->esc_state = IS_CSI;
415 break; 382 break;
416 default: 383 default:
417 if (ch >= 32) { 384 if (ch >= 32) {
418 - term_insert_char(ch); 385 + readline_insert_char(rs, ch);
419 } 386 }
420 break; 387 break;
421 } 388 }
422 break; 389 break;
423 case IS_ESC: 390 case IS_ESC:
424 if (ch == '[') { 391 if (ch == '[') {
425 - term_esc_state = IS_CSI;  
426 - term_esc_param = 0; 392 + rs->esc_state = IS_CSI;
  393 + rs->esc_param = 0;
427 } else { 394 } else {
428 - term_esc_state = IS_NORM; 395 + rs->esc_state = IS_NORM;
429 } 396 }
430 break; 397 break;
431 case IS_CSI: 398 case IS_CSI:
432 switch(ch) { 399 switch(ch) {
433 case 'A': 400 case 'A':
434 case 'F': 401 case 'F':
435 - term_up_char(); 402 + readline_up_char(rs);
436 break; 403 break;
437 case 'B': 404 case 'B':
438 case 'E': 405 case 'E':
439 - term_down_char(); 406 + readline_down_char(rs);
440 break; 407 break;
441 case 'D': 408 case 'D':
442 - term_backward_char(); 409 + readline_backward_char(rs);
443 break; 410 break;
444 case 'C': 411 case 'C':
445 - term_forward_char(); 412 + readline_forward_char(rs);
446 break; 413 break;
447 case '0' ... '9': 414 case '0' ... '9':
448 - term_esc_param = term_esc_param * 10 + (ch - '0'); 415 + rs->esc_param = rs->esc_param * 10 + (ch - '0');
449 goto the_end; 416 goto the_end;
450 case '~': 417 case '~':
451 - switch(term_esc_param) { 418 + switch(rs->esc_param) {
452 case 1: 419 case 1:
453 - term_bol(); 420 + readline_bol(rs);
454 break; 421 break;
455 case 3: 422 case 3:
456 - term_delete_char(); 423 + readline_delete_char(rs);
457 break; 424 break;
458 case 4: 425 case 4:
459 - term_eol(); 426 + readline_eol(rs);
460 break; 427 break;
461 } 428 }
462 break; 429 break;
463 default: 430 default:
464 break; 431 break;
465 } 432 }
466 - term_esc_state = IS_NORM; 433 + rs->esc_state = IS_NORM;
467 the_end: 434 the_end:
468 break; 435 break;
469 } 436 }
470 - term_update(); 437 + readline_update(rs);
471 } 438 }
472 439
473 -void readline_start(const char *prompt, int is_password, 440 +void readline_start(ReadLineState *rs, const char *prompt, int read_password,
474 ReadLineFunc *readline_func, void *opaque) 441 ReadLineFunc *readline_func, void *opaque)
475 { 442 {
476 - pstrcpy(term_prompt, sizeof(term_prompt), prompt);  
477 - term_readline_func = readline_func;  
478 - term_readline_opaque = opaque;  
479 - term_is_password = is_password;  
480 - term_cmd_buf_index = 0;  
481 - term_cmd_buf_size = 0; 443 + pstrcpy(rs->prompt, sizeof(rs->prompt), prompt);
  444 + rs->readline_func = readline_func;
  445 + rs->readline_opaque = opaque;
  446 + rs->read_password = read_password;
  447 + rs->cmd_buf_index = 0;
  448 + rs->cmd_buf_size = 0;
482 } 449 }
483 450
484 -const char *readline_get_history(unsigned int index) 451 +const char *readline_get_history(ReadLineState *rs, unsigned int index)
485 { 452 {
486 - if (index >= TERM_MAX_CMDS) 453 + if (index >= READLINE_MAX_CMDS)
487 return NULL; 454 return NULL;
488 - return term_history[index]; 455 + return rs->history[index];
  456 +}
  457 +
  458 +ReadLineState *readline_init(Monitor *mon,
  459 + ReadLineCompletionFunc *completion_finder)
  460 +{
  461 + ReadLineState *rs = qemu_mallocz(sizeof(*rs));
  462 +
  463 + if (!rs)
  464 + return NULL;
  465 +
  466 + rs->hist_entry = -1;
  467 + rs->mon = mon;
  468 + rs->completion_finder = completion_finder;
  469 +
  470 + return rs;
489 } 471 }
readline.h
@@ -3,18 +3,52 @@ @@ -3,18 +3,52 @@
3 3
4 #include "qemu-common.h" 4 #include "qemu-common.h"
5 5
  6 +#define READLINE_CMD_BUF_SIZE 4095
  7 +#define READLINE_MAX_CMDS 64
  8 +#define READLINE_MAX_COMPLETIONS 256
  9 +
6 typedef void ReadLineFunc(Monitor *mon, const char *str, void *opaque); 10 typedef void ReadLineFunc(Monitor *mon, const char *str, void *opaque);
  11 +typedef void ReadLineCompletionFunc(const char *cmdline);
  12 +
  13 +typedef struct ReadLineState {
  14 + char cmd_buf[READLINE_CMD_BUF_SIZE + 1];
  15 + int cmd_buf_index;
  16 + int cmd_buf_size;
  17 +
  18 + char last_cmd_buf[READLINE_CMD_BUF_SIZE + 1];
  19 + int last_cmd_buf_index;
  20 + int last_cmd_buf_size;
  21 +
  22 + int esc_state;
  23 + int esc_param;
7 24
8 -void readline_add_completion(const char *str);  
9 -void readline_set_completion_index(int index);  
10 -void readline_find_completion(const char *cmdline); 25 + char *history[READLINE_MAX_CMDS];
  26 + int hist_entry;
11 27
12 -const char *readline_get_history(unsigned int index); 28 + ReadLineCompletionFunc *completion_finder;
  29 + char *completions[READLINE_MAX_COMPLETIONS];
  30 + int nb_completions;
  31 + int completion_index;
13 32
14 -void readline_handle_byte(int ch); 33 + ReadLineFunc *readline_func;
  34 + void *readline_opaque;
  35 + int read_password;
  36 + char prompt[256];
  37 + Monitor *mon;
  38 +} ReadLineState;
15 39
16 -void readline_start(const char *prompt, int is_password, 40 +void readline_add_completion(ReadLineState *rs, const char *str);
  41 +void readline_set_completion_index(ReadLineState *rs, int completion_index);
  42 +
  43 +const char *readline_get_history(ReadLineState *rs, unsigned int index);
  44 +
  45 +void readline_handle_byte(ReadLineState *rs, int ch);
  46 +
  47 +void readline_start(ReadLineState *rs, const char *prompt, int read_password,
17 ReadLineFunc *readline_func, void *opaque); 48 ReadLineFunc *readline_func, void *opaque);
18 -void readline_show_prompt(void); 49 +void readline_show_prompt(ReadLineState *rs);
  50 +
  51 +ReadLineState *readline_init(Monitor *mon,
  52 + ReadLineCompletionFunc *completion_finder);
19 53
20 #endif /* !READLINE_H */ 54 #endif /* !READLINE_H */