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 | 31 | #endif |
| 32 | 32 | |
| 33 | 33 | #define TERM_CMD_BUF_SIZE 4095 |
| 34 | +#define TERM_MAX_CMDS 64 | |
| 34 | 35 | |
| 35 | 36 | #define IS_NORM 0 |
| 36 | 37 | #define IS_ESC 1 |
| ... | ... | @@ -44,6 +45,9 @@ static int term_cmd_buf_size; |
| 44 | 45 | static int term_esc_state; |
| 45 | 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 | 52 | * Supported types: |
| 49 | 53 | * |
| ... | ... | @@ -190,6 +194,17 @@ static void do_info_registers(void) |
| 190 | 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 | 208 | static void do_quit(void) |
| 194 | 209 | { |
| 195 | 210 | exit(0); |
| ... | ... | @@ -499,6 +514,8 @@ static term_cmd_t info_cmds[] = { |
| 499 | 514 | "", "show the block devices" }, |
| 500 | 515 | { "registers", "", do_info_registers, |
| 501 | 516 | "", "show the cpu registers" }, |
| 517 | + { "history", "", do_info_history, | |
| 518 | + "", "show the command line history", }, | |
| 502 | 519 | { NULL, NULL, }, |
| 503 | 520 | }; |
| 504 | 521 | |
| ... | ... | @@ -1056,6 +1073,13 @@ static void term_show_prompt(void) |
| 1056 | 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 | 1083 | static void term_insert_char(int ch) |
| 1060 | 1084 | { |
| 1061 | 1085 | if (term_cmd_buf_index < TERM_CMD_BUF_SIZE) { |
| ... | ... | @@ -1120,6 +1144,92 @@ static void term_eol(void) |
| 1120 | 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 | 1233 | /* return true if command handled */ |
| 1124 | 1234 | static void term_handle_byte(int ch) |
| 1125 | 1235 | { |
| ... | ... | @@ -1135,6 +1245,7 @@ static void term_handle_byte(int ch) |
| 1135 | 1245 | case 10: |
| 1136 | 1246 | case 13: |
| 1137 | 1247 | term_cmd_buf[term_cmd_buf_size] = '\0'; |
| 1248 | + term_hist_add(term_cmd_buf); | |
| 1138 | 1249 | term_printf("\n"); |
| 1139 | 1250 | term_handle_command(term_cmd_buf); |
| 1140 | 1251 | term_show_prompt(); |
| ... | ... | @@ -1146,6 +1257,9 @@ static void term_handle_byte(int ch) |
| 1146 | 1257 | case 8: |
| 1147 | 1258 | term_backspace(); |
| 1148 | 1259 | break; |
| 1260 | + case 155: | |
| 1261 | + term_esc_state = IS_CSI; | |
| 1262 | + break; | |
| 1149 | 1263 | default: |
| 1150 | 1264 | if (ch >= 32) { |
| 1151 | 1265 | term_insert_char(ch); |
| ... | ... | @@ -1163,6 +1277,14 @@ static void term_handle_byte(int ch) |
| 1163 | 1277 | break; |
| 1164 | 1278 | case IS_CSI: |
| 1165 | 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 | 1288 | case 'D': |
| 1167 | 1289 | term_backward_char(); |
| 1168 | 1290 | break; |
| ... | ... | @@ -1290,5 +1412,6 @@ void monitor_init(void) |
| 1290 | 1412 | QEMU_VERSION); |
| 1291 | 1413 | term_show_prompt(); |
| 1292 | 1414 | } |
| 1415 | + term_hist_entry = -1; | |
| 1293 | 1416 | qemu_add_fd_read_handler(0, term_can_read, term_read, NULL); |
| 1294 | 1417 | } | ... | ... |