nostrscript.c (5046B)
1 // 2 // nostrscript.c 3 // damus 4 // 5 // Created by William Casarin on 2023-06-02. 6 // 7 8 #include "nostrscript.h" 9 #include "wasm.h" 10 #include "array_size.h" 11 12 // function to check if the character is in surrogate pair range 13 static INLINE int is_surrogate(uint16_t uc) { 14 return (uc - 0xd800u) < 2048u; 15 } 16 17 // function to convert utf16 to utf8 18 static int utf16_to_utf8(u16 utf16, u8 *utf8) { 19 if (utf16 < 0x80) { // 1-byte sequence 20 utf8[0] = (uint8_t) utf16; 21 return 1; 22 } 23 else if (utf16 < 0x800) { // 2-byte sequence 24 utf8[0] = (uint8_t) (0xc0 | (utf16 >> 6)); 25 utf8[1] = (uint8_t) (0x80 | (utf16 & 0x3f)); 26 return 2; 27 } 28 else if (!is_surrogate(utf16)) { // 3-byte sequence 29 utf8[0] = (uint8_t) (0xe0 | (utf16 >> 12)); 30 utf8[1] = (uint8_t) (0x80 | ((utf16 >> 6) & 0x3f)); 31 utf8[2] = (uint8_t) (0x80 | (utf16 & 0x3f)); 32 return 3; 33 } 34 else { // surrogate pair, return error 35 return -1; 36 } 37 } 38 39 static int nostr_cmd(struct wasm_interp *interp) { 40 struct val *params = NULL; 41 const char *val = NULL; 42 int len, cmd, ival; 43 44 if (!get_params(interp, ¶ms, 3) || params == NULL) 45 return interp_error(interp, "get params"); 46 47 // command 48 cmd = params[0].num.i32; 49 50 // value 51 52 ival = params[1].num.i32; 53 if (!mem_ptr_str(interp, ival, &val)) 54 val = 0; 55 56 // length 57 len = params[2].num.i32; 58 59 intptr_t iptr = ival; 60 return nscript_nostr_cmd(interp, cmd, val ? (void*)val : (void*)iptr, len); 61 } 62 63 static int print_utf16_str(u16 *chars) { 64 u16 *p = chars; 65 int c; 66 67 while (*p) { 68 if (utf16_to_utf8(*p, (u8*)&c) == -1) 69 return 0; 70 71 printf("%c", c); 72 73 p++; 74 } 75 76 return 1; 77 } 78 79 static int nostr_log(struct wasm_interp *interp) { 80 struct val *vals; 81 const char *str; 82 struct callframe *callframe; 83 84 if (!get_params(interp, &vals, 1)) 85 return interp_error(interp, "nostr_log get params"); 86 87 if (!mem_ptr_str(interp, vals[0].num.i32, &str)) 88 return interp_error(interp, "nostr_log log param"); 89 90 if (!(callframe = top_callframes(&interp->callframes, 2))) 91 return interp_error(interp, "nostr_log callframe"); 92 93 printf("nostr_log:%s: ", callframe->func->name); 94 95 print_utf16_str((u16*)str); 96 printf("\n"); 97 98 return 1; 99 } 100 101 static int nostr_set_bool(struct wasm_interp *interp) { 102 struct val *params = NULL; 103 const u16 *setting; 104 u32 val, len; 105 106 if (!get_params(interp, ¶ms, 3) || params == NULL) 107 return 0; 108 109 if (!mem_ptr_str(interp, params[0].num.i32, (const char**)&setting)) 110 return 0; 111 112 len = params[1].num.i32; 113 val = params[2].num.i32 > 0 ? 1 : 0; 114 115 return nscript_set_bool(interp, setting, len, val); 116 } 117 118 static int nostr_pool_send_to(struct wasm_interp *interp) { 119 struct val *params = NULL; 120 const u16 *req, *to; 121 int req_len, to_len; 122 123 if (!get_params(interp, ¶ms, 4) || params == NULL) 124 return 0; 125 126 if (!mem_ptr_str(interp, params[0].num.i32, (const char**)&req)) 127 return 0; 128 129 req_len = params[1].num.i32; 130 131 if (!mem_ptr_str(interp, params[2].num.i32, (const char**)&to)) 132 return 0; 133 134 to_len = params[3].num.i32; 135 136 return nscript_pool_send_to(interp, req, req_len, to, to_len); 137 } 138 139 static int nscript_abort(struct wasm_interp *interp) { 140 struct val *params = NULL; 141 const char *msg = "", *filename; 142 int line, col; 143 144 if (!get_params(interp, ¶ms, 4) || params == NULL) 145 return interp_error(interp, "get params"); 146 147 if (params[0].ref.addr != 0 && !mem_ptr_str(interp, params[0].ref.addr, &msg)) 148 return interp_error(interp, "abort msg"); 149 150 if (!mem_ptr_str(interp, params[1].ref.addr, &filename)) 151 return interp_error(interp, "abort filename"); 152 153 line = params[2].num.i32; 154 col = params[3].num.i32; 155 156 printf("nscript_abort:"); 157 print_utf16_str((u16*)filename); 158 printf(":%d:%d: ", line, col); 159 print_utf16_str((u16*)msg); 160 printf("\n"); 161 162 return 0; 163 } 164 165 static struct builtin nscript_builtins[] = { 166 { .name = "null", .fn = 0 }, 167 { .name = "nostr_log", .fn = nostr_log }, 168 { .name = "nostr_cmd", .fn = nostr_cmd }, 169 { .name = "nostr_pool_send_to", .fn = nostr_pool_send_to }, 170 { .name = "nostr_set_bool", .fn = nostr_set_bool }, 171 { .name = "abort", .fn = nscript_abort }, 172 }; 173 174 int nscript_load(struct wasm_parser *p, struct wasm_interp *interp, unsigned char *wasm, unsigned long len) { 175 wasm_parser_init(p, wasm, len, len * 16, nscript_builtins, ARRAY_SIZE(nscript_builtins)); 176 177 if (!parse_wasm(p)) { 178 wasm_parser_free(p); 179 return NSCRIPT_PARSE_ERR; 180 } 181 182 if (!wasm_interp_init(interp, &p->module)) { 183 print_error_backtrace(&interp->errors); 184 wasm_parser_free(p); 185 return NSCRIPT_INIT_ERR; 186 } 187 188 //setup_wasi(&interp, argc, argv, env); 189 //wasm_parser_free(&p); 190 191 return NSCRIPT_LOADED; 192 }