Revision aa455485 monitor.c
b/monitor.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 |
} |
Also available in: Unified diff