1 #include <bash/config.h>
3 #include <bash/builtins.h>
4 #include <bash/shell.h>
8 static SCM magic_variables_alist
= SCM_EOL
;
11 magic_dynamic_value_body(void *data
)
13 struct variable
* self
= data
;
14 const char *varname
= self
->name
;
15 SCM symbol
= scm_string_to_symbol(scm_from_utf8_string(varname
));
16 SCM thunk
= scm_assq_ref(magic_variables_alist
, symbol
);
17 SCM value
= scm_call_0(thunk
);
18 char *newvalue
= scm_to_utf8_stringn(value
, NULL
);
21 self
->value
= newvalue
;
26 magic_dynamic_value_exception_handler(void *_unused
, SCM key
, SCM args
)
28 return scm_print_exception
29 (scm_current_error_port(), SCM_BOOL_F
, key
, args
);
32 static struct variable
*
33 magic_dynamic_value(struct variable
*self
)
35 scm_internal_catch(SCM_BOOL_T
, &magic_dynamic_value_body
, self
,
36 &magic_dynamic_value_exception_handler
, NULL
);
41 scm_bind_magic_variable(SCM symbol
, SCM thunk
)
46 SCM_ASSERT_TYPE(scm_is_symbol(symbol
), symbol
,
47 SCM_ARG1
, __func__
, "symbol");
48 SCM_ASSERT_TYPE(scm_is_true(scm_thunk_p(thunk
)), thunk
,
49 SCM_ARG2
, __func__
, "thunk");
51 varname
= scm_to_utf8_stringn(scm_symbol_to_string(symbol
), NULL
);
52 v
= bind_variable(varname
, NULL
, 0);
53 v
->dynamic_value
= &magic_dynamic_value
;
54 magic_variables_alist
= scm_assq_set_x(magic_variables_alist
, symbol
, thunk
);
61 extern char **make_builtin_argv (WORD_LIST
*, int *);
63 struct guile_builtin_state
{
64 int argc
; /* Formed by `make_builtin_argv' in `guile_builtin' */
67 int retval
; /* Passed back from do_guile_builtin */
71 guile_builtin_body (void *data
)
73 const struct guile_builtin_state
*state
= data
;
74 return scm_c_primitive_load_path(state
->filename
);
77 guile_builtin_exception_handler (void *data
, SCM key
, SCM args
)
79 struct guile_builtin_state
*state
= data
;
80 state
->retval
= EXECUTION_FAILURE
;
81 return scm_print_exception
82 (scm_current_error_port(), SCM_BOOL_F
, key
, args
);
86 do_guile_builtin (void *data
)
88 struct guile_builtin_state
*state
= data
;
89 scm_c_define_gsubr("bash:bind-magic-variable", 2, 0, 0,
90 &scm_bind_magic_variable
);
92 /* For Guile, argv[0] will be filename to be loaded. Not too useful, */
93 /* but it is all about minimizing C codebase */
94 scm_set_program_arguments(state
->argc
, state
->argv
, state
->filename
);
95 scm_internal_catch(SCM_BOOL_T
, &guile_builtin_body
, state
,
96 &guile_builtin_exception_handler
, state
);
101 guile_builtin (WORD_LIST
*list
)
103 struct guile_builtin_state state
;
107 argv
= make_builtin_argv(list
, &argc
);
109 builtin_error("not enough arguments.");
111 return EXECUTION_FAILURE
;
113 state
.filename
= argv
[1];
114 state
.argc
= argc
- 2;
115 state
.argv
= argv
+ 2;
116 state
.retval
= EXECUTION_SUCCESS
;
117 scm_with_guile(do_guile_builtin
, &state
);
122 static char* const guile_doc
[] = {
124 "Load Guile code from file with access to (gnu bash) module",
125 "to control Bash internals. Feel free to crash it all. ",
127 "Return code 0, unless exception is thrown",
131 struct builtin scm_struct
= {
133 .function
= guile_builtin
,
134 .flags
= BUILTIN_ENABLED
,
135 .long_doc
= guile_doc
,
136 .short_doc
= "scm FILENAME [ARGS ...]",