131 lines
2.5 KiB
C
131 lines
2.5 KiB
C
#include "command.h"
|
|
#include "context.h"
|
|
#include "line-ed/line-ed.h"
|
|
|
|
#include <fx/collections/array.h>
|
|
#include <fx/string.h>
|
|
|
|
static struct line_ed *ed = NULL;
|
|
|
|
extern struct command cmd_quit;
|
|
extern struct command cmd_info;
|
|
extern struct command cmd_memory;
|
|
extern struct command cmd_breakpoint;
|
|
extern struct command cmd_attach;
|
|
extern struct command cmd_continue;
|
|
|
|
static const struct command *commands[] = {
|
|
&cmd_quit,
|
|
&cmd_info,
|
|
&cmd_memory,
|
|
&cmd_breakpoint,
|
|
&cmd_attach,
|
|
&cmd_continue,
|
|
};
|
|
static const size_t nr_commands = sizeof commands / sizeof commands[0];
|
|
|
|
static int tokenise_command(const char *s, int *out_argc, char ***out_argv)
|
|
{
|
|
fx_array *args = fx_array_create();
|
|
if (!args) {
|
|
return -1;
|
|
}
|
|
|
|
fx_string *str = fx_string_create_from_cstr(s);
|
|
if (!str) {
|
|
fx_array_unref(args);
|
|
return -1;
|
|
}
|
|
|
|
const char *delim = " ";
|
|
const fx_iterator *it
|
|
= fx_string_tokenise(str, &delim, 1, FX_STRING_TOK_F_NORMAL);
|
|
fx_foreach(tok, it)
|
|
{
|
|
const char *tok_cstr = NULL;
|
|
fx_value_get_cstr(tok, &tok_cstr);
|
|
fx_string *tok_str = fx_string_create_from_cstr(tok_cstr);
|
|
fx_array_push_back(args, FX_VALUE_OBJECT(tok_str));
|
|
fx_string_unref(tok_str);
|
|
}
|
|
|
|
fx_string_unref(str);
|
|
|
|
int argc = fx_array_get_size(args);
|
|
char **argv = calloc(argc, sizeof *argv);
|
|
if (!argv) {
|
|
fx_array_unref(args);
|
|
return -1;
|
|
}
|
|
|
|
for (int i = 0; i < argc; i++) {
|
|
const fx_value *arg_value = fx_array_get_ref(args, i);
|
|
const char *arg_cstr = NULL;
|
|
fx_value_get_cstr(arg_value, &arg_cstr);
|
|
|
|
char *arg_cstr_owned = fx_strdup(arg_cstr);
|
|
argv[i] = arg_cstr_owned;
|
|
}
|
|
fx_array_unref(args);
|
|
|
|
*out_argc = argc;
|
|
*out_argv = argv;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int repl(struct debug_context *ctx)
|
|
{
|
|
ed = line_ed_create();
|
|
if (!ed) {
|
|
return -1;
|
|
}
|
|
|
|
int ret = 0;
|
|
line_ed_set_flags(ed, LINE_ED_NO_TRAILING_LINEFEED);
|
|
|
|
fx_stringstream *line = fx_stringstream_create();
|
|
while (!ctx->ctx_quit && line_ed_readline(ed, line) != LINE_ED_EOF) {
|
|
const char *cmd_cstr = fx_stringstream_ptr(line);
|
|
int argc;
|
|
char **argv = NULL;
|
|
if (tokenise_command(cmd_cstr, &argc, &argv) != 0) {
|
|
ret = -1;
|
|
break;
|
|
}
|
|
|
|
if (argc == 0) {
|
|
goto skip;
|
|
}
|
|
|
|
const struct command *cmd
|
|
= command_find(commands, nr_commands, argv[0]);
|
|
if (cmd) {
|
|
command_execute(
|
|
cmd,
|
|
ctx,
|
|
argc - 1,
|
|
(const char **)argv + 1,
|
|
NULL);
|
|
}
|
|
|
|
skip:
|
|
fx_stringstream_reset(line);
|
|
}
|
|
|
|
fx_stringstream_unref(line);
|
|
line_ed_destroy(ed);
|
|
ed = NULL;
|
|
return ret;
|
|
}
|
|
|
|
int repl_suspend(void)
|
|
{
|
|
return line_ed_suspend(ed);
|
|
}
|
|
|
|
int repl_resume(void)
|
|
{
|
|
return line_ed_resume(ed);
|
|
}
|