Commit aa455485c97afa6096a97b54b3bfdf784e5ea9fd
1 parent
9307c4c1
history support (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@704 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
123 additions
and
0 deletions
monitor.c
@@ -31,6 +31,7 @@ | @@ -31,6 +31,7 @@ | ||
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | #define TERM_CMD_BUF_SIZE 4095 | 33 | #define TERM_CMD_BUF_SIZE 4095 |
34 | +#define TERM_MAX_CMDS 64 | ||
34 | 35 | ||
35 | #define IS_NORM 0 | 36 | #define IS_NORM 0 |
36 | #define IS_ESC 1 | 37 | #define IS_ESC 1 |
@@ -44,6 +45,9 @@ static int term_cmd_buf_size; | @@ -44,6 +45,9 @@ static int term_cmd_buf_size; | ||
44 | static int term_esc_state; | 45 | static int term_esc_state; |
45 | static int term_esc_param; | 46 | static int term_esc_param; |
46 | 47 | ||
48 | +static char *term_history[TERM_MAX_CMDS]; | ||
49 | +static int term_hist_entry; | ||
50 | + | ||
47 | /* | 51 | /* |
48 | * Supported types: | 52 | * Supported types: |
49 | * | 53 | * |
@@ -190,6 +194,17 @@ static void do_info_registers(void) | @@ -190,6 +194,17 @@ static void do_info_registers(void) | ||
190 | #endif | 194 | #endif |
191 | } | 195 | } |
192 | 196 | ||
197 | +static void do_info_history (void) | ||
198 | +{ | ||
199 | + int i; | ||
200 | + | ||
201 | + for (i = 0; i < TERM_MAX_CMDS; i++) { | ||
202 | + if (term_history[i] == NULL) | ||
203 | + break; | ||
204 | + term_printf("%d: '%s'\n", i, term_history[i]); | ||
205 | + } | ||
206 | +} | ||
207 | + | ||
193 | static void do_quit(void) | 208 | static void do_quit(void) |
194 | { | 209 | { |
195 | exit(0); | 210 | exit(0); |
@@ -499,6 +514,8 @@ static term_cmd_t info_cmds[] = { | @@ -499,6 +514,8 @@ static term_cmd_t info_cmds[] = { | ||
499 | "", "show the block devices" }, | 514 | "", "show the block devices" }, |
500 | { "registers", "", do_info_registers, | 515 | { "registers", "", do_info_registers, |
501 | "", "show the cpu registers" }, | 516 | "", "show the cpu registers" }, |
517 | + { "history", "", do_info_history, | ||
518 | + "", "show the command line history", }, | ||
502 | { NULL, NULL, }, | 519 | { NULL, NULL, }, |
503 | }; | 520 | }; |
504 | 521 | ||
@@ -1056,6 +1073,13 @@ static void term_show_prompt(void) | @@ -1056,6 +1073,13 @@ static void term_show_prompt(void) | ||
1056 | term_esc_state = IS_NORM; | 1073 | term_esc_state = IS_NORM; |
1057 | } | 1074 | } |
1058 | 1075 | ||
1076 | +static void term_print_cmdline (const char *cmdline) | ||
1077 | +{ | ||
1078 | + term_show_prompt(); | ||
1079 | + term_printf(cmdline); | ||
1080 | + term_flush(); | ||
1081 | +} | ||
1082 | + | ||
1059 | static void term_insert_char(int ch) | 1083 | static void term_insert_char(int ch) |
1060 | { | 1084 | { |
1061 | if (term_cmd_buf_index < TERM_CMD_BUF_SIZE) { | 1085 | if (term_cmd_buf_index < TERM_CMD_BUF_SIZE) { |
@@ -1120,6 +1144,92 @@ static void term_eol(void) | @@ -1120,6 +1144,92 @@ static void term_eol(void) | ||
1120 | term_forward_char(); | 1144 | term_forward_char(); |
1121 | } | 1145 | } |
1122 | 1146 | ||
1147 | +static void term_up_char(void) | ||
1148 | +{ | ||
1149 | + int idx; | ||
1150 | + | ||
1151 | + if (term_hist_entry == 0) | ||
1152 | + return; | ||
1153 | + if (term_hist_entry == -1) { | ||
1154 | + /* Find latest entry */ | ||
1155 | + for (idx = 0; idx < TERM_MAX_CMDS; idx++) { | ||
1156 | + if (term_history[idx] == NULL) | ||
1157 | + break; | ||
1158 | + } | ||
1159 | + term_hist_entry = idx; | ||
1160 | + } | ||
1161 | + term_hist_entry--; | ||
1162 | + if (term_hist_entry >= 0) { | ||
1163 | + strcpy(term_cmd_buf, term_history[term_hist_entry]); | ||
1164 | + term_printf("\n"); | ||
1165 | + term_print_cmdline(term_cmd_buf); | ||
1166 | + term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf); | ||
1167 | + } | ||
1168 | +} | ||
1169 | + | ||
1170 | +static void term_down_char(void) | ||
1171 | +{ | ||
1172 | + if (term_hist_entry == TERM_MAX_CMDS - 1 || term_hist_entry == -1) | ||
1173 | + return; | ||
1174 | + if (term_history[++term_hist_entry] != NULL) { | ||
1175 | + strcpy(term_cmd_buf, term_history[term_hist_entry]); | ||
1176 | + } else { | ||
1177 | + term_hist_entry = -1; | ||
1178 | + } | ||
1179 | + term_printf("\n"); | ||
1180 | + term_print_cmdline(term_cmd_buf); | ||
1181 | + term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf); | ||
1182 | +} | ||
1183 | + | ||
1184 | +static void term_hist_add(const char *cmdline) | ||
1185 | +{ | ||
1186 | + char *hist_entry, *new_entry; | ||
1187 | + int idx; | ||
1188 | + | ||
1189 | + if (cmdline[0] == '\0') | ||
1190 | + return; | ||
1191 | + new_entry = NULL; | ||
1192 | + if (term_hist_entry != -1) { | ||
1193 | + /* We were editing an existing history entry: replace it */ | ||
1194 | + hist_entry = term_history[term_hist_entry]; | ||
1195 | + idx = term_hist_entry; | ||
1196 | + if (strcmp(hist_entry, cmdline) == 0) { | ||
1197 | + goto same_entry; | ||
1198 | + } | ||
1199 | + } | ||
1200 | + /* Search cmdline in history buffers */ | ||
1201 | + for (idx = 0; idx < TERM_MAX_CMDS; idx++) { | ||
1202 | + hist_entry = term_history[idx]; | ||
1203 | + if (hist_entry == NULL) | ||
1204 | + break; | ||
1205 | + if (strcmp(hist_entry, cmdline) == 0) { | ||
1206 | + same_entry: | ||
1207 | + new_entry = hist_entry; | ||
1208 | + /* Put this entry at the end of history */ | ||
1209 | + memmove(&term_history[idx], &term_history[idx + 1], | ||
1210 | + &term_history[TERM_MAX_CMDS] - &term_history[idx + 1]); | ||
1211 | + term_history[TERM_MAX_CMDS - 1] = NULL; | ||
1212 | + for (; idx < TERM_MAX_CMDS; idx++) { | ||
1213 | + if (term_history[idx] == NULL) | ||
1214 | + break; | ||
1215 | + } | ||
1216 | + break; | ||
1217 | + } | ||
1218 | + } | ||
1219 | + if (idx == TERM_MAX_CMDS) { | ||
1220 | + /* Need to get one free slot */ | ||
1221 | + free(term_history[0]); | ||
1222 | + memcpy(term_history, &term_history[1], | ||
1223 | + &term_history[TERM_MAX_CMDS] - &term_history[1]); | ||
1224 | + term_history[TERM_MAX_CMDS - 1] = NULL; | ||
1225 | + idx = TERM_MAX_CMDS - 1; | ||
1226 | + } | ||
1227 | + if (new_entry == NULL) | ||
1228 | + new_entry = strdup(cmdline); | ||
1229 | + term_history[idx] = new_entry; | ||
1230 | + term_hist_entry = -1; | ||
1231 | +} | ||
1232 | + | ||
1123 | /* return true if command handled */ | 1233 | /* return true if command handled */ |
1124 | static void term_handle_byte(int ch) | 1234 | static void term_handle_byte(int ch) |
1125 | { | 1235 | { |
@@ -1135,6 +1245,7 @@ static void term_handle_byte(int ch) | @@ -1135,6 +1245,7 @@ static void term_handle_byte(int ch) | ||
1135 | case 10: | 1245 | case 10: |
1136 | case 13: | 1246 | case 13: |
1137 | term_cmd_buf[term_cmd_buf_size] = '\0'; | 1247 | term_cmd_buf[term_cmd_buf_size] = '\0'; |
1248 | + term_hist_add(term_cmd_buf); | ||
1138 | term_printf("\n"); | 1249 | term_printf("\n"); |
1139 | term_handle_command(term_cmd_buf); | 1250 | term_handle_command(term_cmd_buf); |
1140 | term_show_prompt(); | 1251 | term_show_prompt(); |
@@ -1146,6 +1257,9 @@ static void term_handle_byte(int ch) | @@ -1146,6 +1257,9 @@ static void term_handle_byte(int ch) | ||
1146 | case 8: | 1257 | case 8: |
1147 | term_backspace(); | 1258 | term_backspace(); |
1148 | break; | 1259 | break; |
1260 | + case 155: | ||
1261 | + term_esc_state = IS_CSI; | ||
1262 | + break; | ||
1149 | default: | 1263 | default: |
1150 | if (ch >= 32) { | 1264 | if (ch >= 32) { |
1151 | term_insert_char(ch); | 1265 | term_insert_char(ch); |
@@ -1163,6 +1277,14 @@ static void term_handle_byte(int ch) | @@ -1163,6 +1277,14 @@ static void term_handle_byte(int ch) | ||
1163 | break; | 1277 | break; |
1164 | case IS_CSI: | 1278 | case IS_CSI: |
1165 | switch(ch) { | 1279 | switch(ch) { |
1280 | + case 'A': | ||
1281 | + case 'F': | ||
1282 | + term_up_char(); | ||
1283 | + break; | ||
1284 | + case 'B': | ||
1285 | + case 'E': | ||
1286 | + term_down_char(); | ||
1287 | + break; | ||
1166 | case 'D': | 1288 | case 'D': |
1167 | term_backward_char(); | 1289 | term_backward_char(); |
1168 | break; | 1290 | break; |
@@ -1290,5 +1412,6 @@ void monitor_init(void) | @@ -1290,5 +1412,6 @@ void monitor_init(void) | ||
1290 | QEMU_VERSION); | 1412 | QEMU_VERSION); |
1291 | term_show_prompt(); | 1413 | term_show_prompt(); |
1292 | } | 1414 | } |
1415 | + term_hist_entry = -1; | ||
1293 | qemu_add_fd_read_handler(0, term_can_read, term_read, NULL); | 1416 | qemu_add_fd_read_handler(0, term_can_read, term_read, NULL); |
1294 | } | 1417 | } |