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 81 static int term_outbuf_index;
82 82 static BlockDriverCompletionFunc *password_completion_cb;
83 83 static void *password_opaque;
  84 +ReadLineState *rs;
84 85  
85 86 Monitor *cur_mon = NULL;
86 87  
... ... @@ -91,7 +92,7 @@ static CPUState *mon_cpu = NULL;
91 92 static void monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
92 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 98 void monitor_flush(Monitor *mon)
... ... @@ -366,7 +367,7 @@ static void do_info_history(Monitor *mon)
366 367  
367 368 i = 0;
368 369 for(;;) {
369   - str = readline_get_history(i);
  370 + str = readline_get_history(rs, i);
370 371 if (!str)
371 372 break;
372 373 monitor_printf(mon, "%d: '%s'\n", i, str);
... ... @@ -2687,7 +2688,7 @@ static void cmd_completion(const char *name, const char *list)
2687 2688 memcpy(cmd, pstart, len);
2688 2689 cmd[len] = '\0';
2689 2690 if (name[0] == '\0' || !strncmp(name, cmd, strlen(name))) {
2690   - readline_add_completion(cmd);
  2691 + readline_add_completion(rs, cmd);
2691 2692 }
2692 2693 if (*p == '\0')
2693 2694 break;
... ... @@ -2740,7 +2741,7 @@ static void file_completion(const char *input)
2740 2741 stat(file, &sb);
2741 2742 if(S_ISDIR(sb.st_mode))
2742 2743 pstrcat(file, sizeof(file), "/");
2743   - readline_add_completion(file);
  2744 + readline_add_completion(rs, file);
2744 2745 }
2745 2746 }
2746 2747 closedir(ffs);
... ... @@ -2753,7 +2754,7 @@ static void block_completion_it(void *opaque, BlockDriverState *bs)
2753 2754  
2754 2755 if (input[0] == '\0' ||
2755 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 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 2789 const char *cmdname;
2789 2790 char *args[MAX_ARGS];
... ... @@ -2813,7 +2814,7 @@ void readline_find_completion(const char *cmdline)
2813 2814 cmdname = "";
2814 2815 else
2815 2816 cmdname = args[0];
2816   - readline_set_completion_index(strlen(cmdname));
  2817 + readline_set_completion_index(rs, strlen(cmdname));
2817 2818 for(cmd = mon_cmds; cmd->name != NULL; cmd++) {
2818 2819 cmd_completion(cmdname, cmd->name);
2819 2820 }
... ... @@ -2837,23 +2838,23 @@ void readline_find_completion(const char *cmdline)
2837 2838 switch(*ptype) {
2838 2839 case 'F':
2839 2840 /* file completion */
2840   - readline_set_completion_index(strlen(str));
  2841 + readline_set_completion_index(rs, strlen(str));
2841 2842 file_completion(str);
2842 2843 break;
2843 2844 case 'B':
2844 2845 /* block device name completion */
2845   - readline_set_completion_index(strlen(str));
  2846 + readline_set_completion_index(rs, strlen(str));
2846 2847 bdrv_iterate(block_completion_it, (void *)str);
2847 2848 break;
2848 2849 case 's':
2849 2850 /* XXX: more generic ? */
2850 2851 if (!strcmp(cmd->name, "info")) {
2851   - readline_set_completion_index(strlen(str));
  2852 + readline_set_completion_index(rs, strlen(str));
2852 2853 for(cmd = info_cmds; cmd->name != NULL; cmd++) {
2853 2854 cmd_completion(str, cmd->name);
2854 2855 }
2855 2856 } else if (!strcmp(cmd->name, "sendkey")) {
2856   - readline_set_completion_index(strlen(str));
  2857 + readline_set_completion_index(rs, strlen(str));
2857 2858 for(key = key_defs; key->name != NULL; key++) {
2858 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 2877 {
2877 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 2884 static int monitor_suspended;
... ... @@ -2886,7 +2887,7 @@ static void monitor_command_cb(Monitor *mon, const char *cmdline, void *opaque)
2886 2887 {
2887 2888 monitor_handle_command(mon, cmdline);
2888 2889 if (!monitor_suspended)
2889   - readline_show_prompt();
  2890 + readline_show_prompt(rs);
2890 2891 else
2891 2892 monitor_suspended = 2;
2892 2893 }
... ... @@ -2905,8 +2906,8 @@ void monitor_resume(Monitor *mon)
2905 2906  
2906 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 2913 static void term_event(void *opaque, int event)
... ... @@ -2935,6 +2936,7 @@ void monitor_init(CharDriverState *chr)
2935 2936 mon = qemu_mallocz(sizeof(*mon));
2936 2937  
2937 2938 mon->chr = chr;
  2939 + rs = readline_init(mon, monitor_find_completion);
2938 2940  
2939 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 2944 if (!cur_mon)
2943 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 2950 static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque)
... ...
readline.c
... ... @@ -24,148 +24,118 @@
24 24 #include "readline.h"
25 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 27 #define IS_NORM 0
32 28 #define IS_ESC 1
33 29 #define IS_CSI 2
34 30  
35 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 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 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 55 for(i = 0; i < len; i++)
86   - monitor_printf(mon, "*");
  56 + monitor_printf(rs->mon, "*");
87 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 67 if (delta > 0) {
98 68 for(i = 0;i < delta; i++) {
99   - monitor_printf(mon, "\033[C");
  69 + monitor_printf(rs->mon, "\033[C");
100 70 }
101 71 } else {
102 72 delta = -delta;
103 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 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 131 return;
162 132 }
163 133  
164   - start = term_cmd_buf_index - 1;
  134 + start = rs->cmd_buf_index - 1;
165 135  
166 136 /* find first word (backwards) */
167 137 while (start > 0) {
168   - if (!qemu_isspace(term_cmd_buf[start])) {
  138 + if (!qemu_isspace(rs->cmd_buf[start])) {
169 139 break;
170 140 }
171 141  
... ... @@ -174,7 +144,7 @@ static void term_backword(void)
174 144  
175 145 /* find first space (backwards) */
176 146 while (start > 0) {
177   - if (qemu_isspace(term_cmd_buf[start])) {
  147 + if (qemu_isspace(rs->cmd_buf[start])) {
178 148 ++start;
179 149 break;
180 150 }
... ... @@ -183,61 +153,61 @@ static void term_backword(void)
183 153 }
184 154  
185 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 177 int idx;
208 178  
209   - if (term_hist_entry == 0)
  179 + if (rs->hist_entry == 0)
210 180 return;
211   - if (term_hist_entry == -1) {
  181 + if (rs->hist_entry == -1) {
212 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 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 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 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 212 char *hist_entry, *new_entry;
243 213 int idx;
... ... @@ -245,99 +215,99 @@ static void term_hist_add(const char *cmdline)
245 215 if (cmdline[0] == '\0')
246 216 return;
247 217 new_entry = NULL;
248   - if (term_hist_entry != -1) {
  218 + if (rs->hist_entry != -1) {
249 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 222 if (strcmp(hist_entry, cmdline) == 0) {
253 223 goto same_entry;
254 224 }
255 225 }
256 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 229 if (hist_entry == NULL)
260 230 break;
261 231 if (strcmp(hist_entry, cmdline) == 0) {
262 232 same_entry:
263 233 new_entry = hist_entry;
264 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 240 break;
271 241 }
272 242 break;
273 243 }
274 244 }
275   - if (idx == TERM_MAX_CMDS) {
  245 + if (idx == READLINE_MAX_CMDS) {
276 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 253 if (new_entry == NULL)
284 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 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 275 Monitor *mon = cur_mon;
306 276 int len, i, j, max_width, nb_cols, max_prefix;
307 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 285 qemu_free(cmdline);
316 286  
317 287 /* no completion found */
318   - if (nb_completions <= 0)
  288 + if (rs->nb_completions <= 0)
319 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 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 298 } else {
329 299 monitor_printf(mon, "\n");
330 300 max_width = 0;
331 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 304 if (i==0) {
335 305 max_prefix = len;
336 306 } else {
337 307 if (len < max_prefix)
338 308 max_prefix = len;
339 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 311 max_prefix = j;
342 312 }
343 313 }
... ... @@ -345,8 +315,8 @@ static void term_completion(void)
345 315 max_width = len;
346 316 }
347 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 321 max_width += 2;
352 322 if (max_width < 10)
... ... @@ -355,135 +325,147 @@ static void term_completion(void)
355 325 max_width = 80;
356 326 nb_cols = 80 / max_width;
357 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 332 j = 0;
363 333 }
364 334 }
365   - readline_show_prompt();
  335 + readline_show_prompt(rs);
366 336 }
367 337 }
368 338  
369 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 343 case IS_NORM:
376 344 switch(ch) {
377 345 case 1:
378   - term_bol();
  346 + readline_bol(rs);
379 347 break;
380 348 case 4:
381   - term_delete_char();
  349 + readline_delete_char(rs);
382 350 break;
383 351 case 5:
384   - term_eol();
  352 + readline_eol(rs);
385 353 break;
386 354 case 9:
387   - term_completion();
  355 + readline_completion(rs);
388 356 break;
389 357 case 10:
390 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 368 break;
402 369 case 23:
403 370 /* ^W */
404   - term_backword();
  371 + readline_backword(rs);
405 372 break;
406 373 case 27:
407   - term_esc_state = IS_ESC;
  374 + rs->esc_state = IS_ESC;
408 375 break;
409 376 case 127:
410 377 case 8:
411   - term_backspace();
  378 + readline_backspace(rs);
412 379 break;
413 380 case 155:
414   - term_esc_state = IS_CSI;
  381 + rs->esc_state = IS_CSI;
415 382 break;
416 383 default:
417 384 if (ch >= 32) {
418   - term_insert_char(ch);
  385 + readline_insert_char(rs, ch);
419 386 }
420 387 break;
421 388 }
422 389 break;
423 390 case IS_ESC:
424 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 394 } else {
428   - term_esc_state = IS_NORM;
  395 + rs->esc_state = IS_NORM;
429 396 }
430 397 break;
431 398 case IS_CSI:
432 399 switch(ch) {
433 400 case 'A':
434 401 case 'F':
435   - term_up_char();
  402 + readline_up_char(rs);
436 403 break;
437 404 case 'B':
438 405 case 'E':
439   - term_down_char();
  406 + readline_down_char(rs);
440 407 break;
441 408 case 'D':
442   - term_backward_char();
  409 + readline_backward_char(rs);
443 410 break;
444 411 case 'C':
445   - term_forward_char();
  412 + readline_forward_char(rs);
446 413 break;
447 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 416 goto the_end;
450 417 case '~':
451   - switch(term_esc_param) {
  418 + switch(rs->esc_param) {
452 419 case 1:
453   - term_bol();
  420 + readline_bol(rs);
454 421 break;
455 422 case 3:
456   - term_delete_char();
  423 + readline_delete_char(rs);
457 424 break;
458 425 case 4:
459   - term_eol();
  426 + readline_eol(rs);
460 427 break;
461 428 }
462 429 break;
463 430 default:
464 431 break;
465 432 }
466   - term_esc_state = IS_NORM;
  433 + rs->esc_state = IS_NORM;
467 434 the_end:
468 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 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 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 3  
4 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 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 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 54 #endif /* !READLINE_H */
... ...