diff --git a/webpage/build.sh b/webpage/build.sh new file mode 100755 index 0000000..b539682 --- /dev/null +++ b/webpage/build.sh @@ -0,0 +1,18 @@ +#!/bin/sh +set -e +PACKAGE=$(sed -n 's/^PACKAGE\s*=\s*//p' ../Makefile) +VERSION=$(sed -n 's/^VERSION\s*=\s*//p' ../Makefile) +( + cd .. + make dist-gzip +) +cd playground +tar xzf ../../"$PACKAGE-$VERSION".tar.gz +rm -rf dist +mv "$PACKAGE-$VERSION" dist +cd dist +emconfigure ./configure CFLAGS="-O2" LDFLAGS="-sASYNCIFY" +cd src +emmake make -j"$(nproc)" libapfl.a +cd ../.. +emcc -sASYNCIFY -O3 -oplayground.js playground.c dist/src/libapfl.a diff --git a/webpage/playground/.gitignore b/webpage/playground/.gitignore new file mode 100644 index 0000000..e603fde --- /dev/null +++ b/webpage/playground/.gitignore @@ -0,0 +1,3 @@ +dist/ +playground.wasm +playground.js diff --git a/webpage/playground/index.html b/webpage/playground/index.html new file mode 100644 index 0000000..c3b9df3 --- /dev/null +++ b/webpage/playground/index.html @@ -0,0 +1,143 @@ + + + + + apfl Playground + + + + + +
+

+        
+ > + +
+ + + diff --git a/webpage/playground/playground.c b/webpage/playground/playground.c new file mode 100644 index 0000000..049bb1f --- /dev/null +++ b/webpage/playground/playground.c @@ -0,0 +1,117 @@ +#include + +#include +#include +#include +#include + +#include "dist/src/apfl.h" +#include "dist/src/format.h" + +struct playground_source_reader_data { + char *str; + size_t len; + size_t off; + bool eof; +}; + +EM_ASYNC_JS(char *, get_input, (int need), { + var s = await window.playground_get_input(!!need); + var lengthBytes = lengthBytesUTF8(s)+1; + var stringOnWasmHeap = _malloc(lengthBytes); + stringToUTF8(s, stringOnWasmHeap, lengthBytes); + return stringOnWasmHeap; +}); + +EM_JS(void, web_writer, (int error, const char* str, int size), { + window.playground_write(!!error, UTF8ToString(str, size)); +}); + +static bool +web_fmt_write(void *opaque, const char *buf, size_t len) +{ + int error = (int)opaque; + web_writer(error, buf, (int)len); + return true; +} + +static bool +playground_source_reader_cb(void *context, char *buf, size_t *len, bool need) +{ + struct playground_source_reader_data *r = context; + + size_t remain = r->len - r->off; + if (remain == 0) { + free(r->str); + r->str = get_input(need ? 1 : 0); + assert(r->str != NULL); + + r->len = strlen(r->str); + r->off = 0; + } + + remain = r->len - r->off; + assert(remain > 0); + + if (remain < *len) { + *len = remain; + } + memcpy(buf, r->str+r->off, *len); + r->off += *len; + + return true; +} + +int +main(void) +{ + int rv = 0; + + struct apfl_format_writer w_ok = {.write = web_fmt_write, .opaque = (void *)0}; + struct apfl_format_writer w_err = {.write = web_fmt_write, .opaque = (void *)1}; + + apfl_ctx ctx = apfl_ctx_new(apfl_allocator_default()); + if (ctx == NULL) { + assert(apfl_format_put_string(w_err, "Failed to init the context\n")); + return 1; + } + + struct playground_source_reader_data source_reader_data = { + .str = NULL, + .len = 0, + .off = 0, + .eof = false, + }; + + apfl_iterative_runner runner = apfl_iterative_runner_new(ctx, (struct apfl_source_reader) { + .callback = playground_source_reader_cb, + .opaque = &source_reader_data, + }); + if (runner == NULL) { + apfl_ctx_destroy(ctx); + assert(apfl_format_put_string(w_err, "Failed to init runner\n")); + return 1; + } + + while (apfl_iterative_runner_next(runner)) { + switch (apfl_iterative_runner_get_result(runner)) { + case APFL_RESULT_OK : + assert(apfl_debug_print_val(ctx, -1, w_ok)); + break; + case APFL_RESULT_ERR: + assert(apfl_debug_print_val(ctx, -1, w_err)); + assert(apfl_format_put_string(w_err, "Error occurred during evaluation.\n")); + break; + case APFL_RESULT_ERR_FATAL: + assert(apfl_format_put_string(w_err, "Fatal error occurred during evaluation.\n")); + rv = 1; + goto exit; + } + } + +exit: + free(source_reader_data.str); + apfl_iterative_runner_destroy(runner); + apfl_ctx_destroy(ctx); + return rv; +}