]> git.proxmox.com Git - mirror_qemu.git/blame - monitor.c
output disassembled code to monitor console
[mirror_qemu.git] / monitor.c
CommitLineData
9dc39cba
FB
1/*
2 * QEMU monitor
3 *
4 * Copyright (c) 2003-2004 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
9dc39cba 24#include "vl.h"
9307c4c1 25#include "disas.h"
81d0912d 26#include <dirent.h>
9dc39cba
FB
27
28//#define DEBUG
81d0912d 29//#define DEBUG_COMPLETION
9dc39cba 30
9307c4c1
FB
31#ifndef offsetof
32#define offsetof(type, field) ((size_t) &((type *)0)->field)
33#endif
34
9dc39cba 35#define TERM_CMD_BUF_SIZE 4095
aa455485 36#define TERM_MAX_CMDS 64
81d0912d 37#define NB_COMPLETIONS_MAX 256
9dc39cba
FB
38
39#define IS_NORM 0
40#define IS_ESC 1
41#define IS_CSI 2
42
43#define printf do_not_use_printf
44
45static char term_cmd_buf[TERM_CMD_BUF_SIZE + 1];
46static int term_cmd_buf_index;
47static int term_cmd_buf_size;
81d0912d
FB
48
49static char term_last_cmd_buf[TERM_CMD_BUF_SIZE + 1];
50static int term_last_cmd_buf_index;
51static int term_last_cmd_buf_size;
52
9dc39cba
FB
53static int term_esc_state;
54static int term_esc_param;
55
aa455485
FB
56static char *term_history[TERM_MAX_CMDS];
57static int term_hist_entry;
81d0912d
FB
58static CharDriverState *monitor_hd;
59
60static int nb_completions;
61static int completion_index;
62static char *completions[NB_COMPLETIONS_MAX];
63
aa455485 64
9307c4c1
FB
65/*
66 * Supported types:
67 *
68 * 'F' filename
81d0912d 69 * 'B' block device name
9307c4c1
FB
70 * 's' string (accept optional quote)
71 * 'i' integer
72 * '/' optional gdb-like print format (like "/10x")
73 *
74 * '?' optional type (for 'F', 's' and 'i')
75 *
76 */
77
9dc39cba
FB
78typedef struct term_cmd_t {
79 const char *name;
9307c4c1
FB
80 const char *args_type;
81 void (*handler)();
9dc39cba
FB
82 const char *params;
83 const char *help;
84} term_cmd_t;
85
86static term_cmd_t term_cmds[];
87static term_cmd_t info_cmds[];
88
81d0912d
FB
89static void add_completion(const char *str);
90
9dc39cba
FB
91void term_printf(const char *fmt, ...)
92{
81d0912d 93 char buf[4096];
9dc39cba
FB
94 va_list ap;
95 va_start(ap, fmt);
81d0912d
FB
96 vsnprintf(buf, sizeof(buf), fmt, ap);
97 qemu_chr_write(monitor_hd, buf, strlen(buf));
9dc39cba
FB
98 va_end(ap);
99}
100
101void term_flush(void)
102{
9dc39cba
FB
103}
104
105static int compare_cmd(const char *name, const char *list)
106{
107 const char *p, *pstart;
108 int len;
109 len = strlen(name);
110 p = list;
111 for(;;) {
112 pstart = p;
113 p = strchr(p, '|');
114 if (!p)
115 p = pstart + strlen(pstart);
116 if ((p - pstart) == len && !memcmp(pstart, name, len))
117 return 1;
118 if (*p == '\0')
119 break;
120 p++;
121 }
122 return 0;
123}
124
125static void help_cmd1(term_cmd_t *cmds, const char *prefix, const char *name)
126{
127 term_cmd_t *cmd;
128
129 for(cmd = cmds; cmd->name != NULL; cmd++) {
130 if (!name || !strcmp(name, cmd->name))
131 term_printf("%s%s %s -- %s\n", prefix, cmd->name, cmd->params, cmd->help);
132 }
133}
134
135static void help_cmd(const char *name)
136{
137 if (name && !strcmp(name, "info")) {
138 help_cmd1(info_cmds, "info ", NULL);
139 } else {
140 help_cmd1(term_cmds, "", name);
f193c797
FB
141 if (name && !strcmp(name, "log")) {
142 CPULogItem *item;
143 term_printf("Log items (comma separated):\n");
144 term_printf("%-10s %s\n", "none", "remove all logs");
145 for(item = cpu_log_items; item->mask != 0; item++) {
146 term_printf("%-10s %s\n", item->name, item->help);
147 }
148 }
9dc39cba
FB
149 }
150}
151
9307c4c1 152static void do_help(const char *name)
9dc39cba 153{
9307c4c1 154 help_cmd(name);
9dc39cba
FB
155}
156
9307c4c1 157static void do_commit(void)
9dc39cba
FB
158{
159 int i;
160
161 for (i = 0; i < MAX_DISKS; i++) {
162 if (bs_table[i])
163 bdrv_commit(bs_table[i]);
164 }
165}
166
9307c4c1 167static void do_info(const char *item)
9dc39cba
FB
168{
169 term_cmd_t *cmd;
9dc39cba 170
9307c4c1 171 if (!item)
9dc39cba 172 goto help;
9dc39cba 173 for(cmd = info_cmds; cmd->name != NULL; cmd++) {
9307c4c1 174 if (compare_cmd(item, cmd->name))
9dc39cba
FB
175 goto found;
176 }
177 help:
9307c4c1 178 help_cmd("info");
9dc39cba
FB
179 return;
180 found:
9307c4c1 181 cmd->handler();
9dc39cba
FB
182}
183
9307c4c1 184static void do_info_network(void)
9dc39cba
FB
185{
186 int i, j;
187 NetDriverState *nd;
188
189 for(i = 0; i < nb_nics; i++) {
190 nd = &nd_table[i];
191 term_printf("%d: ifname=%s macaddr=", i, nd->ifname);
192 for(j = 0; j < 6; j++) {
193 if (j > 0)
194 term_printf(":");
195 term_printf("%02x", nd->macaddr[j]);
196 }
197 term_printf("\n");
198 }
199}
200
9307c4c1 201static void do_info_block(void)
9dc39cba
FB
202{
203 bdrv_info();
204}
205
9307c4c1
FB
206static void do_info_registers(void)
207{
208#ifdef TARGET_I386
209 cpu_dump_state(cpu_single_env, stdout, X86_DUMP_FPU | X86_DUMP_CCOP);
210#else
211 cpu_dump_state(cpu_single_env, stdout, 0);
212#endif
213}
214
aa455485
FB
215static void do_info_history (void)
216{
217 int i;
218
219 for (i = 0; i < TERM_MAX_CMDS; i++) {
220 if (term_history[i] == NULL)
221 break;
222 term_printf("%d: '%s'\n", i, term_history[i]);
223 }
224}
225
9307c4c1 226static void do_quit(void)
9dc39cba
FB
227{
228 exit(0);
229}
230
231static int eject_device(BlockDriverState *bs, int force)
232{
233 if (bdrv_is_inserted(bs)) {
234 if (!force) {
235 if (!bdrv_is_removable(bs)) {
236 term_printf("device is not removable\n");
237 return -1;
238 }
239 if (bdrv_is_locked(bs)) {
240 term_printf("device is locked\n");
241 return -1;
242 }
243 }
244 bdrv_close(bs);
245 }
246 return 0;
247}
248
9307c4c1 249static void do_eject(int force, const char *filename)
9dc39cba
FB
250{
251 BlockDriverState *bs;
9dc39cba 252
9307c4c1 253 bs = bdrv_find(filename);
9dc39cba
FB
254 if (!bs) {
255 term_printf("device not found\n");
256 return;
257 }
258 eject_device(bs, force);
259}
260
9307c4c1 261static void do_change(const char *device, const char *filename)
9dc39cba
FB
262{
263 BlockDriverState *bs;
264
9307c4c1 265 bs = bdrv_find(device);
9dc39cba
FB
266 if (!bs) {
267 term_printf("device not found\n");
268 return;
269 }
270 if (eject_device(bs, 0) < 0)
271 return;
9307c4c1 272 bdrv_open(bs, filename, 0);
9dc39cba
FB
273}
274
9307c4c1 275static void do_screen_dump(const char *filename)
59a983b9 276{
9307c4c1 277 vga_screen_dump(filename);
59a983b9
FB
278}
279
9307c4c1 280static void do_log(const char *items)
f193c797
FB
281{
282 int mask;
283
9307c4c1 284 if (!strcmp(items, "none")) {
f193c797
FB
285 mask = 0;
286 } else {
9307c4c1 287 mask = cpu_str_to_log_mask(items);
f193c797 288 if (!mask) {
9307c4c1 289 help_cmd("log");
f193c797
FB
290 return;
291 }
292 }
293 cpu_set_log(mask);
294}
295
9307c4c1 296static void do_savevm(const char *filename)
8a7ddc38 297{
9307c4c1
FB
298 if (qemu_savevm(filename) < 0)
299 term_printf("I/O error when saving VM to '%s'\n", filename);
8a7ddc38
FB
300}
301
9307c4c1 302static void do_loadvm(const char *filename)
8a7ddc38 303{
9307c4c1
FB
304 if (qemu_loadvm(filename) < 0)
305 term_printf("I/O error when loading VM from '%s'\n", filename);
8a7ddc38
FB
306}
307
9307c4c1 308static void do_stop(void)
8a7ddc38
FB
309{
310 vm_stop(EXCP_INTERRUPT);
311}
312
9307c4c1 313static void do_cont(void)
8a7ddc38
FB
314{
315 vm_start();
316}
317
67b915a5 318#ifdef CONFIG_GDBSTUB
9307c4c1 319static void do_gdbserver(int has_port, int port)
8a7ddc38 320{
9307c4c1
FB
321 if (!has_port)
322 port = DEFAULT_GDBSTUB_PORT;
8a7ddc38
FB
323 if (gdbserver_start(port) < 0) {
324 qemu_printf("Could not open gdbserver socket on port %d\n", port);
325 } else {
326 qemu_printf("Waiting gdb connection on port %d\n", port);
327 }
328}
67b915a5 329#endif
8a7ddc38 330
9307c4c1
FB
331static void term_printc(int c)
332{
333 term_printf("'");
334 switch(c) {
335 case '\'':
336 term_printf("\\'");
337 break;
338 case '\\':
339 term_printf("\\\\");
340 break;
341 case '\n':
342 term_printf("\\n");
343 break;
344 case '\r':
345 term_printf("\\r");
346 break;
347 default:
348 if (c >= 32 && c <= 126) {
349 term_printf("%c", c);
350 } else {
351 term_printf("\\x%02x", c);
352 }
353 break;
354 }
355 term_printf("'");
356}
357
358static void memory_dump(int count, int format, int wsize,
359 target_ulong addr, int is_physical)
360{
361 int nb_per_line, l, line_size, i, max_digits, len;
362 uint8_t buf[16];
363 uint64_t v;
364
365 if (format == 'i') {
366 int flags;
367 flags = 0;
368#ifdef TARGET_I386
4c27ba27 369 if (wsize == 2) {
9307c4c1 370 flags = 1;
4c27ba27
FB
371 } else if (wsize == 4) {
372 flags = 0;
373 } else {
374 /* as default we use the current CS size */
375 flags = 0;
376 if (!(cpu_single_env->segs[R_CS].flags & DESC_B_MASK))
377 flags = 1;
378 }
379#endif
9307c4c1
FB
380 monitor_disas(addr, count, is_physical, flags);
381 return;
382 }
383
384 len = wsize * count;
385 if (wsize == 1)
386 line_size = 8;
387 else
388 line_size = 16;
389 nb_per_line = line_size / wsize;
390 max_digits = 0;
391
392 switch(format) {
393 case 'o':
394 max_digits = (wsize * 8 + 2) / 3;
395 break;
396 default:
397 case 'x':
398 max_digits = (wsize * 8) / 4;
399 break;
400 case 'u':
401 case 'd':
402 max_digits = (wsize * 8 * 10 + 32) / 33;
403 break;
404 case 'c':
405 wsize = 1;
406 break;
407 }
408
409 while (len > 0) {
410 term_printf("0x%08x:", addr);
411 l = len;
412 if (l > line_size)
413 l = line_size;
414 if (is_physical) {
415 cpu_physical_memory_rw(addr, buf, l, 0);
416 } else {
417 cpu_memory_rw_debug(cpu_single_env, addr, buf, l, 0);
418 }
419 i = 0;
420 while (i < l) {
421 switch(wsize) {
422 default:
423 case 1:
424 v = ldub_raw(buf + i);
425 break;
426 case 2:
427 v = lduw_raw(buf + i);
428 break;
429 case 4:
430 v = ldl_raw(buf + i);
431 break;
432 case 8:
433 v = ldq_raw(buf + i);
434 break;
435 }
436 term_printf(" ");
437 switch(format) {
438 case 'o':
439 term_printf("%#*llo", max_digits, v);
440 break;
441 case 'x':
442 term_printf("0x%0*llx", max_digits, v);
443 break;
444 case 'u':
445 term_printf("%*llu", max_digits, v);
446 break;
447 case 'd':
448 term_printf("%*lld", max_digits, v);
449 break;
450 case 'c':
451 term_printc(v);
452 break;
453 }
454 i += wsize;
455 }
456 term_printf("\n");
457 addr += l;
458 len -= l;
459 }
460}
461
462static void do_memory_dump(int count, int format, int size, int addr)
463{
464 memory_dump(count, format, size, addr, 0);
465}
466
467static void do_physical_memory_dump(int count, int format, int size, int addr)
468{
469 memory_dump(count, format, size, addr, 1);
470}
471
472static void do_print(int count, int format, int size, int val)
473{
474 switch(format) {
475 case 'o':
476 term_printf("%#o", val);
477 break;
478 case 'x':
479 term_printf("%#x", val);
480 break;
481 case 'u':
482 term_printf("%u", val);
483 break;
484 default:
485 case 'd':
486 term_printf("%d", val);
487 break;
488 case 'c':
489 term_printc(val);
490 break;
491 }
492 term_printf("\n");
493}
494
a3a91a35
FB
495typedef struct {
496 int keycode;
497 const char *name;
498} KeyDef;
499
500static const KeyDef key_defs[] = {
501 { 0x2a, "shift" },
502 { 0x36, "shift_r" },
503
504 { 0x38, "alt" },
505 { 0xb8, "alt_r" },
506 { 0x1d, "ctrl" },
507 { 0x9d, "ctrl_r" },
508
509 { 0xdd, "menu" },
510
511 { 0x01, "esc" },
512
513 { 0x02, "1" },
514 { 0x03, "2" },
515 { 0x04, "3" },
516 { 0x05, "4" },
517 { 0x06, "5" },
518 { 0x07, "6" },
519 { 0x08, "7" },
520 { 0x09, "8" },
521 { 0x0a, "9" },
522 { 0x0b, "0" },
523 { 0x0e, "backspace" },
524
525 { 0x0f, "tab" },
526 { 0x10, "q" },
527 { 0x11, "w" },
528 { 0x12, "e" },
529 { 0x13, "r" },
530 { 0x14, "t" },
531 { 0x15, "y" },
532 { 0x16, "u" },
533 { 0x17, "i" },
534 { 0x18, "o" },
535 { 0x19, "p" },
536
537 { 0x1c, "ret" },
538
539 { 0x1e, "a" },
540 { 0x1f, "s" },
541 { 0x20, "d" },
542 { 0x21, "f" },
543 { 0x22, "g" },
544 { 0x23, "h" },
545 { 0x24, "j" },
546 { 0x25, "k" },
547 { 0x26, "l" },
548
549 { 0x2c, "z" },
550 { 0x2d, "x" },
551 { 0x2e, "c" },
552 { 0x2f, "v" },
553 { 0x30, "b" },
554 { 0x31, "n" },
555 { 0x32, "m" },
556
557 { 0x39, "spc" },
00ffa62a 558 { 0x3a, "caps_lock" },
a3a91a35
FB
559 { 0x3b, "f1" },
560 { 0x3c, "f2" },
561 { 0x3d, "f3" },
562 { 0x3e, "f4" },
563 { 0x3f, "f5" },
564 { 0x40, "f6" },
565 { 0x41, "f7" },
566 { 0x42, "f8" },
567 { 0x43, "f9" },
568 { 0x44, "f10" },
00ffa62a 569 { 0x45, "num_lock" },
a3a91a35
FB
570 { 0x46, "scroll_lock" },
571
572 { 0x56, "<" },
573
574 { 0x57, "f11" },
575 { 0x58, "f12" },
576
577 { 0xb7, "print" },
578
579 { 0xc7, "home" },
580 { 0xc9, "pgup" },
581 { 0xd1, "pgdn" },
582 { 0xcf, "end" },
583
584 { 0xcb, "left" },
585 { 0xc8, "up" },
586 { 0xd0, "down" },
587 { 0xcd, "right" },
588
589 { 0xd2, "insert" },
590 { 0xd3, "delete" },
591 { 0, NULL },
592};
593
594static int get_keycode(const char *key)
595{
596 const KeyDef *p;
597
598 for(p = key_defs; p->name != NULL; p++) {
599 if (!strcmp(key, p->name))
600 return p->keycode;
601 }
602 return -1;
603}
604
605static void do_send_key(const char *string)
606{
607 char keybuf[16], *q;
608 uint8_t keycodes[16];
609 const char *p;
610 int nb_keycodes, keycode, i;
611
612 nb_keycodes = 0;
613 p = string;
614 while (*p != '\0') {
615 q = keybuf;
616 while (*p != '\0' && *p != '-') {
617 if ((q - keybuf) < sizeof(keybuf) - 1) {
618 *q++ = *p;
619 }
620 p++;
621 }
622 *q = '\0';
623 keycode = get_keycode(keybuf);
624 if (keycode < 0) {
625 term_printf("unknown key: '%s'\n", keybuf);
626 return;
627 }
628 keycodes[nb_keycodes++] = keycode;
629 if (*p == '\0')
630 break;
631 p++;
632 }
633 /* key down events */
634 for(i = 0; i < nb_keycodes; i++) {
635 keycode = keycodes[i];
636 if (keycode & 0x80)
637 kbd_put_keycode(0xe0);
638 kbd_put_keycode(keycode & 0x7f);
639 }
640 /* key up events */
641 for(i = nb_keycodes - 1; i >= 0; i--) {
642 keycode = keycodes[i];
643 if (keycode & 0x80)
644 kbd_put_keycode(0xe0);
645 kbd_put_keycode(keycode | 0x80);
646 }
647}
648
3440557b
FB
649static void do_ioport_read(int count, int format, int size, int addr, int has_index, int index)
650{
651 uint32_t val;
652 int suffix;
653
654 if (has_index) {
655 cpu_outb(NULL, addr & 0xffff, index & 0xff);
656 addr++;
657 }
658 addr &= 0xffff;
659
660 switch(size) {
661 default:
662 case 1:
663 val = cpu_inb(NULL, addr);
664 suffix = 'b';
665 break;
666 case 2:
667 val = cpu_inw(NULL, addr);
668 suffix = 'w';
669 break;
670 case 4:
671 val = cpu_inl(NULL, addr);
672 suffix = 'l';
673 break;
674 }
675 term_printf("port%c[0x%04x] = %#0*x\n",
676 suffix, addr, size * 2, val);
677}
a3a91a35 678
e4f9082b
FB
679static void do_system_reset(void)
680{
681 qemu_system_reset_request();
682}
683
9dc39cba 684static term_cmd_t term_cmds[] = {
9307c4c1 685 { "help|?", "s?", do_help,
9dc39cba 686 "[cmd]", "show the help" },
9307c4c1 687 { "commit", "", do_commit,
9dc39cba 688 "", "commit changes to the disk images (if -snapshot is used)" },
9307c4c1 689 { "info", "s?", do_info,
9dc39cba 690 "subcommand", "show various information about the system state" },
9307c4c1 691 { "q|quit", "", do_quit,
9dc39cba 692 "", "quit the emulator" },
81d0912d 693 { "eject", "-fB", do_eject,
9dc39cba 694 "[-f] device", "eject a removable media (use -f to force it)" },
81d0912d 695 { "change", "BF", do_change,
9dc39cba 696 "device filename", "change a removable media" },
9307c4c1 697 { "screendump", "F", do_screen_dump,
59a983b9 698 "filename", "save screen into PPM image 'filename'" },
9307c4c1 699 { "log", "s", do_log,
f193c797 700 "item1[,...]", "activate logging of the specified items to '/tmp/qemu.log'" },
9307c4c1 701 { "savevm", "F", do_savevm,
8a7ddc38 702 "filename", "save the whole virtual machine state to 'filename'" },
9307c4c1 703 { "loadvm", "F", do_loadvm,
8a7ddc38 704 "filename", "restore the whole virtual machine state from 'filename'" },
9307c4c1
FB
705 { "stop", "", do_stop,
706 "", "stop emulation", },
707 { "c|cont", "", do_cont,
708 "", "resume emulation", },
67b915a5 709#ifdef CONFIG_GDBSTUB
9307c4c1
FB
710 { "gdbserver", "i?", do_gdbserver,
711 "[port]", "start gdbserver session (default port=1234)", },
67b915a5 712#endif
9307c4c1
FB
713 { "x", "/i", do_memory_dump,
714 "/fmt addr", "virtual memory dump starting at 'addr'", },
715 { "xp", "/i", do_physical_memory_dump,
716 "/fmt addr", "physical memory dump starting at 'addr'", },
717 { "p|print", "/i", do_print,
718 "/fmt expr", "print expression value (use $reg for CPU register access)", },
3440557b
FB
719 { "i", "/ii.", do_ioport_read,
720 "/fmt addr", "I/O port read" },
721
a3a91a35
FB
722 { "sendkey", "s", do_send_key,
723 "keys", "send keys to the VM (e.g. 'sendkey ctrl-alt-f1')" },
e4f9082b
FB
724 { "system_reset", "", do_system_reset,
725 "", "reset the system" },
f193c797 726 { NULL, NULL, },
9dc39cba
FB
727};
728
729static term_cmd_t info_cmds[] = {
9307c4c1 730 { "network", "", do_info_network,
9dc39cba 731 "", "show the network state" },
9307c4c1 732 { "block", "", do_info_block,
9dc39cba 733 "", "show the block devices" },
9307c4c1
FB
734 { "registers", "", do_info_registers,
735 "", "show the cpu registers" },
aa455485
FB
736 { "history", "", do_info_history,
737 "", "show the command line history", },
4a0fb71e
FB
738 { "irq", "", irq_info,
739 "", "show the interrupts statistics (if available)", },
4c27ba27
FB
740 { "pic", "", pic_info,
741 "", "show i8259 (PIC) state", },
86e0c048
FB
742 { "pci", "", pci_info,
743 "", "show PCI info", },
9dc39cba
FB
744 { NULL, NULL, },
745};
746
9307c4c1
FB
747/*******************************************************************/
748
749static const char *pch;
750static jmp_buf expr_env;
751
752typedef struct MonitorDef {
753 const char *name;
754 int offset;
755 int (*get_value)(struct MonitorDef *md);
756} MonitorDef;
757
57206fd4
FB
758#if defined(TARGET_I386)
759static int monitor_get_pc (struct MonitorDef *md)
760{
761 return cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base;
762}
763#endif
764
a541f297
FB
765#if defined(TARGET_PPC)
766static int monitor_get_ccr (struct MonitorDef *md)
767{
768 unsigned int u;
769 int i;
770
771 u = 0;
772 for (i = 0; i < 8; i++)
773 u |= cpu_single_env->crf[i] << (32 - (4 * i));
774
775 return u;
776}
777
778static int monitor_get_msr (struct MonitorDef *md)
779{
780 return (cpu_single_env->msr[MSR_POW] << MSR_POW) |
781 (cpu_single_env->msr[MSR_ILE] << MSR_ILE) |
782 (cpu_single_env->msr[MSR_EE] << MSR_EE) |
783 (cpu_single_env->msr[MSR_PR] << MSR_PR) |
784 (cpu_single_env->msr[MSR_FP] << MSR_FP) |
785 (cpu_single_env->msr[MSR_ME] << MSR_ME) |
786 (cpu_single_env->msr[MSR_FE0] << MSR_FE0) |
787 (cpu_single_env->msr[MSR_SE] << MSR_SE) |
788 (cpu_single_env->msr[MSR_BE] << MSR_BE) |
789 (cpu_single_env->msr[MSR_FE1] << MSR_FE1) |
790 (cpu_single_env->msr[MSR_IP] << MSR_IP) |
791 (cpu_single_env->msr[MSR_IR] << MSR_IR) |
792 (cpu_single_env->msr[MSR_DR] << MSR_DR) |
793 (cpu_single_env->msr[MSR_RI] << MSR_RI) |
794 (cpu_single_env->msr[MSR_LE] << MSR_LE);
795}
796
797static int monitor_get_xer (struct MonitorDef *md)
798{
799 return (cpu_single_env->xer[XER_SO] << XER_SO) |
800 (cpu_single_env->xer[XER_OV] << XER_OV) |
801 (cpu_single_env->xer[XER_CA] << XER_CA) |
802 (cpu_single_env->xer[XER_BC] << XER_BC);
803}
9fddaa0c
FB
804
805uint32_t cpu_ppc_load_decr (CPUState *env);
806static int monitor_get_decr (struct MonitorDef *md)
807{
808 return cpu_ppc_load_decr(cpu_single_env);
809}
810
811uint32_t cpu_ppc_load_tbu (CPUState *env);
812static int monitor_get_tbu (struct MonitorDef *md)
813{
814 return cpu_ppc_load_tbu(cpu_single_env);
815}
816
817uint32_t cpu_ppc_load_tbl (CPUState *env);
818static int monitor_get_tbl (struct MonitorDef *md)
819{
820 return cpu_ppc_load_tbl(cpu_single_env);
821}
a541f297
FB
822#endif
823
9307c4c1
FB
824static MonitorDef monitor_defs[] = {
825#ifdef TARGET_I386
57206fd4
FB
826
827#define SEG(name, seg) \
828 { name, offsetof(CPUState, segs[seg].selector) },\
829 { name ".base", offsetof(CPUState, segs[seg].base) },\
830 { name ".limit", offsetof(CPUState, segs[seg].limit) },
831
9307c4c1
FB
832 { "eax", offsetof(CPUState, regs[0]) },
833 { "ecx", offsetof(CPUState, regs[1]) },
834 { "edx", offsetof(CPUState, regs[2]) },
835 { "ebx", offsetof(CPUState, regs[3]) },
836 { "esp|sp", offsetof(CPUState, regs[4]) },
837 { "ebp|fp", offsetof(CPUState, regs[5]) },
838 { "esi", offsetof(CPUState, regs[6]) },
839 { "esi", offsetof(CPUState, regs[7]) },
840 { "eflags", offsetof(CPUState, eflags) },
57206fd4
FB
841 { "eip", offsetof(CPUState, eip) },
842 SEG("cs", R_CS)
843 SEG("ds", R_DS)
844 SEG("es", R_ES)
845 SEG("fs", R_FS)
846 SEG("gs", R_GS)
847 { "pc", 0, monitor_get_pc, },
a541f297
FB
848#elif defined(TARGET_PPC)
849 { "r0", offsetof(CPUState, gpr[0]) },
850 { "r1", offsetof(CPUState, gpr[1]) },
851 { "r2", offsetof(CPUState, gpr[2]) },
852 { "r3", offsetof(CPUState, gpr[3]) },
853 { "r4", offsetof(CPUState, gpr[4]) },
854 { "r5", offsetof(CPUState, gpr[5]) },
855 { "r6", offsetof(CPUState, gpr[6]) },
856 { "r7", offsetof(CPUState, gpr[7]) },
857 { "r8", offsetof(CPUState, gpr[8]) },
858 { "r9", offsetof(CPUState, gpr[9]) },
859 { "r10", offsetof(CPUState, gpr[10]) },
860 { "r11", offsetof(CPUState, gpr[11]) },
861 { "r12", offsetof(CPUState, gpr[12]) },
862 { "r13", offsetof(CPUState, gpr[13]) },
863 { "r14", offsetof(CPUState, gpr[14]) },
864 { "r15", offsetof(CPUState, gpr[15]) },
865 { "r16", offsetof(CPUState, gpr[16]) },
866 { "r17", offsetof(CPUState, gpr[17]) },
867 { "r18", offsetof(CPUState, gpr[18]) },
868 { "r19", offsetof(CPUState, gpr[19]) },
869 { "r20", offsetof(CPUState, gpr[20]) },
870 { "r21", offsetof(CPUState, gpr[21]) },
871 { "r22", offsetof(CPUState, gpr[22]) },
872 { "r23", offsetof(CPUState, gpr[23]) },
873 { "r24", offsetof(CPUState, gpr[24]) },
874 { "r25", offsetof(CPUState, gpr[25]) },
875 { "r26", offsetof(CPUState, gpr[26]) },
876 { "r27", offsetof(CPUState, gpr[27]) },
877 { "r28", offsetof(CPUState, gpr[28]) },
878 { "r29", offsetof(CPUState, gpr[29]) },
879 { "r30", offsetof(CPUState, gpr[30]) },
880 { "r31", offsetof(CPUState, gpr[31]) },
57206fd4 881 { "nip|pc", offsetof(CPUState, nip) },
a541f297
FB
882 { "lr", offsetof(CPUState, lr) },
883 { "ctr", offsetof(CPUState, ctr) },
9fddaa0c 884 { "decr", 0, &monitor_get_decr, },
a541f297
FB
885 { "ccr", 0, &monitor_get_ccr, },
886 { "msr", 0, &monitor_get_msr, },
887 { "xer", 0, &monitor_get_xer, },
9fddaa0c
FB
888 { "tbu", 0, &monitor_get_tbu, },
889 { "tbl", 0, &monitor_get_tbl, },
a541f297
FB
890 { "sdr1", offsetof(CPUState, sdr1) },
891 { "sr0", offsetof(CPUState, sr[0]) },
892 { "sr1", offsetof(CPUState, sr[1]) },
893 { "sr2", offsetof(CPUState, sr[2]) },
894 { "sr3", offsetof(CPUState, sr[3]) },
895 { "sr4", offsetof(CPUState, sr[4]) },
896 { "sr5", offsetof(CPUState, sr[5]) },
897 { "sr6", offsetof(CPUState, sr[6]) },
898 { "sr7", offsetof(CPUState, sr[7]) },
899 { "sr8", offsetof(CPUState, sr[8]) },
900 { "sr9", offsetof(CPUState, sr[9]) },
901 { "sr10", offsetof(CPUState, sr[10]) },
902 { "sr11", offsetof(CPUState, sr[11]) },
903 { "sr12", offsetof(CPUState, sr[12]) },
904 { "sr13", offsetof(CPUState, sr[13]) },
905 { "sr14", offsetof(CPUState, sr[14]) },
906 { "sr15", offsetof(CPUState, sr[15]) },
907 /* Too lazy to put BATs and SPRs ... */
9307c4c1
FB
908#endif
909 { NULL },
910};
911
912static void expr_error(const char *fmt)
9dc39cba 913{
9307c4c1
FB
914 term_printf(fmt);
915 term_printf("\n");
916 longjmp(expr_env, 1);
917}
918
919static int get_monitor_def(int *pval, const char *name)
920{
921 MonitorDef *md;
922 for(md = monitor_defs; md->name != NULL; md++) {
923 if (compare_cmd(name, md->name)) {
924 if (md->get_value) {
925 *pval = md->get_value(md);
926 } else {
927 *pval = *(uint32_t *)((uint8_t *)cpu_single_env + md->offset);
928 }
929 return 0;
930 }
931 }
932 return -1;
933}
934
935static void next(void)
936{
937 if (pch != '\0') {
938 pch++;
939 while (isspace(*pch))
940 pch++;
941 }
942}
943
944static int expr_sum(void);
945
946static int expr_unary(void)
947{
948 int n;
949 char *p;
950
951 switch(*pch) {
952 case '+':
953 next();
954 n = expr_unary();
955 break;
956 case '-':
957 next();
958 n = -expr_unary();
959 break;
960 case '~':
961 next();
962 n = ~expr_unary();
963 break;
964 case '(':
965 next();
966 n = expr_sum();
967 if (*pch != ')') {
968 expr_error("')' expected");
969 }
970 next();
971 break;
81d0912d
FB
972 case '\'':
973 pch++;
974 if (*pch == '\0')
975 expr_error("character constant expected");
976 n = *pch;
977 pch++;
978 if (*pch != '\'')
979 expr_error("missing terminating \' character");
980 next();
981 break;
9307c4c1
FB
982 case '$':
983 {
984 char buf[128], *q;
985
986 pch++;
987 q = buf;
988 while ((*pch >= 'a' && *pch <= 'z') ||
989 (*pch >= 'A' && *pch <= 'Z') ||
990 (*pch >= '0' && *pch <= '9') ||
57206fd4 991 *pch == '_' || *pch == '.') {
9307c4c1
FB
992 if ((q - buf) < sizeof(buf) - 1)
993 *q++ = *pch;
994 pch++;
995 }
996 while (isspace(*pch))
997 pch++;
998 *q = 0;
999 if (get_monitor_def(&n, buf))
1000 expr_error("unknown register");
1001 }
1002 break;
1003 case '\0':
1004 expr_error("unexpected end of expression");
1005 n = 0;
1006 break;
1007 default:
1008 n = strtoul(pch, &p, 0);
1009 if (pch == p) {
1010 expr_error("invalid char in expression");
1011 }
1012 pch = p;
1013 while (isspace(*pch))
1014 pch++;
1015 break;
1016 }
1017 return n;
1018}
1019
1020
1021static int expr_prod(void)
1022{
1023 int val, val2, op;
1024
1025 val = expr_unary();
1026 for(;;) {
1027 op = *pch;
1028 if (op != '*' && op != '/' && op != '%')
1029 break;
1030 next();
1031 val2 = expr_unary();
1032 switch(op) {
1033 default:
1034 case '*':
1035 val *= val2;
1036 break;
1037 case '/':
1038 case '%':
1039 if (val2 == 0)
5b60212f 1040 expr_error("division by zero");
9307c4c1
FB
1041 if (op == '/')
1042 val /= val2;
1043 else
1044 val %= val2;
1045 break;
1046 }
1047 }
1048 return val;
1049}
1050
1051static int expr_logic(void)
1052{
1053 int val, val2, op;
1054
1055 val = expr_prod();
1056 for(;;) {
1057 op = *pch;
1058 if (op != '&' && op != '|' && op != '^')
1059 break;
1060 next();
1061 val2 = expr_prod();
1062 switch(op) {
1063 default:
1064 case '&':
1065 val &= val2;
1066 break;
1067 case '|':
1068 val |= val2;
1069 break;
1070 case '^':
1071 val ^= val2;
1072 break;
1073 }
1074 }
1075 return val;
1076}
1077
1078static int expr_sum(void)
1079{
1080 int val, val2, op;
1081
1082 val = expr_logic();
1083 for(;;) {
1084 op = *pch;
1085 if (op != '+' && op != '-')
1086 break;
1087 next();
1088 val2 = expr_logic();
1089 if (op == '+')
1090 val += val2;
1091 else
1092 val -= val2;
1093 }
1094 return val;
1095}
1096
1097static int get_expr(int *pval, const char **pp)
1098{
1099 pch = *pp;
1100 if (setjmp(expr_env)) {
1101 *pp = pch;
1102 return -1;
1103 }
1104 while (isspace(*pch))
1105 pch++;
1106 *pval = expr_sum();
1107 *pp = pch;
1108 return 0;
1109}
1110
1111static int get_str(char *buf, int buf_size, const char **pp)
1112{
1113 const char *p;
1114 char *q;
1115 int c;
1116
81d0912d 1117 q = buf;
9307c4c1
FB
1118 p = *pp;
1119 while (isspace(*p))
1120 p++;
1121 if (*p == '\0') {
1122 fail:
81d0912d 1123 *q = '\0';
9307c4c1
FB
1124 *pp = p;
1125 return -1;
1126 }
9307c4c1
FB
1127 if (*p == '\"') {
1128 p++;
1129 while (*p != '\0' && *p != '\"') {
1130 if (*p == '\\') {
1131 p++;
1132 c = *p++;
1133 switch(c) {
1134 case 'n':
1135 c = '\n';
1136 break;
1137 case 'r':
1138 c = '\r';
1139 break;
1140 case '\\':
1141 case '\'':
1142 case '\"':
1143 break;
1144 default:
1145 qemu_printf("unsupported escape code: '\\%c'\n", c);
1146 goto fail;
1147 }
1148 if ((q - buf) < buf_size - 1) {
1149 *q++ = c;
1150 }
1151 } else {
1152 if ((q - buf) < buf_size - 1) {
1153 *q++ = *p;
1154 }
1155 p++;
1156 }
1157 }
1158 if (*p != '\"') {
5b60212f 1159 qemu_printf("unterminated string\n");
9307c4c1
FB
1160 goto fail;
1161 }
1162 p++;
1163 } else {
1164 while (*p != '\0' && !isspace(*p)) {
1165 if ((q - buf) < buf_size - 1) {
1166 *q++ = *p;
1167 }
1168 p++;
1169 }
9307c4c1 1170 }
81d0912d 1171 *q = '\0';
9307c4c1
FB
1172 *pp = p;
1173 return 0;
1174}
1175
1176static int default_fmt_format = 'x';
1177static int default_fmt_size = 4;
1178
1179#define MAX_ARGS 16
1180
1181static void term_handle_command(const char *cmdline)
1182{
1183 const char *p, *pstart, *typestr;
1184 char *q;
1185 int c, nb_args, len, i, has_arg;
9dc39cba 1186 term_cmd_t *cmd;
9307c4c1
FB
1187 char cmdname[256];
1188 char buf[1024];
1189 void *str_allocated[MAX_ARGS];
1190 void *args[MAX_ARGS];
9dc39cba
FB
1191
1192#ifdef DEBUG
1193 term_printf("command='%s'\n", cmdline);
1194#endif
1195
9307c4c1 1196 /* extract the command name */
9dc39cba 1197 p = cmdline;
9307c4c1
FB
1198 q = cmdname;
1199 while (isspace(*p))
1200 p++;
1201 if (*p == '\0')
1202 return;
1203 pstart = p;
1204 while (*p != '\0' && *p != '/' && !isspace(*p))
1205 p++;
1206 len = p - pstart;
1207 if (len > sizeof(cmdname) - 1)
1208 len = sizeof(cmdname) - 1;
1209 memcpy(cmdname, pstart, len);
1210 cmdname[len] = '\0';
1211
1212 /* find the command */
1213 for(cmd = term_cmds; cmd->name != NULL; cmd++) {
1214 if (compare_cmd(cmdname, cmd->name))
1215 goto found;
1216 }
1217 term_printf("unknown command: '%s'\n", cmdname);
1218 return;
1219 found:
1220
1221 for(i = 0; i < MAX_ARGS; i++)
1222 str_allocated[i] = NULL;
1223
1224 /* parse the parameters */
1225 typestr = cmd->args_type;
1226 nb_args = 0;
9dc39cba 1227 for(;;) {
9307c4c1
FB
1228 c = *typestr;
1229 if (c == '\0')
9dc39cba 1230 break;
9307c4c1
FB
1231 typestr++;
1232 switch(c) {
1233 case 'F':
81d0912d 1234 case 'B':
9307c4c1
FB
1235 case 's':
1236 {
1237 int ret;
1238 char *str;
1239
1240 while (isspace(*p))
1241 p++;
1242 if (*typestr == '?') {
1243 typestr++;
1244 if (*p == '\0') {
1245 /* no optional string: NULL argument */
1246 str = NULL;
1247 goto add_str;
1248 }
1249 }
1250 ret = get_str(buf, sizeof(buf), &p);
1251 if (ret < 0) {
81d0912d
FB
1252 switch(c) {
1253 case 'F':
9307c4c1 1254 term_printf("%s: filename expected\n", cmdname);
81d0912d
FB
1255 break;
1256 case 'B':
1257 term_printf("%s: block device name expected\n", cmdname);
1258 break;
1259 default:
9307c4c1 1260 term_printf("%s: string expected\n", cmdname);
81d0912d
FB
1261 break;
1262 }
9307c4c1
FB
1263 goto fail;
1264 }
1265 str = qemu_malloc(strlen(buf) + 1);
1266 strcpy(str, buf);
1267 str_allocated[nb_args] = str;
1268 add_str:
1269 if (nb_args >= MAX_ARGS) {
1270 error_args:
1271 term_printf("%s: too many arguments\n", cmdname);
1272 goto fail;
1273 }
1274 args[nb_args++] = str;
1275 }
9dc39cba 1276 break;
9307c4c1
FB
1277 case '/':
1278 {
1279 int count, format, size;
1280
1281 while (isspace(*p))
1282 p++;
1283 if (*p == '/') {
1284 /* format found */
1285 p++;
1286 count = 1;
1287 if (isdigit(*p)) {
1288 count = 0;
1289 while (isdigit(*p)) {
1290 count = count * 10 + (*p - '0');
1291 p++;
1292 }
1293 }
1294 size = -1;
1295 format = -1;
1296 for(;;) {
1297 switch(*p) {
1298 case 'o':
1299 case 'd':
1300 case 'u':
1301 case 'x':
1302 case 'i':
1303 case 'c':
1304 format = *p++;
1305 break;
1306 case 'b':
1307 size = 1;
1308 p++;
1309 break;
1310 case 'h':
1311 size = 2;
1312 p++;
1313 break;
1314 case 'w':
1315 size = 4;
1316 p++;
1317 break;
1318 case 'g':
1319 case 'L':
1320 size = 8;
1321 p++;
1322 break;
1323 default:
1324 goto next;
1325 }
1326 }
1327 next:
1328 if (*p != '\0' && !isspace(*p)) {
1329 term_printf("invalid char in format: '%c'\n", *p);
1330 goto fail;
1331 }
9307c4c1
FB
1332 if (format < 0)
1333 format = default_fmt_format;
4c27ba27
FB
1334 if (format != 'i') {
1335 /* for 'i', not specifying a size gives -1 as size */
1336 if (size < 0)
1337 size = default_fmt_size;
1338 }
9307c4c1
FB
1339 default_fmt_size = size;
1340 default_fmt_format = format;
1341 } else {
1342 count = 1;
1343 format = default_fmt_format;
4c27ba27
FB
1344 if (format != 'i') {
1345 size = default_fmt_size;
1346 } else {
1347 size = -1;
1348 }
9307c4c1
FB
1349 }
1350 if (nb_args + 3 > MAX_ARGS)
1351 goto error_args;
1352 args[nb_args++] = (void*)count;
1353 args[nb_args++] = (void*)format;
1354 args[nb_args++] = (void*)size;
1355 }
9dc39cba 1356 break;
9307c4c1
FB
1357 case 'i':
1358 {
1359 int val;
1360 while (isspace(*p))
1361 p++;
3440557b 1362 if (*typestr == '?' || *typestr == '.') {
9307c4c1 1363 typestr++;
3440557b
FB
1364 if (*typestr == '?') {
1365 if (*p == '\0')
1366 has_arg = 0;
1367 else
1368 has_arg = 1;
1369 } else {
1370 if (*p == '.') {
1371 p++;
1372 while (isspace(*p))
1373 p++;
1374 has_arg = 1;
1375 } else {
1376 has_arg = 0;
1377 }
1378 }
9307c4c1
FB
1379 if (nb_args >= MAX_ARGS)
1380 goto error_args;
1381 args[nb_args++] = (void *)has_arg;
1382 if (!has_arg) {
1383 if (nb_args >= MAX_ARGS)
1384 goto error_args;
1385 val = -1;
1386 goto add_num;
1387 }
1388 }
1389 if (get_expr(&val, &p))
1390 goto fail;
1391 add_num:
1392 if (nb_args >= MAX_ARGS)
1393 goto error_args;
1394 args[nb_args++] = (void *)val;
1395 }
1396 break;
1397 case '-':
1398 {
1399 int has_option;
1400 /* option */
1401
1402 c = *typestr++;
1403 if (c == '\0')
1404 goto bad_type;
1405 while (isspace(*p))
1406 p++;
1407 has_option = 0;
1408 if (*p == '-') {
1409 p++;
1410 if (*p != c) {
1411 term_printf("%s: unsupported option -%c\n",
1412 cmdname, *p);
1413 goto fail;
1414 }
1415 p++;
1416 has_option = 1;
1417 }
1418 if (nb_args >= MAX_ARGS)
1419 goto error_args;
1420 args[nb_args++] = (void *)has_option;
1421 }
1422 break;
1423 default:
1424 bad_type:
1425 term_printf("%s: unknown type '%c'\n", cmdname, c);
1426 goto fail;
1427 }
9dc39cba 1428 }
9307c4c1
FB
1429 /* check that all arguments were parsed */
1430 while (isspace(*p))
1431 p++;
1432 if (*p != '\0') {
1433 term_printf("%s: extraneous characters at the end of line\n",
1434 cmdname);
1435 goto fail;
9dc39cba 1436 }
9307c4c1
FB
1437
1438 switch(nb_args) {
1439 case 0:
1440 cmd->handler();
1441 break;
1442 case 1:
1443 cmd->handler(args[0]);
1444 break;
1445 case 2:
1446 cmd->handler(args[0], args[1]);
1447 break;
1448 case 3:
1449 cmd->handler(args[0], args[1], args[2]);
1450 break;
1451 case 4:
1452 cmd->handler(args[0], args[1], args[2], args[3]);
1453 break;
1454 case 5:
1455 cmd->handler(args[0], args[1], args[2], args[3], args[4]);
1456 break;
3440557b
FB
1457 case 6:
1458 cmd->handler(args[0], args[1], args[2], args[3], args[4], args[5]);
1459 break;
9307c4c1
FB
1460 default:
1461 term_printf("unsupported number of arguments: %d\n", nb_args);
1462 goto fail;
9dc39cba 1463 }
9307c4c1
FB
1464 fail:
1465 for(i = 0; i < MAX_ARGS; i++)
1466 qemu_free(str_allocated[i]);
9dc39cba 1467 return;
9dc39cba
FB
1468}
1469
81d0912d
FB
1470static void cmd_completion(const char *name, const char *list)
1471{
1472 const char *p, *pstart;
1473 char cmd[128];
1474 int len;
1475
1476 p = list;
1477 for(;;) {
1478 pstart = p;
1479 p = strchr(p, '|');
1480 if (!p)
1481 p = pstart + strlen(pstart);
1482 len = p - pstart;
1483 if (len > sizeof(cmd) - 2)
1484 len = sizeof(cmd) - 2;
1485 memcpy(cmd, pstart, len);
1486 cmd[len] = '\0';
1487 if (name[0] == '\0' || !strncmp(name, cmd, strlen(name))) {
1488 add_completion(cmd);
1489 }
1490 if (*p == '\0')
1491 break;
1492 p++;
1493 }
1494}
1495
1496static void file_completion(const char *input)
1497{
1498 DIR *ffs;
1499 struct dirent *d;
1500 char path[1024];
1501 char file[1024], file_prefix[1024];
1502 int input_path_len;
1503 const char *p;
1504
1505 p = strrchr(input, '/');
1506 if (!p) {
1507 input_path_len = 0;
1508 pstrcpy(file_prefix, sizeof(file_prefix), input);
1509 strcpy(path, ".");
1510 } else {
1511 input_path_len = p - input + 1;
1512 memcpy(path, input, input_path_len);
1513 if (input_path_len > sizeof(path) - 1)
1514 input_path_len = sizeof(path) - 1;
1515 path[input_path_len] = '\0';
1516 pstrcpy(file_prefix, sizeof(file_prefix), p + 1);
1517 }
1518#ifdef DEBUG_COMPLETION
1519 term_printf("input='%s' path='%s' prefix='%s'\n", input, path, file_prefix);
1520#endif
1521 ffs = opendir(path);
1522 if (!ffs)
1523 return;
1524 for(;;) {
1525 struct stat sb;
1526 d = readdir(ffs);
1527 if (!d)
1528 break;
1529 if (strstart(d->d_name, file_prefix, NULL)) {
1530 memcpy(file, input, input_path_len);
1531 strcpy(file + input_path_len, d->d_name);
1532 /* stat the file to find out if it's a directory.
1533 * In that case add a slash to speed up typing long paths
1534 */
1535 stat(file, &sb);
1536 if(S_ISDIR(sb.st_mode))
1537 strcat(file, "/");
1538 add_completion(file);
1539 }
1540 }
1541 closedir(ffs);
1542}
1543
1544static void block_completion_it(void *opaque, const char *name)
1545{
1546 const char *input = opaque;
1547
1548 if (input[0] == '\0' ||
1549 !strncmp(name, (char *)input, strlen(input))) {
1550 add_completion(name);
1551 }
1552}
1553
1554/* NOTE: this parser is an approximate form of the real command parser */
1555static void parse_cmdline(const char *cmdline,
1556 int *pnb_args, char **args)
1557{
1558 const char *p;
1559 int nb_args, ret;
1560 char buf[1024];
1561
1562 p = cmdline;
1563 nb_args = 0;
1564 for(;;) {
1565 while (isspace(*p))
1566 p++;
1567 if (*p == '\0')
1568 break;
1569 if (nb_args >= MAX_ARGS)
1570 break;
1571 ret = get_str(buf, sizeof(buf), &p);
1572 args[nb_args] = qemu_strdup(buf);
1573 nb_args++;
1574 if (ret < 0)
1575 break;
1576 }
1577 *pnb_args = nb_args;
1578}
1579
1580static void find_completion(const char *cmdline)
1581{
1582 const char *cmdname;
1583 char *args[MAX_ARGS];
1584 int nb_args, i, len;
1585 const char *ptype, *str;
1586 term_cmd_t *cmd;
1587
1588 parse_cmdline(cmdline, &nb_args, args);
1589#ifdef DEBUG_COMPLETION
1590 for(i = 0; i < nb_args; i++) {
1591 term_printf("arg%d = '%s'\n", i, (char *)args[i]);
1592 }
1593#endif
1594
1595 /* if the line ends with a space, it means we want to complete the
1596 next arg */
1597 len = strlen(cmdline);
1598 if (len > 0 && isspace(cmdline[len - 1])) {
1599 if (nb_args >= MAX_ARGS)
1600 return;
1601 args[nb_args++] = qemu_strdup("");
1602 }
1603 if (nb_args <= 1) {
1604 /* command completion */
1605 if (nb_args == 0)
1606 cmdname = "";
1607 else
1608 cmdname = args[0];
1609 completion_index = strlen(cmdname);
1610 for(cmd = term_cmds; cmd->name != NULL; cmd++) {
1611 cmd_completion(cmdname, cmd->name);
1612 }
1613 } else {
1614 /* find the command */
1615 for(cmd = term_cmds; cmd->name != NULL; cmd++) {
1616 if (compare_cmd(args[0], cmd->name))
1617 goto found;
1618 }
1619 return;
1620 found:
1621 ptype = cmd->args_type;
1622 for(i = 0; i < nb_args - 2; i++) {
1623 if (*ptype != '\0') {
1624 ptype++;
1625 while (*ptype == '?')
1626 ptype++;
1627 }
1628 }
1629 str = args[nb_args - 1];
1630 switch(*ptype) {
1631 case 'F':
1632 /* file completion */
1633 completion_index = strlen(str);
1634 file_completion(str);
1635 break;
1636 case 'B':
1637 /* block device name completion */
1638 completion_index = strlen(str);
1639 bdrv_iterate(block_completion_it, (void *)str);
1640 break;
1641 default:
1642 break;
1643 }
1644 }
1645 for(i = 0; i < nb_args; i++)
1646 qemu_free(args[i]);
1647}
1648
1649static void term_show_prompt2(void)
9dc39cba
FB
1650{
1651 term_printf("(qemu) ");
1652 fflush(stdout);
81d0912d
FB
1653 term_last_cmd_buf_index = 0;
1654 term_last_cmd_buf_size = 0;
1655 term_esc_state = IS_NORM;
1656}
1657
1658static void term_show_prompt(void)
1659{
1660 term_show_prompt2();
9dc39cba
FB
1661 term_cmd_buf_index = 0;
1662 term_cmd_buf_size = 0;
9dc39cba
FB
1663}
1664
81d0912d
FB
1665/* update the displayed command line */
1666static void term_update(void)
aa455485 1667{
81d0912d
FB
1668 int i, delta;
1669
1670 if (term_cmd_buf_size != term_last_cmd_buf_size ||
1671 memcmp(term_cmd_buf, term_last_cmd_buf, term_cmd_buf_size) != 0) {
1672 for(i = 0; i < term_last_cmd_buf_index; i++) {
1673 term_printf("\033[D");
1674 }
1675 term_cmd_buf[term_cmd_buf_size] = '\0';
1676 term_printf("%s", term_cmd_buf);
1677 term_printf("\033[K");
1678 memcpy(term_last_cmd_buf, term_cmd_buf, term_cmd_buf_size);
1679 term_last_cmd_buf_size = term_cmd_buf_size;
1680 term_last_cmd_buf_index = term_cmd_buf_size;
1681 }
1682 if (term_cmd_buf_index != term_last_cmd_buf_index) {
1683 delta = term_cmd_buf_index - term_last_cmd_buf_index;
1684 if (delta > 0) {
1685 for(i = 0;i < delta; i++) {
1686 term_printf("\033[C");
1687 }
1688 } else {
1689 delta = -delta;
1690 for(i = 0;i < delta; i++) {
1691 term_printf("\033[D");
1692 }
1693 }
1694 term_last_cmd_buf_index = term_cmd_buf_index;
1695 }
aa455485
FB
1696 term_flush();
1697}
1698
9dc39cba
FB
1699static void term_insert_char(int ch)
1700{
1701 if (term_cmd_buf_index < TERM_CMD_BUF_SIZE) {
1702 memmove(term_cmd_buf + term_cmd_buf_index + 1,
1703 term_cmd_buf + term_cmd_buf_index,
1704 term_cmd_buf_size - term_cmd_buf_index);
1705 term_cmd_buf[term_cmd_buf_index] = ch;
1706 term_cmd_buf_size++;
9dc39cba 1707 term_cmd_buf_index++;
9dc39cba
FB
1708 }
1709}
1710
1711static void term_backward_char(void)
1712{
1713 if (term_cmd_buf_index > 0) {
1714 term_cmd_buf_index--;
9dc39cba
FB
1715 }
1716}
1717
1718static void term_forward_char(void)
1719{
1720 if (term_cmd_buf_index < term_cmd_buf_size) {
1721 term_cmd_buf_index++;
9dc39cba
FB
1722 }
1723}
1724
1725static void term_delete_char(void)
1726{
1727 if (term_cmd_buf_index < term_cmd_buf_size) {
1728 memmove(term_cmd_buf + term_cmd_buf_index,
1729 term_cmd_buf + term_cmd_buf_index + 1,
1730 term_cmd_buf_size - term_cmd_buf_index - 1);
9dc39cba 1731 term_cmd_buf_size--;
9dc39cba
FB
1732 }
1733}
1734
1735static void term_backspace(void)
1736{
1737 if (term_cmd_buf_index > 0) {
1738 term_backward_char();
1739 term_delete_char();
1740 }
1741}
1742
1743static void term_bol(void)
1744{
81d0912d 1745 term_cmd_buf_index = 0;
9dc39cba
FB
1746}
1747
1748static void term_eol(void)
1749{
81d0912d 1750 term_cmd_buf_index = term_cmd_buf_size;
9dc39cba
FB
1751}
1752
aa455485
FB
1753static void term_up_char(void)
1754{
1755 int idx;
1756
1757 if (term_hist_entry == 0)
1758 return;
1759 if (term_hist_entry == -1) {
1760 /* Find latest entry */
1761 for (idx = 0; idx < TERM_MAX_CMDS; idx++) {
1762 if (term_history[idx] == NULL)
1763 break;
1764 }
1765 term_hist_entry = idx;
1766 }
1767 term_hist_entry--;
1768 if (term_hist_entry >= 0) {
95ce326e
FB
1769 pstrcpy(term_cmd_buf, sizeof(term_cmd_buf),
1770 term_history[term_hist_entry]);
aa455485
FB
1771 term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf);
1772 }
1773}
1774
1775static void term_down_char(void)
1776{
1777 if (term_hist_entry == TERM_MAX_CMDS - 1 || term_hist_entry == -1)
1778 return;
1779 if (term_history[++term_hist_entry] != NULL) {
95ce326e
FB
1780 pstrcpy(term_cmd_buf, sizeof(term_cmd_buf),
1781 term_history[term_hist_entry]);
aa455485
FB
1782 } else {
1783 term_hist_entry = -1;
1784 }
aa455485
FB
1785 term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf);
1786}
1787
1788static void term_hist_add(const char *cmdline)
1789{
1790 char *hist_entry, *new_entry;
1791 int idx;
1792
1793 if (cmdline[0] == '\0')
1794 return;
1795 new_entry = NULL;
1796 if (term_hist_entry != -1) {
1797 /* We were editing an existing history entry: replace it */
1798 hist_entry = term_history[term_hist_entry];
1799 idx = term_hist_entry;
1800 if (strcmp(hist_entry, cmdline) == 0) {
1801 goto same_entry;
1802 }
1803 }
1804 /* Search cmdline in history buffers */
1805 for (idx = 0; idx < TERM_MAX_CMDS; idx++) {
1806 hist_entry = term_history[idx];
1807 if (hist_entry == NULL)
1808 break;
1809 if (strcmp(hist_entry, cmdline) == 0) {
1810 same_entry:
1811 new_entry = hist_entry;
1812 /* Put this entry at the end of history */
1813 memmove(&term_history[idx], &term_history[idx + 1],
1814 &term_history[TERM_MAX_CMDS] - &term_history[idx + 1]);
1815 term_history[TERM_MAX_CMDS - 1] = NULL;
1816 for (; idx < TERM_MAX_CMDS; idx++) {
1817 if (term_history[idx] == NULL)
1818 break;
1819 }
1820 break;
1821 }
1822 }
1823 if (idx == TERM_MAX_CMDS) {
1824 /* Need to get one free slot */
1825 free(term_history[0]);
1826 memcpy(term_history, &term_history[1],
1827 &term_history[TERM_MAX_CMDS] - &term_history[1]);
1828 term_history[TERM_MAX_CMDS - 1] = NULL;
1829 idx = TERM_MAX_CMDS - 1;
1830 }
1831 if (new_entry == NULL)
1832 new_entry = strdup(cmdline);
1833 term_history[idx] = new_entry;
1834 term_hist_entry = -1;
1835}
1836
81d0912d
FB
1837/* completion support */
1838
1839static void add_completion(const char *str)
1840{
1841 if (nb_completions < NB_COMPLETIONS_MAX) {
1842 completions[nb_completions++] = qemu_strdup(str);
1843 }
1844}
1845
1846static void term_completion(void)
1847{
1848 int len, i, j, max_width, nb_cols;
1849 char *cmdline;
1850
1851 nb_completions = 0;
1852
1853 cmdline = qemu_malloc(term_cmd_buf_index + 1);
1854 if (!cmdline)
1855 return;
1856 memcpy(cmdline, term_cmd_buf, term_cmd_buf_index);
1857 cmdline[term_cmd_buf_index] = '\0';
1858 find_completion(cmdline);
1859 qemu_free(cmdline);
1860
1861 /* no completion found */
1862 if (nb_completions <= 0)
1863 return;
1864 if (nb_completions == 1) {
1865 len = strlen(completions[0]);
1866 for(i = completion_index; i < len; i++) {
1867 term_insert_char(completions[0][i]);
1868 }
1869 /* extra space for next argument. XXX: make it more generic */
1870 if (len > 0 && completions[0][len - 1] != '/')
1871 term_insert_char(' ');
1872 } else {
1873 term_printf("\n");
1874 max_width = 0;
1875 for(i = 0; i < nb_completions; i++) {
1876 len = strlen(completions[i]);
1877 if (len > max_width)
1878 max_width = len;
1879 }
1880 max_width += 2;
1881 if (max_width < 10)
1882 max_width = 10;
1883 else if (max_width > 80)
1884 max_width = 80;
1885 nb_cols = 80 / max_width;
1886 j = 0;
1887 for(i = 0; i < nb_completions; i++) {
1888 term_printf("%-*s", max_width, completions[i]);
1889 if (++j == nb_cols || i == (nb_completions - 1)) {
1890 term_printf("\n");
1891 j = 0;
1892 }
1893 }
1894 term_show_prompt2();
1895 }
1896}
1897
9dc39cba
FB
1898/* return true if command handled */
1899static void term_handle_byte(int ch)
1900{
1901 switch(term_esc_state) {
1902 case IS_NORM:
1903 switch(ch) {
1904 case 1:
1905 term_bol();
1906 break;
81d0912d
FB
1907 case 4:
1908 term_delete_char();
1909 break;
9dc39cba
FB
1910 case 5:
1911 term_eol();
1912 break;
81d0912d
FB
1913 case 9:
1914 term_completion();
1915 break;
9dc39cba
FB
1916 case 10:
1917 case 13:
1918 term_cmd_buf[term_cmd_buf_size] = '\0';
aa455485 1919 term_hist_add(term_cmd_buf);
9dc39cba
FB
1920 term_printf("\n");
1921 term_handle_command(term_cmd_buf);
1922 term_show_prompt();
1923 break;
1924 case 27:
1925 term_esc_state = IS_ESC;
1926 break;
1927 case 127:
1928 case 8:
1929 term_backspace();
1930 break;
aa455485
FB
1931 case 155:
1932 term_esc_state = IS_CSI;
1933 break;
9dc39cba
FB
1934 default:
1935 if (ch >= 32) {
1936 term_insert_char(ch);
1937 }
1938 break;
1939 }
1940 break;
1941 case IS_ESC:
1942 if (ch == '[') {
1943 term_esc_state = IS_CSI;
1944 term_esc_param = 0;
1945 } else {
1946 term_esc_state = IS_NORM;
1947 }
1948 break;
1949 case IS_CSI:
1950 switch(ch) {
aa455485
FB
1951 case 'A':
1952 case 'F':
1953 term_up_char();
1954 break;
1955 case 'B':
1956 case 'E':
1957 term_down_char();
1958 break;
9dc39cba
FB
1959 case 'D':
1960 term_backward_char();
1961 break;
1962 case 'C':
1963 term_forward_char();
1964 break;
1965 case '0' ... '9':
1966 term_esc_param = term_esc_param * 10 + (ch - '0');
1967 goto the_end;
1968 case '~':
1969 switch(term_esc_param) {
1970 case 1:
1971 term_bol();
1972 break;
1973 case 3:
1974 term_delete_char();
1975 break;
1976 case 4:
1977 term_eol();
1978 break;
1979 }
1980 break;
1981 default:
1982 break;
1983 }
1984 term_esc_state = IS_NORM;
1985 the_end:
1986 break;
1987 }
81d0912d 1988 term_update();
9dc39cba
FB
1989}
1990
1991static int term_can_read(void *opaque)
1992{
81d0912d 1993 return 128;
9dc39cba
FB
1994}
1995
1996static void term_read(void *opaque, const uint8_t *buf, int size)
1997{
1998 int i;
1999 for(i = 0; i < size; i++)
81d0912d 2000 term_handle_byte(buf[i]);
9dc39cba
FB
2001}
2002
81d0912d 2003void monitor_init(CharDriverState *hd, int show_banner)
9dc39cba 2004{
81d0912d
FB
2005 monitor_hd = hd;
2006 if (show_banner) {
9dc39cba
FB
2007 term_printf("QEMU %s monitor - type 'help' for more information\n",
2008 QEMU_VERSION);
2009 term_show_prompt();
2010 }
aa455485 2011 term_hist_entry = -1;
81d0912d 2012 qemu_chr_add_read_handler(hd, term_can_read, term_read, NULL);
9dc39cba 2013}