summaryrefslogtreecommitdiffhomepage
path: root/lib.c
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2021-05-10 16:29:16 +0200
committerJo-Philipp Wich <jo@mein.io>2021-05-10 16:31:50 +0200
commite546bbaf6bbee16356beb675cc3e806d9793688e (patch)
treefc7643b7fa5384b0abf8ff3780bca72f38ca1db1 /lib.c
parent0cb10c62a0d663fe42cebb4134e7cfcd3c461156 (diff)
lib: implement render(), an include variant capturing output in a string
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c50
1 files changed, 49 insertions, 1 deletions
diff --git a/lib.c b/lib.c
index 9d8241b..453f976 100644
--- a/lib.c
+++ b/lib.c
@@ -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 }
};