Implement --repl switch

extensions
Volodymyr Shymanskyy 5 years ago
parent 645cfb86d7
commit 34f73792cb

@ -4,89 +4,222 @@
#include "m3.h"
#include "m3_api_wasi.h"
#include "m3_api_libc.h"
#include "m3_env.h"
#define FATAL(msg, ...) { printf("Error: [Fatal] " msg "\n", ##__VA_ARGS__); goto _onfatal; }
int main (int i_argc, const char * i_argv [])
M3Result repl_load (IM3Runtime env, const char* fn)
{
// m3_PrintM3Info ();
M3Result result = c_m3Err_none;
IM3Runtime env = NULL;
if (i_argc < 3) FATAL("not enough arguments");
u8* wasm = NULL;
u32 fsize = 0;
//printf("Loading WebAssembly...\n");
FILE* f = fopen (i_argv[1], "rb");
if (f)
{
fseek (f, 0, SEEK_END);
fsize = ftell(f);
fseek (f, 0, SEEK_SET);
if (fsize > 1000000) FATAL("file is too big");
FILE* f = fopen (fn, "rb");
if (!f) {
return "cannot open file";
}
fseek (f, 0, SEEK_END);
fsize = ftell(f);
fseek (f, 0, SEEK_SET);
wasm = (u8*) malloc(fsize);
fread (wasm, 1, fsize, f);
fclose (f);
} else {
FATAL("cannot open file");
if (fsize > 10*1024*1024) {
return "file too big";
}
IM3Module module;
result = m3_ParseModule (& module, wasm, fsize);
if (result) FATAL("m3_ParseModule: %s", result);
wasm = (u8*) malloc(fsize);
fread (wasm, 1, fsize, f);
fclose (f);
// TODO: Detect stack exhaustion
env = m3_NewRuntime (8*1024);
if (!env) FATAL("m3_NewRuntime");
IM3Module module;
result = m3_ParseModule (&module, wasm, fsize);
if (result) return result;
result = m3_LoadModule (env, module);
if (result) FATAL("m3_LoadModule: %s", result);
if (result) return result;
return result;
}
M3Result repl_call (IM3Runtime env, const char* name, int argc, const char* argv[])
{
// TODO
if (argc) {
if (!strcmp(name, "main") || !strcmp(name, "_main")) {
return "passing arguments to libc main() not implemented";
} else if (!strcmp(name, "_start")) {
return "passing arguments to wasi _start() not implemented";
}
}
result = m3_LinkWASI (module);
if (result) FATAL("m3_LinkWASI: %s", result);
M3Result result = c_m3Err_none;
IM3Function func;
result = m3_FindFunction (& func, env, "__post_instantiate");
result = m3_FindFunction (&func, env, name);
if (result) return result;
if (not result)
{
result = m3_Call (func);
if (result) FATAL("__post_instantiate failed: %s", result);
result = m3_CallWithArgs (func, argc, argv);
if (result) return result;
return result;
}
void repl_free(IM3Runtime* env) {
if (*env) {
m3_FreeRuntime (*env);
}
else m3_IgnoreErrorInfo (env);
}
const char* fname = i_argv[2];
M3Result repl_init(IM3Runtime* env) {
repl_free(env);
*env = m3_NewRuntime (8*1024);
if (*env == NULL) {
return "m3_NewRuntime failed";
}
return c_m3Err_none;
}
result = m3_FindFunction (& func, env, fname);
if (result) FATAL("m3_FindFunction: %s", result);
int split_argv(char *str, const char** argv)
{
int result = 0;
char* curr = str;
int len = 0;
for (int i = 0; str[i] != '\0'; i++) {
if (strchr(" \n\r\t", str[i])) {
if (len) { // Found space after non-space
str[i] = '\0';
argv[result++] = curr;
len = 0;
}
} else {
if (!len) { // Found non-space after space
curr = &str[i];
}
len++;
}
}
argv[result] = NULL;
return result;
}
//printf("Running...\n");
void print_version() {
printf("wasm3 v0.4.0\n");
}
if (!strcmp(fname, "_main") || !strcmp(fname, "main")) {
i_argc -= 2;
i_argv += 2;
result = m3_CallMain (func, i_argc, i_argv);
if (result) FATAL("m3_CallMain: %s", result);
void print_usage() {
printf("Usage:\n");
printf(" wasm3 <file> [args...]\n");
printf(" wasm3 --func <function> <file> [args...]\n");
printf("Repl usage:\n");
printf(" wasm3 --repl [file] [function] [args...]\n");
printf(" wasm3 --repl --func <function> <file> [args...]\n");
}
#define ARGV_SHIFT() { i_argc--; i_argv++; }
#define ARGV_SET(x) { if (i_argc > 0) { x = i_argv[0]; ARGV_SHIFT(); } }
int main (int i_argc, const char* i_argv[])
{
M3Result result = c_m3Err_none;
IM3Runtime env = NULL;
bool argRepl = false;
const char* argFile = NULL;
const char* argFunc = NULL;
// m3_PrintM3Info ();
m3stack_t stack = (m3stack_t)(env->stack);
return stack[0];
ARGV_SHIFT(); // Skip executable name
while (i_argc > 0)
{
const char* arg = i_argv[0];
if (arg[0] != '-') break;
ARGV_SHIFT();
if (!strcmp("--help", arg) or !strcmp("-h", arg)) {
print_usage();
return 0;
} else if (!strcmp("--version", arg)) {
print_version();
return 0;
} else if (!strcmp("--repl", arg)) {
argRepl = true;
} else if (!strcmp("--func", arg) or !strcmp("-f", arg)) {
ARGV_SET(argFunc);
}
}
if (argRepl) {
ARGV_SET(argFile);
if (!argFunc) ARGV_SET(argFunc);
} else {
i_argc -= 3;
i_argv += 3;
result = m3_CallWithArgs (func, i_argc, i_argv);
if (i_argc < 1) {
print_usage();
return 1;
}
ARGV_SET(argFile);
if (!argFunc) argFunc = "_start";
}
m3_FreeRuntime (env);
//printf("=== argFile: %s, argFunc: %s, args: %d\n", argFile, argFunc, i_argc);
result = repl_init(&env);
if (result) FATAL("repl_init: %s", result);
free (wasm);
if (argFile) {
result = repl_load(env, argFile);
if (result) FATAL("repl_load: %s", result);
result = m3_LinkWASI (env->modules);
if (result) FATAL("m3_LinkWASI: %s", result);
result = m3_LinkLibC (env->modules);
if (result) FATAL("m3_LinkLibC: %s", result);
if (argFunc) {
result = repl_call(env, argFunc, i_argc, i_argv);
if (result) FATAL("repl_call: %s", result);
}
}
while (argRepl)
{
char cmd_buff[128] = {};
const char* argv[32] = {};
fprintf(stdout, "> ");
fflush(stdout);
if (!fgets(cmd_buff, sizeof(cmd_buff), stdin)) {
return 0;
}
int argc = split_argv(cmd_buff, argv);
if (argc <= 0) {
continue;
}
M3Result result = c_m3Err_none;
if (!strcmp("init", argv[0])) {
result = repl_init(&env);
} else if (!strcmp("exit", argv[0])) {
repl_free(&env);
return 0;
} else if (!strcmp("load", argv[0])) {
result = repl_load(env, argv[1]);
} else if (!strcmp("call", argv[0])) {
result = repl_call(env, argv[1], argc-2, argv+2);
} else {
result = "no such command";
}
if (result) {
printf ("Error: %s", result);
M3ErrorInfo info = m3_GetErrorInfo (env);
if (strlen(info.message)) {
printf (" (%s)\n", info.message);
} else {
printf ("\n");
}
}
}
_onfatal:
if (result) {

Loading…
Cancel
Save