From 7f4e519edc089d9bfc2797c92afd52e688acb14d Mon Sep 17 00:00:00 2001 From: Huang Qi <757509347@qq.com> Date: Wed, 9 Dec 2020 16:45:41 +0800 Subject: [PATCH] product-mini/nuttx: Add support for repl mode (#466) Signed-off-by: Huang Qi Co-authored-by: Huang Qi --- product-mini/platforms/nuttx/main.c | 86 ++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) diff --git a/product-mini/platforms/nuttx/main.c b/product-mini/platforms/nuttx/main.c index 520d8dd21..2467cf8ed 100644 --- a/product-mini/platforms/nuttx/main.c +++ b/product-mini/platforms/nuttx/main.c @@ -7,6 +7,7 @@ #define _GNU_SOURCE #endif #include +#include #include #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);