Revision aa455485

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