cmdlist: use new architecture (STUB)

I fixed the tests, and the basic functionallity of detecting pipelines works,
but detecting nested cmdgroups is not yet implemented
This commit is contained in:
Khaïs COLIN 2025-03-18 12:36:19 +01:00
parent 8f7e7f7dfe
commit 56fe943efc
Signed by: logistic-bot
SSH key fingerprint: SHA256:RlpiqKeXpcPFZZ4y9Ou4xi2M8OhRJovIwDlbCaMsuAo
13 changed files with 116 additions and 69 deletions

View file

@ -33,6 +33,7 @@ srcs = \
src/parser/cmdgroup/cmdgroup.c \ src/parser/cmdgroup/cmdgroup.c \
src/parser/command_list/command_list_builder.c \ src/parser/command_list/command_list_builder.c \
src/parser/command_list/command_list.c \ src/parser/command_list/command_list.c \
src/parser/command_list/command_list_item.c \
src/parser/command_list/operator.c \ src/parser/command_list/operator.c \
src/parser/matchers/blank.c \ src/parser/matchers/blank.c \
src/parser/matchers/identifier.c \ src/parser/matchers/identifier.c \

View file

@ -208,22 +208,22 @@ not remain in effect after the subshell completes.
The exit status of this construct is the exit status of LIST. The exit status of this construct is the exit status of LIST.
```c ```c
typedef enum e_cmdgroup_item_type typedef enum e_cmdlist_item_type
{ {
TYPE_INVALID, TYPE_INVALID,
TYPE_CMDGROUP, TYPE_CMDGROUP,
TYPE_PIPELINE, TYPE_PIPELINE,
} t_cmdgroup_item_type; } t_cmdlist_item_type;
typedef struct s_cmdlist_item typedef struct s_cmdlist_item
{ {
enum e_cmdgroup_item_type type; enum e_cmdlist_item_type type;
union u_cmdgroup_item_inner union u_cmdlist_item_inner
{ {
t_cmdgroup *cmdgroup; t_cmdgroup *cmdgroup;
struct s_pipeline *pipeline; struct s_pipeline *pipeline;
} inner; } inner;
} t_cmdgroup_item; } t_cmdlist_item;
typedef s_cmdlist typedef s_cmdlist
{ {

View file

@ -6,15 +6,16 @@
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */ /* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/24 17:49:46 by khais #+# #+# */ /* Created: 2025/02/24 17:49:46 by khais #+# #+# */
/* Updated: 2025/03/04 15:23:00 by khais ### ########.fr */ /* Updated: 2025/03/18 14:43:39 by khais ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "command_list.h" #include "command_list.h"
#include "command_list_item.h"
#include "command_list_builder.h" #include "command_list_builder.h"
#include "command_list_item_type.h"
#include "operator.h" #include "operator.h"
#include "libft.h" #include "libft.h"
#include "../../ft_errno.h"
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
@ -45,9 +46,11 @@ static void cmdlist_builder_delimit(
t_cmdlist_builder *builder, t_cmdlist_builder *builder,
t_wordlist **words) t_wordlist **words)
{ {
builder->cmdlist->pipelines[builder->idx] builder->cmdlist->cmds[builder->idx] = cmdlist_item_create();
builder->cmdlist->cmds[builder->idx]->inner.pipeline
= pipeline_from_wordlist(builder->current_wordlist); = pipeline_from_wordlist(builder->current_wordlist);
if (builder->cmdlist->pipelines[builder->idx] == NULL) builder->cmdlist->cmds[builder->idx]->type = TYPE_PIPELINE;
if (builder->cmdlist->cmds[builder->idx]->inner.pipeline == NULL)
{ {
cmdlist_builder_error(builder); cmdlist_builder_error(builder);
wordlist_destroy(*words); wordlist_destroy(*words);
@ -104,12 +107,12 @@ void cmdlist_destroy(t_cmdlist *cmd)
if (cmd == NULL) if (cmd == NULL)
return ; return ;
i = 0; i = 0;
while (i < cmd->num_pipelines) while (i < cmd->num_cmds)
{ {
pipeline_destroy(cmd->pipelines[i]); cmdlist_item_destroy(cmd->cmds[i]);
i++; i++;
} }
free(cmd->pipelines); free(cmd->cmds);
free(cmd->operators); free(cmd->operators);
free(cmd); free(cmd);
} }

View file

@ -6,7 +6,7 @@
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */ /* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/24 17:45:01 by khais #+# #+# */ /* Created: 2025/02/24 17:45:01 by khais #+# #+# */
/* Updated: 2025/03/09 14:22:19 by khais ### ########.fr */ /* Updated: 2025/03/18 12:59:56 by khais ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -16,6 +16,7 @@
# include "../wordlist/wordlist.h" # include "../wordlist/wordlist.h"
# include "../pipeline/pipeline.h" # include "../pipeline/pipeline.h"
# include "operator.h" # include "operator.h"
# include "../../buffer/buffer.h"
/* /*
** cf. 3.2.4 Lists of Commands ** cf. 3.2.4 Lists of Commands
@ -62,15 +63,15 @@
typedef struct s_cmdlist typedef struct s_cmdlist
{ {
/* /*
** Array of pipelines contained in this command list. ** Array of pointers to commands in this command list
** **
** These should be executed left to right. ** These should be executed left to right.
*/ */
t_pipeline **pipelines; struct s_cmdlist_item **cmds;
/* /*
** Number of pipelines in this command list. ** Number of commands in this command list.
*/ */
int num_pipelines; int num_cmds;
/* /*
** Operators that separate the pipelines. ** Operators that separate the pipelines.
** **
@ -85,5 +86,6 @@ typedef struct s_cmdlist
t_cmdlist *cmdlist_from_wordlist(const t_wordlist *wordlist); t_cmdlist *cmdlist_from_wordlist(const t_wordlist *wordlist);
void cmdlist_destroy(t_cmdlist *cmd); void cmdlist_destroy(t_cmdlist *cmd);
void cmdlist_debug(t_cmdlist *cmd, t_buffer **indent, bool is_last);
#endif // COMMAND_LIST_H #endif // COMMAND_LIST_H

View file

@ -6,7 +6,7 @@
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */ /* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/26 13:51:18 by khais #+# #+# */ /* Created: 2025/02/26 13:51:18 by khais #+# #+# */
/* Updated: 2025/03/09 14:24:05 by khais ### ########.fr */ /* Updated: 2025/03/18 13:31:57 by khais ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -53,15 +53,15 @@ static t_cmdlist *allocate_command_list(t_wordlist *words)
output = ft_calloc(1, sizeof(t_cmdlist)); output = ft_calloc(1, sizeof(t_cmdlist));
if (output == NULL) if (output == NULL)
return (NULL); return (NULL);
output->num_pipelines = command_list_count_pipelines(words); output->num_cmds = command_list_count_pipelines(words);
output->pipelines output->cmds
= ft_calloc(output->num_pipelines, sizeof(t_pipeline *)); = ft_calloc(output->num_cmds, sizeof(struct s_cmdlist_item **));
if (output->pipelines == NULL) if (output->cmds == NULL)
return (free(output), NULL); return (free(output), NULL);
output->operators output->operators
= ft_calloc(output->num_pipelines, sizeof(t_operator)); = ft_calloc(output->num_cmds, sizeof(t_operator));
if (output->operators == NULL) if (output->operators == NULL)
return (free(output->pipelines), free(output), NULL); return (free(output->cmds), free(output), NULL);
return (output); return (output);
} }
@ -100,5 +100,5 @@ void cmdlist_builder_next_word(
*/ */
bool cmdlist_builder_at_last_pipeline(t_cmdlist_builder *builder) bool cmdlist_builder_at_last_pipeline(t_cmdlist_builder *builder)
{ {
return (builder->idx == builder->cmdlist->num_pipelines - 1); return (builder->idx == builder->cmdlist->num_cmds - 1);
} }

View file

@ -6,7 +6,7 @@
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */ /* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/26 13:50:25 by khais #+# #+# */ /* Created: 2025/02/26 13:50:25 by khais #+# #+# */
/* Updated: 2025/03/04 15:23:55 by khais ### ########.fr */ /* Updated: 2025/03/18 12:59:57 by khais ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */

View file

@ -0,0 +1,36 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* command_list_item.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/03/18 13:02:02 by khais #+# #+# */
/* Updated: 2025/03/18 13:35:25 by khais ### ########.fr */
/* */
/* ************************************************************************** */
#include "command_list_item.h"
#include "libft.h"
void cmdlist_item_destroy(t_cmdlist_item *cmd)
{
if (cmd == NULL)
return ;
if (cmd->type == TYPE_CMDGROUP)
cmdgroup_destroy(cmd->inner.cmdgroup);
if (cmd->type == TYPE_PIPELINE)
pipeline_destroy(cmd->inner.pipeline);
free(cmd);
}
t_cmdlist_item *cmdlist_item_create(void)
{
t_cmdlist_item *item;
item = ft_calloc(1, sizeof(t_cmdlist_item));
if (item == NULL)
return (NULL);
item->type = TYPE_INVALID;
return (item);
}

View file

@ -1,30 +1,32 @@
/* ************************************************************************** */ /* ************************************************************************** */
/* */ /* */
/* ::: :::::::: */ /* ::: :::::::: */
/* cmdgroup_item.h :+: :+: :+: */ /* command_list_item.h :+: :+: :+: */
/* +:+ +:+ +:+ */ /* +:+ +:+ +:+ */
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */ /* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/03/11 15:43:15 by khais #+# #+# */ /* Created: 2025/03/18 12:54:31 by khais #+# #+# */
/* Updated: 2025/03/11 18:10:24 by khais ### ########.fr */ /* Updated: 2025/03/18 13:34:14 by khais ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef CMDGROUP_ITEM_H #ifndef COMMAND_LIST_ITEM_H
# define CMDGROUP_ITEM_H # define COMMAND_LIST_ITEM_H
# include "cmdgroup_item_type.h" # include "../cmdgroup/cmdgroup.h"
# include "../command_list/command_list.h" # include "command_list_item_type.h"
# include "cmdgroup.h"
typedef struct s_cmdgroup_item typedef struct s_cmdlist_item
{ {
enum e_cmdgroup_item_type type; enum e_cmdlist_item_type type;
union u_cmdgroup_item_inner union u_cmdlist_item_inner
{ {
t_cmdgroup *cmdgroup; t_cmdgroup *cmdgroup;
struct s_cmdlist *cmdlist; struct s_pipeline *pipeline;
} inner; } inner;
} t_cmdgroup_item; } t_cmdlist_item;
#endif // CMDGROUP_ITEM_H void cmdlist_item_destroy(t_cmdlist_item *cmd);
t_cmdlist_item *cmdlist_item_create(void);
#endif // COMMAND_LIST_ITEM_H

View file

@ -1,23 +1,23 @@
/* ************************************************************************** */ /* ************************************************************************** */
/* */ /* */
/* ::: :::::::: */ /* ::: :::::::: */
/* cmdgroup_item_type.h :+: :+: :+: */ /* command_list_item_type.h :+: :+: :+: */
/* +:+ +:+ +:+ */ /* +:+ +:+ +:+ */
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */ /* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/03/11 15:45:33 by khais #+# #+# */ /* Created: 2025/03/18 12:56:30 by khais #+# #+# */
/* Updated: 2025/03/11 15:46:25 by khais ### ########.fr */ /* Updated: 2025/03/18 12:58:38 by khais ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef CMDGROUP_ITEM_TYPE_H #ifndef COMMAND_LIST_ITEM_TYPE_H
# define CMDGROUP_ITEM_TYPE_H # define COMMAND_LIST_ITEM_TYPE_H
typedef enum e_cmdgroup_item_type typedef enum e_cmdlist_item_type
{ {
TYPE_INVALID = 0, TYPE_INVALID,
TYPE_GROUP, TYPE_CMDGROUP,
TYPE_LIST, TYPE_PIPELINE,
} t_cmdgroup_item_type; } t_cmdlist_item_type;
#endif // CMDGROUP_ITEM_TYPE_H #endif // COMMAND_LIST_ITEM_TYPE_H

View file

@ -2,11 +2,11 @@
# file are prefixed with test_ # file are prefixed with test_
rawtests = \ rawtests = \
expansion \ expansion \
test_cmdlist_use_after_free \
test_here_doc \ test_here_doc \
test_wordlist_idx \ test_wordlist_idx \
test_redirection_parsing \ test_redirection_parsing \
test_quote_removal \ test_quote_removal \
test_cmdlist_use_after_free \
test_metacharacters \ test_metacharacters \
test_parse_command_lists \ test_parse_command_lists \
test_parse_pipelines \ test_parse_pipelines \

View file

@ -1,12 +1,12 @@
/* ************************************************************************** */ /* ************************************************************************** */
/* */ /* */
/* ::: :::::::: */ /* ::: :::::::: */
/* cmdlist_use_after_free.c :+: :+: :+: */ /* test_cmdlist_use_after_free.c :+: :+: :+: */
/* +:+ +:+ +:+ */ /* +:+ +:+ +:+ */
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */ /* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/03/03 11:40:37 by khais #+# #+# */ /* Created: 2025/03/03 11:40:37 by khais #+# #+# */
/* Updated: 2025/03/04 13:27:54 by khais ### ########.fr */ /* Updated: 2025/03/18 14:23:19 by khais ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -17,8 +17,11 @@
int main(void) int main(void)
{ {
t_wordlist *words = minishell_wordsplit("|"); t_wordlist *words;
t_cmdlist *cmd = cmdlist_from_wordlist(words); t_cmdlist *cmd;
cmd = NULL;
words = minishell_wordsplit("|");
cmd = cmdlist_from_wordlist(words);
wordlist_destroy(words); wordlist_destroy(words);
assert(cmd == NULL); assert(cmd == NULL);
return (0); return (0);

View file

@ -6,7 +6,7 @@
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */ /* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/24 17:40:48 by khais #+# #+# */ /* Created: 2025/02/24 17:40:48 by khais #+# #+# */
/* Updated: 2025/03/11 16:30:05 by khais ### ########.fr */ /* Updated: 2025/03/18 13:09:51 by khais ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -33,7 +33,7 @@ static void test_parse_command_list_single_pipeline(void)
assert(cmd != NULL); assert(cmd != NULL);
assert_pipelineequal("echo this | cat -e", cmd, 0); assert_pipelineequal("echo this | cat -e", cmd, 0);
assert(cmd->operators[0] == OP_END); assert(cmd->operators[0] == OP_END);
assert(cmd->num_pipelines == 1); assert(cmd->num_cmds == 1);
cmdlist_destroy(cmd); cmdlist_destroy(cmd);
} }
@ -45,7 +45,7 @@ static void test_parse_command_list_simple_and(void)
assert_pipelineequal("echo this | cat -e", cmd, 0); assert_pipelineequal("echo this | cat -e", cmd, 0);
assert(cmd->operators[0] == OP_AND); assert(cmd->operators[0] == OP_AND);
assert_pipelineequal("echo works | wc -c", cmd, 1); assert_pipelineequal("echo works | wc -c", cmd, 1);
assert(cmd->num_pipelines == 2); assert(cmd->num_cmds == 2);
cmdlist_destroy(cmd); cmdlist_destroy(cmd);
} }
@ -57,7 +57,7 @@ static void test_parse_command_list_simple_or(void)
assert_pipelineequal("echo this | cat -e", cmd, 0); assert_pipelineequal("echo this | cat -e", cmd, 0);
assert(cmd->operators[0] == OP_OR); assert(cmd->operators[0] == OP_OR);
assert_pipelineequal("echo works | wc -c", cmd, 1); assert_pipelineequal("echo works | wc -c", cmd, 1);
assert(cmd->num_pipelines == 2); assert(cmd->num_cmds == 2);
cmdlist_destroy(cmd); cmdlist_destroy(cmd);
} }
@ -71,7 +71,7 @@ static void test_parse_command_list_triple_or(void)
assert_pipelineequal("echo works | wc -c", cmd, 1); assert_pipelineequal("echo works | wc -c", cmd, 1);
assert(cmd->operators[1] == OP_OR); assert(cmd->operators[1] == OP_OR);
assert_pipelineequal("echo as well | cut -d' ' -f1", cmd, 2); assert_pipelineequal("echo as well | cut -d' ' -f1", cmd, 2);
assert(cmd->num_pipelines == 3); assert(cmd->num_cmds == 3);
cmdlist_destroy(cmd); cmdlist_destroy(cmd);
} }
@ -86,7 +86,7 @@ static void test_parse_command_list_triple_both_operators(void)
assert(cmd->operators[1] == OP_AND); assert(cmd->operators[1] == OP_AND);
assert_pipelineequal("echo as well | cut -d' ' -f1", cmd, 2); assert_pipelineequal("echo as well | cut -d' ' -f1", cmd, 2);
assert(cmd->operators[2] == OP_END); assert(cmd->operators[2] == OP_END);
assert(cmd->num_pipelines == 3); assert(cmd->num_cmds == 3);
cmdlist_destroy(cmd); cmdlist_destroy(cmd);
} }
@ -121,7 +121,7 @@ static void test_parse_command_list_simple_command(void)
assert(cmd != NULL); assert(cmd != NULL);
assert_pipelineequal("echo this", cmd, 0); assert_pipelineequal("echo this", cmd, 0);
assert(cmd->operators[0] == OP_END); assert(cmd->operators[0] == OP_END);
assert(cmd->num_pipelines == 1); assert(cmd->num_cmds == 1);
cmdlist_destroy(cmd); cmdlist_destroy(cmd);
} }

View file

@ -6,7 +6,7 @@
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */ /* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/13 15:21:09 by khais #+# #+# */ /* Created: 2025/02/13 15:21:09 by khais #+# #+# */
/* Updated: 2025/03/18 11:50:23 by khais ### ########.fr */ /* Updated: 2025/03/18 13:09:16 by khais ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -19,7 +19,7 @@
#include "parse_pipeline.h" #include "parse_pipeline.h"
#include "../src/parser/wordlist/wordlist.h" #include "../src/parser/wordlist/wordlist.h"
#include "../src/parser/wordsplit/wordsplit.h" #include "../src/parser/wordsplit/wordsplit.h"
#include "../src/parser/cmdgroup/cmdgroup_item.h" #include "../src/parser/command_list/command_list_item.h"
void assert_strequal(char *str1, char *str2) void assert_strequal(char *str1, char *str2)
{ {
@ -84,9 +84,9 @@ void assert_pipelineequal_raw(t_pipeline *expected, t_pipeline *got)
void assert_pipelineequal(char *expected, t_cmdlist *cmd, int idx) void assert_pipelineequal(char *expected, t_cmdlist *cmd, int idx)
{ {
ft_printf("Expected command list %p to have at least %d pipelines, and got %d\n", cmd, idx + 1, cmd->num_pipelines); ft_printf("Expected command list %p to have at least %d pipelines, and got %d\n", cmd, idx + 1, cmd->num_cmds);
assert(cmd->num_pipelines >= idx + 1); assert(cmd->num_cmds >= idx + 1);
t_pipeline *got = cmd->pipelines[idx]; t_pipeline *got = cmd->cmds[idx]->inner.pipeline;
ft_dprintf(STDERR_FILENO, "Expected pipeline %p to equal [%s]\n", got, expected); ft_dprintf(STDERR_FILENO, "Expected pipeline %p to equal [%s]\n", got, expected);
t_pipeline *expected_pipeline = parse_pipeline(expected); t_pipeline *expected_pipeline = parse_pipeline(expected);
assert_pipelineequal_raw(expected_pipeline, got); assert_pipelineequal_raw(expected_pipeline, got);
@ -136,7 +136,7 @@ void assert_cmdgroup_itemlistequal(char *expected_str, t_cmdgroup *got_cmd, int
} }
ft_dprintf(STDERR_FILENO, "checking if the list matches...\n"); ft_dprintf(STDERR_FILENO, "checking if the list matches...\n");
int i = 0; int i = 0;
while (i < expected->num_pipelines) while (i < expected->num_cmds)
{ {
i++; i++;
} }