From b3440fe23169112d0e37651e41e8cf249255aa6a Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sun, 14 Jun 2026 19:39:49 +0100 Subject: [PATCH] runtime: cmdcall: implement resolution of native commands --- bshell.runtime/runtime/cmdcall.c | 141 ++++++++++++++++++++++++++----- 1 file changed, 119 insertions(+), 22 deletions(-) diff --git a/bshell.runtime/runtime/cmdcall.c b/bshell.runtime/runtime/cmdcall.c index efa8b74..5e0d5c7 100644 --- a/bshell.runtime/runtime/cmdcall.c +++ b/bshell.runtime/runtime/cmdcall.c @@ -77,11 +77,119 @@ static const fx_value *get_arg(struct bshell_cmdcall_p *cmdcall, size_t index) return &cmdcall->cmd_args.items[cmdcall->cmd_args.count - index - 1]; } -static bshell_command *__resolve_call_target( - const char *callable_name, - struct bshell_runtime *rt) +static bshell_command *resolve_cmdlet( + struct bshell_cmdcall_p *cmdcall, + struct bshell_runtime *rt, + fx_string *cmd_name) { - return bshell_runtime_find_command(rt, callable_name); + while (1) { + const char *cmd_name_cstr = fx_string_get_cstr(cmd_name); + bshell_command *cmd + = bshell_runtime_find_command(rt, cmd_name_cstr); + if (!cmd) { + break; + } + + bshell_alias_class *alias + = fx_object_get_interface(cmd, BSHELL_TYPE_ALIAS); + if (alias) { + fx_string_clear(cmd_name); + fx_string_append_cstr(cmd_name, alias->a_target_name); + bshell_command_unref(cmd); + continue; + } + + return cmd; + } + + return NULL; +} + +static const fx_string *get_path(void) +{ + fx_process *self = fx_process_get_self(); + if (!self) { + return NULL; + } + + const fx_hashtable *env = fx_process_get_environment(self); + if (!env) { + return NULL; + } + + const fx_value *path_v = fx_hashtable_get(env, &FX_CSTR("PATH")); + if (!path_v) { + return NULL; + } + + const fx_string *path = NULL; + fx_value_get_object(path_v, (fx_object **)&path); + return path; +} + +static bshell_command *resolve_native_command_local( + struct bshell_cmdcall_p *cmdcall, + struct bshell_runtime *rt, + fx_string *cmd_name) +{ + const char *cmd_name_cstr = fx_string_get_cstr(cmd_name); + fx_path *cmd_path = fx_path_create_from_cstr(cmd_name_cstr); + if (!fx_path_is_file(cmd_path)) { + fx_path_unref(cmd_path); + return NULL; + } + + bshell_command *result + = bshell_native_command_create(fx_path_ptr(cmd_path)); + fx_path_unref(cmd_path); + return result; +} + +static bshell_command *resolve_native_command( + struct bshell_cmdcall_p *cmdcall, + struct bshell_runtime *rt, + fx_string *cmd_name) +{ + const char *cmd_name_cstr = fx_string_get_cstr(cmd_name); + if (cmd_name_cstr[0] == '/' + || (cmd_name_cstr[0] == '.' && cmd_name_cstr[1] == '/') + || (cmd_name_cstr[0] == '.' && cmd_name_cstr[1] == '.' + && cmd_name_cstr[2] == '/')) { + return resolve_native_command_local(cmdcall, rt, cmd_name); + } + + fx_path *cmd_name_path = fx_path_create_from_cstr(cmd_name_cstr); + const char *delim[] = {":"}; + const fx_string *path = get_path(); + const fx_iterator *it = fx_string_tokenise( + path, + delim, + sizeof delim / sizeof delim[0], + FX_STRING_TOK_F_NORMAL); + bshell_command *result = NULL; + + fx_foreach(v, it) + { + const char *tok = NULL; + fx_value_get_cstr(v, &tok); + + fx_path *dir_path = fx_path_create_from_cstr(tok); + const fx_path *parts[] = {dir_path, cmd_name_path}; + fx_path *full_path + = fx_path_join(parts, sizeof parts / sizeof parts[0]); + fx_path_unref(dir_path); + if (!fx_path_is_file(full_path)) { + fx_path_unref(full_path); + continue; + } + + result = bshell_native_command_create(fx_path_ptr(full_path)); + fx_path_unref(full_path); + break; + } + + fx_iterator_unref(it); + return result; } static enum bshell_status resolve_call_target( @@ -100,28 +208,17 @@ static enum bshell_status resolve_call_target( fx_string *cmd_name_s = NULL; fx_value_get_object(cmd_name_v, &cmd_name_s); - while (1) { - const char *cmd_name_cstr = fx_string_get_cstr(cmd_name_s); - bshell_command *cmd - = bshell_runtime_find_command(rt, cmd_name_cstr); - if (!cmd) { - break; - } - - bshell_alias_class *alias - = fx_object_get_interface(cmd, BSHELL_TYPE_ALIAS); - if (alias) { - fx_string_clear(cmd_name_s); - fx_string_append_cstr(cmd_name_s, alias->a_target_name); - bshell_command_unref(cmd); - continue; - } - - cmdcall->cmd_target = cmd; + if ((cmdcall->cmd_target = resolve_cmdlet(cmdcall, rt, cmd_name_s))) { cmdcall->cmd_type = CMDCALL_CMDLET; return BSHELL_SUCCESS; } + if ((cmdcall->cmd_target + = resolve_native_command(cmdcall, rt, cmd_name_s))) { + cmdcall->cmd_type = CMDCALL_NATIVE; + return BSHELL_SUCCESS; + } + const char *cmd_name_cstr = fx_string_get_cstr(cmd_name_s); #if BSHELL_INTERACTIVE == 1 fx_printf("[bold,bright_red]");