Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
qemu
提交
81d0912d
Q
qemu
项目概览
openeuler
/
qemu
通知
10
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Q
qemu
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
81d0912d
编写于
7月 14, 2004
作者:
B
bellard
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
completion support
git-svn-id:
svn://svn.savannah.nongnu.org/qemu/trunk@1020
c046a42c-6fe2-441c-8c8c-71466251a162
上级
d1d9f421
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
348 addition
and
113 deletion
+348
-113
block.c
block.c
+9
-0
monitor.c
monitor.c
+339
-113
未找到文件。
block.c
浏览文件 @
81d0912d
...
...
@@ -470,6 +470,15 @@ BlockDriverState *bdrv_find(const char *name)
return
NULL
;
}
void
bdrv_iterate
(
void
(
*
it
)(
void
*
opaque
,
const
char
*
name
),
void
*
opaque
)
{
BlockDriverState
*
bs
;
for
(
bs
=
bdrv_first
;
bs
!=
NULL
;
bs
=
bs
->
next
)
{
it
(
opaque
,
bs
->
device_name
);
}
}
void
bdrv_info
(
void
)
{
BlockDriverState
*
bs
;
...
...
monitor.c
浏览文件 @
81d0912d
...
...
@@ -23,8 +23,10 @@
*/
#include "vl.h"
#include "disas.h"
#include <dirent.h>
//#define DEBUG
//#define DEBUG_COMPLETION
#ifndef offsetof
#define offsetof(type, field) ((size_t) &((type *)0)->field)
...
...
@@ -32,6 +34,7 @@
#define TERM_CMD_BUF_SIZE 4095
#define TERM_MAX_CMDS 64
#define NB_COMPLETIONS_MAX 256
#define IS_NORM 0
#define IS_ESC 1
...
...
@@ -42,16 +45,28 @@
static
char
term_cmd_buf
[
TERM_CMD_BUF_SIZE
+
1
];
static
int
term_cmd_buf_index
;
static
int
term_cmd_buf_size
;
static
char
term_last_cmd_buf
[
TERM_CMD_BUF_SIZE
+
1
];
static
int
term_last_cmd_buf_index
;
static
int
term_last_cmd_buf_size
;
static
int
term_esc_state
;
static
int
term_esc_param
;
static
char
*
term_history
[
TERM_MAX_CMDS
];
static
int
term_hist_entry
;
static
CharDriverState
*
monitor_hd
;
static
int
nb_completions
;
static
int
completion_index
;
static
char
*
completions
[
NB_COMPLETIONS_MAX
];
/*
* Supported types:
*
* 'F' filename
* 'B' block device name
* 's' string (accept optional quote)
* 'i' integer
* '/' optional gdb-like print format (like "/10x")
...
...
@@ -71,17 +86,20 @@ typedef struct term_cmd_t {
static
term_cmd_t
term_cmds
[];
static
term_cmd_t
info_cmds
[];
static
void
add_completion
(
const
char
*
str
);
void
term_printf
(
const
char
*
fmt
,
...)
{
char
buf
[
4096
];
va_list
ap
;
va_start
(
ap
,
fmt
);
vprintf
(
fmt
,
ap
);
vsnprintf
(
buf
,
sizeof
(
buf
),
fmt
,
ap
);
qemu_chr_write
(
monitor_hd
,
buf
,
strlen
(
buf
));
va_end
(
ap
);
}
void
term_flush
(
void
)
{
fflush
(
stdout
);
}
static
int
compare_cmd
(
const
char
*
name
,
const
char
*
list
)
...
...
@@ -232,8 +250,6 @@ static void do_eject(int force, const char *filename)
{
BlockDriverState
*
bs
;
term_printf
(
"%d %s
\n
"
,
force
,
filename
);
bs
=
bdrv_find
(
filename
);
if
(
!
bs
)
{
term_printf
(
"device not found
\n
"
);
...
...
@@ -674,9 +690,9 @@ static term_cmd_t term_cmds[] = {
"subcommand"
,
"show various information about the system state"
},
{
"q|quit"
,
""
,
do_quit
,
""
,
"quit the emulator"
},
{
"eject"
,
"-f
s
"
,
do_eject
,
{
"eject"
,
"-f
B
"
,
do_eject
,
"[-f] device"
,
"eject a removable media (use -f to force it)"
},
{
"change"
,
"
s
F"
,
do_change
,
{
"change"
,
"
B
F"
,
do_change
,
"device filename"
,
"change a removable media"
},
{
"screendump"
,
"F"
,
do_screen_dump
,
"filename"
,
"save screen into PPM image 'filename'"
},
...
...
@@ -953,6 +969,16 @@ static int expr_unary(void)
}
next
();
break
;
case
'\''
:
pch
++
;
if
(
*
pch
==
'\0'
)
expr_error
(
"character constant expected"
);
n
=
*
pch
;
pch
++
;
if
(
*
pch
!=
'\''
)
expr_error
(
"missing terminating
\'
character"
);
next
();
break
;
case
'$'
:
{
char
buf
[
128
],
*
q
;
...
...
@@ -1088,15 +1114,16 @@ static int get_str(char *buf, int buf_size, const char **pp)
char
*
q
;
int
c
;
q
=
buf
;
p
=
*
pp
;
while
(
isspace
(
*
p
))
p
++
;
if
(
*
p
==
'\0'
)
{
fail:
*
q
=
'\0'
;
*
pp
=
p
;
return
-
1
;
}
q
=
buf
;
if
(
*
p
==
'\"'
)
{
p
++
;
while
(
*
p
!=
'\0'
&&
*
p
!=
'\"'
)
{
...
...
@@ -1140,8 +1167,8 @@ static int get_str(char *buf, int buf_size, const char **pp)
}
p
++
;
}
*
q
=
'\0'
;
}
*
q
=
'\0'
;
*
pp
=
p
;
return
0
;
}
...
...
@@ -1204,6 +1231,7 @@ static void term_handle_command(const char *cmdline)
typestr
++
;
switch
(
c
)
{
case
'F'
:
case
'B'
:
case
's'
:
{
int
ret
;
...
...
@@ -1221,10 +1249,17 @@ static void term_handle_command(const char *cmdline)
}
ret
=
get_str
(
buf
,
sizeof
(
buf
),
&
p
);
if
(
ret
<
0
)
{
if
(
c
==
'F'
)
switch
(
c
)
{
case
'F'
:
term_printf
(
"%s: filename expected
\n
"
,
cmdname
);
else
break
;
case
'B'
:
term_printf
(
"%s: block device name expected
\n
"
,
cmdname
);
break
;
default:
term_printf
(
"%s: string expected
\n
"
,
cmdname
);
break
;
}
goto
fail
;
}
str
=
qemu_malloc
(
strlen
(
buf
)
+
1
);
...
...
@@ -1432,19 +1467,232 @@ static void term_handle_command(const char *cmdline)
return
;
}
static
void
term_show_prompt
(
void
)
static
void
cmd_completion
(
const
char
*
name
,
const
char
*
list
)
{
const
char
*
p
,
*
pstart
;
char
cmd
[
128
];
int
len
;
p
=
list
;
for
(;;)
{
pstart
=
p
;
p
=
strchr
(
p
,
'|'
);
if
(
!
p
)
p
=
pstart
+
strlen
(
pstart
);
len
=
p
-
pstart
;
if
(
len
>
sizeof
(
cmd
)
-
2
)
len
=
sizeof
(
cmd
)
-
2
;
memcpy
(
cmd
,
pstart
,
len
);
cmd
[
len
]
=
'\0'
;
if
(
name
[
0
]
==
'\0'
||
!
strncmp
(
name
,
cmd
,
strlen
(
name
)))
{
add_completion
(
cmd
);
}
if
(
*
p
==
'\0'
)
break
;
p
++
;
}
}
static
void
file_completion
(
const
char
*
input
)
{
DIR
*
ffs
;
struct
dirent
*
d
;
char
path
[
1024
];
char
file
[
1024
],
file_prefix
[
1024
];
int
input_path_len
;
const
char
*
p
;
p
=
strrchr
(
input
,
'/'
);
if
(
!
p
)
{
input_path_len
=
0
;
pstrcpy
(
file_prefix
,
sizeof
(
file_prefix
),
input
);
strcpy
(
path
,
"."
);
}
else
{
input_path_len
=
p
-
input
+
1
;
memcpy
(
path
,
input
,
input_path_len
);
if
(
input_path_len
>
sizeof
(
path
)
-
1
)
input_path_len
=
sizeof
(
path
)
-
1
;
path
[
input_path_len
]
=
'\0'
;
pstrcpy
(
file_prefix
,
sizeof
(
file_prefix
),
p
+
1
);
}
#ifdef DEBUG_COMPLETION
term_printf
(
"input='%s' path='%s' prefix='%s'
\n
"
,
input
,
path
,
file_prefix
);
#endif
ffs
=
opendir
(
path
);
if
(
!
ffs
)
return
;
for
(;;)
{
struct
stat
sb
;
d
=
readdir
(
ffs
);
if
(
!
d
)
break
;
if
(
strstart
(
d
->
d_name
,
file_prefix
,
NULL
))
{
memcpy
(
file
,
input
,
input_path_len
);
strcpy
(
file
+
input_path_len
,
d
->
d_name
);
/* stat the file to find out if it's a directory.
* In that case add a slash to speed up typing long paths
*/
stat
(
file
,
&
sb
);
if
(
S_ISDIR
(
sb
.
st_mode
))
strcat
(
file
,
"/"
);
add_completion
(
file
);
}
}
closedir
(
ffs
);
}
static
void
block_completion_it
(
void
*
opaque
,
const
char
*
name
)
{
const
char
*
input
=
opaque
;
if
(
input
[
0
]
==
'\0'
||
!
strncmp
(
name
,
(
char
*
)
input
,
strlen
(
input
)))
{
add_completion
(
name
);
}
}
/* NOTE: this parser is an approximate form of the real command parser */
static
void
parse_cmdline
(
const
char
*
cmdline
,
int
*
pnb_args
,
char
**
args
)
{
const
char
*
p
;
int
nb_args
,
ret
;
char
buf
[
1024
];
p
=
cmdline
;
nb_args
=
0
;
for
(;;)
{
while
(
isspace
(
*
p
))
p
++
;
if
(
*
p
==
'\0'
)
break
;
if
(
nb_args
>=
MAX_ARGS
)
break
;
ret
=
get_str
(
buf
,
sizeof
(
buf
),
&
p
);
args
[
nb_args
]
=
qemu_strdup
(
buf
);
nb_args
++
;
if
(
ret
<
0
)
break
;
}
*
pnb_args
=
nb_args
;
}
static
void
find_completion
(
const
char
*
cmdline
)
{
const
char
*
cmdname
;
char
*
args
[
MAX_ARGS
];
int
nb_args
,
i
,
len
;
const
char
*
ptype
,
*
str
;
term_cmd_t
*
cmd
;
parse_cmdline
(
cmdline
,
&
nb_args
,
args
);
#ifdef DEBUG_COMPLETION
for
(
i
=
0
;
i
<
nb_args
;
i
++
)
{
term_printf
(
"arg%d = '%s'
\n
"
,
i
,
(
char
*
)
args
[
i
]);
}
#endif
/* if the line ends with a space, it means we want to complete the
next arg */
len
=
strlen
(
cmdline
);
if
(
len
>
0
&&
isspace
(
cmdline
[
len
-
1
]))
{
if
(
nb_args
>=
MAX_ARGS
)
return
;
args
[
nb_args
++
]
=
qemu_strdup
(
""
);
}
if
(
nb_args
<=
1
)
{
/* command completion */
if
(
nb_args
==
0
)
cmdname
=
""
;
else
cmdname
=
args
[
0
];
completion_index
=
strlen
(
cmdname
);
for
(
cmd
=
term_cmds
;
cmd
->
name
!=
NULL
;
cmd
++
)
{
cmd_completion
(
cmdname
,
cmd
->
name
);
}
}
else
{
/* find the command */
for
(
cmd
=
term_cmds
;
cmd
->
name
!=
NULL
;
cmd
++
)
{
if
(
compare_cmd
(
args
[
0
],
cmd
->
name
))
goto
found
;
}
return
;
found:
ptype
=
cmd
->
args_type
;
for
(
i
=
0
;
i
<
nb_args
-
2
;
i
++
)
{
if
(
*
ptype
!=
'\0'
)
{
ptype
++
;
while
(
*
ptype
==
'?'
)
ptype
++
;
}
}
str
=
args
[
nb_args
-
1
];
switch
(
*
ptype
)
{
case
'F'
:
/* file completion */
completion_index
=
strlen
(
str
);
file_completion
(
str
);
break
;
case
'B'
:
/* block device name completion */
completion_index
=
strlen
(
str
);
bdrv_iterate
(
block_completion_it
,
(
void
*
)
str
);
break
;
default:
break
;
}
}
for
(
i
=
0
;
i
<
nb_args
;
i
++
)
qemu_free
(
args
[
i
]);
}
static
void
term_show_prompt2
(
void
)
{
term_printf
(
"(qemu) "
);
fflush
(
stdout
);
term_last_cmd_buf_index
=
0
;
term_last_cmd_buf_size
=
0
;
term_esc_state
=
IS_NORM
;
}
static
void
term_show_prompt
(
void
)
{
term_show_prompt2
();
term_cmd_buf_index
=
0
;
term_cmd_buf_size
=
0
;
term_esc_state
=
IS_NORM
;
}
static
void
term_print_cmdline
(
const
char
*
cmdline
)
/* update the displayed command line */
static
void
term_update
(
void
)
{
term_show_prompt
();
term_printf
(
"%s"
,
cmdline
);
int
i
,
delta
;
if
(
term_cmd_buf_size
!=
term_last_cmd_buf_size
||
memcmp
(
term_cmd_buf
,
term_last_cmd_buf
,
term_cmd_buf_size
)
!=
0
)
{
for
(
i
=
0
;
i
<
term_last_cmd_buf_index
;
i
++
)
{
term_printf
(
"
\033
[D"
);
}
term_cmd_buf
[
term_cmd_buf_size
]
=
'\0'
;
term_printf
(
"%s"
,
term_cmd_buf
);
term_printf
(
"
\033
[K"
);
memcpy
(
term_last_cmd_buf
,
term_cmd_buf
,
term_cmd_buf_size
);
term_last_cmd_buf_size
=
term_cmd_buf_size
;
term_last_cmd_buf_index
=
term_cmd_buf_size
;
}
if
(
term_cmd_buf_index
!=
term_last_cmd_buf_index
)
{
delta
=
term_cmd_buf_index
-
term_last_cmd_buf_index
;
if
(
delta
>
0
)
{
for
(
i
=
0
;
i
<
delta
;
i
++
)
{
term_printf
(
"
\033
[C"
);
}
}
else
{
delta
=
-
delta
;
for
(
i
=
0
;
i
<
delta
;
i
++
)
{
term_printf
(
"
\033
[D"
);
}
}
term_last_cmd_buf_index
=
term_cmd_buf_index
;
}
term_flush
();
}
...
...
@@ -1456,9 +1704,7 @@ static void term_insert_char(int ch)
term_cmd_buf_size
-
term_cmd_buf_index
);
term_cmd_buf
[
term_cmd_buf_index
]
=
ch
;
term_cmd_buf_size
++
;
term_printf
(
"
\033
[@%c"
,
ch
);
term_cmd_buf_index
++
;
term_flush
();
}
}
...
...
@@ -1466,8 +1712,6 @@ static void term_backward_char(void)
{
if
(
term_cmd_buf_index
>
0
)
{
term_cmd_buf_index
--
;
term_printf
(
"
\033
[D"
);
term_flush
();
}
}
...
...
@@ -1475,8 +1719,6 @@ static void term_forward_char(void)
{
if
(
term_cmd_buf_index
<
term_cmd_buf_size
)
{
term_cmd_buf_index
++
;
term_printf
(
"
\033
[C"
);
term_flush
();
}
}
...
...
@@ -1486,9 +1728,7 @@ static void term_delete_char(void)
memmove
(
term_cmd_buf
+
term_cmd_buf_index
,
term_cmd_buf
+
term_cmd_buf_index
+
1
,
term_cmd_buf_size
-
term_cmd_buf_index
-
1
);
term_printf
(
"
\033
[P"
);
term_cmd_buf_size
--
;
term_flush
();
}
}
...
...
@@ -1502,14 +1742,12 @@ static void term_backspace(void)
static
void
term_bol
(
void
)
{
while
(
term_cmd_buf_index
>
0
)
term_backward_char
();
term_cmd_buf_index
=
0
;
}
static
void
term_eol
(
void
)
{
while
(
term_cmd_buf_index
<
term_cmd_buf_size
)
term_forward_char
();
term_cmd_buf_index
=
term_cmd_buf_size
;
}
static
void
term_up_char
(
void
)
...
...
@@ -1530,8 +1768,6 @@ static void term_up_char(void)
if
(
term_hist_entry
>=
0
)
{
pstrcpy
(
term_cmd_buf
,
sizeof
(
term_cmd_buf
),
term_history
[
term_hist_entry
]);
term_printf
(
"
\n
"
);
term_print_cmdline
(
term_cmd_buf
);
term_cmd_buf_index
=
term_cmd_buf_size
=
strlen
(
term_cmd_buf
);
}
}
...
...
@@ -1546,8 +1782,6 @@ static void term_down_char(void)
}
else
{
term_hist_entry
=
-
1
;
}
term_printf
(
"
\n
"
);
term_print_cmdline
(
term_cmd_buf
);
term_cmd_buf_index
=
term_cmd_buf_size
=
strlen
(
term_cmd_buf
);
}
...
...
@@ -1600,6 +1834,67 @@ static void term_hist_add(const char *cmdline)
term_hist_entry
=
-
1
;
}
/* completion support */
static
void
add_completion
(
const
char
*
str
)
{
if
(
nb_completions
<
NB_COMPLETIONS_MAX
)
{
completions
[
nb_completions
++
]
=
qemu_strdup
(
str
);
}
}
static
void
term_completion
(
void
)
{
int
len
,
i
,
j
,
max_width
,
nb_cols
;
char
*
cmdline
;
nb_completions
=
0
;
cmdline
=
qemu_malloc
(
term_cmd_buf_index
+
1
);
if
(
!
cmdline
)
return
;
memcpy
(
cmdline
,
term_cmd_buf
,
term_cmd_buf_index
);
cmdline
[
term_cmd_buf_index
]
=
'\0'
;
find_completion
(
cmdline
);
qemu_free
(
cmdline
);
/* no completion found */
if
(
nb_completions
<=
0
)
return
;
if
(
nb_completions
==
1
)
{
len
=
strlen
(
completions
[
0
]);
for
(
i
=
completion_index
;
i
<
len
;
i
++
)
{
term_insert_char
(
completions
[
0
][
i
]);
}
/* extra space for next argument. XXX: make it more generic */
if
(
len
>
0
&&
completions
[
0
][
len
-
1
]
!=
'/'
)
term_insert_char
(
' '
);
}
else
{
term_printf
(
"
\n
"
);
max_width
=
0
;
for
(
i
=
0
;
i
<
nb_completions
;
i
++
)
{
len
=
strlen
(
completions
[
i
]);
if
(
len
>
max_width
)
max_width
=
len
;
}
max_width
+=
2
;
if
(
max_width
<
10
)
max_width
=
10
;
else
if
(
max_width
>
80
)
max_width
=
80
;
nb_cols
=
80
/
max_width
;
j
=
0
;
for
(
i
=
0
;
i
<
nb_completions
;
i
++
)
{
term_printf
(
"%-*s"
,
max_width
,
completions
[
i
]);
if
(
++
j
==
nb_cols
||
i
==
(
nb_completions
-
1
))
{
term_printf
(
"
\n
"
);
j
=
0
;
}
}
term_show_prompt2
();
}
}
/* return true if command handled */
static
void
term_handle_byte
(
int
ch
)
{
...
...
@@ -1609,9 +1904,15 @@ static void term_handle_byte(int ch)
case
1
:
term_bol
();
break
;
case
4
:
term_delete_char
();
break
;
case
5
:
term_eol
();
break
;
case
9
:
term_completion
();
break
;
case
10
:
case
13
:
term_cmd_buf
[
term_cmd_buf_size
]
=
'\0'
;
...
...
@@ -1684,104 +1985,29 @@ static void term_handle_byte(int ch)
the_end:
break
;
}
}
/*************************************************************/
/* serial console support */
#define TERM_ESCAPE 0x01
/* ctrl-a is used for escape */
static
int
term_got_escape
,
term_command
;
void
term_print_help
(
void
)
{
term_printf
(
"
\n
"
"C-a h print this help
\n
"
"C-a x exit emulatior
\n
"
"C-a s save disk data back to file (if -snapshot)
\n
"
"C-a b send break (magic sysrq)
\n
"
"C-a c switch between console and monitor
\n
"
"C-a C-a send C-a
\n
"
);
}
/* called when a char is received */
static
void
term_received_byte
(
int
ch
)
{
if
(
!
serial_console
)
{
/* if no serial console, handle every command */
term_handle_byte
(
ch
);
}
else
{
if
(
term_got_escape
)
{
term_got_escape
=
0
;
switch
(
ch
)
{
case
'h'
:
term_print_help
();
break
;
case
'x'
:
exit
(
0
);
break
;
case
's'
:
{
int
i
;
for
(
i
=
0
;
i
<
MAX_DISKS
;
i
++
)
{
if
(
bs_table
[
i
])
bdrv_commit
(
bs_table
[
i
]);
}
}
break
;
case
'b'
:
if
(
serial_console
)
serial_receive_break
(
serial_console
);
break
;
case
'c'
:
if
(
!
term_command
)
{
term_show_prompt
();
term_command
=
1
;
}
else
{
term_command
=
0
;
}
break
;
case
TERM_ESCAPE
:
goto
send_char
;
}
}
else
if
(
ch
==
TERM_ESCAPE
)
{
term_got_escape
=
1
;
}
else
{
send_char:
if
(
term_command
)
{
term_handle_byte
(
ch
);
}
else
{
if
(
serial_console
)
serial_receive_byte
(
serial_console
,
ch
);
}
}
}
term_update
();
}
static
int
term_can_read
(
void
*
opaque
)
{
if
(
serial_console
)
{
return
serial_can_receive
(
serial_console
);
}
else
{
return
128
;
}
return
128
;
}
static
void
term_read
(
void
*
opaque
,
const
uint8_t
*
buf
,
int
size
)
{
int
i
;
for
(
i
=
0
;
i
<
size
;
i
++
)
term_
received
_byte
(
buf
[
i
]);
term_
handle
_byte
(
buf
[
i
]);
}
void
monitor_init
(
void
)
void
monitor_init
(
CharDriverState
*
hd
,
int
show_banner
)
{
if
(
!
serial_console
)
{
monitor_hd
=
hd
;
if
(
show_banner
)
{
term_printf
(
"QEMU %s monitor - type 'help' for more information
\n
"
,
QEMU_VERSION
);
term_show_prompt
();
}
term_hist_entry
=
-
1
;
qemu_
add_fd_read_handler
(
0
,
term_can_read
,
term_read
,
NULL
);
qemu_
chr_add_read_handler
(
hd
,
term_can_read
,
term_read
,
NULL
);
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录