From 937171d606561317f45aa6639f4178a93a2b0bb4 Mon Sep 17 00:00:00 2001 From: Takuma Tsubo Date: Tue, 6 May 2025 13:12:41 +0900 Subject: [PATCH 01/12] =?UTF-8?q?expand=5Ftokens=E3=81=AE=E6=A7=8B?= =?UTF-8?q?=E9=80=A0=E3=82=92=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- inc/parser/parser.h | 15 +++++- src/parser/expand_tokens.c | 87 ++++++++++++-------------------- src/parser/join_expanded_parts.c | 51 +++++++++++++++++++ src/parser/split_by_quote.c | 87 ++++++++++++++++++++++++++++++++ 4 files changed, 184 insertions(+), 56 deletions(-) create mode 100644 src/parser/join_expanded_parts.c create mode 100644 src/parser/split_by_quote.c diff --git a/inc/parser/parser.h b/inc/parser/parser.h index e064b88..c3e336e 100644 --- a/inc/parser/parser.h +++ b/inc/parser/parser.h @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/21 14:14:59 by ttsubo #+# #+# */ -/* Updated: 2025/05/05 18:38:15 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 13:08:26 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,6 +17,19 @@ # include "expand_env.h" # include "libft.h" +typedef enum e_quote +{ + QUOTE_NONE, + QUOTE_SINGLE, + QUOTE_DOUBLE +} t_quote; + +typedef struct s_part +{ + char *text; + t_quote quote; +} t_part; + size_t count_cmds(char **tokens); char **next_cmd_start(char **token_ptr); t_cmd **calloc_cmds(char **tokens); diff --git a/src/parser/expand_tokens.c b/src/parser/expand_tokens.c index 2bd0a83..fbff445 100644 --- a/src/parser/expand_tokens.c +++ b/src/parser/expand_tokens.c @@ -6,12 +6,23 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/02 17:08:42 by ttsubo #+# #+# */ -/* Updated: 2025/05/02 17:52:43 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 13:08:55 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ #include "parser.h" +static void _free_part(void *ptr) +{ + t_part *part; + + part = ptr; + if (!part) + return ; + free(part->text); + free(part); +} + static size_t _tokens_len(char **tokens) { size_t i; @@ -22,71 +33,37 @@ static size_t _tokens_len(char **tokens) return (i); } -/** - * @note pre: $? in str - */ -static char *_expand_dollar(char *str, t_minish *minish) -{ - char *pre; - char *suf; - char *sts_str; - char *joined; - char *final; - - pre = ft_substr(str, 0, ft_strlen_until(str, '$')); - sts_str = ft_itoa(minish->last_status); - suf = ft_strdup(str + ft_strlen_until(str, '$') + 2); - if (!pre || !sts_str || !suf) - return (free(pre), free(sts_str), free(suf), NULL); - joined = ft_strjoin(pre, sts_str); - final = ft_strjoin(joined, suf); - return (free(pre), free(sts_str), free(suf), free(joined), final); -} - -static char *_expand(char *token, t_minish *minish) +char *expand_token(char *token, t_minish *minish) { + t_list *parts; char *result; - char *tmp; - result = ft_strdup(token); - if (!result) + parts = split_by_quote(token); + if (!parts) return (NULL); - while (ft_strchr(result, '$')) - { - tmp = result; - if (ft_strnstr(result, "$?", ft_strlen(result))) - result = _expand_dollar(tmp, minish); - else - result = expand_env(tmp, minish); - free(tmp); - if (!result) - return (NULL); - } + result = join_expanded_parts(parts, minish); + ft_lstclear(parts, _free_part); return (result); } char **expand_tokens(char **tokens, t_minish *minish) { - size_t token_i; - size_t len; - char **expanded; + size_t i; + size_t count; + char **result; - len = _tokens_len(tokens); - expanded = ft_calloc(sizeof(char *), len + 1); - if (!expanded) + count = _tokens_len(tokens); + result = ft_calloc(sizeof(char *), count + 1); + if (!result) return (NULL); - token_i = 0; - while (token_i < len) + i = 0; + while (i < count) { - expanded[token_i] = _expand(tokens[token_i], minish); - if (!expanded[token_i]) - { - while (0 < token_i) - free(expanded[--token_i]); - free(expanded); - return (NULL); - } - token_i++; + result[i] = expand_token(tokens[i], minish); + printf("DBG:expand: '%s' → '%s'\n", tokens[i], result[i]); + if (!result[i]) + return (free_strs(&result), NULL); + i++; } - return (expanded); + return (result); } diff --git a/src/parser/join_expanded_parts.c b/src/parser/join_expanded_parts.c new file mode 100644 index 0000000..80323c8 --- /dev/null +++ b/src/parser/join_expanded_parts.c @@ -0,0 +1,51 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* join_expanded_parts.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ttsubo +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/05/06 13:05:02 by ttsubo #+# #+# */ +/* Updated: 2025/05/06 13:05:39 by ttsubo ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser.h" + +char *strjoin_and_free(char *s1, char *s2) +{ + char *joined; + + if (!s1 || !s2) + return (NULL); + joined = ft_strjoin(s1, s2); + free_str(s1); + free_str(s2); + return (joined); +} + +char *join_expanded_parts(t_list *parts, t_minish *minish) +{ + char *result; + char *tmp; + t_part *part; + + result = ft_strdup(""); + if (!result) + return (NULL); + while (parts) + { + part = (t_part *)parts->content; + if (part->quote == QUOTE_SINGLE) + tmp = ft_strdup(part->text); + else + tmp = expand_env(part->text, minish); + if (!tmp) + return (free_str(result), NULL); + result = strjoin_and_free(result, tmp); + if (!result) + return (NULL); + parts = parts->next; + } + return (result); +} diff --git a/src/parser/split_by_quote.c b/src/parser/split_by_quote.c new file mode 100644 index 0000000..adf918a --- /dev/null +++ b/src/parser/split_by_quote.c @@ -0,0 +1,87 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* split_by_quote.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ttsubo +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/05/06 13:03:29 by ttsubo #+# #+# */ +/* Updated: 2025/05/06 13:08:48 by ttsubo ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser.h" + +static t_part *_make_part(char *text, t_quote quote) +{ + t_part *part; + + if (!text) + return (NULL); + part = ft_calloc(1, sizeof(t_part)); + if (!part) + return (free_str(text), NULL); + part->text = text; + part->quote = quote; + return (part); +} + +static bool _handle_unquoted_segment(const char *s, size_t *i, t_list **parts) +{ + size_t start; + t_part *part; + + start = *i; + while (s[*i] && is_quote(s[*i])) + (*i)++; + if (*i == start) + return (false); + part = _make_part(ft_substr(s, start, *i - start), QUOTE_NONE); + if (!part) + return (false); + ft_lstadd_back(parts, ft_lstnew(part)); + return (true); +} + +static bool _handle_quoted_segment(const char *s, size_t *i, t_list **parts) +{ + char quote; + size_t start; + t_part *part; + + quote = s[*i]; + start = ++(*i); + while (s[*i] && s[*i] != quote) + (*i)++; + if (!s[*i]) + return (false); + part = _make_part(ft_substr(s, start, *i - start), get_quote_type(quote)); + if (!part) + return (false); + ft_lstadd_back(parts, ft_lstnew(part)); + (*i)++; + return (true); +} + +t_list *split_by_quote(char *token) +{ + t_list *parts; + size_t i; + + parts = NULL; + i = 0; + while (token[i]) + { + if (is_quote(token[i])) + { + if (!_handle_quoted_segment(token, &i, &parts)) + return (ft_lstclear(&parts, free), NULL); + } + else + { + if (!_handle_unquoted_segment(token, &i, &parts)) + return (ft_lstclear(&parts, free), NULL); + } + } + return (parts); +} From cdab7bb6a66d79586497a1732bcb3d45f3888487 Mon Sep 17 00:00:00 2001 From: Takuma Tsubo Date: Tue, 6 May 2025 13:19:08 +0900 Subject: [PATCH 02/12] fix build error --- Makefile | 5 +++-- inc/parser/parser.h | 4 +++- src/parser/expand_tokens.c | 4 ++-- src/parser/join_expanded_parts.c | 8 ++++---- src/parser/split_by_quote.c | 15 ++++++++++++--- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 39c781a..3d0e1a8 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # By: ttsubo +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/04/03 12:55:20 by ttsubo #+# #+# # -# Updated: 2025/05/05 18:42:27 by ttsubo ### ########.fr # +# Updated: 2025/05/06 13:15:51 by ttsubo ### ########.fr # # # # **************************************************************************** # @@ -68,7 +68,8 @@ TOKENIZER_SRC = tokenizer.c tokenizer_error.c read_token.c \ is_quote_closed.c get_token_capa.c is_redirect_validate.c PARSER_SRC = allocate_cmds.c parser.c parser_utils.c setup_cmds.c \ allocate_cmds_utils.c allocate_cmds_utils_2.c \ - expand_env.c expand_tokens.c trim_quote_tokens.c + expand_env.c expand_tokens.c trim_quote_tokens.c \ + split_by_quote.c join_expanded_parts.c BUILTIN_SRC = cd.c exit.c pwd.c echo.c env.c unset.c export.c \ env_utils.c env_utils_2.c env_utils_3.c builtin_utils.c \ export_exec.c export_print_sorted_env.c export_error.c split_key_value.c diff --git a/inc/parser/parser.h b/inc/parser/parser.h index c3e336e..e80dab9 100644 --- a/inc/parser/parser.h +++ b/inc/parser/parser.h @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/21 14:14:59 by ttsubo #+# #+# */ -/* Updated: 2025/05/06 13:08:26 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 13:14:12 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -46,5 +46,7 @@ size_t count_args_until_separator(char **tokens); int is_separator(char *token); t_cmd **allocate_cmds(char **tokens); t_cmd **setup_cmds(t_cmd **cmds, char **tokens); +t_list *split_by_quote(char *token); +char *join_expanded_parts(t_list *parts, t_minish *minish); #endif \ No newline at end of file diff --git a/src/parser/expand_tokens.c b/src/parser/expand_tokens.c index fbff445..6bd0ce0 100644 --- a/src/parser/expand_tokens.c +++ b/src/parser/expand_tokens.c @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/02 17:08:42 by ttsubo #+# #+# */ -/* Updated: 2025/05/06 13:08:55 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 13:14:37 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -42,7 +42,7 @@ char *expand_token(char *token, t_minish *minish) if (!parts) return (NULL); result = join_expanded_parts(parts, minish); - ft_lstclear(parts, _free_part); + ft_lstclear(&parts, _free_part); return (result); } diff --git a/src/parser/join_expanded_parts.c b/src/parser/join_expanded_parts.c index 80323c8..be7eef5 100644 --- a/src/parser/join_expanded_parts.c +++ b/src/parser/join_expanded_parts.c @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/06 13:05:02 by ttsubo #+# #+# */ -/* Updated: 2025/05/06 13:05:39 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 13:18:19 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,8 +19,8 @@ char *strjoin_and_free(char *s1, char *s2) if (!s1 || !s2) return (NULL); joined = ft_strjoin(s1, s2); - free_str(s1); - free_str(s2); + free_str(&s1); + free_str(&s2); return (joined); } @@ -41,7 +41,7 @@ char *join_expanded_parts(t_list *parts, t_minish *minish) else tmp = expand_env(part->text, minish); if (!tmp) - return (free_str(result), NULL); + return (free_str(&result), NULL); result = strjoin_and_free(result, tmp); if (!result) return (NULL); diff --git a/src/parser/split_by_quote.c b/src/parser/split_by_quote.c index adf918a..092377f 100644 --- a/src/parser/split_by_quote.c +++ b/src/parser/split_by_quote.c @@ -6,12 +6,21 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/06 13:03:29 by ttsubo #+# #+# */ -/* Updated: 2025/05/06 13:08:48 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 13:17:46 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ #include "parser.h" +static t_quote _get_quote_type(char quote) +{ + if (quote == '\'') + return (QUOTE_SINGLE); + else if (quote == '"') + return (QUOTE_DOUBLE); + return (QUOTE_NONE); +} + static t_part *_make_part(char *text, t_quote quote) { t_part *part; @@ -20,7 +29,7 @@ static t_part *_make_part(char *text, t_quote quote) return (NULL); part = ft_calloc(1, sizeof(t_part)); if (!part) - return (free_str(text), NULL); + return (free_str(&text), NULL); part->text = text; part->quote = quote; return (part); @@ -55,7 +64,7 @@ static bool _handle_quoted_segment(const char *s, size_t *i, t_list **parts) (*i)++; if (!s[*i]) return (false); - part = _make_part(ft_substr(s, start, *i - start), get_quote_type(quote)); + part = _make_part(ft_substr(s, start, *i - start), _get_quote_type(quote)); if (!part) return (false); ft_lstadd_back(parts, ft_lstnew(part)); From bdae7d8381adc2f593c725bbe201e1ee2ffb7843 Mon Sep 17 00:00:00 2001 From: Takuma Tsubo Date: Tue, 6 May 2025 13:26:00 +0900 Subject: [PATCH 03/12] bug fix --- src/parser/split_by_quote.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/parser/split_by_quote.c b/src/parser/split_by_quote.c index 092377f..0198b7f 100644 --- a/src/parser/split_by_quote.c +++ b/src/parser/split_by_quote.c @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/06 13:03:29 by ttsubo #+# #+# */ -/* Updated: 2025/05/06 13:17:46 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 13:24:13 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -41,7 +41,7 @@ static bool _handle_unquoted_segment(const char *s, size_t *i, t_list **parts) t_part *part; start = *i; - while (s[*i] && is_quote(s[*i])) + while (s[*i] && !is_quote(s[*i])) (*i)++; if (*i == start) return (false); From 860f283202abe6052f140d5bfac71bc79404d32b Mon Sep 17 00:00:00 2001 From: Takuma Tsubo Date: Tue, 6 May 2025 13:30:33 +0900 Subject: [PATCH 04/12] =?UTF-8?q?$=3F=E5=AF=BE=E5=BF=9C(=E7=B0=A1=E6=98=93?= =?UTF-8?q?=E7=89=88=20=E6=96=87=E5=AD=97=E5=88=97=E3=81=AE=E9=80=94?= =?UTF-8?q?=E4=B8=AD=E3=81=AF=E6=A4=9C=E7=9F=A5=E3=81=9B=E3=81=9A)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/parser/expand_env.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/parser/expand_env.c b/src/parser/expand_env.c index c8dca0b..5159de6 100644 --- a/src/parser/expand_env.c +++ b/src/parser/expand_env.c @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/26 09:15:09 by ttsubo #+# #+# */ -/* Updated: 2025/04/26 20:56:43 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 13:28:18 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -88,6 +88,8 @@ char *expand_env(char *token, t_minish *minish) t_expand_temp tmp; char *result; + if (ft_strncmp(token, "$?", 2) == 0) + return (ft_itoa(minish->last_status)); env_ptr = ft_strchr(token, '$'); if (!env_ptr) return (ft_strdup(token)); From e942f89fbf624a3e6199f14fcc25c3eb139dbd27 Mon Sep 17 00:00:00 2001 From: Takuma Tsubo Date: Tue, 6 May 2025 14:05:08 +0900 Subject: [PATCH 05/12] create_expand_vars --- .../expand_env.h => parser/expand_vars.h} | 11 +++-- inc/parser/parser.h | 5 ++- src/parser/expand_env.c | 41 ++++++++++++------- src/parser/join_expanded_parts.c | 4 +- 4 files changed, 37 insertions(+), 24 deletions(-) rename inc/{builtin/expand_env.h => parser/expand_vars.h} (81%) diff --git a/inc/builtin/expand_env.h b/inc/parser/expand_vars.h similarity index 81% rename from inc/builtin/expand_env.h rename to inc/parser/expand_vars.h index 5df7632..db79f6f 100644 --- a/inc/builtin/expand_env.h +++ b/inc/parser/expand_vars.h @@ -1,20 +1,19 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* expand_env.h :+: :+: :+: */ +/* expand_vars.h :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/26 11:24:25 by ttsubo #+# #+# */ -/* Updated: 2025/05/04 12:15:01 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 14:02:52 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ -#ifndef EXPAND_ENV_H -# define EXPAND_ENV_H +#ifndef EXPAND_VARS_H +# define EXPAND_VARS_H # include "common.h" -# include "env_utils.h" # include "struct.h" # include @@ -34,6 +33,6 @@ typedef struct s_expand_temp char *result; } t_expand_temp; -char *expand_env(char *token, t_minish *minish); +char *expand_vars(const char *token, t_minish *minish); #endif \ No newline at end of file diff --git a/inc/parser/parser.h b/inc/parser/parser.h index e80dab9..52834b6 100644 --- a/inc/parser/parser.h +++ b/inc/parser/parser.h @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/21 14:14:59 by ttsubo #+# #+# */ -/* Updated: 2025/05/06 13:14:12 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 14:01:10 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,7 +14,8 @@ # define PARSER_H # include "common.h" -# include "expand_env.h" +# include "env_utils.h" +# include "expand_vars.h" # include "libft.h" typedef enum e_quote diff --git a/src/parser/expand_env.c b/src/parser/expand_env.c index 5159de6..7560963 100644 --- a/src/parser/expand_env.c +++ b/src/parser/expand_env.c @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/26 09:15:09 by ttsubo #+# #+# */ -/* Updated: 2025/05/06 13:28:18 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 14:03:12 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -62,8 +62,8 @@ static void _free_tmp(t_expand_temp *tmp) free(tmp->suffix); } -static void _set_tmpstr(t_minish *minish, char *token, - t_expand_env *ex_env, t_expand_temp *tmp) +static void _set_tmpstr(t_minish *minish, const char *token, t_expand_env *ex_env, + t_expand_temp *tmp) { tmp->key = _ft_strndup(token + ex_env->key_st, ex_env->key_len); tmp->value = ft_strdup(get_env_value(minish->env, tmp->key)); @@ -74,14 +74,8 @@ static void _set_tmpstr(t_minish *minish, char *token, tmp->result = _join_str(*tmp); } -/** - * @brief Expand env vars beginning with $ in the tkn->input str. - * - * @param tkn - * @param minish - * @return t_tokenizer* - */ -char *expand_env(char *token, t_minish *minish) +static char *_expand_one(const char *token, t_minish *minish, + bool *has_expandable) { const char *env_ptr; t_expand_env ex_env; @@ -92,19 +86,38 @@ char *expand_env(char *token, t_minish *minish) return (ft_itoa(minish->last_status)); env_ptr = ft_strchr(token, '$'); if (!env_ptr) - return (ft_strdup(token)); + return (*has_expandable = false, ft_strdup(token)); ft_bzero(&tmp, sizeof(tmp)); ex_env.key_len = 0; ex_env.pre_len = env_ptr - token; ex_env.key_st = ex_env.pre_len + 1; if (!is_key_start(token[ex_env.key_st])) - return (ft_strdup(token)); + return (*has_expandable = false, ft_strdup(token)); while (is_key_char(token[ex_env.key_st + ex_env.key_len])) ex_env.key_len++; _set_tmpstr(minish, token, &ex_env, &tmp); if (!tmp.result) - return (_free_tmp(&tmp), ft_strdup(token)); + return (*has_expandable = false, _free_tmp(&tmp), ft_strdup(token)); result = ft_strdup(tmp.result); _free_tmp(&tmp); return (result); } + +char *expand_vars(const char *token, t_minish *minish) +{ + bool has_expandable; + char *result; + char *next; + + result = ft_strdup(token); + if (!result) + return (NULL); + has_expandable = true; + while (has_expandable) + { + next = _expand_one(result, minish, &has_expandable); + free(result); + result = next; + } + return (result); +} \ No newline at end of file diff --git a/src/parser/join_expanded_parts.c b/src/parser/join_expanded_parts.c index be7eef5..a73c379 100644 --- a/src/parser/join_expanded_parts.c +++ b/src/parser/join_expanded_parts.c @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/06 13:05:02 by ttsubo #+# #+# */ -/* Updated: 2025/05/06 13:18:19 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 13:56:52 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -39,7 +39,7 @@ char *join_expanded_parts(t_list *parts, t_minish *minish) if (part->quote == QUOTE_SINGLE) tmp = ft_strdup(part->text); else - tmp = expand_env(part->text, minish); + tmp = expand_vars(part->text, minish); if (!tmp) return (free_str(&result), NULL); result = strjoin_and_free(result, tmp); From fd9f916adb260583b187fa20b6dc85f9d1845033 Mon Sep 17 00:00:00 2001 From: Takuma Tsubo Date: Tue, 6 May 2025 15:12:21 +0900 Subject: [PATCH 06/12] =?UTF-8?q?expand=5Fenv=E3=82=92=E5=A4=A7=E5=B9=85?= =?UTF-8?q?=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- inc/parser/expand_vars.h | 4 +- inc/parser/parser.h | 3 +- src/parser/expand_env.c | 134 ++++++++++++++++----------------------- 3 files changed, 60 insertions(+), 81 deletions(-) diff --git a/inc/parser/expand_vars.h b/inc/parser/expand_vars.h index db79f6f..827bd7c 100644 --- a/inc/parser/expand_vars.h +++ b/inc/parser/expand_vars.h @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/26 11:24:25 by ttsubo #+# #+# */ -/* Updated: 2025/05/06 14:02:52 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 14:44:25 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -33,6 +33,6 @@ typedef struct s_expand_temp char *result; } t_expand_temp; -char *expand_vars(const char *token, t_minish *minish); +char *expand_vars(const char *token, t_minish *minish); #endif \ No newline at end of file diff --git a/inc/parser/parser.h b/inc/parser/parser.h index 52834b6..b0b40f0 100644 --- a/inc/parser/parser.h +++ b/inc/parser/parser.h @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/21 14:14:59 by ttsubo #+# #+# */ -/* Updated: 2025/05/06 14:01:10 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 14:26:28 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -49,5 +49,6 @@ t_cmd **allocate_cmds(char **tokens); t_cmd **setup_cmds(t_cmd **cmds, char **tokens); t_list *split_by_quote(char *token); char *join_expanded_parts(t_list *parts, t_minish *minish); +char *strjoin_and_free(char *s1, char *s2); #endif \ No newline at end of file diff --git a/src/parser/expand_env.c b/src/parser/expand_env.c index 7560963..92ad838 100644 --- a/src/parser/expand_env.c +++ b/src/parser/expand_env.c @@ -6,108 +6,86 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/26 09:15:09 by ttsubo #+# #+# */ -/* Updated: 2025/05/06 14:03:12 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 15:10:47 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ +#include "expand_vars.h" #include "parser.h" -static char *_ft_strndup(const char *s1, size_t n) +static char *_expand_sts(int last_status, size_t *i) { - char *d; - - if (!s1) - return (NULL); - d = malloc(n + 1); - if (!d) - return (NULL); - ft_strlcpy(d, s1, n + 1); - return (d); + *i = *i + 1; + return (ft_itoa(last_status)); } -static char *_join_str(t_expand_temp tmp) +static char *_expand_var(const char *token, size_t *i, t_minish *minish) { - size_t pre_len; - size_t val_len; - size_t suff_len; - size_t total_len; - char *result; + size_t len; + char *key; + char *value; - pre_len = ft_strlen(tmp.prefix); - val_len = ft_strlen(tmp.value); - suff_len = ft_strlen(tmp.suffix); - total_len = pre_len + val_len + suff_len + 1; - result = malloc(total_len); - if (!result) - return (NULL); - ft_strlcpy(result, tmp.prefix, total_len); - ft_strlcat(result, tmp.value, total_len); - ft_strlcat(result, tmp.suffix, total_len); - return (result); + len = 0; + while (is_key_char(token[*i + len])) + len++; + key = ft_substr(token, *i, len); + value = ft_strdup(get_env_value(minish->env, key)); + free_str(&key); + *i += len; + if (!value) + return (ft_strdup("")); + else + return (value); } -/** - * @brief expand_temp is used to release memory allocations. - * - * @param tmp - * @note tmp->suffix is part of tkn->input, so free() is not executed. - * @note tmp->result is assigned to tkn->input, so free() is not executed. - */ -static void _free_tmp(t_expand_temp *tmp) +static char *_expand_dollar(const char *token, size_t *i, t_minish *minish, + bool *has_expandable) { - free(tmp->key); - free(tmp->value); - free(tmp->result); - free(tmp->prefix); - free(tmp->suffix); -} + char *tmp; -static void _set_tmpstr(t_minish *minish, const char *token, t_expand_env *ex_env, - t_expand_temp *tmp) -{ - tmp->key = _ft_strndup(token + ex_env->key_st, ex_env->key_len); - tmp->value = ft_strdup(get_env_value(minish->env, tmp->key)); - if (!tmp->value) - tmp->value = ft_strdup(""); - tmp->prefix = _ft_strndup(token, ex_env->pre_len); - tmp->suffix = ft_strdup(token + ex_env->key_st + ex_env->key_len); - tmp->result = _join_str(*tmp); + *has_expandable = true; + if (token[*i] == '?') + tmp = _expand_sts(minish->last_status, i); + else if (is_key_start(token[*i])) + tmp = _expand_var(token, i, minish); + else + tmp = ft_strdup("$"); + return (tmp); } static char *_expand_one(const char *token, t_minish *minish, bool *has_expandable) { - const char *env_ptr; - t_expand_env ex_env; - t_expand_temp tmp; - char *result; + char *result; + char *tmp; + size_t i; - if (ft_strncmp(token, "$?", 2) == 0) - return (ft_itoa(minish->last_status)); - env_ptr = ft_strchr(token, '$'); - if (!env_ptr) - return (*has_expandable = false, ft_strdup(token)); - ft_bzero(&tmp, sizeof(tmp)); - ex_env.key_len = 0; - ex_env.pre_len = env_ptr - token; - ex_env.key_st = ex_env.pre_len + 1; - if (!is_key_start(token[ex_env.key_st])) - return (*has_expandable = false, ft_strdup(token)); - while (is_key_char(token[ex_env.key_st + ex_env.key_len])) - ex_env.key_len++; - _set_tmpstr(minish, token, &ex_env, &tmp); - if (!tmp.result) - return (*has_expandable = false, _free_tmp(&tmp), ft_strdup(token)); - result = ft_strdup(tmp.result); - _free_tmp(&tmp); + result = ft_strdup(""); + if (!result) + return (NULL); + i = 0; + *has_expandable = false; + while (token[i]) + { + if (token[i] == '$') + { + i++; + tmp = _expand_dollar(token, &i, minish, has_expandable); + } + else + tmp = ft_substr(token, i++, 1); + if (!tmp) + return (free_str(&result), NULL); + result = strjoin_and_free(result, tmp); + } return (result); } char *expand_vars(const char *token, t_minish *minish) { - bool has_expandable; - char *result; - char *next; + bool has_expandable; + char *result; + char *next; result = ft_strdup(token); if (!result) @@ -120,4 +98,4 @@ char *expand_vars(const char *token, t_minish *minish) result = next; } return (result); -} \ No newline at end of file +} From b5c5ed9e5060241e87e3b2754f9de054adaa8ae0 Mon Sep 17 00:00:00 2001 From: Takuma Tsubo Date: Tue, 6 May 2025 15:12:54 +0900 Subject: [PATCH 07/12] =?UTF-8?q?debug=20print=20=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/parser/expand_tokens.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/parser/expand_tokens.c b/src/parser/expand_tokens.c index 6bd0ce0..79a5295 100644 --- a/src/parser/expand_tokens.c +++ b/src/parser/expand_tokens.c @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/02 17:08:42 by ttsubo #+# #+# */ -/* Updated: 2025/05/06 13:14:37 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 15:12:41 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -60,7 +60,6 @@ char **expand_tokens(char **tokens, t_minish *minish) while (i < count) { result[i] = expand_token(tokens[i], minish); - printf("DBG:expand: '%s' → '%s'\n", tokens[i], result[i]); if (!result[i]) return (free_strs(&result), NULL); i++; From 39a37a511422a2c13d91e7f05e282912be58e9b4 Mon Sep 17 00:00:00 2001 From: cacapon Date: Tue, 6 May 2025 19:20:15 +0900 Subject: [PATCH 08/12] add has_closing_quote --- inc/common/common.h | 3 ++- src/common/is_quote.c | 13 ++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/inc/common/common.h b/inc/common/common.h index a341b36..8f27c74 100644 --- a/inc/common/common.h +++ b/inc/common/common.h @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/29 11:44:19 by ttsubo #+# #+# */ -/* Updated: 2025/05/05 18:38:08 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 19:16:39 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -25,6 +25,7 @@ bool is_key_start(int c); bool is_key_char(int c); bool is_valid_key(char *str); bool is_quote(char c); +bool has_closing_quote(const char *s, char quote, size_t i); void error_mes(char *name, char *mes); #endif \ No newline at end of file diff --git a/src/common/is_quote.c b/src/common/is_quote.c index c00eccf..d6ab2b1 100644 --- a/src/common/is_quote.c +++ b/src/common/is_quote.c @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/05 14:07:03 by ttsubo #+# #+# */ -/* Updated: 2025/05/05 14:15:15 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 19:16:10 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,3 +16,14 @@ bool is_quote(char c) { return (c == '\'' || c == '"'); } + +bool has_closing_quote(const char *s, char quote, size_t i) +{ + while (s[i]) + { + if (s[i] == quote) + return (true); + i++; + } + return (false); +} From f4fb56692cc7f8bc4bcf648ed2c846f9112cee90 Mon Sep 17 00:00:00 2001 From: cacapon Date: Tue, 6 May 2025 19:20:38 +0900 Subject: [PATCH 09/12] add has_closing_quote --- inc/common/common.h | 4 ++-- src/common/is_quote.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/inc/common/common.h b/inc/common/common.h index 8f27c74..deb9201 100644 --- a/inc/common/common.h +++ b/inc/common/common.h @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/29 11:44:19 by ttsubo #+# #+# */ -/* Updated: 2025/05/06 19:16:39 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 19:19:56 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -25,7 +25,7 @@ bool is_key_start(int c); bool is_key_char(int c); bool is_valid_key(char *str); bool is_quote(char c); -bool has_closing_quote(const char *s, char quote, size_t i); +bool has_closing_quote(const char *s, char quote, size_t i); void error_mes(char *name, char *mes); #endif \ No newline at end of file diff --git a/src/common/is_quote.c b/src/common/is_quote.c index d6ab2b1..d16061e 100644 --- a/src/common/is_quote.c +++ b/src/common/is_quote.c @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/05 14:07:03 by ttsubo #+# #+# */ -/* Updated: 2025/05/06 19:16:10 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 19:20:10 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,7 +17,7 @@ bool is_quote(char c) return (c == '\'' || c == '"'); } -bool has_closing_quote(const char *s, char quote, size_t i) +bool has_closing_quote(const char *s, char quote, size_t i) { while (s[i]) { From 5d99fc25340db199a6c7aa74739d74114f2bb8ad Mon Sep 17 00:00:00 2001 From: cacapon Date: Tue, 6 May 2025 20:11:40 +0900 Subject: [PATCH 10/12] =?UTF-8?q?=E9=96=89=E3=81=98=E3=81=A6=E3=81=84?= =?UTF-8?q?=E3=81=AA=E3=81=84=E3=82=B7=E3=83=B3=E3=82=B0=E3=83=AB=E3=82=AF?= =?UTF-8?q?=E3=82=AA=E3=83=BC=E3=83=88=E3=81=AE=E5=AF=BE=E5=BF=9C=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/parser/split_by_quote.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/parser/split_by_quote.c b/src/parser/split_by_quote.c index 0198b7f..5df8518 100644 --- a/src/parser/split_by_quote.c +++ b/src/parser/split_by_quote.c @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/06 13:03:29 by ttsubo #+# #+# */ -/* Updated: 2025/05/06 13:24:13 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 20:10:34 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -39,16 +39,28 @@ static bool _handle_unquoted_segment(const char *s, size_t *i, t_list **parts) { size_t start; t_part *part; + char *one; + bool i_eq_st; start = *i; + i_eq_st = false; while (s[*i] && !is_quote(s[*i])) (*i)++; if (*i == start) + { + i_eq_st = true; + one = ft_substr(s, *i, 1); + if (!one) return (false); + part = _make_part(one, QUOTE_NONE); + } + else part = _make_part(ft_substr(s, start, *i - start), QUOTE_NONE); if (!part) return (false); ft_lstadd_back(parts, ft_lstnew(part)); + if (i_eq_st) + (*i)++; return (true); } @@ -81,7 +93,7 @@ t_list *split_by_quote(char *token) i = 0; while (token[i]) { - if (is_quote(token[i])) + if (is_quote(token[i]) && has_closing_quote(token, token[i], i)) { if (!_handle_quoted_segment(token, &i, &parts)) return (ft_lstclear(&parts, free), NULL); From 1ae6dfe5b31eda4d595ecd76f39c79915cb29a68 Mon Sep 17 00:00:00 2001 From: cacapon Date: Tue, 6 May 2025 20:37:23 +0900 Subject: [PATCH 11/12] bug fix --- src/parser/split_by_quote.c | 9 +++++---- src/parser/trim_quote_tokens.c | 3 +-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/parser/split_by_quote.c b/src/parser/split_by_quote.c index 5df8518..5c68665 100644 --- a/src/parser/split_by_quote.c +++ b/src/parser/split_by_quote.c @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/06 13:03:29 by ttsubo #+# #+# */ -/* Updated: 2025/05/06 20:10:34 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 20:33:18 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -67,16 +67,17 @@ static bool _handle_unquoted_segment(const char *s, size_t *i, t_list **parts) static bool _handle_quoted_segment(const char *s, size_t *i, t_list **parts) { char quote; - size_t start; + size_t i_st; t_part *part; quote = s[*i]; - start = ++(*i); + i_st = (*i)++; while (s[*i] && s[*i] != quote) (*i)++; if (!s[*i]) return (false); - part = _make_part(ft_substr(s, start, *i - start), _get_quote_type(quote)); + (*i)++; + part = _make_part(ft_substr(s, i_st, *i - i_st), _get_quote_type(quote)); if (!part) return (false); ft_lstadd_back(parts, ft_lstnew(part)); diff --git a/src/parser/trim_quote_tokens.c b/src/parser/trim_quote_tokens.c index 22a3ff3..79f787b 100644 --- a/src/parser/trim_quote_tokens.c +++ b/src/parser/trim_quote_tokens.c @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/05 14:52:11 by ttsubo #+# #+# */ -/* Updated: 2025/05/05 14:52:43 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 20:12:44 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -29,7 +29,6 @@ static void _copy_quoted_content(char *token, char *result, size_t *pt_i, else { r_i = *pr_i; - result[r_i++] = quote; t_i = *pt_i; while (token[t_i]) result[r_i++] = token[t_i++]; From 873b0d157cf560929ce8af17383ab3b6cb770ca5 Mon Sep 17 00:00:00 2001 From: cacapon Date: Tue, 6 May 2025 20:50:19 +0900 Subject: [PATCH 12/12] =?UTF-8?q?=E6=9D=A1=E4=BB=B6=E5=BC=8F=E3=82=92?= =?UTF-8?q?=E6=AD=A3=E3=81=97=E3=81=8F=E5=8B=95=E3=81=8B=E3=81=9B=E3=81=A6?= =?UTF-8?q?=E3=81=AA=E3=81=8B=E3=81=A3=E3=81=9F=E7=AE=87=E6=89=80=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/parser/split_by_quote.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/parser/split_by_quote.c b/src/parser/split_by_quote.c index 5c68665..bc05c77 100644 --- a/src/parser/split_by_quote.c +++ b/src/parser/split_by_quote.c @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/06 13:03:29 by ttsubo #+# #+# */ -/* Updated: 2025/05/06 20:33:18 by ttsubo ### ########.fr */ +/* Updated: 2025/05/06 20:50:12 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -51,11 +51,11 @@ static bool _handle_unquoted_segment(const char *s, size_t *i, t_list **parts) i_eq_st = true; one = ft_substr(s, *i, 1); if (!one) - return (false); + return (false); part = _make_part(one, QUOTE_NONE); } else - part = _make_part(ft_substr(s, start, *i - start), QUOTE_NONE); + part = _make_part(ft_substr(s, start, *i - start), QUOTE_NONE); if (!part) return (false); ft_lstadd_back(parts, ft_lstnew(part)); @@ -94,7 +94,7 @@ t_list *split_by_quote(char *token) i = 0; while (token[i]) { - if (is_quote(token[i]) && has_closing_quote(token, token[i], i)) + if (is_quote(token[i]) && has_closing_quote(token, token[i], i + 1)) { if (!_handle_quoted_segment(token, &i, &parts)) return (ft_lstclear(&parts, free), NULL);