#include #include #include #include #include #include #include #include #include #include struct bshell_function_p { char *func_name; fx_array *func_positional_params; bshell_scriptblock *func_body; }; static void init(fx_object *obj, void *priv) { struct bshell_function_p *func_p = priv; func_p->func_positional_params = fx_array_create(); func_p->func_body = bshell_scriptblock_create(); } static void fini(fx_object *obj, void *priv) { struct bshell_function_p *func_p = priv; if (func_p->func_name) { free(func_p->func_name); } fx_array_unref(func_p->func_positional_params); bshell_scriptblock_unref(func_p->func_body); } static enum bshell_status get_callable_name( const bshell_function *func, fx_string *out) { struct bshell_function_p *func_p = fx_object_get_private(func, BSHELL_TYPE_FUNCTION); fx_string_append_cstrf(out, "%s", func_p->func_name); return BSHELL_SUCCESS; } static enum bshell_status begin_processing( bshell_command *cmd, enum bshell_command_position position) { return BSHELL_SUCCESS; } static enum bshell_status process_record( bshell_command *cmd, bshell_pipeline *pipeline, struct bshell_runtime *rt) { struct bshell_function_p *func_p = fx_object_get_private(cmd, BSHELL_TYPE_FUNCTION); bshell_runtime_push_scope(rt, func_p->func_body); const fx_iterator *param_it = fx_iterator_begin(func_p->func_positional_params); size_t i = 1; fx_foreach(v, param_it) { fx_string *param = NULL; fx_value_get_object(v, ¶m); const fx_value *arg = bshell_command_get_arg(cmd, i); if (!arg) { break; } bshell_variable *var = bshell_runtime_define_var( rt, fx_string_get_cstr(param)); bshell_variable_set_value(var, *arg); } fx_iterator_unref(param_it); #if 0 bshell_variable *item = bshell_runtime_define_var(rt, "_"); bshell_variable_set_value(item, &in); #endif fx_value out = bshell_runtime_eval(rt); bshell_runtime_pop_scope(rt); if (fx_value_is_set(&out)) { bshell_pipeline_write_value(pipeline, out, false); fx_value_unset(&out); } return BSHELL_SUCCESS; } static enum bshell_status end_processing(bshell_command *cmd) { return BSHELL_SUCCESS; } bshell_function *bshell_function_create(const char *name) { bshell_function *out = fx_object_create(BSHELL_TYPE_FUNCTION); if (!out) { return NULL; } struct bshell_function_p *func = fx_object_get_private(out, BSHELL_TYPE_FUNCTION); func->func_name = fx_strdup(name); if (!func->func_name) { bshell_function_unref(out); return NULL; } return out; } void bshell_function_add_positional_parameter( bshell_function *func, const char *name) { fx_string *str = fx_string_create_from_cstr(name); if (!str) { return; } struct bshell_function_p *func_p = fx_object_get_private(func, BSHELL_TYPE_FUNCTION); fx_array_push_back( func_p->func_positional_params, FX_VALUE_OBJECT(str)); fx_string_unref(str); } static const char *function_get_name(const struct bshell_function_p *func) { return func->func_name; } static const fx_array *function_get_positional_parameters( const struct bshell_function_p *func) { return func->func_positional_params; } static bshell_scriptblock *function_get_body(struct bshell_function_p *func) { return func->func_body; } const char *bshell_function_get_name(const bshell_function *func) { FX_CLASS_DISPATCH_STATIC_0( BSHELL_TYPE_FUNCTION, function_get_name, func); } const fx_array *bshell_function_get_positional_parameters( const bshell_function *func) { FX_CLASS_DISPATCH_STATIC_0( BSHELL_TYPE_FUNCTION, function_get_positional_parameters, func); } bshell_scriptblock *bshell_function_get_body(bshell_function *func) { FX_CLASS_DISPATCH_STATIC_0( BSHELL_TYPE_FUNCTION, function_get_body, func); } FX_TYPE_CLASS_BEGIN(bshell_function) FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT) FX_INTERFACE_ENTRY(to_string) = NULL; FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT) FX_TYPE_VTABLE_INTERFACE_BEGIN(bshell_command, BSHELL_TYPE_COMMAND) FX_INTERFACE_ENTRY(c_command_type) = "Function"; FX_INTERFACE_ENTRY(c_get_callable_name) = get_callable_name; FX_INTERFACE_ENTRY(c_begin_processing) = begin_processing; FX_INTERFACE_ENTRY(c_process_record) = process_record; FX_INTERFACE_ENTRY(c_end_processing) = end_processing; FX_TYPE_VTABLE_INTERFACE_END(bshell_command, BSHELL_TYPE_COMMAND) FX_TYPE_CLASS_END(bshell_function) FX_TYPE_DEFINITION_BEGIN(bshell_function) FX_TYPE_ID(0x041f1918, 0x6155, 0x4cee, 0xbb01, 0xfef2d6aa1bcf); FX_TYPE_NAME("bshell.runtime.function"); FX_TYPE_EXTENDS(BSHELL_TYPE_COMMAND); FX_TYPE_CLASS(bshell_function_class); FX_TYPE_INSTANCE_INIT(init); FX_TYPE_INSTANCE_FINI(fini); FX_TYPE_INSTANCE_PRIVATE(struct bshell_function_p); FX_TYPE_DEFINITION_END(bshell_function)