Просмотр исходного кода

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>
Huang Qi 5 лет назад
Родитель
Сommit
7f4e519edc
1 измененных файлов с 85 добавлено и 1 удалено
  1. 85 1
      product-mini/platforms/nuttx/main.c

+ 85 - 1
product-mini/platforms/nuttx/main.c

@@ -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);