mirror of
https://codeberg.org/la-chouette/minishell.git
synced 2025-12-06 07:28:09 +01:00
Compare commits
60 commits
1504ee7de4
...
6f75f2d181
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f75f2d181 | |||
| df73b3d0c7 | |||
| 8feacccb15 | |||
| 425722801b | |||
| f9f8a804a3 | |||
| 7af032539a | |||
| 881c7f264c | |||
| ceee5f99d4 | |||
| 10e8738336 | |||
| 3a309062d8 | |||
| cb8f64367d | |||
| 67b2347df9 | |||
| f0145d26f4 | |||
| be183b99ee | |||
| f06f6e26e2 | |||
| 32e3976774 | |||
| 0cfa2677c5 | |||
| d40560bb37 | |||
| 1ef8b7a0ae | |||
| 0de583cf45 | |||
| 715c2aced8 | |||
| f1c132337b | |||
| 24ba87abba | |||
| 5b7367925f | |||
| 9e79a0829a | |||
| 0842fdfe1d | |||
| cea8043ec9 | |||
| 4de1d0024a | |||
| 5e84e9a111 | |||
| 218be08049 | |||
| b7871be426 | |||
| 811ce3ef8e | |||
| e033909819 | |||
| 9a58198303 | |||
| d4197fec38 | |||
| fde0bf4dc9 | |||
| 055dabc546 | |||
| dbba36dc44 | |||
| 86e658fcca | |||
| 283458b24f | |||
| 54f6c2a609 | |||
| 0c489f25bb | |||
| d40b6c3586 | |||
| 53693e171e | |||
| 7425195350 | |||
| 1c9653a5a5 | |||
| 1866da6ea6 | |||
|
|
4baad88a44 | ||
|
|
926774846f | ||
|
|
d0cea8828d | ||
|
|
72714855f7 | ||
|
|
10a3c9c411 | ||
|
|
90d213bf98 | ||
|
|
9acee63d22 | ||
|
|
1a22a39336 | ||
|
|
fea514ea63 | ||
|
|
5f95751b36 | ||
|
|
f490cc22f5 | ||
|
|
4d9fabc794 | ||
|
|
10d7b65b08 |
86 changed files with 2161 additions and 1476 deletions
45
Makefile
45
Makefile
|
|
@ -15,7 +15,10 @@ IFLAGS = -I$(LIBFTDIR)
|
|||
LINCLUDE = -L$(LIBFTDIR)
|
||||
|
||||
ifeq ($(CFLAGS),)
|
||||
CFLAGS = -Wall -Wextra -Werror $(DEBUG)
|
||||
CFLAGS = -Wall -Wextra \
|
||||
$(DEBUG) \
|
||||
# -Werror \
|
||||
|
||||
endif
|
||||
export CFLAGS
|
||||
srcs = \
|
||||
|
|
@ -25,27 +28,36 @@ srcs = \
|
|||
src/env/env_convert.c \
|
||||
src/env/env_manip.c \
|
||||
src/env/envp.c \
|
||||
src/executing/cmd/cmd_execute.c \
|
||||
src/executing/common/do_waitpid.c \
|
||||
src/executing/connec_cmd/connec_cmd_execute.c \
|
||||
src/executing/group_cmd/group_cmd_execute.c \
|
||||
src/executing/here_doc/here_doc.c \
|
||||
src/executing/here_doc/here_doc_errors.c \
|
||||
src/executing/here_doc/here_doc_expand_line.c \
|
||||
src/executing/here_doc/random_filename.c \
|
||||
src/executing/here_doc/strip_newline.c \
|
||||
src/executing/simple_cmd/builtin_cd.c \
|
||||
src/executing/simple_cmd/builtin_echo.c \
|
||||
src/executing/simple_cmd/builtin_env.c \
|
||||
src/executing/simple_cmd/builtin_exit.c \
|
||||
src/executing/simple_cmd/builtin_export.c \
|
||||
src/executing/simple_cmd/builtin_invalid.c \
|
||||
src/executing/simple_cmd/builtin_pwd.c \
|
||||
src/executing/simple_cmd/builtins.c \
|
||||
src/executing/simple_cmd/builtin_unset.c \
|
||||
src/executing/simple_cmd/simple_cmd_execute.c \
|
||||
src/executing/simple_cmd/subprocess.c \
|
||||
src/ft_errno.c \
|
||||
src/get_command.c \
|
||||
src/parser/cmdgroup/cmdgroup.c \
|
||||
src/parser/cmdgroup/cmdgroup_builder.c \
|
||||
src/parser/cmd/cmd.c \
|
||||
src/parser/cmd/cmd_debug.c \
|
||||
src/parser/cmd/cmd_destroy.c \
|
||||
src/parser/cmdgroup/paren.c \
|
||||
src/parser/cmdlist/cmdlist.c \
|
||||
src/parser/cmdlist/cmdlist_builder.c \
|
||||
src/parser/cmdlist/cmdlist_debug.c \
|
||||
src/parser/cmdlist/cmdlist_item.c \
|
||||
src/parser/cmdlist/operator.c \
|
||||
src/parser/connec_cmd/connec_cmd_debug.c \
|
||||
src/parser/connec_cmd/connec_reorient_subtree.c \
|
||||
src/parser/group_cmd/group_cmd_debug.c \
|
||||
src/parser/group_cmd/group_cmd_parse.c \
|
||||
src/parser/matchers/blank.c \
|
||||
src/parser/matchers/identifier.c \
|
||||
src/parser/matchers/metacharacter.c \
|
||||
|
|
@ -53,13 +65,16 @@ srcs = \
|
|||
src/parser/matchers/operator_start.c \
|
||||
src/parser/matchers/pipe.c \
|
||||
src/parser/matchers/quote.c \
|
||||
src/parser/pipeline/pipeline.c \
|
||||
src/parser/pipeline/pipeline_debug.c \
|
||||
src/parser/pipeline/optional_pipeline_parse.c \
|
||||
src/parser/pipeline/pipeline_parse.c \
|
||||
src/parser/pipeline/pipeline_parse_baseops.c \
|
||||
src/parser/redirect/redirect.c \
|
||||
src/parser/redirect/redirect_debug.c \
|
||||
src/parser/redirect/redirect_from_words.c \
|
||||
src/parser/redirect/redirect_parse.c \
|
||||
src/parser/remove_quotes/cmdgroup_remove_quotes.c \
|
||||
src/parser/remove_quotes/remove_quotes.c \
|
||||
src/parser/simple_cmd/simple_cmd.c \
|
||||
src/parser/simple_cmd/simple_cmd_parse.c \
|
||||
src/parser/worddesc/worddesc.c \
|
||||
src/parser/wordlist/wordlist.c \
|
||||
src/parser/wordlist/wordlist_copy.c \
|
||||
|
|
@ -73,6 +88,9 @@ srcs = \
|
|||
src/parser/wordsplit/wordsplit.c \
|
||||
src/parser/wordsplit/wordsplit_utils.c \
|
||||
src/postprocess/expansion/expand_vars.c \
|
||||
src/postprocess/expansion/expand_wildcard.c \
|
||||
src/postprocess/fieldsplit/fieldsplit.c \
|
||||
src/sig/sig.c \
|
||||
src/subst/path_split.c \
|
||||
src/subst/replace_substr.c \
|
||||
src/subst/simple_filename_exp.c \
|
||||
|
|
@ -83,6 +101,8 @@ srcs = \
|
|||
src/subst/wildcard_exp_utils.c \
|
||||
src/subst/wildcard_exp_utils2.c \
|
||||
src/treedrawing.c \
|
||||
src/parser/cmd_parsing.c
|
||||
|
||||
|
||||
objs = $(srcs:.c=.o)
|
||||
export objs
|
||||
|
|
@ -100,12 +120,13 @@ all: $(NAME)
|
|||
$(NAME): $(minishell_objs) $(LIBFT)
|
||||
$(CC) $(CFLAGS) -o $@ $(minishell_objs) $(LINCLUDE) $(LDLIBS)
|
||||
|
||||
$(LIBFT): CFLAGS+=-DBUFFER_SIZE=1
|
||||
$(LIBFT):
|
||||
+$(MAKE) -C $(LIBFTDIR)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) -c $(CFLAGS) $(IFLAGS) -o $*.o $*.c
|
||||
$(CC) -MM $(CFLAGS) $(IFLAGS) $*.c > $*.d
|
||||
$(CC) -MM $(CFLAGS) $(IFLAGS) -MT $*.o $*.c > $*.d
|
||||
|
||||
clean:
|
||||
+$(MAKE) -C $(LIBFTDIR) clean
|
||||
|
|
|
|||
54
grammar.md
Normal file
54
grammar.md
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
## Initial Grammar (Left recursivity)
|
||||
|
||||
This grammar is conceived to take into account both left associativity
|
||||
and priority of operators to wit () is of highest priority followed by |
|
||||
and then || and && which share the same priority (priorization therefore
|
||||
occurs because of left associativity).
|
||||
|
||||
```
|
||||
LINE -> CMDS eol
|
||||
CMDS -> CMDS LIST_OP PIPELINE
|
||||
CMDS -> PIPELINE
|
||||
PIPELINE -> PIPELINE | GROUP_OR_SIMPLE
|
||||
PIPELINE -> GROUP_OR_SIMPLE
|
||||
GROUP_OR_SIMPLE -> (CMDS) REDIR
|
||||
GROUP_OR_SIMPLE -> SIMPLE
|
||||
SIMPLE -> REDIR word REDIR SIMPLE_LST
|
||||
SIMPLE_LST -> word REDIR SIMPLE_LST
|
||||
SIMPLE_LST -> ε
|
||||
REDIR -> > word REDIR
|
||||
REDIR -> >> word REDIR
|
||||
REDIR -> < word REDIR
|
||||
REDIR -> << word REDIR
|
||||
REDIR -> ε
|
||||
LIST_OP -> &&
|
||||
LIST_OP -> ||
|
||||
```
|
||||
|
||||
|
||||
## Grammar after removal of left recursivity
|
||||
|
||||
The same priorities as the previous version except it is now LL(1) and
|
||||
therefore compatible with descending syntax analysis (LL(1)).
|
||||
|
||||
```
|
||||
LINE -> CMDS eol
|
||||
CMDS -> PIPELINE OPT_CMDS
|
||||
OPT_CMDS -> LIST_OP PIPELINE OPT_CMDS
|
||||
OPT_CMDS -> ε
|
||||
PIPELINE -> GROUP_OR_SIMPLE OPT_PIPELINE
|
||||
OPT_PIPELINE -> | GROUP_OR_SIMPLE OPT_PIPELINE
|
||||
OPT_PIPELINE -> ε
|
||||
GROUP_OR_SIMPLE -> (CMDS) REDIR
|
||||
GROUP_OR_SIMPLE -> SIMPLE
|
||||
SIMPLE -> REDIR word REDIR SIMPLE_LST
|
||||
SIMPLE_LST -> word REDIR SIMPLE_LST
|
||||
SIMPLE_LST -> ε
|
||||
REDIR -> > word REDIR
|
||||
REDIR -> >> word REDIR
|
||||
REDIR -> < word REDIR
|
||||
REDIR -> << word REDIR
|
||||
REDIR -> ε
|
||||
LIST_OP -> &&
|
||||
LIST_OP -> ||
|
||||
```
|
||||
26
src/executing/cmd/cmd_execute.c
Normal file
26
src/executing/cmd/cmd_execute.c
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* cmd_execute.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/04 19:26:37 by khais #+# #+# */
|
||||
/* Updated: 2025/04/07 10:38:07 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "cmd_execute.h"
|
||||
#include "../simple_cmd/simple_cmd_execute.h"
|
||||
#include "../connec_cmd/connec_cmd_execute.h"
|
||||
#include "../group_cmd/group_cmd_execute.h"
|
||||
|
||||
void cmd_execute(t_cmd *cmd, t_minishell *app)
|
||||
{
|
||||
if (cmd->type == FT_SIMPLE)
|
||||
simple_cmd_execute(cmd->value.simple, app);
|
||||
if (cmd->type == FT_GROUP)
|
||||
group_cmd_execute(cmd->value.group, app);
|
||||
if (cmd->type == FT_CONNECTION)
|
||||
connec_cmd_execute(cmd->value.connection, app);
|
||||
}
|
||||
|
|
@ -1,23 +1,20 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* cmdlist_item_type.h :+: :+: :+: */
|
||||
/* cmd_execute.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/18 12:56:30 by khais #+# #+# */
|
||||
/* Updated: 2025/03/18 15:02:27 by khais ### ########.fr */
|
||||
/* Created: 2025/04/04 19:25:39 by khais #+# #+# */
|
||||
/* Updated: 2025/04/04 19:37:46 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef CMDLIST_ITEM_TYPE_H
|
||||
# define CMDLIST_ITEM_TYPE_H
|
||||
#ifndef CMD_EXECUTE_H
|
||||
# define CMD_EXECUTE_H
|
||||
|
||||
typedef enum e_cmdlist_item_type
|
||||
{
|
||||
TYPE_INVALID,
|
||||
TYPE_CMDGROUP,
|
||||
TYPE_PIPELINE,
|
||||
} t_cmdlist_item_type;
|
||||
# include "../../minishell.h"
|
||||
|
||||
#endif // CMDLIST_ITEM_TYPE_H
|
||||
void cmd_execute(t_cmd *cmd, t_minishell *app);
|
||||
|
||||
#endif // CMD_EXECUTE_H
|
||||
|
|
@ -1,46 +1,31 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* operator.h :+: :+: :+: */
|
||||
/* do_waitpid.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/26 12:49:46 by khais #+# #+# */
|
||||
/* Updated: 2025/03/19 14:41:55 by khais ### ########.fr */
|
||||
/* Created: 2025/04/04 19:55:22 by khais #+# #+# */
|
||||
/* Updated: 2025/04/04 19:55:59 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef OPERATOR_H
|
||||
# define OPERATOR_H
|
||||
#include "do_waitpid.h"
|
||||
#include "libft.h"
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
# include "../../buffer/buffer.h"
|
||||
# include <stdbool.h>
|
||||
|
||||
/*
|
||||
** An operator used by a cmdlist
|
||||
*/
|
||||
typedef enum e_operator
|
||||
void do_waitpid(t_minishell *app, int pid)
|
||||
{
|
||||
/*
|
||||
** Not a valid operator
|
||||
*/
|
||||
OP_INVALID,
|
||||
/*
|
||||
** &&
|
||||
*/
|
||||
OP_AND,
|
||||
/*
|
||||
** ||
|
||||
*/
|
||||
OP_OR,
|
||||
/*
|
||||
** End of operator list
|
||||
*/
|
||||
OP_END,
|
||||
} t_operator;
|
||||
int wstatus;
|
||||
|
||||
t_operator match_op(char *op);
|
||||
void operator_debug(t_operator op, t_buffer *leader,
|
||||
bool is_last);
|
||||
|
||||
#endif // OPERATOR_H
|
||||
waitpid(pid, &wstatus, 0);
|
||||
if (WIFEXITED(wstatus))
|
||||
app->last_return_value = WEXITSTATUS(wstatus);
|
||||
if (WIFSIGNALED(wstatus))
|
||||
{
|
||||
app->last_return_value = 128 + WTERMSIG(wstatus);
|
||||
if (WTERMSIG(wstatus) == SIGQUIT)
|
||||
ft_dprintf(STDERR_FILENO, "Quit (core dumped)");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +1,20 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* pipeline_parse_baseops.h :+: :+: :+: */
|
||||
/* do_waitpid.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/24 15:05:16 by khais #+# #+# */
|
||||
/* Updated: 2025/02/24 15:09:01 by khais ### ########.fr */
|
||||
/* Created: 2025/04/04 19:54:53 by khais #+# #+# */
|
||||
/* Updated: 2025/04/04 19:57:07 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#ifndef PIPELINE_PARSE_BASEOPS_H
|
||||
# define PIPELINE_PARSE_BASEOPS_H
|
||||
|
||||
# include "pipeline.h"
|
||||
#ifndef DO_WAITPID_H
|
||||
# define DO_WAITPID_H
|
||||
|
||||
void ignore_word(t_pipeline_builder *builder);
|
||||
bool current_is_pipe(t_pipeline_builder *builder);
|
||||
void next_word(t_pipeline_builder *builder);
|
||||
bool eof(t_pipeline_builder *builder);
|
||||
void push_word(t_pipeline_builder *builder);
|
||||
# include "../../minishell.h"
|
||||
|
||||
#endif // PIPELINE_PARSE_BASEOPS_H
|
||||
void do_waitpid(t_minishell *app, int pid);
|
||||
|
||||
#endif // DO_WAITPID_H
|
||||
55
src/executing/connec_cmd/connec_cmd_execute.c
Normal file
55
src/executing/connec_cmd/connec_cmd_execute.c
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* connec_cmd_execute.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/07 10:38:55 by khais #+# #+# */
|
||||
/* Updated: 2025/04/07 11:36:57 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "connec_cmd_execute.h"
|
||||
#include "../cmd/cmd_execute.h"
|
||||
#include "../common/do_waitpid.h"
|
||||
#include <unistd.h>
|
||||
|
||||
static void connec_and_cmd_execute(t_connec_cmd *cmd, t_minishell *app)
|
||||
{
|
||||
cmd_execute(cmd->first, app);
|
||||
if (app->last_return_value == 0)
|
||||
cmd_execute(cmd->second, app);
|
||||
}
|
||||
|
||||
static void connec_or_cmd_execute(t_connec_cmd *cmd, t_minishell *app)
|
||||
{
|
||||
cmd_execute(cmd->first, app);
|
||||
if (app->last_return_value != 0)
|
||||
cmd_execute(cmd->second, app);
|
||||
}
|
||||
|
||||
static void connec_pipe_cmd_execute(t_connec_cmd *cmd, t_minishell *app)
|
||||
{
|
||||
int pid1;
|
||||
int pid2;
|
||||
|
||||
pid1 = fork();
|
||||
if (pid1 == 0)
|
||||
cmd_execute(cmd->first, app);
|
||||
pid2 = fork();
|
||||
if (pid2 == 0)
|
||||
cmd_execute(cmd->second, app);
|
||||
do_waitpid(app, pid1);
|
||||
do_waitpid(app, pid2);
|
||||
}
|
||||
|
||||
void connec_cmd_execute(t_connec_cmd *cmd, t_minishell *app)
|
||||
{
|
||||
if (cmd->connector == FT_AND)
|
||||
connec_and_cmd_execute(cmd, app);
|
||||
if (cmd->connector == FT_OR)
|
||||
connec_or_cmd_execute(cmd, app);
|
||||
if (cmd->connector == FT_PIPE)
|
||||
connec_pipe_cmd_execute(cmd, app);
|
||||
}
|
||||
20
src/executing/connec_cmd/connec_cmd_execute.h
Normal file
20
src/executing/connec_cmd/connec_cmd_execute.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* connec_cmd_execute.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/07 10:38:19 by khais #+# #+# */
|
||||
/* Updated: 2025/04/07 10:38:48 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef CONNEC_CMD_EXECUTE_H
|
||||
# define CONNEC_CMD_EXECUTE_H
|
||||
|
||||
# include "../../minishell.h"
|
||||
|
||||
void connec_cmd_execute(t_connec_cmd *cmd, t_minishell *app);
|
||||
|
||||
#endif // CONNEC_CMD_EXECUTE_H
|
||||
26
src/executing/group_cmd/group_cmd_execute.c
Normal file
26
src/executing/group_cmd/group_cmd_execute.c
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* group_cmd_execute.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/04 19:50:42 by khais #+# #+# */
|
||||
/* Updated: 2025/04/04 20:01:20 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "group_cmd_execute.h"
|
||||
#include "../cmd/cmd_execute.h"
|
||||
#include "../common/do_waitpid.h"
|
||||
#include <unistd.h>
|
||||
|
||||
void group_cmd_execute(t_group_cmd *cmd, t_minishell *app)
|
||||
{
|
||||
int pid;
|
||||
|
||||
pid = fork();
|
||||
if (pid == 0)
|
||||
cmd_execute(cmd->cmd, app);
|
||||
do_waitpid(app, pid);
|
||||
}
|
||||
20
src/executing/group_cmd/group_cmd_execute.h
Normal file
20
src/executing/group_cmd/group_cmd_execute.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* group_cmd_execute.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/04 19:42:36 by khais #+# #+# */
|
||||
/* Updated: 2025/04/04 19:43:09 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef GROUP_CMD_EXECUTE_H
|
||||
# define GROUP_CMD_EXECUTE_H
|
||||
|
||||
# include "../../minishell.h"
|
||||
|
||||
void group_cmd_execute(t_group_cmd *cmd, t_minishell *app);
|
||||
|
||||
#endif // GROUP_CMD_EXECUTE_H
|
||||
|
|
@ -3,15 +3,14 @@
|
|||
/* ::: :::::::: */
|
||||
/* builtin_cd.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/31 16:20:17 by khais #+# #+# */
|
||||
/* Updated: 2025/03/31 20:04:28 by khais ### ########.fr */
|
||||
/* Updated: 2025/04/07 17:35:16 by jguelen ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "builtins.h"
|
||||
#include "ft_printf.h"
|
||||
#include "libft.h"
|
||||
#include <unistd.h>
|
||||
#include "../../env/env_manip.h"
|
||||
|
|
|
|||
63
src/executing/simple_cmd/builtin_echo.c
Normal file
63
src/executing/simple_cmd/builtin_echo.c
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* builtin_echo.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/03 13:59:13 by khais #+# #+# */
|
||||
/* Updated: 2025/04/03 17:18:54 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "builtins.h"
|
||||
#include "libft.h"
|
||||
#include "simple_cmd_execute.h"
|
||||
|
||||
static bool should_print_newline(t_wordlist **arg)
|
||||
{
|
||||
bool print_newline;
|
||||
bool end_of_args;
|
||||
size_t i;
|
||||
|
||||
print_newline = true;
|
||||
while (*arg != NULL)
|
||||
{
|
||||
if ((*arg)->word->word[0] != '-')
|
||||
break ;
|
||||
i = 1;
|
||||
end_of_args = (*arg)->word->word[i] == '\0';
|
||||
if (end_of_args)
|
||||
break ;
|
||||
while ((*arg)->word->word[i] != '\0' && !end_of_args)
|
||||
{
|
||||
if ((*arg)->word->word[i++] != 'n')
|
||||
end_of_args = true;
|
||||
}
|
||||
if (end_of_args)
|
||||
break ;
|
||||
print_newline = false;
|
||||
(*arg) = (*arg)->next;
|
||||
}
|
||||
return (print_newline);
|
||||
}
|
||||
|
||||
t_builtin_type builtin_echo(t_simple_cmd *cmd, t_minishell *app)
|
||||
{
|
||||
t_wordlist *arg;
|
||||
bool print_newline;
|
||||
|
||||
arg = cmd->words->next;
|
||||
print_newline = should_print_newline(&arg);
|
||||
while (arg != NULL)
|
||||
{
|
||||
ft_printf("%s", arg->word->word);
|
||||
arg = arg->next;
|
||||
if (arg != NULL)
|
||||
ft_printf(" ");
|
||||
}
|
||||
if (print_newline)
|
||||
ft_printf("\n");
|
||||
app->last_return_value = 0;
|
||||
return (BUILTIN_ECHO);
|
||||
}
|
||||
30
src/executing/simple_cmd/builtin_env.c
Normal file
30
src/executing/simple_cmd/builtin_env.c
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* builtin_env.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/02 19:35:52 by khais #+# #+# */
|
||||
/* Updated: 2025/04/02 19:38:16 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "builtins.h"
|
||||
#include "libft.h"
|
||||
|
||||
t_builtin_type builtin_env(t_simple_cmd *cmd, t_minishell *app)
|
||||
{
|
||||
t_env *env;
|
||||
|
||||
if (cmd->words->next != NULL)
|
||||
ft_dprintf(STDERR_FILENO, "minishell: env: ignoring arguments\n");
|
||||
env = app->env;
|
||||
while (env != NULL)
|
||||
{
|
||||
ft_printf("%s=%s\n", env->key, env->value);
|
||||
env = env->next;
|
||||
}
|
||||
app->last_return_value = 0;
|
||||
return (BUILTIN_ENV);
|
||||
}
|
||||
79
src/executing/simple_cmd/builtin_exit.c
Normal file
79
src/executing/simple_cmd/builtin_exit.c
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* builtin_exit.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/01 18:17:56 by khais #+# #+# */
|
||||
/* Updated: 2025/04/15 11:48:05 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "builtins.h"
|
||||
#include <stdlib.h>
|
||||
#include "libft.h"
|
||||
#include "simple_cmd_execute.h"
|
||||
#include "unistd.h"
|
||||
|
||||
static int ft_isspace(char c)
|
||||
{
|
||||
return ((c == ' ' || c == '\f' || c == '\n'
|
||||
|| c == '\r' || c == '\t' || c == '\v'));
|
||||
}
|
||||
|
||||
static int ft_atoi_strict(const char *nptr, bool *ok)
|
||||
{
|
||||
int sign;
|
||||
int calc;
|
||||
|
||||
sign = 1;
|
||||
calc = 0;
|
||||
*ok = true;
|
||||
while (*nptr && ft_isspace(*nptr))
|
||||
nptr++;
|
||||
if (*nptr == '+' || *nptr == '-')
|
||||
{
|
||||
if (nptr[0] == '-')
|
||||
sign = -1;
|
||||
nptr++;
|
||||
}
|
||||
while (*nptr && ft_isdigit(*nptr))
|
||||
{
|
||||
calc = calc * 10 + (*nptr - '0');
|
||||
nptr++;
|
||||
}
|
||||
if (*nptr != '\0')
|
||||
*ok = false;
|
||||
return (sign * calc);
|
||||
}
|
||||
|
||||
static int numeric_arg_required(char *arg)
|
||||
{
|
||||
ft_dprintf(STDERR_FILENO,
|
||||
"minishell: exit: %s: numeric argument required\n", arg);
|
||||
return (2);
|
||||
}
|
||||
|
||||
t_builtin_type builtin_exit(t_simple_cmd *cmd, t_minishell *app)
|
||||
{
|
||||
int status;
|
||||
bool ok;
|
||||
|
||||
status = 0;
|
||||
if (cmd->words->next != NULL)
|
||||
{
|
||||
status = ft_atoi_strict(cmd->words->next->word->word, &ok);
|
||||
if (!ok)
|
||||
status = numeric_arg_required(cmd->words->next->word->word);
|
||||
else if (cmd->words->next->next != NULL)
|
||||
{
|
||||
ft_dprintf(STDERR_FILENO, "minishell: exit: too many arguments\n");
|
||||
app->last_return_value = 1;
|
||||
return (BUILTIN_EXIT);
|
||||
}
|
||||
}
|
||||
simple_cmd_destroy(cmd);
|
||||
env_destroy(app->env);
|
||||
exit(status);
|
||||
}
|
||||
28
src/executing/simple_cmd/builtin_unset.c
Normal file
28
src/executing/simple_cmd/builtin_unset.c
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* builtin_unset.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/03 14:35:53 by khais #+# #+# */
|
||||
/* Updated: 2025/04/03 14:39:45 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "builtins.h"
|
||||
#include "../../env/env_manip.h"
|
||||
|
||||
t_builtin_type builtin_unset(t_simple_cmd *cmd, t_minishell *app)
|
||||
{
|
||||
t_wordlist *arg;
|
||||
|
||||
arg = cmd->words->next;
|
||||
while (arg != NULL)
|
||||
{
|
||||
env_rm_entry(&app->env, arg->word->word);
|
||||
arg = arg->next;
|
||||
}
|
||||
app->last_return_value = 0;
|
||||
return (BUILTIN_UNSET);
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/01 16:37:21 by khais #+# #+# */
|
||||
/* Updated: 2025/04/01 16:37:38 by khais ### ########.fr */
|
||||
/* Updated: 2025/04/03 14:35:30 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
|
|
@ -24,6 +24,14 @@ t_builtin_type get_builtin(t_simple_cmd *cmd)
|
|||
return (BUILTIN_CD);
|
||||
if (ft_strcmp("export", word) == 0)
|
||||
return (BUILTIN_EXPORT);
|
||||
if (ft_strcmp("exit", word) == 0)
|
||||
return (BUILTIN_EXIT);
|
||||
if (ft_strcmp("echo", word) == 0)
|
||||
return (BUILTIN_ECHO);
|
||||
if (ft_strcmp("env", word) == 0)
|
||||
return (BUILTIN_ENV);
|
||||
if (ft_strcmp("unset", word) == 0)
|
||||
return (BUILTIN_UNSET);
|
||||
return (BUILTIN_INVALID);
|
||||
}
|
||||
|
||||
|
|
@ -35,6 +43,10 @@ t_builtin_type execute_builtin(t_simple_cmd *cmd, t_minishell *app)
|
|||
[BUILTIN_PWD] = builtin_pwd,
|
||||
[BUILTIN_CD] = builtin_cd,
|
||||
[BUILTIN_EXPORT] = builtin_export,
|
||||
[BUILTIN_EXIT] = builtin_exit,
|
||||
[BUILTIN_ECHO] = builtin_echo,
|
||||
[BUILTIN_ENV] = builtin_env,
|
||||
[BUILTIN_UNSET] = builtin_unset,
|
||||
};
|
||||
|
||||
type = get_builtin(cmd);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/31 14:16:13 by khais #+# #+# */
|
||||
/* Updated: 2025/04/01 16:37:15 by khais ### ########.fr */
|
||||
/* Updated: 2025/04/03 14:35:44 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
|
|
@ -19,6 +19,10 @@ t_builtin_type builtin_invalid(t_simple_cmd *cmd, t_minishell *app);
|
|||
t_builtin_type builtin_pwd(t_simple_cmd *cmd, t_minishell *app);
|
||||
t_builtin_type builtin_cd(t_simple_cmd *cmd, t_minishell *app);
|
||||
t_builtin_type builtin_export(t_simple_cmd *cmd, t_minishell *app);
|
||||
t_builtin_type builtin_exit(t_simple_cmd *cmd, t_minishell *app);
|
||||
t_builtin_type builtin_echo(t_simple_cmd *cmd, t_minishell *app);
|
||||
t_builtin_type builtin_env(t_simple_cmd *cmd, t_minishell *app);
|
||||
t_builtin_type builtin_unset(t_simple_cmd *cmd, t_minishell *app);
|
||||
|
||||
t_builtin_type get_builtin(t_simple_cmd *cmd);
|
||||
t_builtin_type execute_builtin(t_simple_cmd *cmd, t_minishell *app);
|
||||
|
|
|
|||
|
|
@ -6,32 +6,20 @@
|
|||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/27 16:21:56 by khais #+# #+# */
|
||||
/* Updated: 2025/04/01 16:37:31 by khais ### ########.fr */
|
||||
/* Updated: 2025/04/04 17:09:39 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "simple_cmd_execute.h"
|
||||
#include "builtins.h"
|
||||
#include "subprocess.h"
|
||||
#include "libft.h"
|
||||
#include "../../subst/subst.h"
|
||||
#include "../../env/env_convert.h"
|
||||
#include "../common/do_waitpid.h"
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
static char **argv_from_wordlist(t_wordlist *wordlist)
|
||||
{
|
||||
char **out;
|
||||
int i;
|
||||
|
||||
out = ft_calloc(wordlist_size(wordlist) + 1, sizeof(char *));
|
||||
i = 0;
|
||||
while (wordlist != NULL)
|
||||
{
|
||||
out[i++] = ft_strdup(wordlist->word->word);
|
||||
wordlist = wordlist->next;
|
||||
}
|
||||
return (out);
|
||||
}
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static void command_not_found(t_simple_cmd *cmd)
|
||||
{
|
||||
|
|
@ -56,8 +44,8 @@ void simple_cmd_execute(t_simple_cmd *cmd, t_minishell *app)
|
|||
}
|
||||
pid = fork();
|
||||
if (pid == 0)
|
||||
execve(exe, argv_from_wordlist(cmd->words), envp_from_env(app->env));
|
||||
execute_subprocess(exe, cmd, app);
|
||||
free(exe);
|
||||
waitpid(pid, NULL, 0);
|
||||
do_waitpid(app, pid);
|
||||
return ;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/27 16:20:31 by khais #+# #+# */
|
||||
/* Updated: 2025/04/01 13:54:10 by khais ### ########.fr */
|
||||
/* Created: 2025/04/03 14:35/14 by khais #+# #+# */
|
||||
/* Updated: 2025/04/03 14:35:14 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
|
|
@ -24,6 +24,10 @@ typedef enum e_builtin_type
|
|||
BUILTIN_PWD,
|
||||
BUILTIN_CD,
|
||||
BUILTIN_EXPORT,
|
||||
BUILTIN_EXIT,
|
||||
BUILTIN_ECHO,
|
||||
BUILTIN_ENV,
|
||||
BUILTIN_UNSET,
|
||||
} t_builtin_type;
|
||||
|
||||
#endif // SIMPLE_CMD_EXECUTE_H
|
||||
|
|
|
|||
50
src/executing/simple_cmd/subprocess.c
Normal file
50
src/executing/simple_cmd/subprocess.c
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* subprocess.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/02 18:19:23 by khais #+# #+# */
|
||||
/* Updated: 2025/04/02 18:20:54 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "subprocess.h"
|
||||
#include "../../env/env_convert.h"
|
||||
#include "../../parser/simple_cmd/simple_cmd.h"
|
||||
#include "../../subst/path_split.h"
|
||||
#include <stdio.h>
|
||||
|
||||
static char **argv_from_wordlist(t_wordlist *wordlist)
|
||||
{
|
||||
char **out;
|
||||
int i;
|
||||
|
||||
out = ft_calloc(wordlist_size(wordlist) + 1, sizeof(char *));
|
||||
i = 0;
|
||||
while (wordlist != NULL)
|
||||
{
|
||||
out[i++] = ft_strdup(wordlist->word->word);
|
||||
wordlist = wordlist->next;
|
||||
}
|
||||
return (out);
|
||||
}
|
||||
|
||||
static void ft_execve(char *exe, char **argv, char **envp)
|
||||
{
|
||||
execve(exe, argv, envp);
|
||||
ft_dprintf(STDERR_FILENO, "minishell: %s: ", argv[0]);
|
||||
perror(NULL);
|
||||
free(exe);
|
||||
path_split_destroy(argv);
|
||||
path_split_destroy(envp);
|
||||
}
|
||||
|
||||
void execute_subprocess(char *exe, t_simple_cmd *cmd, t_minishell *app)
|
||||
{
|
||||
ft_execve(exe, argv_from_wordlist(cmd->words), envp_from_env(app->env));
|
||||
simple_cmd_destroy(cmd);
|
||||
env_destroy(app->env);
|
||||
exit(127);
|
||||
}
|
||||
20
src/executing/simple_cmd/subprocess.h
Normal file
20
src/executing/simple_cmd/subprocess.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* subprocess.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/02 18:17:48 by khais #+# #+# */
|
||||
/* Updated: 2025/04/02 18:21:30 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef SUBPROCESS_H
|
||||
# define SUBPROCESS_H
|
||||
|
||||
# include "../../minishell.h"
|
||||
|
||||
void execute_subprocess(char *exe, t_simple_cmd *cmd, t_minishell *app);
|
||||
|
||||
#endif // SUBPROCESS_H
|
||||
|
|
@ -3,65 +3,51 @@
|
|||
/* ::: :::::::: */
|
||||
/* minishell.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: kcolin <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/06 13:44:06 by kcolin #+# #+# */
|
||||
/* Updated: 2025/04/01 13:36:52 by khais ### ########.fr */
|
||||
/* Updated: 2025/04/15 11:53:49 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
#include "env/env.h"
|
||||
#include "get_command.h"
|
||||
#include "parser/cmd/cmd_destroy.h"
|
||||
#include "parser/simple_cmd/simple_cmd.h"
|
||||
#include "parser/wordlist/wordlist.h"
|
||||
#include "parser/wordsplit/wordsplit.h"
|
||||
#include "parser/remove_quotes/remove_quotes.h"
|
||||
#include "libft.h"
|
||||
#include "executing/simple_cmd/simple_cmd_execute.h"
|
||||
#include <stdlib.h>
|
||||
#include "env/env_convert.h"
|
||||
#include "postprocess/expansion/expand_vars.h"
|
||||
|
||||
/*
|
||||
** Parse shell commands from line.
|
||||
**
|
||||
** Frees line before exiting
|
||||
*/
|
||||
static t_simple_cmd *parse_command(char *line)
|
||||
{
|
||||
t_wordlist *words;
|
||||
t_simple_cmd *cmd;
|
||||
|
||||
words = minishell_wordsplit(line);
|
||||
free(line);
|
||||
if (words == NULL)
|
||||
return (NULL);
|
||||
cmd = simple_cmd_from_wordlist(words);
|
||||
return (cmd);
|
||||
}
|
||||
#include "parser/cmd_parsing.h"
|
||||
#include "postprocess/fieldsplit/fieldsplit.h"
|
||||
#include "postprocess/expansion/expand_wildcard.h"
|
||||
#include "sig/sig.h"
|
||||
|
||||
/*
|
||||
** execute command
|
||||
*/
|
||||
static void execute_command(t_simple_cmd *cmd, t_minishell *app)
|
||||
{
|
||||
set_exec_mode_sig_handling();
|
||||
simple_cmd_execute(cmd, app);
|
||||
simple_cmd_destroy(cmd);
|
||||
set_interactive_mode_sig_handling();
|
||||
}
|
||||
|
||||
/*
|
||||
** Do all the post-processing steps relating to a command.
|
||||
**
|
||||
** Currently, this is the following:
|
||||
** 1. variable expansion
|
||||
** 2. quote removal
|
||||
*/
|
||||
static t_simple_cmd *post_process_command(t_simple_cmd *cmd, t_minishell *app)
|
||||
static t_cmd *post_process_command(t_cmd *cmd, t_minishell *app)
|
||||
{
|
||||
if (simple_cmd_expand_vars(cmd, app) == NULL)
|
||||
return (simple_cmd_destroy(cmd), NULL);
|
||||
if (simple_cmd_remove_quotes(cmd) == NULL)
|
||||
if (simple_cmd_fieldsplit(cmd) == NULL)
|
||||
return (simple_cmd_destroy(cmd), NULL);
|
||||
if (simple_cmd_expand_wildcards(cmd) == NULL)
|
||||
return (simple_cmd_destroy(cmd), NULL);
|
||||
return (cmd);
|
||||
}
|
||||
|
|
@ -77,21 +63,44 @@ static void app_init(t_minishell *app, char **envp)
|
|||
|
||||
int main(int argc, char *argv[], char **envp)
|
||||
{
|
||||
char *line;
|
||||
t_simple_cmd *cmd;
|
||||
t_minishell app;
|
||||
char *line;
|
||||
t_cmd *cmd;
|
||||
t_minishell app;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
set_interactive_mode_sig_handling();
|
||||
app_init(&app, envp);
|
||||
line = get_command();
|
||||
while (line != NULL)
|
||||
{
|
||||
cmd = parse_command(line);
|
||||
cmd = post_process_command(cmd, &app);
|
||||
execute_command(cmd, &app);
|
||||
line = get_command();
|
||||
}
|
||||
line = "echo coucou";
|
||||
cmd = minishell_parse(&app, line);
|
||||
cmd_destroy(cmd);
|
||||
env_destroy(app.env);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* int main(int argc, char *argv[], char **envp) */
|
||||
/* { */
|
||||
/* char *line; */
|
||||
/* t_cmd *cmd; */
|
||||
/* t_minishell app; */
|
||||
|
||||
/* (void)argc; */
|
||||
/* (void)argv; */
|
||||
/* app_init(&app, envp); */
|
||||
/* line = get_command(); */
|
||||
/* while (line != NULL) */
|
||||
/* { */
|
||||
/* cmd = minishell_parse(&app, line); */
|
||||
/* cmd = post_process_command(cmd, &app); */
|
||||
/* execute_command(cmd, &app); */
|
||||
/* if (g_signum != -1) */
|
||||
/* { */
|
||||
/* ft_printf("\n"); */
|
||||
/* g_signum = -1; */
|
||||
/* readline_reset(); */
|
||||
/* } */
|
||||
/* line = get_command(); */
|
||||
/* } */
|
||||
/* env_destroy(app.env); */
|
||||
/* return (app.last_return_value); */
|
||||
/* } */
|
||||
|
|
|
|||
|
|
@ -5,16 +5,18 @@
|
|||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/28 14:55/31 by khais #+# #+# */
|
||||
/* Updated: 2025/03/28 14:55:31 by khais ### ########.fr */
|
||||
/* Created: 2025/04/14 15:00/22 by khais #+# #+# */
|
||||
/* Updated: 2025/04/14 15:00:22 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef MINISHELL_H
|
||||
# define MINISHELL_H
|
||||
|
||||
# include "libft.h"
|
||||
# include "env/env.h"
|
||||
# include "parser/wordlist/wordlist.h"
|
||||
# include "parser/wordsplit/wordsplit.h"
|
||||
# include <sys/stat.h>
|
||||
# include <fcntl.h>
|
||||
|
||||
|
|
@ -57,12 +59,14 @@ typedef enum e_cmd_type
|
|||
typedef struct s_cmd
|
||||
{
|
||||
t_cmd_type type;
|
||||
/*
|
||||
** flags will probably be useless to us for now.
|
||||
*/
|
||||
int flags;
|
||||
/*
|
||||
** Line number the command starts on -> will probably be unused.
|
||||
*/
|
||||
int line;
|
||||
t_redirect *redirects;
|
||||
union u_value
|
||||
{
|
||||
struct s_connec_cmd *connection;
|
||||
|
|
@ -73,6 +77,7 @@ typedef struct s_cmd
|
|||
|
||||
typedef enum e_connector
|
||||
{
|
||||
FT_INVALID_CONNECTOR,
|
||||
FT_PIPE,
|
||||
FT_AND,
|
||||
FT_OR,
|
||||
|
|
@ -111,7 +116,10 @@ typedef struct s_simple_cmd
|
|||
typedef struct s_minishell
|
||||
{
|
||||
t_env *env;
|
||||
int lines_read;
|
||||
int last_return_value;
|
||||
} t_minishell;
|
||||
|
||||
t_redirect *t_redirect_add_back(t_redirect **init, t_redirect *back);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
25
src/parser/cmd/cmd.c
Normal file
25
src/parser/cmd/cmd.c
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* cmd.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/14 17:50:28 by khais #+# #+# */
|
||||
/* Updated: 2025/04/14 17:53:52 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "cmd.h"
|
||||
#include "../../ft_errno.h"
|
||||
|
||||
t_cmd *cmd_create(t_cmd_type type)
|
||||
{
|
||||
t_cmd *cmd;
|
||||
|
||||
cmd = ft_calloc(1, sizeof(t_cmd));
|
||||
if (cmd == NULL)
|
||||
return (ft_errno(FT_ENOMEM), NULL);
|
||||
cmd->type = type;
|
||||
return (cmd);
|
||||
}
|
||||
20
src/parser/cmd/cmd.h
Normal file
20
src/parser/cmd/cmd.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* cmd.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/14 17:49:55 by khais #+# #+# */
|
||||
/* Updated: 2025/04/14 17:50:20 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef CMD_H
|
||||
# define CMD_H
|
||||
|
||||
# include "../../minishell.h"
|
||||
|
||||
t_cmd *cmd_create(t_cmd_type type);
|
||||
|
||||
#endif // CMD_H
|
||||
65
src/parser/cmd/cmd_debug.c
Normal file
65
src/parser/cmd/cmd_debug.c
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* cmd_debug.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/09 16:53:27 by khais #+# #+# */
|
||||
/* Updated: 2025/04/14 15:07:59 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "cmd_debug.h"
|
||||
#include "libft.h"
|
||||
#include "../../treedrawing.h"
|
||||
#include "../simple_cmd/simple_cmd.h"
|
||||
#include "../group_cmd/group_cmd_debug.h"
|
||||
#include "../connec_cmd/connec_cmd_debug.h"
|
||||
#include "../redirect/redirect_debug.h"
|
||||
|
||||
static void cmd_type_debug(t_cmd_type type, t_buffer *leader, bool is_last)
|
||||
{
|
||||
indent(leader, is_last);
|
||||
ft_printf("t_cmd_type = ");
|
||||
if (type == FT_CONNECTION)
|
||||
ft_printf("FT_CONNECTION\n");
|
||||
if (type == FT_GROUP)
|
||||
ft_printf("FT_GROUP\n");
|
||||
if (type == FT_SIMPLE)
|
||||
ft_printf("FT_SIMPLE\n");
|
||||
dedent(leader, is_last);
|
||||
}
|
||||
|
||||
static void cmd_value_debug(t_cmd *cmd, t_buffer *leader, bool is_last)
|
||||
{
|
||||
indent(leader, is_last);
|
||||
ft_printf("value\n");
|
||||
if (cmd->type == FT_CONNECTION)
|
||||
connec_cmd_debug(cmd->value.connection, leader, true);
|
||||
if (cmd->type == FT_GROUP)
|
||||
group_cmd_debug(cmd->value.group, leader, true);
|
||||
if (cmd->type == FT_SIMPLE)
|
||||
simple_cmd_debug(cmd->value.simple, leader, true);
|
||||
dedent(leader, is_last);
|
||||
}
|
||||
|
||||
void cmd_debug(t_cmd *cmd, t_buffer *leader, bool is_last)
|
||||
{
|
||||
indent(leader, is_last);
|
||||
if (cmd == NULL)
|
||||
ft_printf("t_cmd = NULL\n");
|
||||
else
|
||||
{
|
||||
ft_printf("t_cmd\n");
|
||||
cmd_type_debug(cmd->type, leader, false);
|
||||
indent(leader, false);
|
||||
ft_printf("flags = %d\n", cmd->flags);
|
||||
dedent(leader, false);
|
||||
indent(leader, false);
|
||||
ft_printf("line = %d\n", cmd->line);
|
||||
dedent(leader, false);
|
||||
cmd_value_debug(cmd, leader, true);
|
||||
}
|
||||
dedent(leader, is_last);
|
||||
}
|
||||
20
src/parser/cmd/cmd_debug.h
Normal file
20
src/parser/cmd/cmd_debug.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* cmd_debug.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/09 16:51:17 by khais #+# #+# */
|
||||
/* Updated: 2025/04/09 16:54:24 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef CMD_DEBUG_H
|
||||
# define CMD_DEBUG_H
|
||||
|
||||
# include "../../minishell.h"
|
||||
|
||||
void cmd_debug(t_cmd *cmd, t_buffer *leader, bool is_last);
|
||||
|
||||
#endif // CMD_DEBUG_H
|
||||
61
src/parser/cmd/cmd_destroy.c
Normal file
61
src/parser/cmd/cmd_destroy.c
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* cmd_destroy.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/09 16:53:02 by khais #+# #+# */
|
||||
/* Updated: 2025/04/14 15:01:23 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "cmd_destroy.h"
|
||||
#include <stdlib.h>
|
||||
#include "../simple_cmd/simple_cmd.h"
|
||||
#include "libft.h"
|
||||
|
||||
void redirect_destroy(t_redirect *redirect)
|
||||
{
|
||||
t_redirect *next;
|
||||
|
||||
while (redirect != NULL)
|
||||
{
|
||||
next = redirect->next;
|
||||
free(redirect->here_doc_eof);
|
||||
worddesc_destroy(redirect->redirectee.filename);
|
||||
free(redirect);
|
||||
redirect = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void connec_cmd_destroy(t_connec_cmd *cmd)
|
||||
{
|
||||
if (cmd == NULL)
|
||||
return ;
|
||||
cmd_destroy(cmd->first);
|
||||
cmd_destroy(cmd->second);
|
||||
free(cmd);
|
||||
}
|
||||
|
||||
static void group_cmd_destroy(t_group_cmd *cmd)
|
||||
{
|
||||
if (cmd == NULL)
|
||||
return ;
|
||||
cmd_destroy(cmd->cmd);
|
||||
redirect_destroy(cmd->redirects);
|
||||
free(cmd);
|
||||
}
|
||||
|
||||
void cmd_destroy(t_cmd *cmd)
|
||||
{
|
||||
if (cmd == NULL)
|
||||
return ;
|
||||
if (cmd->type == FT_CONNECTION)
|
||||
connec_cmd_destroy(cmd->value.connection);
|
||||
if (cmd->type == FT_GROUP)
|
||||
group_cmd_destroy(cmd->value.group);
|
||||
if (cmd->type == FT_SIMPLE)
|
||||
simple_cmd_destroy(cmd->value.simple);
|
||||
free(cmd);
|
||||
}
|
||||
21
src/parser/cmd/cmd_destroy.h
Normal file
21
src/parser/cmd/cmd_destroy.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* cmd_destroy.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/09 16:52:31 by khais #+# #+# */
|
||||
/* Updated: 2025/04/14 15:10:13 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef CMD_DESTROY_H
|
||||
# define CMD_DESTROY_H
|
||||
|
||||
# include "../../minishell.h"
|
||||
|
||||
void cmd_destroy(t_cmd *cmd);
|
||||
void redirect_destroy(t_redirect *redirect);
|
||||
|
||||
#endif // CMD_DESTROY_H
|
||||
127
src/parser/cmd_parsing.c
Normal file
127
src/parser/cmd_parsing.c
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* cmd_parsing.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/31 10:28:28 by jguelen #+# #+# */
|
||||
/* Updated: 2025/04/15 11:38:55 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "cmd_parsing.h"
|
||||
#include <fcntl.h>
|
||||
#include "connec_cmd/connec_reorient_subtree.h"
|
||||
#include "worddesc/worddesc.h"
|
||||
#include "wordlist/wordlist.h"
|
||||
#include <unistd.h>
|
||||
#include "simple_cmd/simple_cmd_parse.h"
|
||||
#include "cmd/cmd_destroy.h"
|
||||
#include "group_cmd/group_cmd_parse.h"
|
||||
#include "pipeline/pipeline_parse.h"
|
||||
|
||||
void parse_error(t_minishell *app, t_worddesc *token)
|
||||
{
|
||||
ft_dprintf(STDERR_FILENO, "minishell: syntax error near unexpected "
|
||||
"token `%s'\n", token->word);
|
||||
app->last_return_value = 2;
|
||||
}
|
||||
|
||||
t_cmd *minishell_group_or_simple_parse(t_minishell *app, t_wordlist *tokens)
|
||||
{
|
||||
if (tokens->word->token_type == OPEN_PARENTH_TOKEN)
|
||||
{
|
||||
worddesc_destroy(wordlist_pop(&tokens));
|
||||
return (minishell_group_cmd_parse(app, tokens));
|
||||
}
|
||||
else
|
||||
return (minishell_simple_cmd_parse(app, tokens));
|
||||
}
|
||||
|
||||
t_cmd *minishell_opt_cmds_parse(t_minishell *app, t_wordlist *tokens,
|
||||
t_connector *connec)
|
||||
{
|
||||
t_worddesc *token;
|
||||
t_cmd *opt;
|
||||
|
||||
token = tokens->word;
|
||||
if (token->token_type == OR_TOKEN || token->token_type == AND_TOKEN)
|
||||
{
|
||||
if (token->token_type == OR_TOKEN)
|
||||
*connec = FT_OR;
|
||||
else
|
||||
*connec = FT_AND;
|
||||
token = wordlist_pop(&tokens);
|
||||
worddesc_destroy(token);
|
||||
opt = minishell_pipeline_parse(app, tokens);
|
||||
if (!opt)
|
||||
ft_errno(FT_EERRNO);
|
||||
return (opt);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
** Parse list of commands or pipeline.
|
||||
*/
|
||||
t_cmd *minishell_cmds_parse(t_minishell *app, t_wordlist *tokens)
|
||||
{
|
||||
t_cmd *subtree;
|
||||
t_cmd *opt;
|
||||
t_cmd *list;
|
||||
t_connector connec;
|
||||
|
||||
subtree = minishell_pipeline_parse(app, tokens);
|
||||
if (!subtree)
|
||||
return (NULL);
|
||||
opt = minishell_opt_cmds_parse(app, tokens, &connec);
|
||||
if (!opt && ft_errno_get() != FT_ESUCCESS)
|
||||
return (cmd_destroy(subtree), NULL);
|
||||
if (!opt)
|
||||
return (subtree);
|
||||
while (opt)
|
||||
{
|
||||
if (connec_reorient_subtree(&list, &subtree, &opt, connec) == NULL)
|
||||
{
|
||||
app->last_return_value = 1;
|
||||
return (ft_perror("minishell_cmds_parse"), NULL);
|
||||
}
|
||||
opt = minishell_opt_cmds_parse(app, tokens, &connec);
|
||||
}
|
||||
if (ft_errno_get() != FT_ESUCCESS)
|
||||
return (cmd_destroy(subtree), NULL);
|
||||
return (list);
|
||||
}
|
||||
|
||||
/*
|
||||
** TODO check if we need to differentiate the cause of a NULL return.
|
||||
*/
|
||||
t_cmd *minishell_parse(t_minishell *app, char *command_line)
|
||||
{
|
||||
t_cmd *root_cmd;
|
||||
t_wordlist *tokens;
|
||||
|
||||
ft_errno(FT_ESUCCESS);
|
||||
app->last_return_value = 0;
|
||||
if (!command_line)
|
||||
return (NULL);
|
||||
tokens = minishell_wordsplit(command_line);
|
||||
if (!tokens)
|
||||
return (NULL);
|
||||
root_cmd = minishell_cmds_parse(app, tokens);
|
||||
if (!root_cmd)
|
||||
{
|
||||
if (ft_errno_get() != FT_ESUCCESS && !app->last_return_value)
|
||||
app->last_return_value = 1;
|
||||
return (wordlist_destroy(tokens), NULL);
|
||||
}
|
||||
if (tokens)
|
||||
{
|
||||
parse_error(app, tokens->word);
|
||||
wordlist_destroy(tokens);
|
||||
cmd_destroy(root_cmd);
|
||||
return (NULL);
|
||||
}
|
||||
return (root_cmd);
|
||||
}
|
||||
30
src/parser/cmd_parsing.h
Normal file
30
src/parser/cmd_parsing.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* cmd_parsing.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/15 10:14:13 by khais #+# #+# */
|
||||
/* Updated: 2025/04/15 11:35:26 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef CMD_PARSING_H
|
||||
# define CMD_PARSING_H
|
||||
|
||||
# include "../minishell.h"
|
||||
# include "../ft_errno.h"
|
||||
# include <stdbool.h>
|
||||
|
||||
void parse_error(t_minishell *app, t_worddesc *token);
|
||||
t_redirect *t_redirect_add_back(t_redirect **init, t_redirect *back);
|
||||
t_cmd *minishell_parse(t_minishell *app, char *command_line);
|
||||
|
||||
t_cmd *minishell_cmds_parse(t_minishell *app, t_wordlist *tokens);
|
||||
t_cmd *minishell_opt_cmds_parse(t_minishell *app, t_wordlist *tokens,
|
||||
t_connector *connec);
|
||||
t_cmd *minishell_group_or_simple_parse(t_minishell *app,
|
||||
t_wordlist *tokens);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* cmdgroup.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/11 15:18:02 by khais #+# #+# */
|
||||
/* Updated: 2025/03/28 15:01:55 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "cmdgroup.h"
|
||||
#include "cmdgroup_builder.h"
|
||||
#include <stdlib.h>
|
||||
#include "libft.h"
|
||||
#include "paren.h"
|
||||
#include "../../treedrawing.h"
|
||||
#include "libft/libft.h"
|
||||
|
||||
/*
|
||||
** Recursively parse a cmdgroup
|
||||
**
|
||||
** This is responsible for parsing one optional set of parentheses surrounding a
|
||||
** cmdlist.
|
||||
**
|
||||
** If parentheses are present, also parse redirections, which may only occur
|
||||
** after the closing parenthesis.
|
||||
*/
|
||||
t_cmdgroup *cmdgroup_from_wordlist(t_wordlist *wordlist)
|
||||
{
|
||||
t_cmdgroup_builder builder;
|
||||
t_wordlist *words;
|
||||
t_paren paren;
|
||||
|
||||
words = wordlist_copy(wordlist);
|
||||
if (words == NULL)
|
||||
return (NULL);
|
||||
if (setup_cmdgroup_builder(&builder, &words) == NULL)
|
||||
return (wordlist_destroy(words), NULL);
|
||||
while (builder.error == false && builder.current_word != NULL)
|
||||
{
|
||||
paren = match_paren(builder.current_word->word);
|
||||
if (paren == PAREN_INVALID)
|
||||
cmdgroup_builder_next_word(&builder, &words);
|
||||
else
|
||||
cmdgroup_builder_paren(&builder, &words, paren);
|
||||
}
|
||||
if (builder.current_wordlist != NULL)
|
||||
cmdgroup_builder_delimit(&builder, &words);
|
||||
if (builder.error == true)
|
||||
return (NULL);
|
||||
return (builder.cmdgroup);
|
||||
}
|
||||
|
||||
void cmdgroup_destroy(t_cmdgroup *cmd)
|
||||
{
|
||||
if (cmd == NULL)
|
||||
return ;
|
||||
cmdlist_destroy(cmd->item);
|
||||
free(cmd);
|
||||
}
|
||||
|
||||
void cmdgroup_debug(t_cmdgroup *cmd, t_buffer *leader, bool is_last)
|
||||
{
|
||||
if (cmd == NULL)
|
||||
return ;
|
||||
indent(leader, is_last);
|
||||
ft_printf("%s\n", "t_cmdgroup");
|
||||
cmdlist_debug(cmd->item, leader, true);
|
||||
dedent(leader, is_last);
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* cmdgroup.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/11 15:11:57 by khais #+# #+# */
|
||||
/* Updated: 2025/03/19 12:10:37 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef CMDGROUP_H
|
||||
# define CMDGROUP_H
|
||||
|
||||
# include "../wordlist/wordlist.h"
|
||||
# include "../cmdlist/cmdlist.h"
|
||||
# include "../../buffer/buffer.h"
|
||||
|
||||
/*
|
||||
** A grouping of commands, surrounded by parentheses.
|
||||
**
|
||||
** A top-level cmdgroup is modeled as having an implicit set of parentheses.
|
||||
*/
|
||||
typedef struct s_cmdgroup
|
||||
{
|
||||
/*
|
||||
** list of the commands inside this group
|
||||
*/
|
||||
struct s_cmdlist *item;
|
||||
/*
|
||||
** redirections to apply to the whole group
|
||||
*/
|
||||
struct s_redirection_list *redirections;
|
||||
} t_cmdgroup;
|
||||
|
||||
t_cmdgroup *cmdgroup_from_wordlist(t_wordlist *words);
|
||||
void cmdgroup_destroy(t_cmdgroup *cmd);
|
||||
void cmdgroup_debug(t_cmdgroup *cmd, t_buffer *leader, bool is_last);
|
||||
|
||||
#endif // CMDGROUP_H
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* cmdgroup_builder.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/20 12:32:14 by khais #+# #+# */
|
||||
/* Updated: 2025/03/20 17:19:55 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "cmdgroup_builder.h"
|
||||
#include "libft.h"
|
||||
|
||||
/*
|
||||
** setup a cmdlist_builder by allocating additionall needed memory and
|
||||
** performing other init steps.
|
||||
*/
|
||||
t_cmdgroup_builder *setup_cmdgroup_builder(t_cmdgroup_builder *builder,
|
||||
t_wordlist **words)
|
||||
{
|
||||
ft_bzero(builder, sizeof (*builder));
|
||||
builder->cmdgroup = ft_calloc(1, sizeof(*builder->cmdgroup));
|
||||
if (builder->cmdgroup == NULL)
|
||||
return (NULL);
|
||||
builder->current_wordlist = NULL;
|
||||
builder->current_word = wordlist_pop(words);
|
||||
return (builder);
|
||||
}
|
||||
|
||||
/*
|
||||
** Advance the state to the next word
|
||||
*/
|
||||
void cmdgroup_builder_next_word(t_cmdgroup_builder *builder,
|
||||
t_wordlist **words)
|
||||
{
|
||||
builder->current_wordlist = wordlist_push(builder->current_wordlist,
|
||||
builder->current_word);
|
||||
builder->current_word = wordlist_pop(words);
|
||||
}
|
||||
|
||||
/*
|
||||
** Delimit the cmdlist, setting up the t_cmdlist item.
|
||||
*/
|
||||
void cmdgroup_builder_delimit(t_cmdgroup_builder *builder,
|
||||
t_wordlist **words)
|
||||
{
|
||||
builder->cmdgroup->item = cmdlist_from_wordlist(builder->current_wordlist);
|
||||
wordlist_destroy(builder->current_wordlist);
|
||||
builder->current_wordlist = NULL;
|
||||
(void)words;
|
||||
}
|
||||
|
||||
/*
|
||||
** discard the current word
|
||||
*/
|
||||
void cmdgroup_builder_discard_word(t_cmdgroup_builder *builder,
|
||||
t_wordlist **words)
|
||||
{
|
||||
worddesc_destroy(builder->current_word);
|
||||
builder->current_word = wordlist_pop(words);
|
||||
}
|
||||
|
||||
/*
|
||||
** Handle encountering a parenthesis token
|
||||
*/
|
||||
void cmdgroup_builder_paren(t_cmdgroup_builder *builder,
|
||||
t_wordlist **words, t_paren paren)
|
||||
{
|
||||
cmdgroup_builder_discard_word(builder, words);
|
||||
(void)paren;
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* cmdgroup_builder.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/20 12:27:20 by khais #+# #+# */
|
||||
/* Updated: 2025/03/20 17:12:52 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef CMDGROUP_BUILDER_H
|
||||
# define CMDGROUP_BUILDER_H
|
||||
|
||||
# include "../wordlist/wordlist.h"
|
||||
# include "cmdgroup.h"
|
||||
# include "paren.h"
|
||||
|
||||
typedef struct s_cmdgroup_builder
|
||||
{
|
||||
/*
|
||||
** set to true if in an error state
|
||||
*/
|
||||
bool error;
|
||||
/*
|
||||
** current word that is being examined
|
||||
*/
|
||||
t_worddesc *current_word;
|
||||
/*
|
||||
** wordlist to be passed to lower stages of parsing
|
||||
*/
|
||||
t_wordlist *current_wordlist;
|
||||
/*
|
||||
** cmdgroup that is being constructed
|
||||
*/
|
||||
t_cmdgroup *cmdgroup;
|
||||
/*
|
||||
** count of parenthesis tokens
|
||||
**
|
||||
** +1 for each opening parenthesis, -1 for each closing
|
||||
*/
|
||||
int paren;
|
||||
} t_cmdgroup_builder;
|
||||
|
||||
t_cmdgroup_builder *setup_cmdgroup_builder(t_cmdgroup_builder *builder,
|
||||
t_wordlist **words);
|
||||
void cmdgroup_builder_next_word(t_cmdgroup_builder *builder,
|
||||
t_wordlist **words);
|
||||
void cmdgroup_builder_delimit(t_cmdgroup_builder *builder,
|
||||
t_wordlist **words);
|
||||
void cmdgroup_builder_paren(t_cmdgroup_builder *builder,
|
||||
t_wordlist **words, t_paren paren);
|
||||
|
||||
#endif // CMDGROUP_BUILDER_H
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* 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);
|
||||
}
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* cmdlist.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/24 17:45:01 by khais #+# #+# */
|
||||
/* Updated: 2025/03/19 16:43:14 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef CMDLIST_H
|
||||
# define CMDLIST_H
|
||||
|
||||
# include "../wordlist/wordlist.h"
|
||||
# include "../pipeline/pipeline.h"
|
||||
# include "operator.h"
|
||||
# include "../../buffer/buffer.h"
|
||||
|
||||
/*
|
||||
** cf. 3.2.4 Lists of Commands
|
||||
**
|
||||
** A list is a sequence of one or more pipelines separated by one of the
|
||||
** **operators** ‘&&’, or ‘||’, and optionally terminated by a newline.
|
||||
**
|
||||
** AND and OR lists are sequences of one or more pipelines separated by the
|
||||
** control operators ‘&&’ and ‘||’, respectively.
|
||||
**
|
||||
** AND and OR lists are executed with left associativity.
|
||||
**
|
||||
** e.g.
|
||||
**
|
||||
** ```shell
|
||||
** A && B && C
|
||||
** ```
|
||||
**
|
||||
** is the same as
|
||||
**
|
||||
** ```shell
|
||||
** (A && B) && C
|
||||
** ```
|
||||
**
|
||||
** An AND list has the form
|
||||
**
|
||||
** ```shell
|
||||
** A && B
|
||||
** ```
|
||||
**
|
||||
** B is executed if and only if A has an exit status of 0 (succes).
|
||||
**
|
||||
** An OR list has the form
|
||||
**
|
||||
** ```shell
|
||||
** A || B
|
||||
** ```
|
||||
**
|
||||
** B is executed if and only if A has a non-zero exit status (failure).
|
||||
**
|
||||
** The return status of AND and OR lists is the exit status of the last command
|
||||
** executed in the list.
|
||||
*/
|
||||
typedef struct s_cmdlist
|
||||
{
|
||||
/*
|
||||
** Array of pointers to commands in this command list
|
||||
**
|
||||
** These should be executed left to right.
|
||||
*/
|
||||
struct s_cmdlist_item **cmds;
|
||||
/*
|
||||
** Number of commands in this command list.
|
||||
*/
|
||||
int num_cmd;
|
||||
/*
|
||||
** Operators that separate the pipelines.
|
||||
**
|
||||
** pipelines[0] operators[0] pipelines[1] operators[1]
|
||||
**
|
||||
** Terminated by OP_END
|
||||
**
|
||||
** In example above, operators[1] == OP_END
|
||||
*/
|
||||
t_operator *operators;
|
||||
} t_cmdlist;
|
||||
|
||||
t_cmdlist *cmdlist_from_wordlist(const t_wordlist *wordlist);
|
||||
void cmdlist_destroy(t_cmdlist *cmd);
|
||||
void cmdlist_debug(t_cmdlist *cmd, t_buffer *leader, bool is_last);
|
||||
|
||||
#endif // CMDLIST_H
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* cmdlist_builder.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/26 13:51:18 by khais #+# #+# */
|
||||
/* Updated: 2025/03/19 16:43:14 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "cmdlist_builder.h"
|
||||
#include "libft.h"
|
||||
|
||||
/*
|
||||
** Count the number of pipelines in the given wordstream
|
||||
**
|
||||
** Pipelines are separated by operators || and &&.
|
||||
**
|
||||
** Does not do error checking about repeated operators, or operators in the
|
||||
** wrong place.
|
||||
*/
|
||||
static int cmdlist_count_pipelines(t_wordlist *words)
|
||||
{
|
||||
t_wordlist *current_word;
|
||||
int count;
|
||||
|
||||
current_word = words;
|
||||
if (current_word == NULL)
|
||||
return (0);
|
||||
count = 1;
|
||||
while (current_word != NULL)
|
||||
{
|
||||
if (match_op(current_word->word->word) != OP_INVALID)
|
||||
count++;
|
||||
current_word = current_word->next;
|
||||
}
|
||||
return (count);
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate memory for a new cmdlist, given the input word stream.
|
||||
**
|
||||
** Handles malloc error.
|
||||
*/
|
||||
static t_cmdlist *allocate_cmdlist(t_wordlist *words)
|
||||
{
|
||||
t_cmdlist *output;
|
||||
|
||||
if (words == NULL)
|
||||
return (NULL);
|
||||
output = ft_calloc(1, sizeof(t_cmdlist));
|
||||
if (output == NULL)
|
||||
return (NULL);
|
||||
output->num_cmd = cmdlist_count_pipelines(words);
|
||||
output->cmds
|
||||
= ft_calloc(output->num_cmd, sizeof(struct s_cmdlist_item **));
|
||||
if (output->cmds == NULL)
|
||||
return (free(output), NULL);
|
||||
output->operators
|
||||
= ft_calloc(output->num_cmd, sizeof(t_operator));
|
||||
if (output->operators == NULL)
|
||||
return (free(output->cmds), free(output), NULL);
|
||||
return (output);
|
||||
}
|
||||
|
||||
/*
|
||||
** setup a given cmdlist_builder by allocating additional needed memory, and
|
||||
** performing other initialization steps.
|
||||
*/
|
||||
t_cmdlist_builder *setup_cmdlist_builder(
|
||||
t_cmdlist_builder *builder,
|
||||
t_wordlist **words)
|
||||
{
|
||||
ft_bzero(builder, sizeof(t_cmdlist_builder));
|
||||
builder->cmdlist = allocate_cmdlist(*words);
|
||||
if (builder->cmdlist == NULL)
|
||||
return (NULL);
|
||||
builder->current_wordlist = NULL;
|
||||
builder->current_word = wordlist_pop(words);
|
||||
builder->idx = 0;
|
||||
return (builder);
|
||||
}
|
||||
|
||||
/*
|
||||
** Advance the state to the next word
|
||||
*/
|
||||
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
|
||||
*/
|
||||
bool cmdlist_builder_at_last_pipeline(t_cmdlist_builder *builder)
|
||||
{
|
||||
return (builder->idx == builder->cmdlist->num_cmd - 1);
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* cmdlist_builder.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/26 13:50:25 by khais #+# #+# */
|
||||
/* Updated: 2025/03/18 15:02:53 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef CMDLIST_BUILDER_H
|
||||
# define CMDLIST_BUILDER_H
|
||||
|
||||
# include "cmdlist.h"
|
||||
|
||||
typedef struct s_cmdlist_builder
|
||||
{
|
||||
/*
|
||||
** list of cmds that we are building
|
||||
*/
|
||||
t_cmdlist *cmdlist;
|
||||
/*
|
||||
** wordlist for the next pipeline
|
||||
*/
|
||||
t_wordlist *current_wordlist;
|
||||
/*
|
||||
** word we are currently examining
|
||||
*/
|
||||
t_worddesc *current_word;
|
||||
/*
|
||||
** index of the pipeline that is about to be inserted into the cmdlist
|
||||
*/
|
||||
int idx;
|
||||
/*
|
||||
** set to true in an error was encountered that requires stopping the
|
||||
** processing.
|
||||
*/
|
||||
bool error;
|
||||
} t_cmdlist_builder;
|
||||
|
||||
t_cmdlist_builder *setup_cmdlist_builder(
|
||||
t_cmdlist_builder *builder,
|
||||
t_wordlist **words);
|
||||
bool cmdlist_builder_at_last_pipeline(
|
||||
t_cmdlist_builder *builder);
|
||||
void cmdlist_builder_next_word(
|
||||
t_cmdlist_builder *builder,
|
||||
t_wordlist **words);
|
||||
|
||||
#endif // CMDLIST_BUILDER_H
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* cmdlist_debug.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/18 15:52:28 by khais #+# #+# */
|
||||
/* Updated: 2025/03/19 16:43:14 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "cmdlist.h"
|
||||
#include "../../treedrawing.h"
|
||||
#include "libft.h"
|
||||
#include "cmdlist_item.h"
|
||||
|
||||
static void cmdlist_array_debug(t_cmdlist *cmd,
|
||||
int i, t_buffer *leader, bool is_last)
|
||||
{
|
||||
indent(leader, is_last);
|
||||
ft_printf("cmd[%d]\n", i);
|
||||
cmdlist_item_debug(cmd->cmds[i], leader, false);
|
||||
operator_debug(cmd->operators[i], leader, true);
|
||||
dedent(leader, is_last);
|
||||
}
|
||||
|
||||
static void cmdlist_num_cmds_debug(int num_cmds, t_buffer *leader, bool is_last)
|
||||
{
|
||||
indent(leader, is_last);
|
||||
ft_printf("num_cmds = %d\n", num_cmds);
|
||||
dedent(leader, is_last);
|
||||
}
|
||||
|
||||
void cmdlist_debug(t_cmdlist *cmd, t_buffer *leader, bool is_last)
|
||||
{
|
||||
int i;
|
||||
bool last;
|
||||
|
||||
if (cmd == NULL)
|
||||
return ;
|
||||
indent(leader, is_last);
|
||||
ft_printf("%s\n", "t_cmdlist");
|
||||
i = 0;
|
||||
last = false;
|
||||
if (cmd->num_cmd == 0)
|
||||
last = true;
|
||||
cmdlist_num_cmds_debug(cmd->num_cmd, leader, last);
|
||||
while (i < cmd->num_cmd)
|
||||
{
|
||||
if (i == cmd->num_cmd - 1)
|
||||
last = true;
|
||||
cmdlist_array_debug(cmd, i, leader, last);
|
||||
i++;
|
||||
}
|
||||
dedent(leader, is_last);
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* cmdlist_item.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/18 13:02:02 by khais #+# #+# */
|
||||
/* Updated: 2025/03/19 14:11:27 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "cmdlist_item.h"
|
||||
#include "cmdlist_item_type.h"
|
||||
#include "libft.h"
|
||||
#include "../../treedrawing.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);
|
||||
}
|
||||
|
||||
void cmdlist_item_debug(t_cmdlist_item *item, t_buffer *leader, bool is_last)
|
||||
{
|
||||
if (item == NULL)
|
||||
return ;
|
||||
indent(leader, is_last);
|
||||
ft_printf("%s\n", "t_cmdlist_item");
|
||||
if (item->type == TYPE_INVALID)
|
||||
{
|
||||
indent(leader, true);
|
||||
ft_printf("%s\n", "type = INVALID");
|
||||
dedent(leader, true);
|
||||
}
|
||||
else if (item->type == TYPE_PIPELINE)
|
||||
pipeline_debug(item->inner.pipeline, leader, true);
|
||||
else if (item->type == TYPE_CMDGROUP)
|
||||
cmdgroup_debug(item->inner.cmdgroup, leader, true);
|
||||
dedent(leader, is_last);
|
||||
}
|
||||
51
src/parser/connec_cmd/connec_cmd_debug.c
Normal file
51
src/parser/connec_cmd/connec_cmd_debug.c
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* connec_cmd_debug.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/09 17:47:18 by khais #+# #+# */
|
||||
/* Updated: 2025/04/09 17:49:02 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "connec_cmd_debug.h"
|
||||
#include "../../treedrawing.h"
|
||||
#include "libft.h"
|
||||
#include "../cmd/cmd_debug.h"
|
||||
|
||||
static void connector_debug(t_connector connector, t_buffer *leader,
|
||||
bool is_last)
|
||||
{
|
||||
indent(leader, is_last);
|
||||
ft_printf("t_connector = ");
|
||||
if (connector == FT_PIPE)
|
||||
ft_printf("FT_PIPE\n");
|
||||
if (connector == FT_AND)
|
||||
ft_printf("FT_AND\n");
|
||||
if (connector == FT_OR)
|
||||
ft_printf("FT_OR\n");
|
||||
dedent(leader, is_last);
|
||||
}
|
||||
|
||||
void connec_cmd_debug(t_connec_cmd *cmd, t_buffer *leader, bool is_last)
|
||||
{
|
||||
indent(leader, is_last);
|
||||
if (cmd == NULL)
|
||||
ft_printf("t_connec_cmd = NULL\n");
|
||||
else
|
||||
{
|
||||
ft_printf("t_connec_cmd\n");
|
||||
indent(leader, false);
|
||||
ft_printf("first\n");
|
||||
cmd_debug(cmd->first, leader, true);
|
||||
dedent(leader, false);
|
||||
indent(leader, false);
|
||||
ft_printf("second\n");
|
||||
cmd_debug(cmd->second, leader, true);
|
||||
dedent(leader, false);
|
||||
connector_debug(cmd->connector, leader, true);
|
||||
}
|
||||
dedent(leader, is_last);
|
||||
}
|
||||
20
src/parser/connec_cmd/connec_cmd_debug.h
Normal file
20
src/parser/connec_cmd/connec_cmd_debug.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* connec_cmd_debug.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/09 17:46:51 by khais #+# #+# */
|
||||
/* Updated: 2025/04/09 17:48:30 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef CONNEC_CMD_DEBUG_H
|
||||
# define CONNEC_CMD_DEBUG_H
|
||||
|
||||
# include "../../minishell.h"
|
||||
|
||||
void connec_cmd_debug(t_connec_cmd *cmd, t_buffer *leader, bool is_last);
|
||||
|
||||
#endif // CONNEC_CMD_DEBUG_H
|
||||
42
src/parser/connec_cmd/connec_reorient_subtree.c
Normal file
42
src/parser/connec_cmd/connec_reorient_subtree.c
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* connec_reorient_subtree.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/15 11:37:35 by khais #+# #+# */
|
||||
/* Updated: 2025/04/15 11:39:41 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "connec_reorient_subtree.h"
|
||||
#include "../cmd/cmd.h"
|
||||
#include "../cmd/cmd_destroy.h"
|
||||
#include "../../ft_errno.h"
|
||||
|
||||
t_cmd *connec_reorient_subtree(t_cmd **list, t_cmd **subtree,
|
||||
t_cmd **opt, t_connector connec)
|
||||
{
|
||||
*list = cmd_create(FT_CONNECTION);
|
||||
if (!*list)
|
||||
{
|
||||
cmd_destroy(*subtree);
|
||||
cmd_destroy(*opt);
|
||||
return (NULL);
|
||||
}
|
||||
(*list)->value.connection = ft_calloc(1, sizeof(t_connec_cmd));
|
||||
if (!(*list)->value.connection)
|
||||
{
|
||||
ft_errno(FT_ENOMEM);
|
||||
cmd_destroy(*subtree);
|
||||
cmd_destroy(*opt);
|
||||
return (free(*list), NULL);
|
||||
}
|
||||
(*list)->type = FT_CONNECTION;
|
||||
(*list)->value.connection->connector = connec;
|
||||
(*list)->value.connection->first = *subtree;
|
||||
(*list)->value.connection->second = *opt;
|
||||
*subtree = *list;
|
||||
return (*subtree);
|
||||
}
|
||||
21
src/parser/connec_cmd/connec_reorient_subtree.h
Normal file
21
src/parser/connec_cmd/connec_reorient_subtree.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* connec_reorient_subtree.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/15 11:37:48 by khais #+# #+# */
|
||||
/* Updated: 2025/04/15 11:40:02 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef CONNEC_REORIENT_SUBTREE_H
|
||||
# define CONNEC_REORIENT_SUBTREE_H
|
||||
|
||||
# include "../../minishell.h"
|
||||
|
||||
t_cmd *connec_reorient_subtree(t_cmd **list, t_cmd **subtree,
|
||||
t_cmd **opt, t_connector connec);
|
||||
|
||||
#endif // CONNEC_REORIENT_SUBTREE_H
|
||||
|
|
@ -1,43 +1,32 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* operator.c :+: :+: :+: */
|
||||
/* group_cmd_debug.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/26 12:51:28 by khais #+# #+# */
|
||||
/* Updated: 2025/03/19 14:44:03 by khais ### ########.fr */
|
||||
/* Created: 2025/04/09 17:43:56 by khais #+# #+# */
|
||||
/* Updated: 2025/04/14 15:06:36 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "operator.h"
|
||||
#include "libft.h"
|
||||
#include "group_cmd_debug.h"
|
||||
#include "../../treedrawing.h"
|
||||
#include "libft.h"
|
||||
#include "../cmd/cmd_debug.h"
|
||||
#include "../redirect/redirect_debug.h"
|
||||
|
||||
/*
|
||||
** Match a string to an operator
|
||||
**
|
||||
** If the string does not match any operator, return OP_INVALID
|
||||
*/
|
||||
t_operator match_op(char *op)
|
||||
{
|
||||
if (ft_strcmp("&&", op) == 0)
|
||||
return (OP_AND);
|
||||
if (ft_strcmp("||", op) == 0)
|
||||
return (OP_OR);
|
||||
return (OP_INVALID);
|
||||
}
|
||||
|
||||
void operator_debug(t_operator op, t_buffer *leader,
|
||||
bool is_last)
|
||||
void group_cmd_debug(t_group_cmd *cmd, t_buffer *leader, bool is_last)
|
||||
{
|
||||
indent(leader, is_last);
|
||||
ft_printf("t_operator = ");
|
||||
if (op == OP_AND)
|
||||
ft_printf("%s\n", "AND");
|
||||
if (op == OP_OR)
|
||||
ft_printf("%s\n", "OR");
|
||||
if (op == OP_END)
|
||||
ft_printf("%s\n", "END");
|
||||
ft_printf("t_group_cmd\n");
|
||||
indent(leader, false);
|
||||
ft_printf("cmd\n");
|
||||
cmd_debug(cmd->cmd, leader, false);
|
||||
dedent(leader, false);
|
||||
indent(leader, true);
|
||||
ft_printf("redirect\n");
|
||||
redirect_debug(cmd->redirects, leader, true);
|
||||
dedent(leader, true);
|
||||
dedent(leader, is_last);
|
||||
}
|
||||
20
src/parser/group_cmd/group_cmd_debug.h
Normal file
20
src/parser/group_cmd/group_cmd_debug.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* group_cmd_debug.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/09 17:43:25 by khais #+# #+# */
|
||||
/* Updated: 2025/04/09 17:45:20 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef GROUP_CMD_DEBUG_H
|
||||
# define GROUP_CMD_DEBUG_H
|
||||
|
||||
# include "../../minishell.h"
|
||||
|
||||
void group_cmd_debug(t_group_cmd *cmd, t_buffer *leader, bool is_last);
|
||||
|
||||
#endif // GROUP_CMD_DEBUG_H
|
||||
43
src/parser/group_cmd/group_cmd_parse.c
Normal file
43
src/parser/group_cmd/group_cmd_parse.c
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* group_cmd_parse.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/15 10:46:28 by khais #+# #+# */
|
||||
/* Updated: 2025/04/15 10:47:19 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "group_cmd_parse.h"
|
||||
#include "../cmd_parsing.h"
|
||||
#include "../cmd/cmd_destroy.h"
|
||||
#include "../cmd/cmd.h"
|
||||
#include "../redirect/redirect_parse.h"
|
||||
|
||||
t_cmd *minishell_group_cmd_parse(t_minishell *app, t_wordlist *tokens)
|
||||
{
|
||||
t_cmd *subtree;
|
||||
t_cmd *group;
|
||||
|
||||
subtree = minishell_cmds_parse(app, tokens);
|
||||
if (!subtree
|
||||
|| tokens->word->token_type != CLOSE_PARENTH_TOKEN)
|
||||
{
|
||||
ft_errno(FT_EERRNO);
|
||||
if (tokens->word->token_type != CLOSE_PARENTH_TOKEN)
|
||||
parse_error(app, tokens->word);
|
||||
return (cmd_destroy(subtree), NULL);
|
||||
}
|
||||
worddesc_destroy(wordlist_pop(&tokens));
|
||||
group = cmd_create(FT_GROUP);
|
||||
if (!group)
|
||||
return (cmd_destroy(subtree), NULL);
|
||||
group->value.group->cmd = subtree;
|
||||
group->value.group->redirects = minishell_redirect_parse(app, tokens);
|
||||
if (group->value.group->redirects == NULL
|
||||
&& ft_errno_get() != FT_ESUCCESS)
|
||||
return (cmd_destroy(group), NULL);
|
||||
return (group);
|
||||
}
|
||||
20
src/parser/group_cmd/group_cmd_parse.h
Normal file
20
src/parser/group_cmd/group_cmd_parse.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* group_cmd_parse.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/15 10:45:49 by khais #+# #+# */
|
||||
/* Updated: 2025/04/15 10:46:15 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef GROUP_CMD_PARSE_H
|
||||
# define GROUP_CMD_PARSE_H
|
||||
|
||||
# include "../../minishell.h"
|
||||
|
||||
t_cmd *minishell_group_cmd_parse(t_minishell *app, t_wordlist *tokens);
|
||||
|
||||
#endif // GROUP_CMD_PARSE_H
|
||||
33
src/parser/pipeline/optional_pipeline_parse.c
Normal file
33
src/parser/pipeline/optional_pipeline_parse.c
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* optional_pipeline_parse.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/15 10:43:04 by khais #+# #+# */
|
||||
/* Updated: 2025/04/15 10:43:40 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "optional_pipeline_parse.h"
|
||||
#include "../../ft_errno.h"
|
||||
#include "../cmd_parsing.h"
|
||||
|
||||
t_cmd *minishell_optional_pipeline_parse(t_minishell *app, t_wordlist *tokens)
|
||||
{
|
||||
t_cmd *opt;
|
||||
t_worddesc *token;
|
||||
|
||||
token = tokens->word;
|
||||
if (token->token_type == PIPE_TOKEN)
|
||||
{
|
||||
token = wordlist_pop(&tokens);
|
||||
worddesc_destroy(token);
|
||||
opt = minishell_group_or_simple_parse(app, tokens);
|
||||
if (!opt)
|
||||
ft_errno(FT_EERRNO);
|
||||
return (opt);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
21
src/parser/pipeline/optional_pipeline_parse.h
Normal file
21
src/parser/pipeline/optional_pipeline_parse.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* optional_pipeline_parse.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/15 10:42:34 by khais #+# #+# */
|
||||
/* Updated: 2025/04/15 10:42:57 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef OPTIONAL_PIPELINE_PARSE_H
|
||||
# define OPTIONAL_PIPELINE_PARSE_H
|
||||
|
||||
# include "../../minishell.h"
|
||||
|
||||
t_cmd *minishell_optional_pipeline_parse(t_minishell *app,
|
||||
t_wordlist *tokens);
|
||||
|
||||
#endif // OPTIONAL_PIPELINE_PARSE_H
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* pipeline.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/21 13:23:50 by khais #+# #+# */
|
||||
/* Updated: 2025/03/19 14:38:58 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "pipeline.h"
|
||||
#include "pipeline_parse.h"
|
||||
#include "libft.h"
|
||||
|
||||
/*
|
||||
** Parse a pipeline from the given wordlist.
|
||||
**
|
||||
** Return NULL and set ft_errno in case of error.
|
||||
**
|
||||
** Makes a copy of words
|
||||
*/
|
||||
t_pipeline *pipeline_from_wordlist(const t_wordlist *words)
|
||||
{
|
||||
t_pipeline *pipeline;
|
||||
t_pipeline_builder builder;
|
||||
|
||||
if (words == NULL)
|
||||
return (NULL);
|
||||
pipeline = ft_calloc(1, sizeof(t_pipeline));
|
||||
if (pipeline == NULL)
|
||||
return (NULL);
|
||||
pipeline->num_cmd = pipeline_count_cmds(words);
|
||||
pipeline->cmds = ft_calloc(pipeline->num_cmd, sizeof(t_simple_cmd *));
|
||||
if (pipeline->cmds == NULL)
|
||||
return (NULL);
|
||||
ft_bzero(&builder, sizeof(t_pipeline_builder));
|
||||
builder.words = wordlist_copy(words);
|
||||
builder.pipeline = pipeline;
|
||||
pipeline = pipeline_parse_wordlist(&builder);
|
||||
return (pipeline);
|
||||
}
|
||||
|
||||
/*
|
||||
** Destroy the given pipeline, freeing all memory.
|
||||
*/
|
||||
void pipeline_destroy(t_pipeline *pipeline)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (pipeline == NULL)
|
||||
return ;
|
||||
i = 0;
|
||||
while (i < pipeline->num_cmd)
|
||||
{
|
||||
simple_cmd_destroy(pipeline->cmds[i]);
|
||||
i++;
|
||||
}
|
||||
free(pipeline->cmds);
|
||||
free(pipeline);
|
||||
}
|
||||
|
||||
/*
|
||||
** Free all memory for the given builder, set freed variables to NULL, and set
|
||||
** error to true
|
||||
*/
|
||||
void builder_destroy(t_pipeline_builder *builder)
|
||||
{
|
||||
pipeline_destroy(builder->pipeline);
|
||||
builder->pipeline = NULL;
|
||||
worddesc_destroy(builder->current_word);
|
||||
builder->current_word = NULL;
|
||||
wordlist_destroy(builder->words);
|
||||
builder->words = NULL;
|
||||
builder->error = true;
|
||||
}
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* pipeline.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/21 13:19:51 by khais #+# #+# */
|
||||
/* Updated: 2025/03/19 14:40:08 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef PIPELINE_H
|
||||
# define PIPELINE_H
|
||||
|
||||
# include "../simple_cmd/simple_cmd.h"
|
||||
# include "../../buffer/buffer.h"
|
||||
# include <stdbool.h>
|
||||
|
||||
/*
|
||||
** cf. 3.2.3 Pipelines
|
||||
**
|
||||
** A pipeline is a sequence of one or more commands separated by the control
|
||||
** operator '|'.
|
||||
**
|
||||
** The output of each command in the pipeline is connected via a pipe to the
|
||||
** input of the next command.
|
||||
**
|
||||
** That is, each command reads the previous command’s output.
|
||||
**
|
||||
** This connection is performed before any redirections specified by the first
|
||||
** command.
|
||||
**
|
||||
** The shell waits for all commands in the pipeline to complete before reading
|
||||
** the next command.
|
||||
**
|
||||
** Each command in a multi-command pipeline, where pipes are created, is
|
||||
** executed in its own _subshell_, which is a separate process.
|
||||
**
|
||||
** e.g.
|
||||
**
|
||||
** ```shell
|
||||
** export TT=1 | echo $TT
|
||||
** ```
|
||||
**
|
||||
** prints an empty string, because TT is unset in the second subshell.
|
||||
**
|
||||
** The exit status of a pipeline is the exit status of the last command in the
|
||||
** pipeline.
|
||||
**
|
||||
** The shell waits for all commands in the pipeline to terminate before
|
||||
** returning a value.
|
||||
*/
|
||||
typedef struct s_pipeline
|
||||
{
|
||||
/*
|
||||
** The commands in the pipeline
|
||||
*/
|
||||
t_simple_cmd **cmds;
|
||||
/*
|
||||
** The number of commands in this pipeline
|
||||
*/
|
||||
int num_cmd;
|
||||
} t_pipeline;
|
||||
|
||||
typedef struct s_pipeline_builder
|
||||
{
|
||||
/*
|
||||
** index of the command we are currently working on
|
||||
*/
|
||||
int idx;
|
||||
/*
|
||||
** wordlist that is being built up to be the wordlist of the command being
|
||||
** parsed
|
||||
*/
|
||||
t_wordlist *current_wordlist;
|
||||
/*
|
||||
** word that is currently being considered
|
||||
*/
|
||||
t_worddesc *current_word;
|
||||
/*
|
||||
** linked list of words that are being parsed
|
||||
*/
|
||||
t_wordlist *words;
|
||||
/*
|
||||
** pipeline that is currently being constructed
|
||||
*/
|
||||
t_pipeline *pipeline;
|
||||
/*
|
||||
** true if an error occured, which should interrupt processing
|
||||
*/
|
||||
bool error;
|
||||
} t_pipeline_builder;
|
||||
|
||||
t_pipeline *pipeline_from_wordlist(const t_wordlist *words);
|
||||
void pipeline_destroy(t_pipeline *pipeline);
|
||||
void builder_destroy(t_pipeline_builder *builder);
|
||||
void pipeline_debug(t_pipeline *pipeline, t_buffer *leader,
|
||||
bool is_last);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* pipeline_debug.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/19 14:38:51 by khais #+# #+# */
|
||||
/* Updated: 2025/03/19 14:39:55 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "libft.h"
|
||||
#include "../../treedrawing.h"
|
||||
#include "pipeline.h"
|
||||
|
||||
static void pipeline_num_cmds_debug(int num_cmds, t_buffer *leader,
|
||||
bool is_last)
|
||||
{
|
||||
indent(leader, is_last);
|
||||
ft_printf("num_cmd = %d\n", num_cmds);
|
||||
dedent(leader, is_last);
|
||||
}
|
||||
|
||||
static void pipeline_array_debug(t_pipeline *pipeline,
|
||||
int i, t_buffer *leader, bool is_last)
|
||||
{
|
||||
indent(leader, is_last);
|
||||
ft_printf("cmd[%d]\n", i);
|
||||
simple_cmd_debug(pipeline->cmds[i], leader, true);
|
||||
dedent(leader, is_last);
|
||||
}
|
||||
|
||||
void pipeline_debug(t_pipeline *pipeline, t_buffer *leader, bool is_last)
|
||||
{
|
||||
int i;
|
||||
bool last;
|
||||
|
||||
if (pipeline == NULL)
|
||||
return ;
|
||||
indent(leader, is_last);
|
||||
ft_printf("%s\n", "t_pipeline");
|
||||
i = 0;
|
||||
last = false;
|
||||
if (pipeline->num_cmd == 0)
|
||||
last = true;
|
||||
pipeline_num_cmds_debug(pipeline->num_cmd, leader, last);
|
||||
while (i < pipeline->num_cmd)
|
||||
{
|
||||
if (i == pipeline->num_cmd - 1)
|
||||
last = true;
|
||||
pipeline_array_debug(pipeline, i, leader, last);
|
||||
i++;
|
||||
}
|
||||
dedent(leader, is_last);
|
||||
}
|
||||
|
|
@ -5,123 +5,41 @@
|
|||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/24 14:36:43 by khais #+# #+# */
|
||||
/* Updated: 2025/03/04 13:19:46 by khais ### ########.fr */
|
||||
/* Created: 2025/04/15 11:35:08 by khais #+# #+# */
|
||||
/* Updated: 2025/04/15 11:38:39 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "pipeline_parse.h"
|
||||
#include "ft_printf.h"
|
||||
#include "pipeline.h"
|
||||
#include "pipeline_parse_baseops.h"
|
||||
#include "../../ft_errno.h"
|
||||
#include "../matchers/pipe.h"
|
||||
#include "unistd.h"
|
||||
#include "libft.h"
|
||||
#include <stdlib.h>
|
||||
#include "optional_pipeline_parse.h"
|
||||
#include "../cmd_parsing.h"
|
||||
#include "../cmd/cmd_destroy.h"
|
||||
#include "../connec_cmd/connec_reorient_subtree.h"
|
||||
|
||||
/*
|
||||
** count the number of commands in a pipeline from the given words.
|
||||
**
|
||||
** A command is separated from the next by a pipe token.
|
||||
**
|
||||
** Note that this does not handle errors such as repeated pipe tokens, or pipe
|
||||
** tokens at the wrong place.
|
||||
*/
|
||||
int pipeline_count_cmds(const t_wordlist *words)
|
||||
t_cmd *minishell_pipeline_parse(t_minishell *app, t_wordlist *tokens)
|
||||
{
|
||||
int count;
|
||||
t_cmd *subtree;
|
||||
t_cmd *opt;
|
||||
t_cmd *pipeline;
|
||||
|
||||
if (words == NULL)
|
||||
return (0);
|
||||
count = 1;
|
||||
while (words != NULL)
|
||||
subtree = minishell_group_or_simple_parse(app, tokens);
|
||||
if (!subtree)
|
||||
return (NULL);
|
||||
opt = minishell_optional_pipeline_parse(app, tokens);
|
||||
if (!opt && ft_errno_get() != FT_ESUCCESS)
|
||||
return (NULL);
|
||||
if (!opt)
|
||||
return (subtree);
|
||||
while (opt)
|
||||
{
|
||||
if (is_pipe(words->word))
|
||||
count++;
|
||||
words = words->next;
|
||||
}
|
||||
return (count);
|
||||
}
|
||||
|
||||
/*
|
||||
** Delimit a command in the pipeline.
|
||||
**
|
||||
** - Create a new simple command from the wordlist that has been accumulated
|
||||
** thus far.
|
||||
** - Reset the current wordlist.
|
||||
** - Ignore the current word, which is assumed to be a pipe token.
|
||||
** - Check if the new current word is a pipe token, and if it is, signal
|
||||
** FT_EUNEXPECTED_PIPE.
|
||||
**
|
||||
** Destroys the builder and sets error in case of error.
|
||||
*/
|
||||
static void pipeline_delimit(t_pipeline_builder *builder)
|
||||
{
|
||||
builder->pipeline->cmds[builder->idx]
|
||||
= simple_cmd_from_wordlist(builder->current_wordlist);
|
||||
if (builder->pipeline->cmds[builder->idx] == NULL)
|
||||
{
|
||||
builder_destroy(builder);
|
||||
return ;
|
||||
}
|
||||
builder->current_wordlist = NULL;
|
||||
ignore_word(builder);
|
||||
if (current_is_pipe(builder))
|
||||
{
|
||||
builder_destroy(builder);
|
||||
ft_errno(FT_EUNEXPECTED_PIPE);
|
||||
return ;
|
||||
}
|
||||
builder->idx++;
|
||||
}
|
||||
|
||||
/*
|
||||
** Parse a pipeline from a wordlist using the given builder.
|
||||
**
|
||||
** - Assumes that current word is unset.
|
||||
** - Load the next word.
|
||||
** - If the current word is a pipe, it means there was a pipe on the start of
|
||||
** the command, which is disalowed. set ft_errno and return NULL.
|
||||
** - While there are still words remaining in the input stream
|
||||
** - If we have a pipe character
|
||||
** - Delimit the current command
|
||||
** - If there was an error
|
||||
** - Return NULL
|
||||
** - If we reached the end of input stream
|
||||
** - This means that there is a hanging pipe at the end of the pipeline.
|
||||
** Destroy the pipeline, set ft_errno, and return NULL.
|
||||
** - Push the current word to the accumulator for the next command
|
||||
** - Advance the state to the next word
|
||||
** - Since there is no pipe token at the end to delimit the last command,
|
||||
** delimit it now
|
||||
** - Return the pipeline. Since all input tokens have been consumed, no
|
||||
** additional memory freeing is required.
|
||||
** in case of error in pipeline_delimit, it will call destroy, which will set
|
||||
** builder->pipeline to NULL
|
||||
*/
|
||||
t_pipeline *pipeline_parse_wordlist(t_pipeline_builder *builder)
|
||||
{
|
||||
next_word(builder);
|
||||
if (current_is_pipe(builder))
|
||||
return (builder_destroy(builder), ft_errno(FT_EUNEXPECTED_PIPE), NULL);
|
||||
while (!eof(builder))
|
||||
{
|
||||
if (current_is_pipe(builder))
|
||||
if (connec_reorient_subtree(&pipeline, &subtree, &opt, FT_PIPE) == NULL)
|
||||
{
|
||||
pipeline_delimit(builder);
|
||||
if (builder->error)
|
||||
return (NULL);
|
||||
if (eof(builder))
|
||||
{
|
||||
builder_destroy(builder);
|
||||
ft_errno(FT_EUNEXPECTED_PIPE);
|
||||
return (NULL);
|
||||
}
|
||||
app->last_return_value = 1;
|
||||
return (ft_perror("minishell_pipeline_parse"), NULL);
|
||||
}
|
||||
push_word(builder);
|
||||
next_word(builder);
|
||||
opt = minishell_optional_pipeline_parse(app, tokens);
|
||||
}
|
||||
pipeline_delimit(builder);
|
||||
return (builder->pipeline);
|
||||
if (ft_errno_get() != FT_ESUCCESS)
|
||||
return (cmd_destroy(subtree), NULL);
|
||||
return (pipeline);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,17 +5,16 @@
|
|||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/24 14:34:55 by khais #+# #+# */
|
||||
/* Updated: 2025/03/04 12:07:12 by khais ### ########.fr */
|
||||
/* Created: 2025/04/15 11:34:38 by khais #+# #+# */
|
||||
/* Updated: 2025/04/15 11:35:00 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef PIPELINE_PARSE_H
|
||||
# define PIPELINE_PARSE_H
|
||||
|
||||
# include "pipeline.h"
|
||||
# include "../../minishell.h"
|
||||
|
||||
int pipeline_count_cmds(const t_wordlist *words);
|
||||
t_pipeline *pipeline_parse_wordlist(t_pipeline_builder *builder);
|
||||
t_cmd *minishell_pipeline_parse(t_minishell *app, t_wordlist *tokens);
|
||||
|
||||
#endif // PIPELINE_PARSE_H
|
||||
|
|
|
|||
|
|
@ -1,65 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* pipeline_parse_baseops.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/24 15:06:33 by khais #+# #+# */
|
||||
/* Updated: 2025/02/24 15:10:09 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "pipeline_parse_baseops.h"
|
||||
#include "../matchers/pipe.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
** Advance the state to the next word
|
||||
*/
|
||||
void next_word(t_pipeline_builder *builder)
|
||||
{
|
||||
builder->current_word = wordlist_pop(&builder->words);
|
||||
}
|
||||
|
||||
/*
|
||||
** If the current word is NULL, return true.
|
||||
**
|
||||
** Used to detect end of word stream.
|
||||
**
|
||||
** Assumes that next_word was previously called.
|
||||
*/
|
||||
bool eof(t_pipeline_builder *builder)
|
||||
{
|
||||
return (builder->current_word == NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
** return true if the given current word is a pipe operator "|"
|
||||
*/
|
||||
bool current_is_pipe(t_pipeline_builder *builder)
|
||||
{
|
||||
return (builder->current_word != NULL && is_pipe(builder->current_word));
|
||||
}
|
||||
|
||||
/*
|
||||
** Remove the current word from the wordstream and advance to the next word.
|
||||
*/
|
||||
void ignore_word(t_pipeline_builder *builder)
|
||||
{
|
||||
worddesc_destroy(builder->current_word);
|
||||
next_word(builder);
|
||||
}
|
||||
|
||||
/*
|
||||
** push the current word to the wordlist that will be used for the next simple
|
||||
** command.
|
||||
**
|
||||
** Resets current word to NULL.
|
||||
*/
|
||||
void push_word(t_pipeline_builder *builder)
|
||||
{
|
||||
builder->current_wordlist
|
||||
= wordlist_push(builder->current_wordlist, builder->current_word);
|
||||
builder->current_word = NULL;
|
||||
}
|
||||
|
|
@ -1,34 +1,37 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* cmdlist_item.h :+: :+: :+: */
|
||||
/* redirect.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/18 12:54:31 by khais #+# #+# */
|
||||
/* Updated: 2025/03/19 14:11:16 by khais ### ########.fr */
|
||||
/* Created: 2025/04/14 17:27:53 by khais #+# #+# */
|
||||
/* Updated: 2025/04/14 17:33:09 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef CMDLIST_ITEM_H
|
||||
# define CMDLIST_ITEM_H
|
||||
#include "redirect.h"
|
||||
|
||||
# include "../cmdgroup/cmdgroup.h"
|
||||
# include "cmdlist_item_type.h"
|
||||
|
||||
typedef struct s_cmdlist_item
|
||||
t_redirect *t_redirect_add_back(t_redirect **init, t_redirect *back)
|
||||
{
|
||||
enum e_cmdlist_item_type type;
|
||||
union u_cmdlist_item_inner
|
||||
t_redirect *tmp;
|
||||
|
||||
if (!(*init))
|
||||
{
|
||||
t_cmdgroup *cmdgroup;
|
||||
struct s_pipeline *pipeline;
|
||||
} inner;
|
||||
} t_cmdlist_item;
|
||||
*init = back;
|
||||
return (*init);
|
||||
}
|
||||
tmp = *init;
|
||||
while (tmp->next)
|
||||
tmp = tmp->next;
|
||||
tmp->next = back;
|
||||
return (*init);
|
||||
}
|
||||
|
||||
void cmdlist_item_destroy(t_cmdlist_item *cmd);
|
||||
t_cmdlist_item *cmdlist_item_create(void);
|
||||
void cmdlist_item_debug(t_cmdlist_item *item, t_buffer *leader,
|
||||
bool is_last);
|
||||
|
||||
#endif // CMDLIST_ITEM_H
|
||||
bool is_redir(t_worddesc *token)
|
||||
{
|
||||
return (token->token_type == OUT_APPEND_REDIR_TOKEN
|
||||
|| token->token_type == OUT_TRUNC_REDIR_TOKEN
|
||||
|| token->token_type == IN_REDIR_TOKEN
|
||||
|| token->token_type == HERE_DOC_REDIR_TOKEN);
|
||||
}
|
||||
21
src/parser/redirect/redirect.h
Normal file
21
src/parser/redirect/redirect.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* redirect.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/14 17:27:27 by khais #+# #+# */
|
||||
/* Updated: 2025/04/14 17:32:01 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef REDIRECT_H
|
||||
# define REDIRECT_H
|
||||
|
||||
# include "../../minishell.h"
|
||||
|
||||
t_redirect *t_redirect_add_back(t_redirect **init, t_redirect *back);
|
||||
bool is_redir(t_worddesc *token);
|
||||
|
||||
#endif // REDIRECT_H
|
||||
94
src/parser/redirect/redirect_debug.c
Normal file
94
src/parser/redirect/redirect_debug.c
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* redirect_debug.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/09 15:07:58 by khais #+# #+# */
|
||||
/* Updated: 2025/04/14 17:23:33 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "redirect_debug.h"
|
||||
#include "../../treedrawing.h"
|
||||
#include "libft.h"
|
||||
|
||||
static void redir_type_debug(t_redir_type type, t_buffer *leader, bool is_last)
|
||||
{
|
||||
indent(leader, is_last);
|
||||
if (type == FT_INVALID_REDIR)
|
||||
ft_printf("redir_type = %s\n", "FT_INVALID_REDIR");
|
||||
if (type == FT_OUTPUT_TRUNC_REDIR)
|
||||
ft_printf("redir_type = %s\n", "FT_OUTPUT_TRUNC_REDIR");
|
||||
if (type == FT_OUTPUT_APPEND_REDIR)
|
||||
ft_printf("redir_type = %s\n", "FT_OUTPUT_APPEND_REDIR");
|
||||
if (type == FT_INPUT_REDIR)
|
||||
ft_printf("redir_type = %s\n", "FT_INPUT_REDIR");
|
||||
if (type == FT_HEREDOC)
|
||||
ft_printf("redir_type = %s\n", "FT_HEREDOC");
|
||||
dedent(leader, is_last);
|
||||
}
|
||||
|
||||
static void redirectee_debug(t_redirectee redirectee, t_buffer *leader,
|
||||
bool is_last)
|
||||
{
|
||||
indent(leader, is_last);
|
||||
ft_printf("t_redirectee\n");
|
||||
indent(leader, false);
|
||||
ft_printf("dest = %d\n", redirectee.dest);
|
||||
dedent(leader, false);
|
||||
worddesc_debug(redirectee.filename, leader, true);
|
||||
dedent(leader, is_last);
|
||||
}
|
||||
|
||||
static void single_redirect_debug(t_redirect *redirect, t_buffer *leader,
|
||||
bool is_last)
|
||||
{
|
||||
if (redirect == NULL)
|
||||
return ;
|
||||
indent(leader, is_last);
|
||||
ft_printf("t_redirect\n");
|
||||
redir_type_debug(redirect->type, leader, false);
|
||||
indent(leader, false);
|
||||
ft_printf("source = %d\n", redirect->source);
|
||||
dedent(leader, false);
|
||||
indent(leader, false);
|
||||
ft_printf("open_flags = %d\n", redirect->open_flags);
|
||||
dedent(leader, false);
|
||||
indent(leader, false);
|
||||
ft_printf("c_flags = %d\n", redirect->c_flags);
|
||||
dedent(leader, false);
|
||||
redirectee_debug(redirect->redirectee, leader, false);
|
||||
indent(leader, true);
|
||||
ft_printf("c_flags = [%s]\n", redirect->here_doc_eof);
|
||||
ft_printf("here_doc_eof = [%s]\n", redirect->here_doc_eof);
|
||||
dedent(leader, true);
|
||||
dedent(leader, is_last);
|
||||
}
|
||||
|
||||
void redirect_debug(t_redirect *redirect, t_buffer *leader, bool is_last)
|
||||
{
|
||||
int i;
|
||||
|
||||
indent(leader, is_last);
|
||||
if (redirect == NULL)
|
||||
ft_printf("redirections = (empty redir list)\n");
|
||||
else
|
||||
{
|
||||
single_redirect_debug(redirect, leader, redirect->next == NULL);
|
||||
redirect = redirect->next;
|
||||
ft_printf("redirections\n");
|
||||
i = 0;
|
||||
while (redirect != NULL)
|
||||
{
|
||||
indent(leader, redirect->next == NULL);
|
||||
ft_printf("redirections[%d]\n", i);
|
||||
single_redirect_debug(redirect, leader, true);
|
||||
dedent(leader, redirect->next == NULL);
|
||||
redirect = redirect->next;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
dedent(leader, is_last);
|
||||
}
|
||||
20
src/parser/redirect/redirect_debug.h
Normal file
20
src/parser/redirect/redirect_debug.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* redirect_debug.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/09 15:06:43 by khais #+# #+# */
|
||||
/* Updated: 2025/04/14 17:22:50 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef REDIRECT_DEBUG_H
|
||||
# define REDIRECT_DEBUG_H
|
||||
|
||||
# include "../../minishell.h"
|
||||
|
||||
void redirect_debug(t_redirect *redirect, t_buffer *leader, bool is_last);
|
||||
|
||||
#endif // REDIRECT_DEBUG_H
|
||||
73
src/parser/redirect/redirect_from_words.c
Normal file
73
src/parser/redirect/redirect_from_words.c
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* redirect_from_words.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/14 17:31:35 by khais #+# #+# */
|
||||
/* Updated: 2025/04/14 17:32:47 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "redirect_from_words.h"
|
||||
#include "../../ft_errno.h"
|
||||
#include "../../executing/here_doc/here_doc.h"
|
||||
|
||||
static t_redir_type redir_type_from_token_type(t_token_type type)
|
||||
{
|
||||
if (type == OUT_APPEND_REDIR_TOKEN)
|
||||
return (FT_OUTPUT_APPEND_REDIR);
|
||||
if (type == OUT_TRUNC_REDIR_TOKEN)
|
||||
return (FT_OUTPUT_TRUNC_REDIR);
|
||||
if (type == IN_REDIR_TOKEN)
|
||||
return (FT_INPUT_REDIR);
|
||||
if (type == HERE_DOC_REDIR_TOKEN)
|
||||
return (FT_HEREDOC);
|
||||
return (FT_INVALID_REDIR);
|
||||
}
|
||||
|
||||
static int redir_source_from_type(t_redir_type type)
|
||||
{
|
||||
if (type == FT_OUTPUT_APPEND_REDIR || type == FT_OUTPUT_TRUNC_REDIR)
|
||||
return (STDOUT_FILENO);
|
||||
if (type == FT_INPUT_REDIR)
|
||||
return (STDIN_FILENO);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int redir_open_flags_from_type(t_redir_type type)
|
||||
{
|
||||
if (type == FT_OUTPUT_APPEND_REDIR)
|
||||
return (O_CREAT | O_APPEND | O_WRONLY);
|
||||
if (type == FT_OUTPUT_TRUNC_REDIR)
|
||||
return (O_CREAT | O_TRUNC | O_WRONLY);
|
||||
return (0);
|
||||
}
|
||||
|
||||
t_redirect *redir_from_words(t_worddesc *operator,
|
||||
t_worddesc *specifier, t_minishell *app)
|
||||
{
|
||||
t_redirect *redir;
|
||||
|
||||
if (operator == NULL || specifier == NULL)
|
||||
return (NULL);
|
||||
redir = ft_calloc(1, sizeof(t_redirect));
|
||||
if (redir == NULL)
|
||||
return (ft_errno(FT_EERRNO), NULL);
|
||||
redir->type = redir_type_from_token_type(operator->token_type);
|
||||
redir->source = redir_source_from_type(redir->type);
|
||||
redir->open_flags = redir_open_flags_from_type(redir->type);
|
||||
redir->c_flags = 0644;
|
||||
redir->redirectee.dest = -1;
|
||||
if (redir->type == FT_HEREDOC)
|
||||
{
|
||||
redir->here_doc_eof = ft_strdup(specifier->word);
|
||||
redir->redirectee.dest = here_doc(specifier, STDIN_FILENO, app);
|
||||
worddesc_destroy(specifier);
|
||||
}
|
||||
else
|
||||
redir->redirectee.filename = specifier;
|
||||
worddesc_destroy(operator);
|
||||
return (redir);
|
||||
}
|
||||
21
src/parser/redirect/redirect_from_words.h
Normal file
21
src/parser/redirect/redirect_from_words.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* redirect_from_words.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/14 17:31:23 by khais #+# #+# */
|
||||
/* Updated: 2025/04/14 17:32:12 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef REDIRECT_FROM_WORDS_H
|
||||
# define REDIRECT_FROM_WORDS_H
|
||||
|
||||
# include "../../minishell.h"
|
||||
|
||||
t_redirect *redir_from_words(t_worddesc *operator,
|
||||
t_worddesc *specifier, t_minishell *app);
|
||||
|
||||
#endif // REDIRECT_FROM_WORDS_H
|
||||
41
src/parser/redirect/redirect_parse.c
Normal file
41
src/parser/redirect/redirect_parse.c
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* redirect_parse.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/15 10:13:58 by khais #+# #+# */
|
||||
/* Updated: 2025/04/15 10:15:08 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "redirect_parse.h"
|
||||
#include "redirect_from_words.h"
|
||||
#include "redirect.h"
|
||||
#include "../../ft_errno.h"
|
||||
#include "../cmd/cmd_destroy.h"
|
||||
|
||||
t_redirect *minishell_redirect_parse(t_minishell *app, t_wordlist *tokens)
|
||||
{
|
||||
t_redirect *redir_list;
|
||||
t_worddesc *redir_operator;
|
||||
t_worddesc *redir_specifier;
|
||||
t_redirect *new_redir;
|
||||
|
||||
redir_list = NULL;
|
||||
while (is_redir(tokens->word))
|
||||
{
|
||||
if (tokens->next == NULL)
|
||||
{
|
||||
ft_errno(FT_EERRNO);
|
||||
return (redirect_destroy(redir_list), NULL);
|
||||
}
|
||||
redir_operator = wordlist_pop(&tokens);
|
||||
redir_specifier = wordlist_pop(&tokens);
|
||||
new_redir = redir_from_words(redir_operator, redir_specifier, app);
|
||||
t_redirect_add_back(&redir_list, new_redir);
|
||||
}
|
||||
ft_errno(FT_ESUCCESS);
|
||||
return (redir_list);
|
||||
}
|
||||
20
src/parser/redirect/redirect_parse.h
Normal file
20
src/parser/redirect/redirect_parse.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* redirect_parse.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/15 10:13:28 by khais #+# #+# */
|
||||
/* Updated: 2025/04/15 10:14:13 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef REDIRECT_PARSE_H
|
||||
# define REDIRECT_PARSE_H
|
||||
|
||||
# include "../../minishell.h"
|
||||
|
||||
t_redirect *minishell_redirect_parse(t_minishell *app, t_wordlist *tokens);
|
||||
|
||||
#endif // REDIRECT_PARSE_H
|
||||
|
|
@ -6,12 +6,11 @@
|
|||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/20 17:36:20 by khais #+# #+# */
|
||||
/* Updated: 2025/03/27 14:27:14 by khais ### ########.fr */
|
||||
/* Updated: 2025/04/15 11:12:11 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "remove_quotes.h"
|
||||
#include "../cmdlist/cmdlist_item.h"
|
||||
|
||||
/*
|
||||
** do quote removal on all words of this simple cmd
|
||||
|
|
@ -38,75 +37,3 @@ t_simple_cmd *simple_cmd_remove_quotes(t_simple_cmd *cmd)
|
|||
cmd->words = new;
|
||||
return (cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
** do quote removal on all simple_cmds within this pipeline
|
||||
*/
|
||||
static t_pipeline *pipeline_remove_quotes(t_pipeline *pipeline)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (pipeline == NULL)
|
||||
return (NULL);
|
||||
i = 0;
|
||||
while (i < pipeline->num_cmd)
|
||||
{
|
||||
if (simple_cmd_remove_quotes(pipeline->cmds[i]) == NULL)
|
||||
return (NULL);
|
||||
i++;
|
||||
}
|
||||
return (pipeline);
|
||||
}
|
||||
|
||||
/*
|
||||
** do quote removal on the contained pipeline or cmdgroup
|
||||
*/
|
||||
static t_cmdlist_item *cmdlist_item_remove_quotes(t_cmdlist_item *item)
|
||||
{
|
||||
if (item == NULL)
|
||||
return (NULL);
|
||||
if (item->type == TYPE_PIPELINE)
|
||||
{
|
||||
if (pipeline_remove_quotes(item->inner.pipeline) == NULL)
|
||||
return (NULL);
|
||||
}
|
||||
if (item->type == TYPE_CMDGROUP)
|
||||
{
|
||||
if (cmdgroup_remove_quotes(item->inner.cmdgroup) == NULL)
|
||||
return (NULL);
|
||||
}
|
||||
return (item);
|
||||
}
|
||||
|
||||
/*
|
||||
** iterate over all cmdlist_items within this cmdlist, and do quote removal on
|
||||
** them
|
||||
*/
|
||||
static t_cmdlist *cmdlist_remove_quotes(t_cmdlist *cmd)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (cmd == NULL)
|
||||
return (NULL);
|
||||
i = 0;
|
||||
while (i < cmd->num_cmd)
|
||||
{
|
||||
if (cmdlist_item_remove_quotes(cmd->cmds[i]) == NULL)
|
||||
return (NULL);
|
||||
i++;
|
||||
}
|
||||
return (cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
** Iterate over all simple_cmd contained within this cmdgroup, and do quote
|
||||
** removal on them.
|
||||
*/
|
||||
t_cmdgroup *cmdgroup_remove_quotes(t_cmdgroup *cmd)
|
||||
{
|
||||
if (cmd == NULL)
|
||||
return (NULL);
|
||||
if (cmdlist_remove_quotes(cmd->item) == NULL)
|
||||
return (NULL);
|
||||
return (cmd);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
/* ::: :::::::: */
|
||||
/* remove_quotes.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/28 13:52:02 by khais #+# #+# */
|
||||
/* Updated: 2025/03/07 11:20:48 by khais ### ########.fr */
|
||||
/* Updated: 2025/03/28 16:05:25 by jguelen ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
|
|
@ -15,6 +15,13 @@
|
|||
#include "../matchers/quote.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
static bool is_ignore_mark(char c)
|
||||
{
|
||||
if (c == '\'' || c == '"' || c == '$' || c == '&')
|
||||
return (true);
|
||||
return (false);
|
||||
}
|
||||
|
||||
/*
|
||||
** use the marker in the given worddesc to create a new worddesc by removing
|
||||
** unquoted quotes.
|
||||
|
|
@ -37,7 +44,7 @@ t_worddesc *remove_quotes(t_worddesc *word)
|
|||
i = 0;
|
||||
while (word->word[i] != '\0')
|
||||
{
|
||||
if (!is_quote(word->word[i]) || is_quote(word->marker[i]))
|
||||
if (!is_quote(word->word[i]) || is_ignore_mark(word->marker[i]))
|
||||
buf = ft_buffer_pushchar(buf, word->word[i]);
|
||||
i++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/28 13:51:03 by khais #+# #+# */
|
||||
/* Updated: 2025/03/27 14:27:27 by khais ### ########.fr */
|
||||
/* Updated: 2025/04/15 11:10:31 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
|
|
@ -14,10 +14,9 @@
|
|||
# define REMOVE_QUOTES_H
|
||||
|
||||
# include "../worddesc/worddesc.h"
|
||||
# include "../cmdgroup/cmdgroup.h"
|
||||
# include "../../minishell.h"
|
||||
|
||||
t_worddesc *remove_quotes(t_worddesc *word);
|
||||
t_cmdgroup *cmdgroup_remove_quotes(t_cmdgroup *cmd);
|
||||
t_simple_cmd *simple_cmd_remove_quotes(t_simple_cmd *cmd);
|
||||
|
||||
#endif // REMOVE_QUOTES_H
|
||||
|
|
|
|||
|
|
@ -6,13 +6,15 @@
|
|||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/21 12:30:07 by khais #+# #+# */
|
||||
/* Updated: 2025/03/28 15:02:17 by khais ### ########.fr */
|
||||
/* Updated: 2025/04/15 14:37:57 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "simple_cmd.h"
|
||||
#include "libft.h"
|
||||
#include "../../treedrawing.h"
|
||||
#include "../cmd/cmd_destroy.h"
|
||||
#include "../redirect/redirect_debug.h"
|
||||
|
||||
/*
|
||||
** parse a wordlist and yield a simple command.
|
||||
|
|
@ -35,6 +37,7 @@ void simple_cmd_destroy(t_simple_cmd *cmd)
|
|||
if (cmd == NULL)
|
||||
return ;
|
||||
wordlist_destroy(cmd->words);
|
||||
redirect_destroy(cmd->redirections);
|
||||
free(cmd);
|
||||
}
|
||||
|
||||
|
|
@ -44,9 +47,7 @@ void simple_cmd_debug(t_simple_cmd *cmd, t_buffer *leader, bool is_last)
|
|||
return ;
|
||||
indent(leader, is_last);
|
||||
ft_printf("%s\n", "t_simple_cmd");
|
||||
indent(leader, false);
|
||||
ft_printf("words = ");
|
||||
wordlist_debug(cmd->words);
|
||||
dedent(leader, true);
|
||||
redirect_debug(cmd->redirections, leader, false);
|
||||
wordlist_debug(cmd->words, leader, true);
|
||||
dedent(leader, is_last);
|
||||
}
|
||||
|
|
|
|||
47
src/parser/simple_cmd/simple_cmd_parse.c
Normal file
47
src/parser/simple_cmd/simple_cmd_parse.c
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* simple_cmd_parse.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/15 10:38:47 by khais #+# #+# */
|
||||
/* Updated: 2025/04/15 10:40:08 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "simple_cmd_parse.h"
|
||||
#include "../../ft_errno.h"
|
||||
#include "../cmd/cmd.h"
|
||||
#include "../redirect/redirect_parse.h"
|
||||
#include "../cmd/cmd_destroy.h"
|
||||
#include "../cmd_parsing.h"
|
||||
|
||||
t_cmd *minishell_simple_cmd_parse(t_minishell *app, t_wordlist *tokens)
|
||||
{
|
||||
t_cmd *simple;
|
||||
t_redirect *redir;
|
||||
|
||||
simple = cmd_create(FT_SIMPLE);
|
||||
if (simple == NULL)
|
||||
return (NULL);
|
||||
simple->value.simple = ft_calloc(1, sizeof(t_simple_cmd));
|
||||
if (simple->value.simple == NULL)
|
||||
return (ft_errno(FT_ENOMEM), free(simple), NULL);
|
||||
redir = minishell_redirect_parse(app, tokens);
|
||||
t_redirect_add_back(&simple->value.simple->redirections, redir);
|
||||
if (ft_errno_get() != FT_ESUCCESS)
|
||||
return (cmd_destroy(simple), NULL);
|
||||
while (tokens && tokens->word->token_type == WORD_TOKEN)
|
||||
{
|
||||
simple->value.simple->words = wordlist_push(simple->value.simple->words,
|
||||
wordlist_pop(&tokens));
|
||||
if (!simple->value.simple->words)
|
||||
return (ft_errno(FT_EERRNO), cmd_destroy(simple), NULL);
|
||||
redir = minishell_redirect_parse(app, tokens);
|
||||
t_redirect_add_back(&simple->value.simple->redirections, redir);
|
||||
}
|
||||
if (!simple->value.simple->words)
|
||||
return (cmd_destroy(simple), parse_error(app, tokens->word), NULL);
|
||||
return (simple);
|
||||
}
|
||||
20
src/parser/simple_cmd/simple_cmd_parse.h
Normal file
20
src/parser/simple_cmd/simple_cmd_parse.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* simple_cmd_parse.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/15 10:38:23 by khais #+# #+# */
|
||||
/* Updated: 2025/04/15 10:38:41 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef SIMPLE_CMD_PARSE_H
|
||||
# define SIMPLE_CMD_PARSE_H
|
||||
|
||||
# include "../../minishell.h"
|
||||
|
||||
t_cmd *minishell_simple_cmd_parse(t_minishell *app, t_wordlist *tokens);
|
||||
|
||||
#endif // SIMPLE_CMD_PARSE_H
|
||||
|
|
@ -3,16 +3,15 @@
|
|||
/* ::: :::::::: */
|
||||
/* worddesc.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/13 17:20:36 by khais #+# #+# */
|
||||
/* Updated: 2025/03/27 13:58:41 by khais ### ########.fr */
|
||||
/* Updated: 2025/04/07 17:40:03 by jguelen ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "worddesc.h"
|
||||
#include "libft.h"
|
||||
#include "libft/libft.h"
|
||||
#include <stdlib.h>
|
||||
#include "../../treedrawing.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
/* ::: :::::::: */
|
||||
/* worddesc.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/27 13:57:44 by khais #+# #+# */
|
||||
/* Updated: 2025/03/27 13:57:49 by khais ### ########.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,25 +52,26 @@ 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
|
||||
**
|
||||
** Possible flags are ''', '"', '$', ' '
|
||||
** Possible flags are ''', '"', '$', '&', ' '
|
||||
**
|
||||
** ' ' the default, no flag, no meaning
|
||||
** ''' corresponding character is single-quoted
|
||||
** '"' corresponding character is double-quoted
|
||||
** '$' corresponding character is a result of $var expansion
|
||||
*/
|
||||
char *marker;
|
||||
char *marker;
|
||||
t_token_type token_type;
|
||||
} t_worddesc;
|
||||
|
||||
t_worddesc *worddesc_create(char *word, char flags, char *marker);
|
||||
|
|
|
|||
|
|
@ -6,12 +6,11 @@
|
|||
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/13 17:07:01 by khais #+# #+# */
|
||||
/* Updated: 2025/03/21 10:43:41 by jguelen ### ########.fr */
|
||||
/* Updated: 2025/04/07 17:40:30 by jguelen ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "wordlist.h"
|
||||
#include "ft_printf.h"
|
||||
#include "libft.h"
|
||||
#include "unistd.h"
|
||||
#include <stdlib.h>
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/21 13:48/52 by khais #+# #+# */
|
||||
/* Updated: 2025/03/21 13:48:52 by khais ### ########.fr */
|
||||
/* Created: 2025/04/14 17:23/51 by khais #+# #+# */
|
||||
/* Updated: 2025/04/14 17:23:51 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
|
|
@ -40,7 +40,8 @@ void wordlist_destroy(t_wordlist *wordlist);
|
|||
t_worddesc *wordlist_get(t_wordlist *wordlist, int idx);
|
||||
t_wordlist *wordlist_push(t_wordlist *wordlist, t_worddesc *worddesc);
|
||||
t_worddesc *wordlist_pop(t_wordlist **wordlist);
|
||||
void wordlist_debug(t_wordlist *wordlist);
|
||||
void wordlist_debug(t_wordlist *wordlist, t_buffer *leader,
|
||||
bool is_last);
|
||||
t_wordlist *wordlist_copy(const t_wordlist *wordlist);
|
||||
void wordlist_destroy_idx(t_wordlist **wordlist, int idx);
|
||||
t_worddesc *wordlist_pop_idx(t_wordlist **wordlist, int idx);
|
||||
|
|
|
|||
|
|
@ -6,24 +6,30 @@
|
|||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/24 18:20:00 by khais #+# #+# */
|
||||
/* Updated: 2025/03/19 14:35:24 by khais ### ########.fr */
|
||||
/* Updated: 2025/04/15 14:38:39 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "wordlist.h"
|
||||
#include "libft.h"
|
||||
#include "../../treedrawing.h"
|
||||
|
||||
/*
|
||||
** Debug-print a wordlist
|
||||
*/
|
||||
void wordlist_debug(t_wordlist *wordlist)
|
||||
void wordlist_debug(t_wordlist *wordlist, t_buffer *leader, bool is_last)
|
||||
{
|
||||
indent(leader, is_last);
|
||||
if (wordlist == NULL)
|
||||
ft_printf("(empty wordlist)");
|
||||
while (wordlist != NULL)
|
||||
ft_printf("t_wordlist = (empty wordlist)\n");
|
||||
else
|
||||
{
|
||||
ft_printf("[%s]", wordlist->word->word);
|
||||
wordlist = wordlist->next;
|
||||
ft_printf("t_wordlist\n");
|
||||
while (wordlist != NULL)
|
||||
{
|
||||
worddesc_debug(wordlist->word, leader, wordlist->next == NULL);
|
||||
wordlist = wordlist->next;
|
||||
}
|
||||
}
|
||||
ft_printf("\n");
|
||||
dedent(leader, is_last);
|
||||
}
|
||||
|
|
|
|||
41
src/postprocess/expansion/expand_wildcard.c
Normal file
41
src/postprocess/expansion/expand_wildcard.c
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* expand_wildcard.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/03 19:28:28 by khais #+# #+# */
|
||||
/* Updated: 2025/04/03 19:52:29 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "expand_wildcard.h"
|
||||
#include "../../subst/subst.h"
|
||||
|
||||
t_simple_cmd *simple_cmd_expand_wildcards(t_simple_cmd *cmd)
|
||||
{
|
||||
t_wordlist *outlist;
|
||||
t_wordlist *inlist;
|
||||
t_worddesc *current;
|
||||
t_wordlist *expansion_result;
|
||||
|
||||
outlist = NULL;
|
||||
inlist = cmd->words;
|
||||
while (inlist != NULL)
|
||||
{
|
||||
current = wordlist_pop(&inlist);
|
||||
expansion_result = expand_star(current);
|
||||
if (expansion_result == NULL)
|
||||
outlist = wordlist_push(outlist, current);
|
||||
else
|
||||
{
|
||||
while (expansion_result != NULL)
|
||||
outlist = wordlist_push(outlist,
|
||||
wordlist_pop(&expansion_result));
|
||||
worddesc_destroy(current);
|
||||
}
|
||||
}
|
||||
cmd->words = outlist;
|
||||
return (cmd);
|
||||
}
|
||||
20
src/postprocess/expansion/expand_wildcard.h
Normal file
20
src/postprocess/expansion/expand_wildcard.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* expand_wildcard.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/03 19:22:10 by khais #+# #+# */
|
||||
/* Updated: 2025/04/03 19:23:24 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef EXPAND_WILDCARD_H
|
||||
# define EXPAND_WILDCARD_H
|
||||
|
||||
# include "../../minishell.h"
|
||||
|
||||
t_simple_cmd *simple_cmd_expand_wildcards(t_simple_cmd *cmd);
|
||||
|
||||
#endif // EXPAND_WILDCARD_H
|
||||
96
src/postprocess/fieldsplit/fieldsplit.c
Normal file
96
src/postprocess/fieldsplit/fieldsplit.c
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* fieldsplit.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/03 15:48:52 by khais #+# #+# */
|
||||
/* Updated: 2025/04/15 11:51:33 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "fieldsplit.h"
|
||||
#include "../../buffer/buffer.h"
|
||||
#include "../../parser/matchers/blank.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
static bool should_delimit(t_worddesc *original, size_t i)
|
||||
{
|
||||
if (is_blank(original->word[i]) && original->marker[i] == '$')
|
||||
return (true);
|
||||
return (false);
|
||||
}
|
||||
|
||||
static void fieldsplit_delimit(t_buffer *word, t_buffer *marker,
|
||||
t_worddesc *original, t_wordlist **outlist)
|
||||
{
|
||||
t_worddesc *out;
|
||||
|
||||
out = worddesc_create(word->buffer, original->flags, marker->buffer);
|
||||
(*outlist) = wordlist_push(*outlist, out);
|
||||
free(word);
|
||||
free(marker);
|
||||
}
|
||||
|
||||
static t_wordlist *minishell_fieldsplit(t_worddesc *original,
|
||||
t_wordlist **outlist)
|
||||
{
|
||||
size_t i;
|
||||
t_buffer *word;
|
||||
t_buffer *marker;
|
||||
|
||||
i = 0;
|
||||
word = ft_buffer_new();
|
||||
marker = ft_buffer_new();
|
||||
while (original->word[i] != '\0')
|
||||
{
|
||||
if (should_delimit(original, i))
|
||||
{
|
||||
fieldsplit_delimit(word, marker, original, outlist);
|
||||
word = ft_buffer_new();
|
||||
marker = ft_buffer_new();
|
||||
while (should_delimit(original, i))
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
word = ft_buffer_pushchar(word, original->word[i]);
|
||||
marker = ft_buffer_pushchar(marker, original->marker[i++]);
|
||||
}
|
||||
}
|
||||
fieldsplit_delimit(word, marker, original, outlist);
|
||||
return (*outlist);
|
||||
}
|
||||
|
||||
static t_wordlist *wordlist_fieldsplit(t_wordlist **original)
|
||||
{
|
||||
t_worddesc *current;
|
||||
t_wordlist *out;
|
||||
|
||||
if (original == NULL || *original == NULL)
|
||||
return (NULL);
|
||||
out = NULL;
|
||||
current = wordlist_pop(original);
|
||||
while (current != NULL)
|
||||
{
|
||||
if (minishell_fieldsplit(current, &out) == NULL)
|
||||
{
|
||||
wordlist_destroy(out);
|
||||
return (NULL);
|
||||
}
|
||||
worddesc_destroy(current);
|
||||
current = wordlist_pop(original);
|
||||
}
|
||||
(*original) = out;
|
||||
return (*original);
|
||||
}
|
||||
|
||||
t_simple_cmd *simple_cmd_fieldsplit(t_simple_cmd *cmd)
|
||||
{
|
||||
if (cmd == NULL)
|
||||
return (NULL);
|
||||
if (wordlist_fieldsplit(&cmd->words) == NULL)
|
||||
return (NULL);
|
||||
return (cmd);
|
||||
}
|
||||
20
src/postprocess/fieldsplit/fieldsplit.h
Normal file
20
src/postprocess/fieldsplit/fieldsplit.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* fieldsplit.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/03 15:46:56 by khais #+# #+# */
|
||||
/* Updated: 2025/04/03 16:06:23 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef FIELDSPLIT_H
|
||||
# define FIELDSPLIT_H
|
||||
|
||||
# include "../../parser/simple_cmd/simple_cmd.h"
|
||||
|
||||
t_simple_cmd *simple_cmd_fieldsplit(t_simple_cmd *cmd);
|
||||
|
||||
#endif // FIELDSPLIT_H
|
||||
|
|
@ -6,11 +6,15 @@
|
|||
/* By: jguelen <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/20 10:26:05 by jguelen #+# #+# */
|
||||
/* Updated: 2025/02/21 17:02:33 by jguelen ### ########.fr */
|
||||
/* Updated: 2025/04/04 17:05:32 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
// stdio must be included before readline
|
||||
#include <stdio.h>
|
||||
#include "readline/readline.h"
|
||||
#include "sig.h"
|
||||
#include "signal.h"
|
||||
|
||||
/*
|
||||
** g_signum exists to store the value of a signal if relevant for later
|
||||
|
|
@ -21,24 +25,33 @@
|
|||
int g_signum = 0;
|
||||
|
||||
/*
|
||||
** Stores the signal number corresponding to the caught signal into g_signum
|
||||
** for later processing.
|
||||
** redisplay prompt
|
||||
*/
|
||||
static void sig_interactive(int signum)
|
||||
{
|
||||
g_signum = signum;
|
||||
if (signum == SIGINT)
|
||||
{
|
||||
rl_replace_line("", 0);
|
||||
ft_printf("\n");
|
||||
rl_on_new_line();
|
||||
rl_redisplay();
|
||||
}
|
||||
}
|
||||
|
||||
void readline_reset(void)
|
||||
{
|
||||
rl_replace_line("", 0);
|
||||
ft_printf("\n");
|
||||
rl_redisplay();
|
||||
}
|
||||
|
||||
/*
|
||||
** Ignores the signal if it was sent by a kill command.
|
||||
** Otherwise stores the value of the caught signal in g_signum for later
|
||||
** processing.
|
||||
** Stores the value of the caught signal in g_signum for later processing.
|
||||
*/
|
||||
static void ignoreif_sent_by_kill(int signum, siginfo_t *siginfo, void *context)
|
||||
static void sig_cmd(int signum, siginfo_t *siginfo, void *context)
|
||||
{
|
||||
(void)context;
|
||||
if (siginfo->si_code == SI_USER)
|
||||
return ;
|
||||
(void)siginfo;
|
||||
g_signum = signum;
|
||||
}
|
||||
|
||||
|
|
@ -53,11 +66,11 @@ int set_interactive_mode_sig_handling(void)
|
|||
|
||||
ft_bzero(&sig_act, sizeof(struct sigaction));
|
||||
sig_act.sa_handler = &sig_interactive;
|
||||
sig_act.sa_flags |= SA_RESTART;
|
||||
if (sigemptyset(&sig_act.sa_mask) == -1)
|
||||
return (-1);
|
||||
if (sigaction(SIGINT, &sig_act, NULL) == -1)
|
||||
return (-1);
|
||||
sig_act.sa_handler = SIG_IGN;
|
||||
if (sigaction(SIGQUIT, &sig_act, NULL) == -1)
|
||||
return (-1);
|
||||
return (0);
|
||||
|
|
@ -75,36 +88,12 @@ int set_exec_mode_sig_handling(void)
|
|||
ft_bzero(&sig_act, sizeof(struct sigaction));
|
||||
if (sigemptyset(&sig_act.sa_mask) == -1)
|
||||
return (-1);
|
||||
sig_act.sa_sigaction = &ignoreif_sent_by_kill;
|
||||
sig_act.sa_sigaction = &sig_cmd;
|
||||
sig_act.sa_flags |= SA_SIGINFO;
|
||||
sig_act.sa_flags |= SA_RESTART;
|
||||
if (sigaction(SIGINT, &sig_act, NULL) == -1)
|
||||
return (-1);
|
||||
if (sigaction(SIGQUIT, &sig_act, NULL) == -1)
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Can be used at the start of a child process.
|
||||
** Check if necessary since execve is executed.
|
||||
** @RETURN Return 0 i case of success, -1 in case of error and errno is set
|
||||
** to indicate the error.
|
||||
*/
|
||||
int set_default_sig_handling(void)
|
||||
{
|
||||
struct sigaction sig;
|
||||
int i;
|
||||
|
||||
ft_bzero(&sig, sizeof(struct sigaction));
|
||||
sig.sa_handler = SIG_DFL;
|
||||
if (sigemptyset(&sig.sa_mask) == -1)
|
||||
return (-1);
|
||||
i = 0;
|
||||
while (i < NSIG)
|
||||
{
|
||||
if (sigaction(i, &sig, NULL) == -1)
|
||||
return (-1);
|
||||
i++;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
/* ::: :::::::: */
|
||||
/* sig.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/19 18:21:55 by jguelen #+# #+# */
|
||||
/* Updated: 2025/03/11 17:36:07 by jguelen ### ########.fr */
|
||||
/* Updated: 2025/04/04 16:58:49 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
|
|
@ -31,6 +31,6 @@ extern int g_signum;
|
|||
|
||||
int set_interactive_mode_sig_handling(void);
|
||||
int set_exec_mode_sig_handling(void);
|
||||
int set_default_sig_handling(void);
|
||||
void readline_reset(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/02 13:40:10 by jguelen #+# #+# */
|
||||
/* Updated: 2025/03/27 18:39:23 by khais ### ########.fr */
|
||||
/* Updated: 2025/04/01 18:38:35 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
|
|
@ -77,8 +77,6 @@ static char *select_path(char *filepath, char **oldpath, char **path,
|
|||
else
|
||||
return (free(*oldpath), path_split_destroy(path), filepath);
|
||||
}
|
||||
if (*oldpath != filepath)
|
||||
free(filepath);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
/* ::: :::::::: */
|
||||
/* wildcard_exp.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/20 15:01:38 by jguelen #+# #+# */
|
||||
/* Updated: 2025/03/21 18:42:04 by jguelen ### ########.fr */
|
||||
/* Updated: 2025/04/03 19:58:36 by khais ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
|
|
@ -104,20 +104,17 @@ static t_wordlist *expand_star_core(t_worddesc *file_pattern)
|
|||
if (current_dir == NULL)
|
||||
return (NULL);
|
||||
file_wordlist = NULL;
|
||||
errno = 0;
|
||||
new = readdir(current_dir);
|
||||
while (new)
|
||||
{
|
||||
if (fits_pattern(new->d_name, file_pattern))
|
||||
{
|
||||
if (add_file_to_list(&file_wordlist, new->d_name) == NULL)
|
||||
return (NULL);
|
||||
return (closedir(current_dir), NULL);
|
||||
}
|
||||
errno = 0;
|
||||
new = readdir(current_dir);
|
||||
}
|
||||
if (errno)
|
||||
return (wordlist_destroy(file_wordlist), NULL);
|
||||
closedir(current_dir);
|
||||
if (!file_wordlist)
|
||||
file_wordlist = wordlist_independant_create(file_pattern);
|
||||
return (wordlist_quicksort_full(file_wordlist));
|
||||
|
|
|
|||
188
test.sh
188
test.sh
|
|
@ -305,6 +305,7 @@ EOF
|
|||
|
||||
EXTRAENV=-i
|
||||
when_run <<EOF "export with strange inputs"
|
||||
export ENV=$(which env)
|
||||
export PATH=$PATH
|
||||
export var
|
||||
echo status=\$?
|
||||
|
|
@ -312,7 +313,7 @@ echo var=[\$var]
|
|||
export blue=
|
||||
echo status=\$?
|
||||
echo blue=[\$blue]
|
||||
env -u PATH env
|
||||
\$ENV -u PATH -u ENV env
|
||||
EOF
|
||||
expecting <<EOF
|
||||
status=0
|
||||
|
|
@ -335,6 +336,191 @@ status=1
|
|||
hello=hi
|
||||
EOF
|
||||
|
||||
when_run <<EOF "empty command is not found"
|
||||
""
|
||||
EOF
|
||||
expecting <<EOF
|
||||
minishell: : command not found
|
||||
EOF
|
||||
|
||||
when_run <<EOF "exit status of last command is preserved"
|
||||
echo \$?
|
||||
ls nonexist
|
||||
echo \$?
|
||||
echo hi
|
||||
echo \$?
|
||||
EOF
|
||||
expecting <<EOF
|
||||
0
|
||||
ls: cannot access 'nonexist': No such file or directory
|
||||
2
|
||||
hi
|
||||
0
|
||||
EOF
|
||||
|
||||
when_run <<EOF "exit works"
|
||||
$MINISHELL
|
||||
exit
|
||||
echo \$?
|
||||
EOF
|
||||
expecting <<EOF
|
||||
0
|
||||
EOF
|
||||
|
||||
when_run <<EOF "exit works with custom exit code"
|
||||
$MINISHELL
|
||||
exit 99
|
||||
echo \$?
|
||||
EOF
|
||||
expecting <<EOF
|
||||
99
|
||||
EOF
|
||||
|
||||
when_run <<EOF "exit works with extreme exit codes"
|
||||
$MINISHELL
|
||||
exit 1234567890
|
||||
echo \$?
|
||||
$MINISHELL
|
||||
exit -1234567890
|
||||
echo \$?
|
||||
EOF
|
||||
expecting <<EOF
|
||||
210
|
||||
46
|
||||
EOF
|
||||
|
||||
when_run <<EOF "exit works with nan input"
|
||||
$MINISHELL
|
||||
exit not-a-number
|
||||
echo \$?
|
||||
EOF
|
||||
expecting <<EOF
|
||||
minishell: exit: not-a-number: numeric argument required
|
||||
2
|
||||
EOF
|
||||
|
||||
when_run <<EOF "exit works with too many arguments"
|
||||
$MINISHELL
|
||||
exit 1 2
|
||||
echo \$?
|
||||
exit
|
||||
echo \$?
|
||||
$MINISHELL
|
||||
exit not-a-number 3
|
||||
echo \$?
|
||||
$MINISHELL
|
||||
exit 3 not-a-number
|
||||
echo \$?
|
||||
exit
|
||||
echo \$?
|
||||
EOF
|
||||
expecting <<EOF
|
||||
minishell: exit: too many arguments
|
||||
1
|
||||
0
|
||||
minishell: exit: not-a-number: numeric argument required
|
||||
2
|
||||
minishell: exit: too many arguments
|
||||
1
|
||||
0
|
||||
EOF
|
||||
|
||||
when_run <<EOF "echo basic tests"
|
||||
echo hello world
|
||||
echo "Hello World"
|
||||
EOF
|
||||
expecting <<EOF
|
||||
hello world
|
||||
Hello World
|
||||
EOF
|
||||
|
||||
when_run <<EOF "echo -n tests"
|
||||
echo -n hello world
|
||||
echo
|
||||
echo -nnnnnnnnnnnnnnnn hello world
|
||||
echo
|
||||
echo -nnnntnnnnnnnnnnnn hello world
|
||||
echo hi -n hello
|
||||
echo -n -n -nnn -n goodbye
|
||||
echo
|
||||
EOF
|
||||
expecting <<EOF
|
||||
hello world
|
||||
hello world
|
||||
-nnnntnnnnnnnnnnnn hello world
|
||||
hi -n hello
|
||||
goodbye
|
||||
EOF
|
||||
|
||||
when_run <<EOF "echo - n"
|
||||
echo - n hi
|
||||
EOF
|
||||
expecting <<EOF
|
||||
- n hi
|
||||
EOF
|
||||
|
||||
EXTRAENV="-i"
|
||||
when_run <<EOF "env works"
|
||||
echo this should be empty:
|
||||
env
|
||||
echo
|
||||
export var=VALUE hi=hello bye=goodbye
|
||||
echo this contains some values
|
||||
env
|
||||
unset var bye
|
||||
echo some vars were unset
|
||||
env
|
||||
EOF
|
||||
expecting <<EOF
|
||||
this should be empty:
|
||||
|
||||
this contains some values
|
||||
var=VALUE
|
||||
hi=hello
|
||||
bye=goodbye
|
||||
some vars were unset
|
||||
hi=hello
|
||||
EOF
|
||||
|
||||
EXTRAENV="-i"
|
||||
when_run <<EOF "env ignores additional arguments"
|
||||
export var=VALUE hi=hello bye=goodbye
|
||||
env -i name="The Other" ls
|
||||
EOF
|
||||
expecting <<EOF
|
||||
minishell: env: ignoring arguments
|
||||
var=VALUE
|
||||
hi=hello
|
||||
bye=goodbye
|
||||
EOF
|
||||
|
||||
when_run <<EOF "echo field splitting tests"
|
||||
export val=" hi there "
|
||||
echo -\$val-
|
||||
echo -"\$val"-
|
||||
export val="hello there"
|
||||
echo -\$val-
|
||||
echo -"\$val"-
|
||||
EOF
|
||||
expecting <<EOF
|
||||
- hi there -
|
||||
- hi there -
|
||||
-hello there-
|
||||
-hello there-
|
||||
EOF
|
||||
|
||||
when_run <<EOF "wildcards"
|
||||
echo *
|
||||
touch hi there hello
|
||||
echo *
|
||||
echo h*
|
||||
EOF
|
||||
expecting <<EOF
|
||||
*
|
||||
hello hi there
|
||||
hello hi
|
||||
EOF
|
||||
|
||||
when_run <<EOF "quoted parentheses are not operators"
|
||||
echo unclosed '('
|
||||
EOF
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ run: $(run_tests)
|
|||
|
||||
%.o: %.c
|
||||
$(CC) -c $(CFLAGS) $(IFLAGS) -o $*.o $*.c
|
||||
$(CC) -MM $(CFLAGS) $(IFLAGS) $*.c > $*.d
|
||||
$(CC) -MM $(CFLAGS) $(IFLAGS) -MT $*.o $*.c > $*.d
|
||||
|
||||
test_%: %.o $(objs)
|
||||
$(CC) $(CFLAGS) -rdynamic -o $@ $*.o $(objs) $(LINCLUDE) $(LDLIBS)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue