aboutsummaryrefslogtreecommitdiff
path: root/test/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/main.c')
-rw-r--r--test/main.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/test/main.c b/test/main.c
new file mode 100644
index 0000000..3c4e663
--- /dev/null
+++ b/test/main.c
@@ -0,0 +1,183 @@
+/*
+ * nanowasm, a tiny WebAssembly/Wasm interpreter
+ * Copyright (C) 2023-2024 Xavier Del Campo Romero
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+#include <nanowasm/nw.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int io_read(void *const buf, const size_t n, void *const user)
+{
+ FILE *const f = user;
+ const size_t r = fread(buf, 1, 1, f);
+
+ if (!r && ferror(f))
+ {
+ fprintf(stderr, "%s: ferror\n", __func__);
+ return -1;
+ }
+
+ return r;
+}
+
+static enum nw_state io_seek(const long offset, const enum nw_whence whence,
+ void *const user)
+{
+ static const int trans[] =
+ {
+ [NW_SEEK_END] = SEEK_END,
+ [NW_SEEK_CUR] = SEEK_CUR,
+ [NW_SEEK_SET] = SEEK_SET
+ };
+
+ if (fseek(user, offset, trans[whence]))
+ {
+ fprintf(stderr, "%s: fseek(3): %s\n", __func__, strerror(errno));
+ return NW_FATAL;
+ }
+
+ return NW_OK;
+}
+
+static enum nw_state io_tell(long *const out, void *const user)
+{
+ const long offset = ftell(user);
+
+ if (offset < 0)
+ {
+ fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno));
+ return NW_FATAL;
+ }
+
+ *out = offset;
+ return NW_OK;
+}
+
+static int io_eof(void *const user)
+{
+ FILE *const f = user;
+
+ return feof(f);
+}
+
+int main(int argc, char *argv[])
+{
+ int ret = EXIT_FAILURE;
+ FILE *f = NULL;
+
+ if (argc != 2)
+ {
+ fprintf(stderr, "%s <wasm>\n", *argv);
+ goto end;
+ }
+
+ const char *const path = argv[1];
+
+ if (!(f = fopen(path, "rb")))
+ {
+ fprintf(stderr, "%s: fopen(3) %s: %s\n", __func__, path,
+ strerror(errno));
+ goto end;
+ }
+
+ static const struct nw_import imports[] =
+ {
+ {
+ .kind = NW_KIND_FUNCTION,
+ .module = "wasi_snapshot_preview1",
+ .field = "proc_exit"
+ }
+ };
+
+ const struct nw_io_cfg io =
+ {
+ .read = io_read,
+ .seek = io_seek,
+ .tell = io_tell,
+ .eof = io_eof,
+ .user = f
+ };
+
+ const struct nw_mod_cfg cfg =
+ {
+ .imports = imports,
+ .n_imports = sizeof imports / sizeof *imports,
+ .io = io
+ };
+
+ struct nw_mod m;
+
+ nw_init(&m, &cfg);
+
+again:
+
+ switch (nw_load(&m))
+ {
+ case NW_OK:
+ break;
+
+ case NW_AGAIN:
+ goto again;
+
+ case NW_FATAL:
+ fprintf(stderr, "%s: nw_load failed\n", __func__);
+ goto end;
+ }
+
+ const struct nw_inst_cfg icfg =
+ {
+ .interp_cfg =
+ {
+ .global = NW_BUF(1),
+ .heap = NW_BUF(1),
+ .stack = NW_BUF(128),
+ .io = io,
+ .m = &m
+ }
+ };
+
+ struct nw_inst inst;
+
+ if (nw_start(&icfg, &inst))
+ {
+ fprintf(stderr, "%s: nw_start failed\n", __func__);
+ goto end;
+ }
+
+again2:
+
+ switch (nw_run(&inst))
+ {
+ case NW_OK:
+ break;
+
+ case NW_AGAIN:
+ goto again2;
+
+ case NW_FATAL:
+ fprintf(stderr, "%s: nw_run failed: %s\n", __func__,
+ nw_exception(&inst));
+ goto end;
+ }
+
+ ret = EXIT_SUCCESS;
+
+end:
+
+ if (f && fclose(f))
+ {
+ fprintf(stderr, "%s: fclose(3) %s: %s\n", __func__, path,
+ strerror(errno));
+ goto end;
+ }
+
+ return ret;
+}