Commit 4c36ba323582773a87e9d277b0ce8febcf2113fd
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
Showing
3 changed files
with
249 additions
and
231 deletions
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 */ | ... | ... |