Commit aa455485c97afa6096a97b54b3bfdf784e5ea9fd

Authored by bellard
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 }
... ...