mirror of
https://codeberg.org/la-chouette/minishell.git
synced 2025-12-06 07:28:09 +01:00
Parsing-refactor: Determining structures.
This commit is contained in:
parent
befe219436
commit
5ff990ef50
17 changed files with 103 additions and 702 deletions
5
Makefile
5
Makefile
|
|
@ -65,11 +65,6 @@ srcs = \
|
||||||
src/parser/wordsplit/tokenizing_6_10.c \
|
src/parser/wordsplit/tokenizing_6_10.c \
|
||||||
src/parser/wordsplit/wordsplit.c \
|
src/parser/wordsplit/wordsplit.c \
|
||||||
src/parser/wordsplit/wordsplit_utils.c \
|
src/parser/wordsplit/wordsplit_utils.c \
|
||||||
src/postprocess/redirections/cmdgroup_redirection_parsing.c \
|
|
||||||
src/postprocess/redirections/redirection.c \
|
|
||||||
src/postprocess/redirections/redirection_list.c \
|
|
||||||
src/postprocess/redirections/redirection_parsing.c \
|
|
||||||
src/postprocess/redirections/redirection_type.c \
|
|
||||||
src/subst/path_split.c \
|
src/subst/path_split.c \
|
||||||
src/subst/replace_substr.c \
|
src/subst/replace_substr.c \
|
||||||
src/subst/simple_filename_exp.c \
|
src/subst/simple_filename_exp.c \
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
/* By: kcolin <marvin@42.fr> +#+ +:+ +#+ */
|
/* By: kcolin <marvin@42.fr> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2025/02/06 13:44:06 by kcolin #+# #+# */
|
/* Created: 2025/02/06 13:44:06 by kcolin #+# #+# */
|
||||||
/* Updated: 2025/03/27 16:50:00 by khais ### ########.fr */
|
/* Updated: 2025/03/28 15:01:31 by khais ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
|
@ -16,7 +16,6 @@
|
||||||
#include "parser/simple_cmd/simple_cmd.h"
|
#include "parser/simple_cmd/simple_cmd.h"
|
||||||
#include "parser/wordlist/wordlist.h"
|
#include "parser/wordlist/wordlist.h"
|
||||||
#include "parser/wordsplit/wordsplit.h"
|
#include "parser/wordsplit/wordsplit.h"
|
||||||
#include "postprocess/redirections/redirection_parsing.h"
|
|
||||||
#include "parser/remove_quotes/remove_quotes.h"
|
#include "parser/remove_quotes/remove_quotes.h"
|
||||||
#include "libft.h"
|
#include "libft.h"
|
||||||
#include "executing/simple_cmd/simple_cmd_execute.h"
|
#include "executing/simple_cmd/simple_cmd_execute.h"
|
||||||
|
|
@ -54,13 +53,10 @@ static void execute_command(t_simple_cmd *cmd, t_minishell *app)
|
||||||
** Do all the post-processing steps relating to a command.
|
** Do all the post-processing steps relating to a command.
|
||||||
**
|
**
|
||||||
** Currently, this is the following:
|
** Currently, this is the following:
|
||||||
** 1. redirection parsing
|
** 1. quote removal
|
||||||
** 2. quote removal
|
|
||||||
*/
|
*/
|
||||||
static t_simple_cmd *post_process_command(t_simple_cmd *cmd)
|
static t_simple_cmd *post_process_command(t_simple_cmd *cmd)
|
||||||
{
|
{
|
||||||
if (parse_redirections(cmd) == NULL)
|
|
||||||
return (simple_cmd_destroy(cmd), NULL);
|
|
||||||
if (simple_cmd_remove_quotes(cmd) == NULL)
|
if (simple_cmd_remove_quotes(cmd) == NULL)
|
||||||
return (simple_cmd_destroy(cmd), NULL);
|
return (simple_cmd_destroy(cmd), NULL);
|
||||||
return (cmd);
|
return (cmd);
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@
|
||||||
/* +:+ +:+ +:+ */
|
/* +:+ +:+ +:+ */
|
||||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2025/03/06 12:46/06 by khais #+# #+# */
|
/* Created: 2025/03/28 14:55/31 by khais #+# #+# */
|
||||||
/* Updated: 2025/03/06 12:46:06 by khais ### ########.fr */
|
/* Updated: 2025/03/28 14:55:31 by khais ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
|
@ -14,6 +14,99 @@
|
||||||
# define MINISHELL_H
|
# define MINISHELL_H
|
||||||
|
|
||||||
# include "env/env.h"
|
# include "env/env.h"
|
||||||
|
# include "parser/wordlist/wordlist.h"
|
||||||
|
# include <sys/stat.h>
|
||||||
|
# include <fcntl.h>
|
||||||
|
|
||||||
|
typedef union u_redirectee
|
||||||
|
{
|
||||||
|
int dest; // file descriptor to redirect
|
||||||
|
t_worddesc *filename; // filename to redirect
|
||||||
|
} t_redirectee;
|
||||||
|
|
||||||
|
typedef enum e_redir_type
|
||||||
|
{
|
||||||
|
FT_INVALID_REDIR,
|
||||||
|
FT_OUTPUT_TRUNC_REDIR,
|
||||||
|
FT_OUTPUT_APPEND_REDIR,
|
||||||
|
FT_INPUT_REDIR,
|
||||||
|
FT_HEREDOC,
|
||||||
|
} t_redir_type;
|
||||||
|
|
||||||
|
typedef struct s_redirect
|
||||||
|
{
|
||||||
|
t_redir_type type;
|
||||||
|
struct s_redirect *next; // next element or NULL.
|
||||||
|
int source; // fd to be redirected.
|
||||||
|
int open_flags;
|
||||||
|
int c_flags; // flags for third arg of open (case O_CREAT).
|
||||||
|
t_redirectee redirectee; // fd or filename where to redirect source.
|
||||||
|
char *here_doc_eof; // The here-document limiter if relevant.
|
||||||
|
} t_redirect;
|
||||||
|
|
||||||
|
typedef enum e_cmd_type
|
||||||
|
{
|
||||||
|
FT_CONNECTION,
|
||||||
|
FT_GROUP,
|
||||||
|
FT_SIMPLE,
|
||||||
|
} t_cmd_type;
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Fundamentally, this is a tree.
|
||||||
|
*/
|
||||||
|
typedef struct s_cmd
|
||||||
|
{
|
||||||
|
t_cmd_type type;
|
||||||
|
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;
|
||||||
|
struct s_group_cmd *group;
|
||||||
|
struct s_simple_cmd *simple;
|
||||||
|
} value;
|
||||||
|
} t_cmd;
|
||||||
|
|
||||||
|
typedef enum e_connector
|
||||||
|
{
|
||||||
|
FT_PIPE,
|
||||||
|
FT_AND,
|
||||||
|
FT_OR,
|
||||||
|
} t_connector;
|
||||||
|
|
||||||
|
/*
|
||||||
|
** This exists to represent pipelines and AND or OR lists.
|
||||||
|
** does include left associativity.
|
||||||
|
*/
|
||||||
|
typedef struct s_connec_cmd
|
||||||
|
{
|
||||||
|
t_cmd *first;
|
||||||
|
t_cmd *second;
|
||||||
|
t_connector connector;
|
||||||
|
} t_connec_cmd;
|
||||||
|
|
||||||
|
/*
|
||||||
|
** We do not deal with { list; } grouping. This is therefore roughly
|
||||||
|
** equivalent to a subshell_com structure in bash. And therefore we
|
||||||
|
** define this only since it will still be a grouping regarding redirections
|
||||||
|
** AND require a subshell every time in the case of minishell.
|
||||||
|
*/
|
||||||
|
typedef struct s_group_cmd
|
||||||
|
{
|
||||||
|
t_cmd *cmd;
|
||||||
|
t_redirect *redirects; // redirections concerning the whole group.
|
||||||
|
} t_group_cmd;
|
||||||
|
|
||||||
|
typedef struct s_simple_cmd
|
||||||
|
{
|
||||||
|
int line; //Probably unused.
|
||||||
|
t_wordlist *words; //argv in list form
|
||||||
|
t_redirect *redirections; //redirections to perform
|
||||||
|
} t_simple_cmd;
|
||||||
|
|
||||||
typedef struct s_minishell
|
typedef struct s_minishell
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2025/03/11 15:18:02 by khais #+# #+# */
|
/* Created: 2025/03/11 15:18:02 by khais #+# #+# */
|
||||||
/* Updated: 2025/03/20 14:46:25 by khais ### ########.fr */
|
/* Updated: 2025/03/28 15:01:55 by khais ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
|
@ -16,7 +16,6 @@
|
||||||
#include "libft.h"
|
#include "libft.h"
|
||||||
#include "paren.h"
|
#include "paren.h"
|
||||||
#include "../../treedrawing.h"
|
#include "../../treedrawing.h"
|
||||||
#include "../../postprocess/redirections/redirection_list.h"
|
|
||||||
#include "libft/libft.h"
|
#include "libft/libft.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -68,7 +67,6 @@ void cmdgroup_debug(t_cmdgroup *cmd, t_buffer *leader, bool is_last)
|
||||||
return ;
|
return ;
|
||||||
indent(leader, is_last);
|
indent(leader, is_last);
|
||||||
ft_printf("%s\n", "t_cmdgroup");
|
ft_printf("%s\n", "t_cmdgroup");
|
||||||
cmdlist_debug(cmd->item, leader, false);
|
cmdlist_debug(cmd->item, leader, true);
|
||||||
redir_list_debug(cmd->redirections, leader, true);
|
|
||||||
dedent(leader, is_last);
|
dedent(leader, is_last);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,13 @@
|
||||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2025/02/21 12:30:07 by khais #+# #+# */
|
/* Created: 2025/02/21 12:30:07 by khais #+# #+# */
|
||||||
/* Updated: 2025/03/19 16:49:12 by khais ### ########.fr */
|
/* Updated: 2025/03/28 15:02:17 by khais ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
#include "simple_cmd.h"
|
#include "simple_cmd.h"
|
||||||
#include "libft.h"
|
#include "libft.h"
|
||||||
#include "../../treedrawing.h"
|
#include "../../treedrawing.h"
|
||||||
#include "../../postprocess/redirections/redirection_list.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** parse a wordlist and yield a simple command.
|
** parse a wordlist and yield a simple command.
|
||||||
|
|
@ -36,7 +35,6 @@ void simple_cmd_destroy(t_simple_cmd *cmd)
|
||||||
if (cmd == NULL)
|
if (cmd == NULL)
|
||||||
return ;
|
return ;
|
||||||
wordlist_destroy(cmd->words);
|
wordlist_destroy(cmd->words);
|
||||||
redir_list_destroy(cmd->redirections);
|
|
||||||
free(cmd);
|
free(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,7 +47,6 @@ void simple_cmd_debug(t_simple_cmd *cmd, t_buffer *leader, bool is_last)
|
||||||
indent(leader, false);
|
indent(leader, false);
|
||||||
ft_printf("words = ");
|
ft_printf("words = ");
|
||||||
wordlist_debug(cmd->words);
|
wordlist_debug(cmd->words);
|
||||||
dedent(leader, false);
|
dedent(leader, true);
|
||||||
redir_list_debug(cmd->redirections, leader, true);
|
|
||||||
dedent(leader, is_last);
|
dedent(leader, is_last);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2025/02/21 12:24:57 by khais #+# #+# */
|
/* Created: 2025/02/21 12:24:57 by khais #+# #+# */
|
||||||
/* Updated: 2025/03/19 14:38:27 by khais ### ########.fr */
|
/* Updated: 2025/03/28 14:52:45 by khais ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
|
@ -16,12 +16,7 @@
|
||||||
# include "../wordlist/wordlist.h"
|
# include "../wordlist/wordlist.h"
|
||||||
# include "../../buffer/buffer.h"
|
# include "../../buffer/buffer.h"
|
||||||
# include <stdbool.h>
|
# include <stdbool.h>
|
||||||
|
# include "../../minishell.h"
|
||||||
typedef struct s_simple_cmd
|
|
||||||
{
|
|
||||||
t_wordlist *words;
|
|
||||||
struct s_redirection_list *redirections;
|
|
||||||
} t_simple_cmd;
|
|
||||||
|
|
||||||
t_simple_cmd *simple_cmd_from_wordlist(t_wordlist *words);
|
t_simple_cmd *simple_cmd_from_wordlist(t_wordlist *words);
|
||||||
void simple_cmd_destroy(t_simple_cmd *cmd);
|
void simple_cmd_destroy(t_simple_cmd *cmd);
|
||||||
|
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
/* ************************************************************************** */
|
|
||||||
/* */
|
|
||||||
/* ::: :::::::: */
|
|
||||||
/* cmdgroup_redirection_parsing.c :+: :+: :+: */
|
|
||||||
/* +:+ +:+ +:+ */
|
|
||||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
|
||||||
/* +#+#+#+#+#+ +#+ */
|
|
||||||
/* Created: 2025/03/19 16:37:09 by khais #+# #+# */
|
|
||||||
/* Updated: 2025/03/20 11:56:28 by khais ### ########.fr */
|
|
||||||
/* */
|
|
||||||
/* ************************************************************************** */
|
|
||||||
|
|
||||||
#include "redirection_parsing.h"
|
|
||||||
#include "../../parser/cmdlist/cmdlist_item.h"
|
|
||||||
|
|
||||||
static t_pipeline *pipeline_parse_redirections(t_pipeline *pipeline)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (pipeline == NULL)
|
|
||||||
return (NULL);
|
|
||||||
i = 0;
|
|
||||||
while (i < pipeline->num_cmd)
|
|
||||||
{
|
|
||||||
if (parse_redirections(pipeline->cmds[i]) == NULL)
|
|
||||||
return (NULL);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
return (pipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
static t_cmdlist_item *cmdlist_item_parse_redirections(t_cmdlist_item *item)
|
|
||||||
{
|
|
||||||
if (item == NULL)
|
|
||||||
return (NULL);
|
|
||||||
if (item->type == TYPE_PIPELINE)
|
|
||||||
{
|
|
||||||
if (pipeline_parse_redirections(item->inner.pipeline) == NULL)
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
if (item->type == TYPE_CMDGROUP)
|
|
||||||
{
|
|
||||||
if (cmdgroup_parse_redirections(item->inner.cmdgroup) == NULL)
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
return (item);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Iterate over all simple_cmd contained withing this cmdlist, and do
|
|
||||||
** redirection parsing on them.
|
|
||||||
*/
|
|
||||||
static t_cmdlist *cmdlist_parse_redirections(t_cmdlist *cmd)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (cmd == NULL)
|
|
||||||
return (NULL);
|
|
||||||
i = 0;
|
|
||||||
while (i < cmd->num_cmd)
|
|
||||||
{
|
|
||||||
if (cmdlist_item_parse_redirections(cmd->cmds[i]) == NULL)
|
|
||||||
return (NULL);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
return (cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Iterate over all simple_cmd contained within this cmdgroup, and do
|
|
||||||
** redirection parsing on them.
|
|
||||||
**
|
|
||||||
** This DOES NOT parse redirections that are applied to a whole cmdgroup. This
|
|
||||||
** MUST be done by cmdgroup_from_wordlist.
|
|
||||||
*/
|
|
||||||
t_cmdgroup *cmdgroup_parse_redirections(t_cmdgroup *cmd)
|
|
||||||
{
|
|
||||||
if (cmd == NULL)
|
|
||||||
return (NULL);
|
|
||||||
if (cmdlist_parse_redirections(cmd->item) == NULL)
|
|
||||||
return (NULL);
|
|
||||||
return (cmd);
|
|
||||||
}
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
/* ************************************************************************** */
|
|
||||||
/* */
|
|
||||||
/* ::: :::::::: */
|
|
||||||
/* redirection.c :+: :+: :+: */
|
|
||||||
/* +:+ +:+ +:+ */
|
|
||||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
|
||||||
/* +#+#+#+#+#+ +#+ */
|
|
||||||
/* Created: 2025/03/07 14:26:26 by khais #+# #+# */
|
|
||||||
/* Updated: 2025/03/19 16:58:50 by khais ### ########.fr */
|
|
||||||
/* */
|
|
||||||
/* ************************************************************************** */
|
|
||||||
|
|
||||||
#include "redirection.h"
|
|
||||||
#include "libft.h"
|
|
||||||
#include "../../treedrawing.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
** create a new redirection, with the given data
|
|
||||||
**
|
|
||||||
** In case of allocation error, marker is not freed
|
|
||||||
*/
|
|
||||||
t_redirection *redirection_create(t_redir_type type,
|
|
||||||
t_worddesc *marker)
|
|
||||||
{
|
|
||||||
t_redirection *outvalue;
|
|
||||||
|
|
||||||
outvalue = ft_calloc(1, sizeof(t_redirection));
|
|
||||||
if (outvalue == NULL)
|
|
||||||
return (NULL);
|
|
||||||
outvalue->marker = marker;
|
|
||||||
outvalue->type = type;
|
|
||||||
return (outvalue);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** free all the memory associated with the given redirection
|
|
||||||
*/
|
|
||||||
void redirection_destroy(t_redirection *redirection)
|
|
||||||
{
|
|
||||||
if (redirection == NULL)
|
|
||||||
return ;
|
|
||||||
worddesc_destroy(redirection->marker);
|
|
||||||
free(redirection);
|
|
||||||
}
|
|
||||||
|
|
||||||
void redirection_debug(t_redirection *redirection, t_buffer *leader,
|
|
||||||
bool is_last)
|
|
||||||
{
|
|
||||||
indent(leader, is_last);
|
|
||||||
if (redirection == NULL)
|
|
||||||
{
|
|
||||||
ft_printf("%s\n", "(no redirections)");
|
|
||||||
dedent(leader, is_last);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
ft_printf("%s\n", "t_redirection");
|
|
||||||
redir_type_debug(redirection->type, leader, false);
|
|
||||||
indent(leader, true);
|
|
||||||
ft_printf("%s = [%s]\n", "marker", redirection->marker->word);
|
|
||||||
dedent(leader, true);
|
|
||||||
dedent(leader, is_last);
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
/* ************************************************************************** */
|
|
||||||
/* */
|
|
||||||
/* ::: :::::::: */
|
|
||||||
/* redirection.h :+: :+: :+: */
|
|
||||||
/* +:+ +:+ +:+ */
|
|
||||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
|
||||||
/* +#+#+#+#+#+ +#+ */
|
|
||||||
/* Created: 2025/03/07 14:26:06 by khais #+# #+# */
|
|
||||||
/* Updated: 2025/03/19 14:37:20 by khais ### ########.fr */
|
|
||||||
/* */
|
|
||||||
/* ************************************************************************** */
|
|
||||||
|
|
||||||
#ifndef REDIRECTION_H
|
|
||||||
# define REDIRECTION_H
|
|
||||||
|
|
||||||
# include "../../parser/worddesc/worddesc.h"
|
|
||||||
# include "redirection_type.h"
|
|
||||||
# include "../../buffer/buffer.h"
|
|
||||||
# include <stdbool.h>
|
|
||||||
|
|
||||||
typedef struct s_redirection
|
|
||||||
{
|
|
||||||
// type of this redirection
|
|
||||||
t_redir_type type;
|
|
||||||
// either the filepath to the given file, or the delimiter for a here_doc
|
|
||||||
// redirection
|
|
||||||
t_worddesc *marker;
|
|
||||||
} t_redirection;
|
|
||||||
|
|
||||||
t_redirection *redirection_create(t_redir_type type,
|
|
||||||
t_worddesc *marker);
|
|
||||||
void redirection_destroy(t_redirection *redirection);
|
|
||||||
void redirection_debug(t_redirection *redirection, t_buffer *leader,
|
|
||||||
bool is_last);
|
|
||||||
|
|
||||||
#endif // REDIRECTION_BASICS_H
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
||||||
/* ************************************************************************** */
|
|
||||||
/* */
|
|
||||||
/* ::: :::::::: */
|
|
||||||
/* redirection_list.c :+: :+: :+: */
|
|
||||||
/* +:+ +:+ +:+ */
|
|
||||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
|
||||||
/* +#+#+#+#+#+ +#+ */
|
|
||||||
/* Created: 2025/03/07 14:29:53 by khais #+# #+# */
|
|
||||||
/* Updated: 2025/03/20 11:39:41 by khais ### ########.fr */
|
|
||||||
/* */
|
|
||||||
/* ************************************************************************** */
|
|
||||||
|
|
||||||
#include "redirection_list.h"
|
|
||||||
#include "redirection.h"
|
|
||||||
#include "libft.h"
|
|
||||||
#include "../../treedrawing.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
** create a new redir list item, with the given item
|
|
||||||
**
|
|
||||||
** may return null in case of allocation failure
|
|
||||||
*/
|
|
||||||
static t_redir_list *redir_list_create(t_redirection *item)
|
|
||||||
{
|
|
||||||
t_redir_list *out;
|
|
||||||
|
|
||||||
out = ft_calloc(1, sizeof(t_redir_list));
|
|
||||||
if (out == NULL)
|
|
||||||
return (NULL);
|
|
||||||
out->redirection = item;
|
|
||||||
return (out);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** free all memory associated with this redir list
|
|
||||||
*/
|
|
||||||
void redir_list_destroy(t_redir_list *lst)
|
|
||||||
{
|
|
||||||
t_redir_list *prev;
|
|
||||||
|
|
||||||
while (lst != NULL)
|
|
||||||
{
|
|
||||||
redirection_destroy(lst->redirection);
|
|
||||||
prev = lst;
|
|
||||||
lst = lst->next;
|
|
||||||
free(prev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Add the given item to the end of the given list.
|
|
||||||
**
|
|
||||||
** If allocation fails, return null.
|
|
||||||
*/
|
|
||||||
t_redir_list *redir_list_push(t_redir_list *lst, t_redirection *item)
|
|
||||||
{
|
|
||||||
t_redir_list *start;
|
|
||||||
|
|
||||||
if (lst == NULL)
|
|
||||||
return (redir_list_create(item));
|
|
||||||
start = lst;
|
|
||||||
while (lst->next != NULL)
|
|
||||||
lst = lst->next;
|
|
||||||
lst->next = redir_list_create(item);
|
|
||||||
if (lst->next == NULL)
|
|
||||||
return (redir_list_destroy(start), NULL);
|
|
||||||
return (start);
|
|
||||||
}
|
|
||||||
|
|
||||||
void redir_list_debug(t_redir_list *lst, t_buffer *leader, bool is_last)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
bool last;
|
|
||||||
|
|
||||||
if (lst == NULL)
|
|
||||||
{
|
|
||||||
indent(leader, is_last);
|
|
||||||
ft_printf("%s\n", "(no redirections)");
|
|
||||||
dedent(leader, is_last);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
indent(leader, is_last);
|
|
||||||
ft_printf("%s\n", "t_redir_list");
|
|
||||||
i = 0;
|
|
||||||
while (lst != NULL)
|
|
||||||
{
|
|
||||||
last = lst->next == NULL;
|
|
||||||
indent(leader, last);
|
|
||||||
ft_printf("%s[%d]\n", "redirection", i);
|
|
||||||
redirection_debug(lst->redirection, leader, true);
|
|
||||||
dedent(leader, last);
|
|
||||||
lst = lst->next;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
dedent(leader, is_last);
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
/* ************************************************************************** */
|
|
||||||
/* */
|
|
||||||
/* ::: :::::::: */
|
|
||||||
/* redirection_list.h :+: :+: :+: */
|
|
||||||
/* +:+ +:+ +:+ */
|
|
||||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
|
||||||
/* +#+#+#+#+#+ +#+ */
|
|
||||||
/* Created: 2025/03/07 14:29:32 by khais #+# #+# */
|
|
||||||
/* Updated: 2025/03/19 16:49:52 by khais ### ########.fr */
|
|
||||||
/* */
|
|
||||||
/* ************************************************************************** */
|
|
||||||
|
|
||||||
#ifndef REDIRECTION_LIST_H
|
|
||||||
# define REDIRECTION_LIST_H
|
|
||||||
|
|
||||||
# include "redirection.h"
|
|
||||||
# include "../../buffer/buffer.h"
|
|
||||||
# include <stdbool.h>
|
|
||||||
|
|
||||||
typedef struct s_redirection_list
|
|
||||||
{
|
|
||||||
t_redirection *redirection;
|
|
||||||
struct s_redirection_list *next;
|
|
||||||
} t_redir_list;
|
|
||||||
|
|
||||||
t_redir_list *redir_list_push(t_redir_list *lst, t_redirection *item);
|
|
||||||
void redir_list_destroy(t_redir_list *lst);
|
|
||||||
void redir_list_debug(t_redir_list *lst,
|
|
||||||
t_buffer *leader, bool is_last);
|
|
||||||
|
|
||||||
#endif // REDIRECTION_LIST_H
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
/* ************************************************************************** */
|
|
||||||
/* */
|
|
||||||
/* ::: :::::::: */
|
|
||||||
/* redirection_parsing.c :+: :+: :+: */
|
|
||||||
/* +:+ +:+ +:+ */
|
|
||||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
|
||||||
/* +#+#+#+#+#+ +#+ */
|
|
||||||
/* Created: 2025/03/07 12:30:04 by khais #+# #+# */
|
|
||||||
/* Updated: 2025/03/19 18:28:28 by khais ### ########.fr */
|
|
||||||
/* */
|
|
||||||
/* ************************************************************************** */
|
|
||||||
|
|
||||||
#include "redirection_parsing.h"
|
|
||||||
#include "redirection.h"
|
|
||||||
#include "redirection_list.h"
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "redirection_type.h"
|
|
||||||
#include "../../ft_errno.h"
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
**
|
|
||||||
** if a redirection token is detected, the current word will be the operator
|
|
||||||
** token. Destroy it.
|
|
||||||
**
|
|
||||||
** the current word is now the marker. save it and destroy it
|
|
||||||
**
|
|
||||||
** create a new redirection with the operator and the marker, and save it.
|
|
||||||
**
|
|
||||||
** in case of error, return NULL, and set ft_errno
|
|
||||||
*/
|
|
||||||
static struct s_simple_cmd *redirection_found(
|
|
||||||
struct s_simple_cmd *cmd,
|
|
||||||
size_t i,
|
|
||||||
t_redir_type type)
|
|
||||||
{
|
|
||||||
t_worddesc *marker;
|
|
||||||
t_redirection *redirection;
|
|
||||||
|
|
||||||
wordlist_destroy_idx(&cmd->words, i);
|
|
||||||
marker = wordlist_pop_idx(&cmd->words, i);
|
|
||||||
if (marker == NULL)
|
|
||||||
return (ft_errno(FT_EMALFORMED_REDIRECTION), NULL);
|
|
||||||
redirection = redirection_create(type, marker);
|
|
||||||
if (redirection == NULL)
|
|
||||||
return (NULL);
|
|
||||||
cmd->redirections = redir_list_push(cmd->redirections, redirection);
|
|
||||||
if (cmd->redirections == NULL)
|
|
||||||
return (redirection_destroy(redirection), NULL);
|
|
||||||
return (cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Modify the given simple_cmd in-place, removing all redirection directives
|
|
||||||
** from words, parsing them, and storing them in redirection.
|
|
||||||
**
|
|
||||||
** In case of allocation failure, all memory allocated in this function is
|
|
||||||
** freed, but the command given in entry is not.
|
|
||||||
**
|
|
||||||
** In case of error, return null (this may leave the given command in an
|
|
||||||
** inconsitent state) (but it can still be freed correctly).
|
|
||||||
**
|
|
||||||
** Algorithm:
|
|
||||||
**
|
|
||||||
** iterate though the words of the given cmd
|
|
||||||
**
|
|
||||||
** if a redirection is detected, call redirection_found
|
|
||||||
*/
|
|
||||||
struct s_simple_cmd *parse_redirections(struct s_simple_cmd *cmd)
|
|
||||||
{
|
|
||||||
t_redir_type type;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (cmd == NULL)
|
|
||||||
return (NULL);
|
|
||||||
i = 0;
|
|
||||||
while (wordlist_get(cmd->words, i) != NULL)
|
|
||||||
{
|
|
||||||
type = redir_type_from_worddesc(wordlist_get(cmd->words, i));
|
|
||||||
if (type != REDIR_INVALID)
|
|
||||||
{
|
|
||||||
if (redirection_found(cmd, i, type) == NULL)
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
return (cmd);
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
/* ************************************************************************** */
|
|
||||||
/* */
|
|
||||||
/* ::: :::::::: */
|
|
||||||
/* redirection_parsing.h :+: :+: :+: */
|
|
||||||
/* +:+ +:+ +:+ */
|
|
||||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
|
||||||
/* +#+#+#+#+#+ +#+ */
|
|
||||||
/* Created: 2025/03/07 11:59:31 by khais #+# #+# */
|
|
||||||
/* Updated: 2025/03/19 16:38:01 by khais ### ########.fr */
|
|
||||||
/* */
|
|
||||||
/* ************************************************************************** */
|
|
||||||
|
|
||||||
#ifndef REDIRECTION_PARSING_H
|
|
||||||
# define REDIRECTION_PARSING_H
|
|
||||||
|
|
||||||
# include "../../parser/simple_cmd/simple_cmd.h"
|
|
||||||
# include "../../parser/cmdgroup/cmdgroup.h"
|
|
||||||
|
|
||||||
t_simple_cmd *parse_redirections(t_simple_cmd *cmd);
|
|
||||||
t_cmdgroup *cmdgroup_parse_redirections(t_cmdgroup *cmd);
|
|
||||||
|
|
||||||
#endif // REDIRECTIONS_H
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
/* ************************************************************************** */
|
|
||||||
/* */
|
|
||||||
/* ::: :::::::: */
|
|
||||||
/* redirection_type.c :+: :+: :+: */
|
|
||||||
/* +:+ +:+ +:+ */
|
|
||||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
|
||||||
/* +#+#+#+#+#+ +#+ */
|
|
||||||
/* Created: 2025/03/07 14:56:29 by khais #+# #+# */
|
|
||||||
/* Updated: 2025/03/19 16:59:14 by khais ### ########.fr */
|
|
||||||
/* */
|
|
||||||
/* ************************************************************************** */
|
|
||||||
|
|
||||||
#include "redirection_type.h"
|
|
||||||
#include "libft.h"
|
|
||||||
#include "../../treedrawing.h"
|
|
||||||
|
|
||||||
t_redir_type redir_type_from_worddesc(t_worddesc *word)
|
|
||||||
{
|
|
||||||
if (ft_strcmp(">", word->word) == 0)
|
|
||||||
return (REDIR_OUTPUT);
|
|
||||||
if (ft_strcmp("<", word->word) == 0)
|
|
||||||
return (REDIR_INPUT);
|
|
||||||
if (ft_strcmp("<<", word->word) == 0)
|
|
||||||
return (REDIR_HERE_DOC);
|
|
||||||
if (ft_strcmp(">>", word->word) == 0)
|
|
||||||
return (REDIR_APPEND);
|
|
||||||
return (REDIR_INVALID);
|
|
||||||
}
|
|
||||||
|
|
||||||
void redir_type_debug(t_redir_type type, t_buffer *leader,
|
|
||||||
bool is_last)
|
|
||||||
{
|
|
||||||
indent(leader, is_last);
|
|
||||||
ft_printf("t_redir_type = ");
|
|
||||||
if (type == REDIR_OUTPUT)
|
|
||||||
ft_printf("%s\n", "REDIR_OUTPUT");
|
|
||||||
if (type == REDIR_INPUT)
|
|
||||||
ft_printf("%s\n", "REDIR_INPUT");
|
|
||||||
if (type == REDIR_HERE_DOC)
|
|
||||||
ft_printf("%s\n", "REDIR_HERE_DOC");
|
|
||||||
if (type == REDIR_APPEND)
|
|
||||||
ft_printf("%s\n", "REDIR_APPEND");
|
|
||||||
dedent(leader, is_last);
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
/* ************************************************************************** */
|
|
||||||
/* */
|
|
||||||
/* ::: :::::::: */
|
|
||||||
/* redirection_type.h :+: :+: :+: */
|
|
||||||
/* +:+ +:+ +:+ */
|
|
||||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
|
||||||
/* +#+#+#+#+#+ +#+ */
|
|
||||||
/* Created: 2025/03/07 14:37:12 by khais #+# #+# */
|
|
||||||
/* Updated: 2025/03/19 16:52:09 by khais ### ########.fr */
|
|
||||||
/* */
|
|
||||||
/* ************************************************************************** */
|
|
||||||
|
|
||||||
#ifndef REDIRECTION_TYPE_H
|
|
||||||
# define REDIRECTION_TYPE_H
|
|
||||||
|
|
||||||
# include "../../parser/worddesc/worddesc.h"
|
|
||||||
# include "../../buffer/buffer.h"
|
|
||||||
# include <stdbool.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Type of redirection.
|
|
||||||
*/
|
|
||||||
typedef enum e_redirection_type
|
|
||||||
{
|
|
||||||
// Invalid
|
|
||||||
REDIR_INVALID,
|
|
||||||
// <
|
|
||||||
REDIR_INPUT,
|
|
||||||
// >
|
|
||||||
REDIR_OUTPUT,
|
|
||||||
// <<
|
|
||||||
REDIR_HERE_DOC,
|
|
||||||
// >>
|
|
||||||
REDIR_APPEND,
|
|
||||||
} t_redir_type;
|
|
||||||
|
|
||||||
t_redir_type redir_type_from_worddesc(t_worddesc *word);
|
|
||||||
void redir_type_debug(t_redir_type type, t_buffer *leader,
|
|
||||||
bool is_last);
|
|
||||||
|
|
||||||
#endif // REDIRECTION_TYPE_H
|
|
||||||
|
|
@ -5,7 +5,6 @@ rawtests = \
|
||||||
test_cmdlist_use_after_free \
|
test_cmdlist_use_after_free \
|
||||||
test_here_doc \
|
test_here_doc \
|
||||||
test_wordlist_idx \
|
test_wordlist_idx \
|
||||||
test_redirection_parsing \
|
|
||||||
test_quote_removal \
|
test_quote_removal \
|
||||||
test_metacharacters \
|
test_metacharacters \
|
||||||
test_parse_cmdlists \
|
test_parse_cmdlists \
|
||||||
|
|
|
||||||
|
|
@ -1,168 +0,0 @@
|
||||||
/* ************************************************************************** */
|
|
||||||
/* */
|
|
||||||
/* ::: :::::::: */
|
|
||||||
/* test_redirection_parsing.c :+: :+: :+: */
|
|
||||||
/* +:+ +:+ +:+ */
|
|
||||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
|
||||||
/* +#+#+#+#+#+ +#+ */
|
|
||||||
/* Created: 2025/03/10 16:50/33 by khais #+# #+# */
|
|
||||||
/* Updated: 2025/03/10 16:50:33 by khais ### ########.fr */
|
|
||||||
/* */
|
|
||||||
/* ************************************************************************** */
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include "../src/parser/simple_cmd/simple_cmd.h"
|
|
||||||
#include "../src/parser/wordsplit/wordsplit.h"
|
|
||||||
#include "../src/postprocess/redirections/redirection_parsing.h"
|
|
||||||
#include "../src/postprocess/redirections/redirection_parsing.h"
|
|
||||||
#include "../src/postprocess/redirections/redirection_list.h"
|
|
||||||
#include "../src/ft_errno.h"
|
|
||||||
#include "ft_printf.h"
|
|
||||||
#include "stdio.h"
|
|
||||||
#include "testutil.h"
|
|
||||||
|
|
||||||
static t_simple_cmd *parse_simple_cmd(char *input)
|
|
||||||
{
|
|
||||||
t_wordlist *words = minishell_wordsplit(input);
|
|
||||||
t_simple_cmd *cmd = simple_cmd_from_wordlist(words);
|
|
||||||
return (cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_redirection_parsing_no_redirections(void)
|
|
||||||
{
|
|
||||||
ft_dprintf(STDERR_FILENO, "==> %s <==\n", __FUNCTION__);
|
|
||||||
t_simple_cmd *cmd = parse_simple_cmd("echo hello world");
|
|
||||||
assert(parse_redirections(cmd) != NULL);
|
|
||||||
assert(cmd->redirections == NULL);
|
|
||||||
simple_cmd_destroy(cmd);
|
|
||||||
do_leak_check();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_redirection_parsing_output_at_start(void)
|
|
||||||
{
|
|
||||||
ft_dprintf(STDERR_FILENO, "==> %s <==\n", __FUNCTION__);
|
|
||||||
t_simple_cmd *cmd = parse_simple_cmd(">outfile echo hello world");
|
|
||||||
assert(parse_redirections(cmd) != NULL);
|
|
||||||
assert_strequal("outfile", cmd->redirections->redirection->marker->word);
|
|
||||||
assert(cmd->redirections->redirection->type == REDIR_OUTPUT);
|
|
||||||
assert(cmd->redirections->next == NULL);
|
|
||||||
assert_strequal("echo", cmd->words->word->word);
|
|
||||||
assert_strequal("hello", cmd->words->next->word->word);
|
|
||||||
assert_strequal("world", cmd->words->next->next->word->word);
|
|
||||||
assert(NULL == cmd->words->next->next->next);
|
|
||||||
simple_cmd_destroy(cmd);
|
|
||||||
do_leak_check();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_redirection_parsing_output_at_end(void)
|
|
||||||
{
|
|
||||||
ft_dprintf(STDERR_FILENO, "==> %s <==\n", __FUNCTION__);
|
|
||||||
t_simple_cmd *cmd = parse_simple_cmd("echo hello world > outfile");
|
|
||||||
assert(parse_redirections(cmd) != NULL);
|
|
||||||
assert_strequal("echo", cmd->words->word->word);
|
|
||||||
assert_strequal("hello", cmd->words->next->word->word);
|
|
||||||
assert_strequal("world", cmd->words->next->next->word->word);
|
|
||||||
assert(NULL == cmd->words->next->next->next);
|
|
||||||
assert_strequal("outfile", cmd->redirections->redirection->marker->word);
|
|
||||||
assert(cmd->redirections->redirection->type == REDIR_OUTPUT);
|
|
||||||
assert(cmd->redirections->next == NULL);
|
|
||||||
simple_cmd_destroy(cmd);
|
|
||||||
do_leak_check();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_redirection_parsing_output_in_middle(void)
|
|
||||||
{
|
|
||||||
ft_dprintf(STDERR_FILENO, "==> %s <==\n", __FUNCTION__);
|
|
||||||
t_simple_cmd *cmd = parse_simple_cmd("echo hello >outfile world");
|
|
||||||
assert(parse_redirections(cmd) != NULL);
|
|
||||||
assert_strequal("echo", cmd->words->word->word);
|
|
||||||
assert_strequal("hello", cmd->words->next->word->word);
|
|
||||||
assert_strequal("world", cmd->words->next->next->word->word);
|
|
||||||
assert(NULL == cmd->words->next->next->next);
|
|
||||||
assert_strequal("outfile", cmd->redirections->redirection->marker->word);
|
|
||||||
assert(cmd->redirections->redirection->type == REDIR_OUTPUT);
|
|
||||||
assert(cmd->redirections->next == NULL);
|
|
||||||
simple_cmd_destroy(cmd);
|
|
||||||
do_leak_check();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_redirection_parsing_output_no_filename_at_end(void)
|
|
||||||
{
|
|
||||||
ft_dprintf(STDERR_FILENO, "==> %s <==\n", __FUNCTION__);
|
|
||||||
ft_errno(FT_ESUCCESS);
|
|
||||||
t_simple_cmd *cmd = parse_simple_cmd("echo hello world >");
|
|
||||||
assert(parse_redirections(cmd) == NULL);
|
|
||||||
assert(FT_EMALFORMED_REDIRECTION == ft_errno_get());
|
|
||||||
simple_cmd_destroy(cmd);
|
|
||||||
do_leak_check();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_redirection_parsing_null(void)
|
|
||||||
{
|
|
||||||
ft_dprintf(STDERR_FILENO, "==> %s <==\n", __FUNCTION__);
|
|
||||||
assert(parse_redirections(NULL) == NULL);
|
|
||||||
do_leak_check();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_redirection_parsing_input_in_middle(void)
|
|
||||||
{
|
|
||||||
ft_dprintf(STDERR_FILENO, "==> %s <==\n", __FUNCTION__);
|
|
||||||
t_simple_cmd *cmd = parse_simple_cmd("echo hello <outfile world");
|
|
||||||
assert(parse_redirections(cmd) != NULL);
|
|
||||||
assert_strequal("echo", cmd->words->word->word);
|
|
||||||
assert_strequal("hello", cmd->words->next->word->word);
|
|
||||||
assert_strequal("world", cmd->words->next->next->word->word);
|
|
||||||
assert(NULL == cmd->words->next->next->next);
|
|
||||||
assert_strequal("outfile", cmd->redirections->redirection->marker->word);
|
|
||||||
assert(cmd->redirections->redirection->type == REDIR_INPUT);
|
|
||||||
assert(cmd->redirections->next == NULL);
|
|
||||||
simple_cmd_destroy(cmd);
|
|
||||||
do_leak_check();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_redirection_parsing_here_doc_in_middle(void)
|
|
||||||
{
|
|
||||||
ft_dprintf(STDERR_FILENO, "==> %s <==\n", __FUNCTION__);
|
|
||||||
t_simple_cmd *cmd = parse_simple_cmd("echo hello <<outfile world");
|
|
||||||
assert(parse_redirections(cmd) != NULL);
|
|
||||||
assert_strequal("echo", cmd->words->word->word);
|
|
||||||
assert_strequal("hello", cmd->words->next->word->word);
|
|
||||||
assert_strequal("world", cmd->words->next->next->word->word);
|
|
||||||
assert(NULL == cmd->words->next->next->next);
|
|
||||||
assert_strequal("outfile", cmd->redirections->redirection->marker->word);
|
|
||||||
assert(cmd->redirections->redirection->type == REDIR_HERE_DOC);
|
|
||||||
assert(cmd->redirections->next == NULL);
|
|
||||||
simple_cmd_destroy(cmd);
|
|
||||||
do_leak_check();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void test_redirection_parsing_append_in_middle(void)
|
|
||||||
{
|
|
||||||
ft_dprintf(STDERR_FILENO, "==> %s <==\n", __FUNCTION__);
|
|
||||||
t_simple_cmd *cmd = parse_simple_cmd("echo hello >> outfile world");
|
|
||||||
assert(parse_redirections(cmd) != NULL);
|
|
||||||
assert_strequal("echo", cmd->words->word->word);
|
|
||||||
assert_strequal("hello", cmd->words->next->word->word);
|
|
||||||
assert_strequal("world", cmd->words->next->next->word->word);
|
|
||||||
assert(NULL == cmd->words->next->next->next);
|
|
||||||
assert_strequal("outfile", cmd->redirections->redirection->marker->word);
|
|
||||||
assert(cmd->redirections->redirection->type == REDIR_APPEND);
|
|
||||||
assert(cmd->redirections->next == NULL);
|
|
||||||
simple_cmd_destroy(cmd);
|
|
||||||
do_leak_check();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
test_redirection_parsing_no_redirections();
|
|
||||||
test_redirection_parsing_output_at_start();
|
|
||||||
test_redirection_parsing_output_at_end();
|
|
||||||
test_redirection_parsing_output_in_middle();
|
|
||||||
test_redirection_parsing_output_no_filename_at_end();
|
|
||||||
test_redirection_parsing_null();
|
|
||||||
test_redirection_parsing_input_in_middle();
|
|
||||||
test_redirection_parsing_here_doc_in_middle();
|
|
||||||
test_redirection_parsing_append_in_middle();
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue