diff --git a/Makefile b/Makefile index e995f52..362f850 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # By: ttsubo +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/04/03 12:55:20 by ttsubo #+# #+# # -# Updated: 2025/04/24 12:11:25 by ttsubo ### ########.fr # +# Updated: 2025/04/24 15:32:30 by ttsubo ### ########.fr # # # # **************************************************************************** # @@ -15,6 +15,7 @@ CC = cc SRC_DIR = src/ TOKENIZER_SRC_DIR = src/tokenizer/ +PERSER_SRC_DIR = src/perser/ BUILTIN_SRC_DIR = src/builtin/ INC_DIR = inc/ OBJ_DIR = obj/ @@ -28,14 +29,17 @@ L_FLG = -lreadline -lft SRC = main.c minish_signal.c initialize.c debug.c TOKENIZER_SRC = tokenizer.c tokenizer_error.c read_token.c \ is_quote_closed.c get_token_capa.c is_redirect_validate.c +PERSER_SRC = allocate_cmds.c perser.c perser_utils.c setup_cmds.c BUILTIN_SRC = cd.c exit.c pwd.c echo.c env.c unset.c \ env_utils.c env_utils_2.c builtin_utils.c SRCS = $(addprefix $(SRC_DIR), $(SRC)) SRCS += $(addprefix $(TOKENIZER_SRC_DIR), $(TOKENIZER_SRC)) +SRCS += $(addprefix $(PERSER_SRC_DIR), $(PERSER_SRC)) SRCS += $(addprefix $(BUILTIN_SRC_DIR), $(BUILTIN_SRC)) OBJS = $(addprefix $(OBJ_DIR), $(SRC:.c=.o)) OBJS += $(addprefix $(OBJ_DIR), $(TOKENIZER_SRC:.c=.o)) +OBJS += $(addprefix $(OBJ_DIR), $(PERSER_SRC:.c=.o)) OBJS += $(addprefix $(OBJ_DIR), $(BUILTIN_SRC:.c=.o)) LIBFT=libft.a @@ -54,6 +58,9 @@ $(OBJ_DIR)%.o: $(SRC_DIR)%.c $(OBJ_DIR)%.o: $(TOKENIZER_SRC_DIR)%.c $(CC) $(W_FLG) $(I_FLG) -c $< -o $@ +$(OBJ_DIR)%.o: $(PERSER_SRC_DIR)%.c + $(CC) $(W_FLG) $(I_FLG) -c $< -o $@ + $(OBJ_DIR)%.o: $(BUILTIN_SRC_DIR)%.c $(CC) $(W_FLG) $(I_FLG) -c $< -o $@ diff --git a/inc/main.h b/inc/main.h index f9e3dda..ae5ff40 100644 --- a/inc/main.h +++ b/inc/main.h @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/03 12:50:38 by ttsubo #+# #+# */ -/* Updated: 2025/04/24 12:13:49 by ttsubo ### ########.fr */ +/* Updated: 2025/04/24 15:28:00 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -24,6 +24,7 @@ # include "minish_signal.h" # include "struct.h" # include "tokenizer.h" +# include "perser.h" # include # include # include diff --git a/inc/perser.h b/inc/perser.h new file mode 100644 index 0000000..9bff788 --- /dev/null +++ b/inc/perser.h @@ -0,0 +1,26 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* perser.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ttsubo +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/21 14:14:59 by ttsubo #+# #+# */ +/* Updated: 2025/04/24 15:22:00 by ttsubo ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef PERSER_H +# define PERSER_H + +# include "cmd.h" +# include "libft.h" + +t_cmd **perser(char **tokens); +size_t cmds_len(t_cmd **cmds); +int is_separator(char *token); +void free_cmds(t_cmd **cmds, size_t count); +t_cmd **allocate_cmds(char **tokens); +t_cmd **setup_cmds(t_cmd **cmds, char **tokens); + +#endif \ No newline at end of file diff --git a/src/main.c b/src/main.c index 31e8d29..c6536e3 100644 --- a/src/main.c +++ b/src/main.c @@ -6,24 +6,36 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/03 12:50:11 by ttsubo #+# #+# */ -/* Updated: 2025/04/24 12:10:52 by ttsubo ### ########.fr */ +/* Updated: 2025/04/24 15:34:41 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ #include "main.h" /** - * @brief debug用 tokenを表示します。 後で削除予定。 + * @brief debug用 cmdを表示します。 後で削除予定。 * * @param tokens */ -static void _dbg_show_tokens(char **tokens) +static void _dbg_show_cmd(t_cmd **cmds) { - printf("DEBUG: show tokens\n"); - printf("["); - while (*tokens) - printf("\"%s\", ", *tokens++); - printf("NULL]\n"); + size_t cmd_i; + size_t arg_i; + + cmd_i = 0; + printf("DEBUG: show cmds\n"); + while (cmds[cmd_i]) + { + arg_i = 0; + printf("cmd[%zu]\n", cmd_i); + printf("\tcmd->type=%d\n", cmds[cmd_i]->type); + printf("\tcmd->argc=%d\n", cmds[cmd_i]->argc); + printf("\tcmd->argv=["); + while (cmds[cmd_i]->argv[arg_i]) + printf("%s,", cmds[cmd_i]->argv[arg_i++]); + printf("NULL]\n"); + cmd_i++; + } } static void _free_tokens(char **tokens) @@ -58,25 +70,25 @@ static bool prompt(char *program_name, t_minish *minish, int *status) { char *line; char **tokens; - t_cmd *cmd; + t_cmd **cmds; + (void) status; line = readline("minish>"); if (!line) return (false); if (line[0] != '\0') add_history(line); tokens = tokenizer(line); - _dbg_show_tokens(tokens); - cmd = parse_command_line(line); - if (!cmd) + cmds = perser(tokens); + if (!cmds) { error_mes(program_name, ": syntax error\n"); cleanup_minish(minish); return (false); } - if (cmd->argc > 0) - *status = invoke_commands(cmd); + _dbg_show_cmd(cmds); _free_tokens(tokens); + free_cmds(cmds, cmds_len(cmds)); free(line); return (true); } diff --git a/src/perser/allocate_cmds.c b/src/perser/allocate_cmds.c new file mode 100644 index 0000000..cff2a8e --- /dev/null +++ b/src/perser/allocate_cmds.c @@ -0,0 +1,61 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* allocate_cmds.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ttsubo +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/24 12:19:28 by ttsubo #+# #+# */ +/* Updated: 2025/04/24 14:59:36 by ttsubo ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "perser.h" + +static size_t _count_cmds(char **tokens) +{ + size_t i; + size_t cmd_count; + + i = 0; + cmd_count = 1; + while (tokens[i]) + { + if (is_separator(tokens[i])) + cmd_count++; + i++; + } + return (cmd_count); +} + +static t_cmd **_allocate_cmds(size_t count) +{ + size_t i; + t_cmd **cmds; + + i = 0; + cmds = ft_calloc(count, sizeof(t_cmd *) + 1); + if (!cmds) + return (NULL); + while (i < count) + { + cmds[i] = ft_calloc(1, sizeof(t_cmd)); + if (!cmds[i]) + return (free_cmds(cmds, i), NULL); + if (i > 0) + cmds[i - 1]->next = cmds[i]; + i++; + } + cmds[i] = NULL; + return (cmds); +} + +t_cmd **allocate_cmds(char **tokens) +{ + t_cmd **cmds; + + cmds = _allocate_cmds(_count_cmds(tokens)); + if (!cmds) + return (NULL); + return (cmds); +} diff --git a/src/perser/perser.c b/src/perser/perser.c new file mode 100644 index 0000000..b20df1f --- /dev/null +++ b/src/perser/perser.c @@ -0,0 +1,32 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* perser.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ttsubo +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/21 14:14:32 by ttsubo #+# #+# */ +/* Updated: 2025/04/24 14:38:19 by ttsubo ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "perser.h" + +/** + * @brief + * + * @param tokens + * @return t_cmd** + */ +t_cmd **perser(char **tokens) +{ + t_cmd **cmds; + + cmds = allocate_cmds(tokens); + if (!cmds) + return (NULL); + cmds = setup_cmds(cmds, tokens); + if (!cmds) + return (NULL); + return (cmds); +} diff --git a/src/perser/perser_utils.c b/src/perser/perser_utils.c new file mode 100644 index 0000000..a623187 --- /dev/null +++ b/src/perser/perser_utils.c @@ -0,0 +1,51 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* perser_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ttsubo +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/24 13:40:56 by ttsubo #+# #+# */ +/* Updated: 2025/04/24 15:00:46 by ttsubo ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "perser.h" + +size_t cmds_len(t_cmd **cmds) +{ + size_t i; + + i = 0; + while (cmds[i]) + i++; + return (i); +} + +void free_cmds(t_cmd **cmds, size_t count) +{ + size_t cmd_i; + size_t arg_i; + + cmd_i = 0; + while (cmd_i < count) + { + arg_i = 0; + while (cmds[cmd_i]->argv && cmds[cmd_i]->argv[arg_i]) + free(cmds[cmd_i]->argv[arg_i++]); + free(cmds[cmd_i]->argv); + free(cmds[cmd_i]); + cmd_i++; + } + free(cmds); +} + +int is_separator(char *token) +{ + return (!ft_strcmp(token, "|") + || !ft_strcmp(token, "<") + || !ft_strcmp(token, ">") + || !ft_strcmp(token, "<<") + || !ft_strcmp(token, ">>") + ); +} diff --git a/src/perser/setup_cmds.c b/src/perser/setup_cmds.c new file mode 100644 index 0000000..ed309c5 --- /dev/null +++ b/src/perser/setup_cmds.c @@ -0,0 +1,84 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* setup_cmds.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: dayano +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/24 13:38:36 by ttsubo #+# #+# */ +/* Updated: 2025/04/24 22:06:17 by dayano ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "perser.h" + +static int _allocate_argv(t_cmd *cmd, char **tokens) +{ + size_t token_i; + size_t argc; + + token_i = 0; + argc = 0; + while (tokens[token_i] && !is_separator(tokens[token_i])) + { + token_i++; + argc++; + } + cmd->argv = ft_calloc(argc + 1, sizeof(char *)); + if (!cmd->argv) + return (1); + return (0); +} + +static void _set_type(t_cmd *cmd, char *token) +{ + if (!ft_strcmp(token, ">")) + cmd->type = REDIR_OUT; + else if (!ft_strcmp(token, ">>")) + cmd->type = REDIR_APPEND; + else if (!ft_strcmp(token, "<")) + cmd->type = REDIR_IN; + else if (!ft_strcmp(token, "<<")) + cmd->type = REDIR_HEREDOC; + else + cmd->type = REDIR_NONE; +} + +static void _next_cmd(t_cmd **cmds, size_t *cmd_i, size_t *arg_i, char *token) +{ + cmds[*cmd_i]->argv[*arg_i] = NULL; + cmds[*cmd_i]->argc = *arg_i; + (*arg_i) = 0; + (*cmd_i)++; + _set_type(cmds[*cmd_i], token); + _allocate_argv(cmds[*cmd_i], &token); +} + +t_cmd **setup_cmds(t_cmd **cmds, char **tokens) +{ + size_t token_i; + size_t cmd_i; + size_t arg_i; + + token_i = 0; + cmd_i = 0; + arg_i = 0; + _set_type(cmds[0], tokens[token_i]); + _allocate_argv(cmds[0], tokens); + while (tokens[token_i]) + { + if (is_separator(tokens[token_i])) + _next_cmd(cmds, &cmd_i, &arg_i, tokens[token_i]); + else + { + cmds[cmd_i]->argv[arg_i] = ft_strdup(tokens[token_i]); + if (!cmds[cmd_i]->argv[arg_i]) + return (free_cmds(cmds, cmds_len(cmds)), NULL); + arg_i++; + } + token_i++; + } + cmds[cmd_i]->argc = arg_i; + cmds[++cmd_i] = NULL; + return (cmds); +} diff --git a/test.mk b/test.mk index fcfa6e5..436c85d 100644 --- a/test.mk +++ b/test.mk @@ -6,7 +6,7 @@ # By: ttsubo +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/04/14 11:48:18 by ttsubo #+# #+# # -# Updated: 2025/04/20 19:58:13 by ttsubo ### ########.fr # +# Updated: 2025/04/24 14:31:51 by ttsubo ### ########.fr # # # # **************************************************************************** # @@ -22,7 +22,7 @@ I_FLG = -Iinc -Ilib/libft L_FLG = -Llib/libft -lft -lreadline # testを追加する場合はSRCにファイル名を追加してください。 -SRC = cd.c exit.c echo.c env.c unset.c tokenizer.c +SRC = cd.c exit.c echo.c env.c unset.c tokenizer.c perser.c OUT = $(addprefix test_, $(SRC:.c=.out)) @@ -34,6 +34,9 @@ test_%.out: tests/builtin/test_%.c src/builtin/%.c test_%.out: tests/tokenizer/test_%.c $(CC) $^ src/tokenizer/*.c $(L_FLG) $(I_FLG) -o $@ +test_%.out: tests/perser/test_%.c + $(CC) $^ src/perser/*.c src/tokenizer/*.c $(L_FLG) $(I_FLG) -o $@ + test_unset.out: tests/builtin/test_unset.c $(CC) $< src/initialize.c src/builtin/*.c $(L_FLG) $(I_FLG) -o $@ diff --git a/tests/perser/test_perser.c b/tests/perser/test_perser.c new file mode 100644 index 0000000..616e56b --- /dev/null +++ b/tests/perser/test_perser.c @@ -0,0 +1,57 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* test_perser.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ttsubo +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/24 14:28:00 by ttsubo #+# #+# */ +/* Updated: 2025/04/24 14:59:28 by ttsubo ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "perser.h" +#include "tokenizer.h" + +static void _free_tokens(char **tokens) +{ + int i; + + i = 0; + while (tokens[i]) + free(tokens[i++]); + free(tokens); +} + +static void _show_cmd(t_cmd *cmd) +{ + size_t arg_i; + + arg_i = 0; + printf("\tcmd->type=%d\n", cmd->type); + printf("\tcmd->argc=%d\n", cmd->argc); + printf("\tcmd->argv=["); + while (cmd->argv[arg_i]) + printf("%s,", cmd->argv[arg_i++]); + printf("NULL]\n"); +} + +int main(int argc, char **argv) +{ + int i; + char **tokens; + t_cmd **cmds; + + if (argc != 2) + return (printf("usage: ./test_tokenizer.out "), 1); + tokens = tokenizer(argv[1]); + cmds = perser(tokens); + if (!tokens) + return (1); + i = 0; + while (cmds[i]) + _show_cmd(cmds[i++]); + _free_tokens(tokens); + free_cmds(cmds, cmds_len(cmds)); + return (0); +}