diff --git a/src/destroy_cmds.c b/src/destroy_cmds.c new file mode 100644 index 0000000..5877b62 --- /dev/null +++ b/src/destroy_cmds.c @@ -0,0 +1,76 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* destroy_cmds.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jguelen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/08 14:26:06 by jguelen #+# #+# */ +/* Updated: 2025/04/08 15:32:12 by jguelen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +void simple_cmd_destroy(t_simple_cmd *cmd) +{ + wordlist_destroy(cmd->words); + redirect_destroy(cmd->redirections); + free(cmd); +} + +void group_cmd_destroy(t_group_cmd *cmd) +{ + t_cmd_destroy(cmd->cmd); + redirect_destroy(cmd->redirects); + free(cmd); +} + +void connec_cmd_destroy(t_connec_cmd *cmd) +{ + t_cmd_destroy(cmd->first); + t_cmd_destroy(cmd->second); + free(cmd); +} + +/* +** here_doc_eof is currently unused so it might disappear. +*/ +void redirect_destroy(t_redirect *redirections) +{ + t_redirect *tmp; + + while (redirections) + { + free(redirections->here_doc_eof); + if (redirections->type == FT_HEREDOC) + close(redirections->redirectee.dest); + else + worddesc_destroy(redirections->redirectee.filename); + tmp = redirections; + redirections = redirections->next; + free(tmp); + } +} + +/* +** This function recursively destroys the whole command tree. +*/ +void t_cmd_destroy(t_cmd *cmd) +{ + if (cmd->type == FT_CONNECTION) + { + t_cmd_destroy(cmd->value.connection->first); + t_cmd_destroy(cmd->value.connection->second); + free(cmd); + return ; + } + if (cmd->type == FT_GROUP) + { + redirect_destroy(cmd->value.group->redirects); + t_cmd_destroy(cmd->value.group->cmd); + free(cmd); + return ; + } + simple_cmd_destroy(cmd->value.simple); +} diff --git a/src/minishell.h b/src/minishell.h index 1b8b67d..55c9dcb 100644 --- a/src/minishell.h +++ b/src/minishell.h @@ -6,7 +6,7 @@ /* By: jguelen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/03/28 14:55:31 by khais #+# #+# */ -/* Updated: 2025/04/07 18:09:12 by jguelen ### ########.fr */ +/* Updated: 2025/04/08 15:12:29 by jguelen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -67,7 +67,6 @@ typedef struct s_cmd ** Line number the command starts on -> will probably be unused. */ int line; - t_redirect *redirects; union u_value { struct s_connec_cmd *connection; @@ -121,4 +120,13 @@ typedef struct s_minishell int last_return_value; } t_minishell; +void simple_cmd_destroy(t_simple_cmd *cmd); +void group_cmd_destroy(t_group_cmd *cmd); +void connec_cmd_destroy(t_connec_cmd *cmd); +void redirect_destroy(t_redirect *redirections); +/* +** This function recursively destroys the whole command tree. +*/ +void t_cmd_destroy(t_cmd *cmd); + #endif diff --git a/src/parser/cmd_parsing.c b/src/parser/cmd_parsing.c index 46e0878..ff6099a 100644 --- a/src/parser/cmd_parsing.c +++ b/src/parser/cmd_parsing.c @@ -6,7 +6,7 @@ /* By: jguelen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/03/31 10:28:28 by jguelen #+# #+# */ -/* Updated: 2025/04/08 13:01:32 by jguelen ### ########.fr */ +/* Updated: 2025/04/08 16:02:39 by jguelen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,7 +16,8 @@ ** NOTE: This file will temporarily include way more functions than allowed. */ /* -** Maybe include desctruction of builder contents here. +** TODO Check if builder grows that destruction is appropriate. +** TODO Remove debugs */ void parse_error(t_minishell *app, t_worddesc *token) { @@ -95,33 +96,24 @@ ft_printf("%s() %s\n", __FUNCTION__, builder->tokens->word->word); return ((t_cmd *)NULL); } -t_cmd *minishell_pipeline_parse(t_minishell *app, t_cmd_builder *builder) -{ -ft_printf("%s() %s\n", __FUNCTION__, builder->tokens->word->word); - t_cmd *subtree; - - subtree = minishell_group_or_smp_parse(app, builder); - - - - - return (subtree); -} - -static t_cmd *cmds_parse_reorient_subtree(t_cmd **list, t_cmd **subtree, +static t_cmd *connec_reorient_subtree(t_cmd **list, t_cmd **subtree, t_cmd **opt, t_connector connec) { *list = ft_calloc(1, sizeof(t_cmd)); if (!*list) { ft_errno(FT_ENOMEM); - return (ft_perror("minishell_cmds_parse"), NULL); + t_cmd_destroy(*subtree); + t_cmd_destroy(*opt); + return (NULL); } (*list)->value.connection = ft_calloc(1, sizeof(t_connec_cmd)); if (!(*list)->value.connection) { ft_errno(FT_ENOMEM); - return (ft_perror("minishell_cmds_parse"), NULL); + t_cmd_destroy(*subtree); + t_cmd_destroy(*opt); + return (free(*list), NULL); } (*list)->type = FT_CONNECTION; (*list)->value.connection->connector = connec; @@ -131,6 +123,36 @@ static t_cmd *cmds_parse_reorient_subtree(t_cmd **list, t_cmd **subtree, return (*subtree); } +t_cmd *minishell_pipeline_parse(t_minishell *app, t_cmd_builder *builder) +{ + t_cmd *subtree; + t_cmd *opt; + t_cmd *pipeline; + +ft_printf("%s() %s\n", __FUNCTION__, builder->tokens->word->word); + + subtree = minishell_group_or_smp_parse(app, builder); + if (!subtree) + return (NULL); + opt = minishell_opt_pipeline_parse(app, builder); + if (!opt && ft_errno_get() != FT_ESUCCESS) + return (NULL); + if (!opt) + return (subtree); + while (opt) + { + if (connec_reorient_subtree(&pipeline, &subtree, &opt, FT_PIPE) == NULL) + { + app->last_return_value = 1; + return (ft_perror("minishell_pipeline_parse"), NULL); + } + opt = minishell_opt_pipeline_parse(app, builder); + } + if (ft_errno_get() != FT_ESUCCESS) + return (t_cmd_destroy(subtree), NULL); + return (pipeline); +} + /* ** Parse list of commands or pipeline. */ @@ -146,28 +168,28 @@ ft_printf("%s() %s\n", __FUNCTION__, builder->tokens->word->word); subtree = minishell_pipeline_parse(app, builder); if (!subtree) - return (NULL); //ft_errno? - opt = minishell_opt_cmds_parse(app, builder, &connec); - if (!opt && ft_errno_get() != FT_ESUCCESS) //error probably already signaled return (NULL); - if (!opt) //Simple Pipeline of some form + opt = minishell_opt_cmds_parse(app, builder, &connec); + if (!opt && ft_errno_get() != FT_ESUCCESS) + return (t_cmd_destroy(subtree), NULL); + if (!opt) return (subtree); while (opt) { - if (cmds_parse_reorient_subtree(&list, &subtree, &opt, connec) == NULL) + if (connec_reorient_subtree(&list, &subtree, &opt, connec) == NULL) { app->last_return_value = 1; - return (NULL); + return (ft_perror("minishell_cmds_parse"), NULL); } opt = minishell_opt_cmds_parse(app, builder, &connec); } if (ft_errno_get() != FT_ESUCCESS) - return (NULL); + return (destroy(subtree), NULL); return (list); } /* -** TODO Include destruction of builder contents if necessary. +** TODO check if we need to differentiate the cause of a NULL return. */ t_cmd *minishell_parse(t_minishell *app, char *command_line) { @@ -182,11 +204,16 @@ t_cmd *minishell_parse(t_minishell *app, char *command_line) return (NULL); root_cmd = minishell_cmds_parse(app, &builder); if (!root_cmd) - return (NULL); // destroy builder contents? + { + wordlist_destroy(builder.tokens); + return (NULL); + } if (builder.tokens) { parse_error(app, builder.tokens->word); - return (NULL); /////// destroy builder contents? + wordlist_destroy(builder.tokens); + t_cmd_destroy(root_cmd); + return (NULL); } return (root_cmd); } diff --git a/src/parser/cmd_parsing.h b/src/parser/cmd_parsing.h index 8734817..35d4e4b 100644 --- a/src/parser/cmd_parsing.h +++ b/src/parser/cmd_parsing.h @@ -6,7 +6,7 @@ /* By: jguelen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/03/28 17:49:55 by jguelen #+# #+# */ -/* Updated: 2025/04/07 17:59:08 by jguelen ### ########.fr */ +/* Updated: 2025/04/08 13:55:42 by jguelen ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/parser/worddesc/worddesc.h b/src/parser/worddesc/worddesc.h index fc84edb..11f2f37 100644 --- a/src/parser/worddesc/worddesc.h +++ b/src/parser/worddesc/worddesc.h @@ -6,7 +6,7 @@ /* By: jguelen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/03/27 13:57:44 by khais #+# #+# */ -/* Updated: 2025/04/07 18:40:53 by jguelen ### ########.fr */ +/* Updated: 2025/04/08 16:25:37 by jguelen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -25,6 +25,21 @@ # define W_HASQUOTEDNULL 0b10000 /* word contains a quoted null character */ # define W_DQUOTE 0b100000 /* word should be treated as if double-quoted */ +typedef enum e_token_type +{ + NOT_TOKEN, + WORD_TOKEN, + OPEN_PARENTH_TOKEN, + CLOSE_PARENTH_TOKEN, + PIPE_TOKEN, + OR_TOKEN, + AND_TOKEN, + OUT_TRUNC_REDIR_TOKEN, + OUT_APPEND_REDIR_TOKEN, + IN_REDIR_TOKEN, + HERE_DOC_REDIR_TOKEN, +} t_token_type; + /* ** A logical word for the parser. ** @@ -37,13 +52,13 @@ typedef struct s_worddesc /* ** The word itself */ - char *word; + char *word; /* ** flags for this word **s_worddesc ** See above for flag definitions */ - char flags; + char flags; /* ** a character mask for word to designate the status ** of its characters and wether or not they are subject to modifications @@ -55,8 +70,8 @@ typedef struct s_worddesc ** '"' corresponding character is double-quoted ** '$' corresponding character is a result of $var expansion */ - char *marker; - int token_type; + char *marker; + t_token_type token_type; } t_worddesc; t_worddesc *worddesc_create(char *word, char flags, char *marker);