product-mini/nuttx: Add support for repl mode (#466)

Signed-off-by: Huang Qi <huangqi3@xiaomi.com>

Co-authored-by: Huang Qi <huangqi3@xiaomi.com>
This commit is contained in:
Huang Qi 2020-12-09 16:45:41 +08:00 committed by GitHub
parent 35acc7f336
commit 7f4e519edc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -7,6 +7,7 @@
#define _GNU_SOURCE
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "bh_platform.h"
@ -26,6 +27,8 @@ print_help()
printf("options:\n");
printf(" -f|--function name Specify a function name of the module to run rather\n"
" than main\n");
printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n"
" that runs commands in the form of `FUNC ARG...`\n");
#if WASM_ENABLE_LOG != 0
printf(" -v=n Set log verbose level (0 to 5, default is 2) larger\n"
" level with more log\n");
@ -72,6 +75,81 @@ app_instance_func(wasm_module_inst_t module_inst, const char *func_name)
return NULL;
}
/**
* Split a space separated strings into an array of strings
* Returns NULL on failure
* Memory must be freed by caller
* Based on: http://stackoverflow.com/a/11198630/471795
*/
static char **
split_string(char *str, int *count)
{
char **res = NULL;
char *p;
int idx = 0;
/* split string and append tokens to 'res' */
do {
p = strtok(str, " ");
str = NULL;
res = (char **)realloc(res, sizeof(char *) * (uint32)(idx + 1));
if (res == NULL) {
return NULL;
}
res[idx++] = p;
} while (p);
/**
* since the function name,
* res[0] might be contains a '\' to indicate a space
* func\name -> func name
*/
p = strchr(res[0], '\\');
while (p) {
*p = ' ';
p = strchr(p, '\\');
}
if (count) {
*count = idx - 1;
}
return res;
}
static void *
app_instance_repl(wasm_module_inst_t module_inst)
{
char *cmd = NULL;
size_t len = 0;
ssize_t n;
while ((printf("webassembly> "), n = getline(&cmd, &len, stdin)) != -1) {
bh_assert(n > 0);
if (cmd[n - 1] == '\n') {
if (n == 1)
continue;
else
cmd[n - 1] = '\0';
}
if (!strcmp(cmd, "__exit__")) {
printf("exit repl mode\n");
break;
}
app_argv = split_string(cmd, &app_argc);
if (app_argv == NULL) {
LOG_ERROR("Wasm prepare param failed: split string failed.\n");
break;
}
if (app_argc != 0) {
wasm_application_execute_func(module_inst, app_argv[0],
app_argc - 1, app_argv + 1);
}
free(app_argv);
}
free(cmd);
return NULL;
}
#if WASM_ENABLE_LIBC_WASI != 0
static bool
validate_env_str(char *env)
@ -152,6 +230,7 @@ main(int argc, char *argv[])
#if WASM_ENABLE_LOG != 0
int log_verbose_level = 2;
#endif
bool is_repl_mode = false;
#if WASM_ENABLE_LIBC_WASI != 0
const char *dir_list[8] = { NULL };
uint32 dir_list_size = 0;
@ -176,6 +255,9 @@ main(int argc, char *argv[])
return print_help();
}
#endif
else if (!strcmp(argv[0], "--repl")) {
is_repl_mode = true;
}
else if (!strncmp(argv[0], "--stack-size=", 13)) {
if (argv[0][13] == '\0')
return print_help();
@ -296,7 +378,9 @@ main(int argc, char *argv[])
goto fail3;
}
if (func_name)
if (is_repl_mode)
app_instance_repl(wasm_module_inst);
else if (func_name)
app_instance_func(wasm_module_inst, func_name);
else
app_instance_main(wasm_module_inst);