1 #include <bash/config.h>
3 #include <bash/builtins.h>
4 #include <bash/shell.h>
9 scm_symbol_to_utf8_string(SCM symbol
)
11 SCM_ASSERT_TYPE(scm_is_symbol(symbol
), symbol
,
12 SCM_ARG1
, __func__
, "symbol");
13 return scm_to_utf8_stringn(scm_symbol_to_string(symbol
), NULL
);
16 static SCM dynamic_variables_alist
= SCM_EOL
;
18 dynamic_value_body(void *data
)
20 struct variable
* self
= data
;
21 const char *varname
= self
->name
;
22 SCM symbol
= scm_string_to_symbol(scm_from_utf8_string(varname
));
23 SCM thunk
= scm_assq_ref(dynamic_variables_alist
, symbol
);
24 SCM value
= scm_call_0(thunk
);
25 char *newvalue
= scm_to_utf8_stringn(value
, NULL
);
28 self
->value
= newvalue
;
33 dynamic_value_exception_handler(void *_unused
, SCM key
, SCM args
)
35 return scm_print_exception
36 (scm_current_error_port(), SCM_BOOL_F
, key
, args
);
39 static struct variable
*
40 dynamic_value(struct variable
*self
)
42 scm_internal_catch(SCM_BOOL_T
, &dynamic_value_body
, self
,
43 &dynamic_value_exception_handler
, NULL
);
48 scm_bind_dynamic_variable(SCM symbol
, SCM thunk
)
53 SCM_ASSERT_TYPE(scm_is_symbol(symbol
), symbol
,
54 SCM_ARG1
, __func__
, "symbol");
55 SCM_ASSERT_TYPE(scm_is_true(scm_thunk_p(thunk
)), thunk
,
56 SCM_ARG2
, __func__
, "thunk");
58 varname
= scm_to_utf8_stringn(scm_symbol_to_string(symbol
), NULL
);
59 v
= bind_variable(varname
, NULL
, 0);
60 v
->dynamic_value
= &dynamic_value
;
61 dynamic_variables_alist
= scm_assq_set_x(dynamic_variables_alist
, symbol
, thunk
);
67 array_walk_function(ARRAY_ELEMENT
*el
, void *data
)
70 SCM index
= scm_from_int64(el
->ind
);
71 SCM value
= scm_from_utf8_string(el
->value
);
72 *alist
= scm_acons(index
, value
, *alist
);
77 scm_array_to_alist(SCM symbol
)
84 SCM_ASSERT_TYPE(scm_is_symbol(symbol
), symbol
,
85 SCM_ARG1
, __func__
, "symbol");
86 varname
= scm_symbol_to_utf8_string(symbol
);
88 GET_ARRAY_FROM_VAR(varname
, v
, array
);
93 array_walk(array
, &array_walk_function
, &alist
);
94 return scm_reverse(alist
);
98 extern char **make_builtin_argv (WORD_LIST
*, int *);
100 struct guile_builtin_state
{
101 int argc
; /* Formed by `make_builtin_argv' in `guile_builtin' */
104 int retval
; /* Passed back from do_guile_builtin */
108 guile_builtin_body (void *data
)
110 const struct guile_builtin_state
*state
= data
;
111 return scm_c_primitive_load_path(state
->filename
);
114 guile_builtin_exception_handler (void *data
, SCM key
, SCM args
)
116 struct guile_builtin_state
*state
= data
;
117 state
->retval
= EXECUTION_FAILURE
;
118 return scm_print_exception
119 (scm_current_error_port(), SCM_BOOL_F
, key
, args
);
123 scm_c_define_public_gsubr(const char *name
, int req
, int opt
, int rest
,
126 scm_c_define_gsubr(name
, req
, opt
, rest
, fn
);
127 scm_c_export(name
, NULL
);
131 void init_bash_module(void *_unused
)
133 scm_c_define_public_gsubr("bind-dynamic-variable", 2, 0, 0,
134 &scm_bind_dynamic_variable
);
135 scm_c_define_public_gsubr("array->alist", 1, 0, 0,
136 &scm_array_to_alist
);
141 do_guile_builtin (void *data
)
143 struct guile_builtin_state
*state
= data
;
144 scm_c_define_module("gnu bash internal", &init_bash_module
, NULL
);
146 /* For Guile, argv[0] will be filename to be loaded. Not too useful, */
147 /* but it is all about minimizing C codebase */
148 scm_set_program_arguments(state
->argc
, state
->argv
, state
->filename
);
149 scm_internal_catch(SCM_BOOL_T
, &guile_builtin_body
, state
,
150 &guile_builtin_exception_handler
, state
);
155 guile_builtin (WORD_LIST
*list
)
157 struct guile_builtin_state state
;
161 argv
= make_builtin_argv(list
, &argc
);
163 builtin_error("not enough arguments.");
165 return EXECUTION_FAILURE
;
167 state
.filename
= argv
[1];
168 state
.argc
= argc
- 2;
169 state
.argv
= argv
+ 2;
170 state
.retval
= EXECUTION_SUCCESS
;
171 scm_with_guile(do_guile_builtin
, &state
);
176 static char* const guile_doc
[] = {
178 "Load Guile code from file with access to (gnu bash) module",
179 "to control Bash internals. Feel free to crash it all. ",
181 "Return code 0, unless exception is thrown",
185 struct builtin scm_struct
= {
187 .function
= guile_builtin
,
188 .flags
= BUILTIN_ENABLED
,
189 .long_doc
= guile_doc
,
190 .short_doc
= "scm FILENAME [ARGS ...]",