minishell/src/parser/cmdlist/cmdlist.c
Khaïs COLIN 73a64b2ec3
fix potential memory leak in cmdlist_from_wordlist
This leak would happen if the alocation of the builder fails. In that case, we
don't free our copy of the wordlist
2025-03-28 14:50:37 +01:00

117 lines
3.5 KiB
C

/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* cmdlist.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/24 17:49:46 by khais #+# #+# */
/* Updated: 2025/03/20 12:23:39 by khais ### ########.fr */
/* */
/* ************************************************************************** */
#include "cmdlist.h"
#include "cmdlist_item.h"
#include "cmdlist_builder.h"
#include "cmdlist_item_type.h"
#include "operator.h"
#include <unistd.h>
#include <stdlib.h>
/*
** 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);
builder->cmdlist = NULL;
wordlist_destroy(builder->current_wordlist);
builder->current_wordlist = NULL;
worddesc_destroy(builder->current_word);
builder->current_word = NULL;
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)
{
builder->cmdlist->cmds[builder->idx] = cmdlist_item_create();
builder->cmdlist->cmds[builder->idx]->inner.pipeline
= pipeline_from_wordlist(builder->current_wordlist);
builder->cmdlist->cmds[builder->idx]->type = TYPE_PIPELINE;
if (builder->cmdlist->cmds[builder->idx]->inner.pipeline == NULL)
{
cmdlist_builder_error(builder);
wordlist_destroy(*words);
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);
wordlist_destroy(builder->current_wordlist);
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.
**
** Makes a copy of the given wordlist
*/
t_cmdlist *cmdlist_from_wordlist(const t_wordlist *wordlist)
{
t_cmdlist_builder builder;
t_wordlist *words;
words = wordlist_copy(wordlist);
if (words == NULL)
return (NULL);
if (setup_cmdlist_builder(&builder, &words) == NULL)
return (wordlist_destroy(words), NULL);
while (builder.error == false && builder.current_word != NULL)
{
if (match_op(builder.current_word->word) == OP_INVALID)
cmdlist_builder_next_word(&builder, &words);
else
cmdlist_builder_delimit(&builder, &words);
}
if (builder.current_wordlist != NULL)
cmdlist_builder_delimit(&builder, &words);
if (builder.error == true)
return (NULL);
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_cmd)
{
cmdlist_item_destroy(cmd->cmds[i]);
i++;
}
free(cmd->cmds);
free(cmd->operators);
free(cmd);
}