diff options
Diffstat (limited to 'test/main.c')
| -rw-r--r-- | test/main.c | 183 |
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; +} |
