diff options
-rw-r--r-- | README.md | 8 | ||||
-rw-r--r-- | lib.c | 54 | ||||
-rw-r--r-- | types.h | 1 | ||||
-rw-r--r-- | vm.c | 8 |
4 files changed, 64 insertions, 7 deletions
@@ -998,7 +998,7 @@ json('{"a":true, "b":123}') // { "a": true, "b": 123 } json('[1,2,') // Throws exception ``` -#### 6.50. `include(path, scope)` +#### 6.50. `include(path[, scope])` Evaluate and include the file at the given path and optionally override the execution scope with the given scope object. @@ -1113,3 +1113,9 @@ an invalid value was passed, otherwise `true`. Raise an exception with the given `message` parameter if the value in `cond` is not truish. When `message` is omitted, the default value is `Assertion failed`. + +#### 6.57. `render(path[, scope])` + +Like `include()` but capture output of included file as string and return it. + +See `include()` for details on scoping. @@ -292,7 +292,7 @@ uc_print_common(uc_vm *vm, size_t nargs, FILE *fh) static uc_value_t * uc_print(uc_vm *vm, size_t nargs) { - return uc_print_common(vm, nargs, stdout); + return uc_print_common(vm, nargs, vm->output); } static uc_value_t * @@ -1495,7 +1495,7 @@ uc_printf(uc_vm *vm, size_t nargs) uc_printf_common(vm, nargs, buf); - len = fwrite(buf->buf, 1, printbuf_length(buf), stdout); + len = fwrite(buf->buf, 1, printbuf_length(buf), vm->output); printbuf_free(buf); @@ -2199,6 +2199,53 @@ uc_include(uc_vm *vm, size_t nargs) } static uc_value_t * +uc_render(uc_vm *vm, size_t nargs) +{ + uc_string_t *ustr = NULL; + FILE *mem, *prev; + size_t len = 0; + + mem = open_memstream((char **)&ustr, &len); + + if (!mem) + goto out; + + /* reserve space for uc_string_t header... */ + if (fseek(mem, sizeof(*ustr), SEEK_SET)) + goto out; + + /* divert VM output to memory fd */ + prev = vm->output; + vm->output = mem; + + /* execute include */ + (void) uc_include(vm, nargs); + + /* restore previous VM output */ + vm->output = prev; + fclose(mem); + + /* update uc_string_t length */ + ustr->header.type = UC_STRING; + ustr->header.refcount = 1; + ustr->length = len - sizeof(*ustr); + + return &ustr->header; + +out: + uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, + "Unable to initialize output memory: %s", + strerror(errno)); + + if (mem) + fclose(mem); + + free(ustr); + + return NULL; +} + +static uc_value_t * uc_warn(uc_vm *vm, size_t nargs) { return uc_print_common(vm, nargs, stderr); @@ -2473,7 +2520,8 @@ static const uc_cfunction_list functions[] = { { "trace", uc_trace }, { "proto", uc_proto }, { "sleep", uc_sleep }, - { "assert", uc_assert } + { "assert", uc_assert }, + { "render", uc_render } }; @@ -259,6 +259,7 @@ struct uc_vm { size_t spread_values; uint8_t trace; uc_stringbuf_t *strbuf; + FILE *output; }; @@ -118,6 +118,8 @@ void uc_vm_init(uc_vm *vm, uc_parse_config *config) vm->strbuf = NULL; + vm->output = stdout; + uc_vm_reset_stack(vm); } @@ -1896,12 +1898,12 @@ uc_vm_insn_print(uc_vm *vm, enum insn_type insn) case UC_OBJECT: case UC_ARRAY: p = ucv_to_jsonstring(vm, v); - fwrite(p, 1, strlen(p), stdout); + fwrite(p, 1, strlen(p), vm->output); free(p); break; case UC_STRING: - fwrite(ucv_string_get(v), 1, ucv_string_length(v), stdout); + fwrite(ucv_string_get(v), 1, ucv_string_length(v), vm->output); break; case UC_NULL: @@ -1909,7 +1911,7 @@ uc_vm_insn_print(uc_vm *vm, enum insn_type insn) default: p = ucv_to_string(vm, v); - fwrite(p, 1, strlen(p), stdout); + fwrite(p, 1, strlen(p), vm->output); free(p); } |