From 90a49bc266055f277591ed6dcfab6174fbb0acd5 Mon Sep 17 00:00:00 2001 From: Dmitry Bogatov Date: Sat, 27 Dec 2014 23:08:02 +0300 Subject: [PATCH] Write magic variables in C * src/scm.c: Make magic variables have all single dynamic_value function, working around problems with garbage collection. * tests/command.scm.in: Temporary disable command.scm tests * tests/magic-var.scm: Adjust testsing code * tests/magic-var.bash: Discover and document magic-var limitations. --- src/scm.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/command.scm.in | 18 ++++++++-------- tests/magic-var.bash.in | 13 +++++++++-- tests/magic-var.scm.in | 21 +++++++++--------- 4 files changed, 88 insertions(+), 21 deletions(-) diff --git a/src/scm.c b/src/scm.c index 94df1b8..2af64c7 100644 --- a/src/scm.c +++ b/src/scm.c @@ -1,9 +1,63 @@ #include +#include #include #include #include #include +static SCM magic_variables_alist = SCM_EOL; + +static SCM +magic_dynamic_value_body(void *data) +{ + struct variable* self = data; + const char *varname = self->name; + SCM symbol = scm_string_to_symbol(scm_from_utf8_string(varname)); + SCM thunk = scm_assq_ref(magic_variables_alist, symbol); + SCM value = scm_call_0(thunk); + char *newvalue = scm_to_utf8_stringn(value, NULL); + + free(self->value); + self->value = newvalue; + return SCM_UNDEFINED; +} + +static SCM +magic_dynamic_value_exception_handler(void *_unused, SCM key, SCM args) +{ + return scm_print_exception + (scm_current_error_port(), SCM_BOOL_F, key, args); +} + +static struct variable* +magic_dynamic_value(struct variable *self) +{ + scm_internal_catch(SCM_BOOL_T, &magic_dynamic_value_body, self, + &magic_dynamic_value_exception_handler, NULL); + return self; +} + +static SCM +scm_bind_magic_variable(SCM symbol, SCM thunk) +{ + char *varname; + struct variable *v; + + SCM_ASSERT_TYPE(scm_is_symbol(symbol), symbol, + SCM_ARG1, __func__, "symbol"); + SCM_ASSERT_TYPE(scm_is_true(scm_thunk_p(thunk)), thunk, + SCM_ARG2, __func__, "thunk"); + + varname = scm_to_utf8_stringn(scm_symbol_to_string(symbol), NULL); + v = bind_variable(varname, NULL, 0); + v->dynamic_value = &magic_dynamic_value; + magic_variables_alist = scm_assq_set_x(magic_variables_alist, symbol, thunk); + free(varname); + return SCM_UNDEFINED; +} + + + extern char **make_builtin_argv (WORD_LIST *, int *); struct guile_builtin_state { @@ -32,6 +86,9 @@ static void* do_guile_builtin (void *data) { struct guile_builtin_state *state = data; + scm_c_define_gsubr("bash:bind-magic-variable", 2, 0, 0, + &scm_bind_magic_variable); + /* For Guile, argv[0] will be filename to be loaded. Not too useful, */ /* but it is all about minimizing C codebase */ scm_set_program_arguments(state->argc, state->argv, state->filename); diff --git a/tests/command.scm.in b/tests/command.scm.in index 0026c6f..850a19c 100644 --- a/tests/command.scm.in +++ b/tests/command.scm.in @@ -7,12 +7,12 @@ (use-modules (system ffi)) (use-modules (system foreign)) -(bind-scm-function - "my_bound" - (lambda () - (define tmpfile (tmpnam)) - (set! ($ "TEST_FILE") tmpfile) - (call-with-output-file - tmpfile - (lambda (port) - (format port "MESSAGE"))))) +;; (bind-scm-function +;; "my_bound" +;; (lambda () +;; (define tmpfile (tmpnam)) +;; (set! ($ "TEST_FILE") tmpfile) +;; (call-with-output-file +;; tmpfile +;; (lambda (port) +;; (format port "MESSAGE"))))) diff --git a/tests/magic-var.bash.in b/tests/magic-var.bash.in index 8646644..13041a7 100755 --- a/tests/magic-var.bash.in +++ b/tests/magic-var.bash.in @@ -1,6 +1,11 @@ #!@BASH@ -. @abs_builddir@/testing-common.bash -load_scheme + +## There is seems to be strange limitation. Code, defining +## magic variables, must be on top level. No sourcing, +## no functions. + +enable -f @abs_top_builddir@/.libs/bash-scm.so scm +scm @abs_builddir@/magic-var.scm ## If dynamic_value functions throws, your code is screwed. ## But it should not crash shell off. @@ -19,3 +24,7 @@ for j in $(seq 10000) ; do ;; esac done +function do_something { + echo $MAGIC +} +do_something diff --git a/tests/magic-var.scm.in b/tests/magic-var.scm.in index 452df27..2045da7 100644 --- a/tests/magic-var.scm.in +++ b/tests/magic-var.scm.in @@ -1,16 +1,17 @@ (set! %load-compiled-path (cons "@abs_top_builddir@/lisp" %load-compiled-path)) (primitive-load "@abs_builddir@/testing-common.scm") -(use-modules (gnu bash variable)) -(bind-magic-variable - "MAGIC" (lambda (name prev-value) - (format #f "MAGIC-~a" (random 24)))) -(bind-magic-variable - "CRASH" - (lambda (name prev-value) +(bash:bind-magic-variable 'MAGIC + (lambda () + (format #f "MAGIC-~a" (random 24)))) + + +(bash:bind-magic-variable + 'CRASH + (lambda () (error 'foo))) -(bind-magic-variable - "TYPEMISMATCH" - (lambda (name prev-value) +(bash:bind-magic-variable + 'TYPEMISMATCH + (lambda () (list 'type-mismatch 23))) -- 2.11.4.GIT