/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* command_list.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: khais +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/02/24 17:49:46 by khais #+# #+# */ /* Updated: 2025/02/26 16:53:55 by khais ### ########.fr */ /* */ /* ************************************************************************** */ #include "command_list.h" #include "command_list_builder.h" #include "operator.h" #include "libft.h" #include "../../ft_errno.h" #include #include /* ** Advance the state to the next word */ static void cmdlist_builder_next_word( t_cmdlist_builder *builder, t_wordlist **words) { builder->current_wordlist = wordlist_push(builder->current_wordlist, builder->current_word); builder->current_word = wordlist_pop(words); } /* ** return true if we are currently adding the last pipeline in the chain */ static bool cmdlist_builder_at_last_pipeline(t_cmdlist_builder *builder) { return (builder->idx == builder->cmdlist->num_pipelines - 1); } /* ** Frees all memory associated with this builder and set error to true. */ static void cmdlist_builder_error(t_cmdlist_builder *builder) { if (builder == NULL) return ; cmdlist_destroy(builder->cmdlist); ft_dprintf(STDERR_FILENO, "current wordlist: %p\n", builder->current_wordlist); ft_dprintf(STDERR_FILENO, "current wordlist->word: %p\n", builder->current_wordlist->word); wordlist_destroy(builder->current_wordlist); ft_dprintf(STDERR_FILENO, "current wordlist has been freed: %p\n", builder->current_wordlist); worddesc_destroy(builder->current_word); builder->error = true; } /* ** Delimit the current pipeline, creating a new t_pipeline object. ** ** Sets the operator for that pipeline. ** ** Assumes that the current word is a valid operator. */ static void cmdlist_builder_delimit( t_cmdlist_builder *builder, t_wordlist **words) { ft_dprintf(STDERR_FILENO, "delimit: "); wordlist_debug(builder->current_wordlist); builder->cmdlist->pipelines[builder->idx] = pipeline_from_wordlist(builder->current_wordlist); if (builder->cmdlist->pipelines[builder->idx] == NULL) { ft_perror("invalid pipeline"); cmdlist_builder_error(builder); ft_dprintf(STDERR_FILENO, "destroyed builder\n"); return ; } if (cmdlist_builder_at_last_pipeline(builder)) builder->cmdlist->operators[builder->idx] = OP_END; else builder->cmdlist->operators[builder->idx] = match_op(builder->current_word->word); builder->current_wordlist = NULL; worddesc_destroy(builder->current_word); builder->current_word = wordlist_pop(words); builder->idx++; } /* ** Create a new command list from the given wordlist. */ t_cmdlist *cmdlist_from_wordlist(t_wordlist *words) { t_cmdlist_builder builder; if (setup_cmdlist_builder(&builder, &words) == NULL) return (NULL); while (builder.error == false && builder.current_word != NULL) { ft_dprintf(STDERR_FILENO, "current word: %s\n", builder.current_word->word); if (match_op(builder.current_word->word) == OP_INVALID) cmdlist_builder_next_word(&builder, &words); else cmdlist_builder_delimit(&builder, &words); } if (builder.error) return (NULL); if (builder.current_wordlist != NULL) cmdlist_builder_delimit(&builder, &words); return (builder.cmdlist); } /* ** destroy the given command list and all associated memory */ void cmdlist_destroy(t_cmdlist *cmd) { int i; if (cmd == NULL) return ; i = 0; while (i < cmd->num_pipelines) { pipeline_destroy(cmd->pipelines[i]); i++; } free(cmd->pipelines); free(cmd->operators); free(cmd); }