2023-06-03 01:51:49 +00:00
|
|
|
//
|
|
|
|
// nostrscript.c
|
|
|
|
// damus
|
|
|
|
//
|
|
|
|
// Created by William Casarin on 2023-06-02.
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "nostrscript.h"
|
|
|
|
#include "wasm.h"
|
|
|
|
#include "array_size.h"
|
|
|
|
|
|
|
|
// function to check if the character is in surrogate pair range
|
|
|
|
static INLINE int is_surrogate(uint16_t uc) {
|
|
|
|
return (uc - 0xd800u) < 2048u;
|
|
|
|
}
|
|
|
|
|
|
|
|
// function to convert utf16 to utf8
|
|
|
|
static int utf16_to_utf8(u16 utf16, u8 *utf8) {
|
|
|
|
if (utf16 < 0x80) { // 1-byte sequence
|
|
|
|
utf8[0] = (uint8_t) utf16;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else if (utf16 < 0x800) { // 2-byte sequence
|
|
|
|
utf8[0] = (uint8_t) (0xc0 | (utf16 >> 6));
|
|
|
|
utf8[1] = (uint8_t) (0x80 | (utf16 & 0x3f));
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
else if (!is_surrogate(utf16)) { // 3-byte sequence
|
|
|
|
utf8[0] = (uint8_t) (0xe0 | (utf16 >> 12));
|
|
|
|
utf8[1] = (uint8_t) (0x80 | ((utf16 >> 6) & 0x3f));
|
|
|
|
utf8[2] = (uint8_t) (0x80 | (utf16 & 0x3f));
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
else { // surrogate pair, return error
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int nostr_cmd(struct wasm_interp *interp) {
|
|
|
|
struct val *params = NULL;
|
|
|
|
const char *val = NULL;
|
|
|
|
int len, cmd, ival;
|
|
|
|
|
|
|
|
if (!get_params(interp, ¶ms, 3) || params == NULL)
|
|
|
|
return interp_error(interp, "get params");
|
|
|
|
|
|
|
|
// command
|
|
|
|
cmd = params[0].num.i32;
|
|
|
|
|
|
|
|
// value
|
|
|
|
|
|
|
|
ival = params[1].num.i32;
|
|
|
|
if (!mem_ptr_str(interp, ival, &val))
|
|
|
|
val = 0;
|
|
|
|
|
|
|
|
// length
|
|
|
|
len = params[2].num.i32;
|
|
|
|
|
2023-07-10 18:05:22 +00:00
|
|
|
intptr_t iptr = ival;
|
|
|
|
return nscript_nostr_cmd(interp, cmd, val ? (void*)val : (void*)iptr, len);
|
2023-06-03 01:51:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int print_utf16_str(u16 *chars) {
|
|
|
|
u16 *p = chars;
|
|
|
|
int c;
|
|
|
|
|
|
|
|
while (*p) {
|
|
|
|
if (utf16_to_utf8(*p, (u8*)&c) == -1)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
printf("%c", c);
|
|
|
|
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int nostr_log(struct wasm_interp *interp) {
|
|
|
|
struct val *vals;
|
|
|
|
const char *str;
|
|
|
|
struct callframe *callframe;
|
|
|
|
|
|
|
|
if (!get_params(interp, &vals, 1))
|
|
|
|
return interp_error(interp, "nostr_log get params");
|
|
|
|
|
|
|
|
if (!mem_ptr_str(interp, vals[0].num.i32, &str))
|
|
|
|
return interp_error(interp, "nostr_log log param");
|
|
|
|
|
|
|
|
if (!(callframe = top_callframes(&interp->callframes, 2)))
|
|
|
|
return interp_error(interp, "nostr_log callframe");
|
|
|
|
|
|
|
|
printf("nostr_log:%s: ", callframe->func->name);
|
|
|
|
|
|
|
|
print_utf16_str((u16*)str);
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2023-07-03 23:59:50 +00:00
|
|
|
static int nostr_set_bool(struct wasm_interp *interp) {
|
|
|
|
struct val *params = NULL;
|
|
|
|
const u16 *setting;
|
|
|
|
u32 val, len;
|
|
|
|
|
|
|
|
if (!get_params(interp, ¶ms, 3) || params == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!mem_ptr_str(interp, params[0].num.i32, (const char**)&setting))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
len = params[1].num.i32;
|
|
|
|
val = params[2].num.i32 > 0 ? 1 : 0;
|
|
|
|
|
|
|
|
return nscript_set_bool(interp, setting, len, val);
|
|
|
|
}
|
|
|
|
|
2023-06-03 01:51:49 +00:00
|
|
|
static int nostr_pool_send_to(struct wasm_interp *interp) {
|
|
|
|
struct val *params = NULL;
|
|
|
|
const u16 *req, *to;
|
|
|
|
int req_len, to_len;
|
|
|
|
|
|
|
|
if (!get_params(interp, ¶ms, 4) || params == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!mem_ptr_str(interp, params[0].num.i32, (const char**)&req))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
req_len = params[1].num.i32;
|
|
|
|
|
|
|
|
if (!mem_ptr_str(interp, params[2].num.i32, (const char**)&to))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
to_len = params[3].num.i32;
|
|
|
|
|
|
|
|
return nscript_pool_send_to(interp, req, req_len, to, to_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int nscript_abort(struct wasm_interp *interp) {
|
|
|
|
struct val *params = NULL;
|
|
|
|
const char *msg = "", *filename;
|
|
|
|
int line, col;
|
|
|
|
|
|
|
|
if (!get_params(interp, ¶ms, 4) || params == NULL)
|
|
|
|
return interp_error(interp, "get params");
|
|
|
|
|
|
|
|
if (params[0].ref.addr != 0 && !mem_ptr_str(interp, params[0].ref.addr, &msg))
|
|
|
|
return interp_error(interp, "abort msg");
|
|
|
|
|
|
|
|
if (!mem_ptr_str(interp, params[1].ref.addr, &filename))
|
|
|
|
return interp_error(interp, "abort filename");
|
|
|
|
|
|
|
|
line = params[2].num.i32;
|
|
|
|
col = params[3].num.i32;
|
|
|
|
|
|
|
|
printf("nscript_abort:");
|
|
|
|
print_utf16_str((u16*)filename);
|
|
|
|
printf(":%d:%d: ", line, col);
|
|
|
|
print_utf16_str((u16*)msg);
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct builtin nscript_builtins[] = {
|
|
|
|
{ .name = "null", .fn = 0 },
|
|
|
|
{ .name = "nostr_log", .fn = nostr_log },
|
|
|
|
{ .name = "nostr_cmd", .fn = nostr_cmd },
|
|
|
|
{ .name = "nostr_pool_send_to", .fn = nostr_pool_send_to },
|
2023-07-03 23:59:50 +00:00
|
|
|
{ .name = "nostr_set_bool", .fn = nostr_set_bool },
|
2023-06-03 01:51:49 +00:00
|
|
|
{ .name = "abort", .fn = nscript_abort },
|
|
|
|
};
|
|
|
|
|
|
|
|
int nscript_load(struct wasm_parser *p, struct wasm_interp *interp, unsigned char *wasm, unsigned long len) {
|
|
|
|
wasm_parser_init(p, wasm, len, len * 16, nscript_builtins, ARRAY_SIZE(nscript_builtins));
|
|
|
|
|
|
|
|
if (!parse_wasm(p)) {
|
|
|
|
wasm_parser_free(p);
|
|
|
|
return NSCRIPT_PARSE_ERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!wasm_interp_init(interp, &p->module)) {
|
|
|
|
print_error_backtrace(&interp->errors);
|
|
|
|
wasm_parser_free(p);
|
|
|
|
return NSCRIPT_INIT_ERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
//setup_wasi(&interp, argc, argv, env);
|
|
|
|
//wasm_parser_free(&p);
|
|
|
|
|
|
|
|
return NSCRIPT_LOADED;
|
|
|
|
}
|