From 90272353f5deb93c09f16b45bcb2648a6e6d126c Mon Sep 17 00:00:00 2001 From: Jikuhara Date: Mon, 29 Sep 2025 14:35:35 +0900 Subject: [PATCH 001/173] add libft --- minishell/libft/.vscode/settings.json | 7 + minishell/libft/Makefile | 112 ++++++++++++ minishell/libft/conversion/ft_atoi.c | 49 ++++++ minishell/libft/conversion/ft_itoa.c | 96 ++++++++++ minishell/libft/conversion/ft_tolower.c | 39 +++++ minishell/libft/conversion/ft_toupper.c | 39 +++++ minishell/libft/judge/ft_isalnum.c | 30 ++++ minishell/libft/judge/ft_isalpha.c | 71 ++++++++ minishell/libft/judge/ft_isascii.c | 100 +++++++++++ minishell/libft/judge/ft_isdigit.c | 84 +++++++++ minishell/libft/judge/ft_isprint.c | 28 +++ minishell/libft/libft.h | 74 ++++++++ minishell/libft/list/ft_lstadd_back.c | 91 ++++++++++ minishell/libft/list/ft_lstadd_front.c | 85 +++++++++ minishell/libft/list/ft_lstclear.c | 33 ++++ minishell/libft/list/ft_lstdelone.c | 91 ++++++++++ minishell/libft/list/ft_lstiter.c | 26 +++ minishell/libft/list/ft_lstlast.c | 84 +++++++++ minishell/libft/list/ft_lstmap.c | 222 ++++++++++++++++++++++++ minishell/libft/list/ft_lstnew.c | 37 ++++ minishell/libft/list/ft_lstsize.c | 88 ++++++++++ minishell/libft/memory/ft_bzero.c | 43 +++++ minishell/libft/memory/ft_calloc.c | 61 +++++++ minishell/libft/memory/ft_memchr.c | 74 ++++++++ minishell/libft/memory/ft_memcmp.c | 78 +++++++++ minishell/libft/memory/ft_memcpy.c | 128 ++++++++++++++ minishell/libft/memory/ft_memmove.c | 59 +++++++ minishell/libft/memory/ft_memrchr.c | 82 +++++++++ minishell/libft/memory/ft_memset.c | 40 +++++ minishell/libft/original/ft_isspace.c | 18 ++ minishell/libft/original/ft_max.c | 55 ++++++ minishell/libft/original/ft_min.c | 54 ++++++ minishell/libft/original/ft_swap.c | 33 ++++ minishell/libft/output/ft_putchar_fd.c | 79 +++++++++ minishell/libft/output/ft_putendl_fd.c | 98 +++++++++++ minishell/libft/output/ft_putnbr_fd.c | 155 +++++++++++++++++ minishell/libft/output/ft_putstr_fd.c | 81 +++++++++ minishell/libft/string/ft_split.c | 130 ++++++++++++++ minishell/libft/string/ft_strchr.c | 77 ++++++++ minishell/libft/string/ft_strdup.c | 47 +++++ minishell/libft/string/ft_striteri.c | 80 +++++++++ minishell/libft/string/ft_strjoin.c | 131 ++++++++++++++ minishell/libft/string/ft_strlcat.c | 59 +++++++ minishell/libft/string/ft_strlcpy.c | 50 ++++++ minishell/libft/string/ft_strlen.c | 38 ++++ minishell/libft/string/ft_strmapi.c | 56 ++++++ minishell/libft/string/ft_strncmp.c | 43 +++++ minishell/libft/string/ft_strnstr.c | 95 ++++++++++ minishell/libft/string/ft_strrchr.c | 65 +++++++ minishell/libft/string/ft_strtrim.c | 133 ++++++++++++++ minishell/libft/string/ft_substr.c | 105 +++++++++++ 51 files changed, 3733 insertions(+) create mode 100644 minishell/libft/.vscode/settings.json create mode 100644 minishell/libft/Makefile create mode 100644 minishell/libft/conversion/ft_atoi.c create mode 100644 minishell/libft/conversion/ft_itoa.c create mode 100644 minishell/libft/conversion/ft_tolower.c create mode 100644 minishell/libft/conversion/ft_toupper.c create mode 100644 minishell/libft/judge/ft_isalnum.c create mode 100644 minishell/libft/judge/ft_isalpha.c create mode 100644 minishell/libft/judge/ft_isascii.c create mode 100644 minishell/libft/judge/ft_isdigit.c create mode 100644 minishell/libft/judge/ft_isprint.c create mode 100644 minishell/libft/libft.h create mode 100644 minishell/libft/list/ft_lstadd_back.c create mode 100644 minishell/libft/list/ft_lstadd_front.c create mode 100644 minishell/libft/list/ft_lstclear.c create mode 100644 minishell/libft/list/ft_lstdelone.c create mode 100644 minishell/libft/list/ft_lstiter.c create mode 100644 minishell/libft/list/ft_lstlast.c create mode 100644 minishell/libft/list/ft_lstmap.c create mode 100644 minishell/libft/list/ft_lstnew.c create mode 100644 minishell/libft/list/ft_lstsize.c create mode 100644 minishell/libft/memory/ft_bzero.c create mode 100644 minishell/libft/memory/ft_calloc.c create mode 100644 minishell/libft/memory/ft_memchr.c create mode 100644 minishell/libft/memory/ft_memcmp.c create mode 100644 minishell/libft/memory/ft_memcpy.c create mode 100644 minishell/libft/memory/ft_memmove.c create mode 100644 minishell/libft/memory/ft_memrchr.c create mode 100644 minishell/libft/memory/ft_memset.c create mode 100644 minishell/libft/original/ft_isspace.c create mode 100644 minishell/libft/original/ft_max.c create mode 100644 minishell/libft/original/ft_min.c create mode 100644 minishell/libft/original/ft_swap.c create mode 100644 minishell/libft/output/ft_putchar_fd.c create mode 100644 minishell/libft/output/ft_putendl_fd.c create mode 100644 minishell/libft/output/ft_putnbr_fd.c create mode 100644 minishell/libft/output/ft_putstr_fd.c create mode 100644 minishell/libft/string/ft_split.c create mode 100644 minishell/libft/string/ft_strchr.c create mode 100644 minishell/libft/string/ft_strdup.c create mode 100644 minishell/libft/string/ft_striteri.c create mode 100644 minishell/libft/string/ft_strjoin.c create mode 100644 minishell/libft/string/ft_strlcat.c create mode 100644 minishell/libft/string/ft_strlcpy.c create mode 100644 minishell/libft/string/ft_strlen.c create mode 100644 minishell/libft/string/ft_strmapi.c create mode 100644 minishell/libft/string/ft_strncmp.c create mode 100644 minishell/libft/string/ft_strnstr.c create mode 100644 minishell/libft/string/ft_strrchr.c create mode 100644 minishell/libft/string/ft_strtrim.c create mode 100644 minishell/libft/string/ft_substr.c diff --git a/minishell/libft/.vscode/settings.json b/minishell/libft/.vscode/settings.json new file mode 100644 index 0000000..2bdaf25 --- /dev/null +++ b/minishell/libft/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "files.associations": { + "stdbool.h": "c", + "libft.h": "c", + "string": "c" + } +} diff --git a/minishell/libft/Makefile b/minishell/libft/Makefile new file mode 100644 index 0000000..1e45f5a --- /dev/null +++ b/minishell/libft/Makefile @@ -0,0 +1,112 @@ +# **************************************************************************** # +# # +# ::: :::::::: # +# Makefile :+: :+: :+: # +# +:+ +:+ +:+ # +# By: kjikuhar +#+ +:+ +#+ # +# +#+#+#+#+#+ +#+ # +# Created: 2025/04/04 16:00:02 by kjikuhar #+# #+# # +# Updated: 2025/06/02 20:46:59 by kjikuhar ### ########.fr # +# # +# **************************************************************************** # + +CC = cc +RM = rm -f +CFLAGS = -Wall -Wextra -Werror -I../includes/ +NAME = libft.a + +SRCS = conversion/ft_atoi.c \ + conversion/ft_itoa.c \ + conversion/ft_tolower.c \ + conversion/ft_toupper.c \ + judge/ft_isalnum.c \ + judge/ft_isalpha.c \ + judge/ft_isascii.c \ + judge/ft_isdigit.c \ + judge/ft_isprint.c \ + list/ft_lstadd_back.c \ + list/ft_lstadd_front.c \ + list/ft_lstclear.c \ + list/ft_lstdelone.c \ + list/ft_lstiter.c \ + list/ft_lstlast.c \ + list/ft_lstmap.c \ + list/ft_lstnew.c \ + list/ft_lstsize.c \ + memory/ft_bzero.c \ + memory/ft_calloc.c \ + memory/ft_memchr.c \ + memory/ft_memcmp.c \ + memory/ft_memcpy.c \ + memory/ft_memmove.c \ + memory/ft_memrchr.c \ + memory/ft_memset.c \ + output/ft_putchar_fd.c \ + output/ft_putendl_fd.c \ + output/ft_putnbr_fd.c \ + output/ft_putstr_fd.c \ + string/ft_split.c \ + string/ft_strchr.c \ + string/ft_strdup.c \ + string/ft_striteri.c \ + string/ft_strjoin.c \ + string/ft_strlcat.c \ + string/ft_strlcpy.c \ + string/ft_strlen.c \ + string/ft_strmapi.c \ + string/ft_strncmp.c \ + string/ft_strnstr.c \ + string/ft_strrchr.c \ + string/ft_strtrim.c \ + string/ft_substr.c \ + original/ft_swap.c \ + original/ft_max.c \ + original/ft_min.c \ + original/ft_isspace.c + +BLACK := \033[30m +RED := \033[31m +GREEN := \033[32m +YELLOW := \033[33m +BLUE := \033[96m +MAGENTA := \033[38;5;206m +CYAN := \033[36m +WHITE := \033[37m +RESET := \033[0m +BOLD := \033[1m +DIM := \033[2m +ITALIC := \033[3m +UNDER := \033[4m +BLINK := \033[5m +REVERSE := \033[7m +HIDDEN := \033[8m +PINK := \033[35m + +OBJS = $(SRCS:.c=.o) + +all: $(NAME) + +$(NAME): $(OBJS) + @echo "Compiled with $(GREEN)$(BOLD)$(CFLAGS)$(RESET)" + @ar crs $(NAME) $(OBJS) + @echo "$(YELLOW)$(BOLD)=========================================" + @echo " You can use My $(NAME)!!" + @echo "=========================================$(RESET)" + +# ========================================= +# You can use My libft.a!! +# ========================================= + +%.o: %.c + @echo "Compiled ✅ $(CYAN) $(BOLD) $^ $(RESET)" + @$(CC) $(CFLAGS) $(INCLUDE) -c -o $@ $^ + +clean: + @$(RM) $(OBJS) + +fclean: clean + @$(RM) $(NAME) + +re: fclean all + +.PHONY: all clean fclean re diff --git a/minishell/libft/conversion/ft_atoi.c b/minishell/libft/conversion/ft_atoi.c new file mode 100644 index 0000000..ddca3db --- /dev/null +++ b/minishell/libft/conversion/ft_atoi.c @@ -0,0 +1,49 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_atoi.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/24 21:08:27 by kjikuhar #+# #+# */ +/* Updated: 2025/05/16 16:54:10 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_atoi(const char *str) +{ + int sign; + int num; + + while (ft_isspace(*str)) + str++; + sign = 1; + if (*str == '+' || *str == '-') + if (*str == '-') + sign *= -1; + num = 0; + while (ft_isdigit((int)*str)) + num = 10 * num + (*str++ - '0'); + return (sign * num); +} + +// #include + +// int main(void) +// { +// char *str[] = {"123", "-3456789", " -112", "123", "0123456789", +// "10123456789", "10101010101010101010101", "10101010101010", +// "10010101010101010101", "9910101010101010101", +// "9010101010101010101", "9510101010101010101", "9210101010101010101", +// "2147483648", "18446744073709551615"}; + +// for (unsigned int i = 0; i < sizeof(str) / sizeof(str[0]); i++) +// { +// printf("%i : %20s : %d\n", i, str[i], atoi(str[i])); +// printf("%i : %20s : %d\n", i, str[i], ft_atoi(str[i])); +// printf("\n"); +// } +// return (0); +// } diff --git a/minishell/libft/conversion/ft_itoa.c b/minishell/libft/conversion/ft_itoa.c new file mode 100644 index 0000000..a1f0b14 --- /dev/null +++ b/minishell/libft/conversion/ft_itoa.c @@ -0,0 +1,96 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_itoa.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/26 11:55:06 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 21:19:09 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +/* Convert the integer 'n'to a ASCII string */ +static int number_len_(int number) +{ + int number_len; + + number_len = 1; + if (number == INT_MIN) + { + return (11); + } + if (number < 0) + { + number *= -1; + number_len++; + } + while (number >= 10) + { + number /= 10; + number_len++; + } + return (number_len); +} + +static char *ft_strcpy(char *dest, char *src) +{ + int i; + + i = 0; + while (src[i] != '\0') + { + dest[i] = src[i]; + i++; + } + dest[i] = '\0'; + return (dest); +} + +char *ft_itoa(int n) +{ + char *dest_str; + int i; + + dest_str = malloc(sizeof(char) * (number_len_(n) + 1)); + if (!dest_str) + return (NULL); + if (n == -2147483648) + { + return (ft_strcpy(dest_str, "-2147483648")); + } + i = number_len_(n) - 1; + if (n < 0) + { + dest_str[0] = '-'; + n *= -1; + } + dest_str[i + 1] = '\0'; + while (n >= 10) + { + dest_str[i] = n % 10 + '0'; + n /= 10; + i--; + } + dest_str[i] = n % 10 + '0'; + return (dest_str); +} + +// #include + +// int main(void) +// { +// int number_set[] = {0, 1, -1, -10, 10, -11, 2147483647, 2147483647, +// -2147483648, -2147483648, 1234567}; +// for (int i = 0; i < (sizeof(number_set) / sizeof(number_set[0])); i++) +// { +// char *number_char = ft_itoa(number_set[i]); +// printf("%d : %11d : %d\n",i, number_set[i], number_len(number_set[i])); +// printf("%d : %11d : %s\n\n",i, number_set[i], number_char); +// free(number_char); +// } + +// return (0); +// } diff --git a/minishell/libft/conversion/ft_tolower.c b/minishell/libft/conversion/ft_tolower.c new file mode 100644 index 0000000..e074da2 --- /dev/null +++ b/minishell/libft/conversion/ft_tolower.c @@ -0,0 +1,39 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_tolower.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/25 18:47:23 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 11:36:10 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_tolower(int c) +{ + if ('A' <= c && c <= 'Z') + return (c + 'a' - 'A'); + return (c); +} + +// #include +// #include + +// int main(void) +// { +// for (int i = 0; i < 26; i++) +// { +// printf("%2d :%c -> %c\n", i,(char)('a'+i),(char)ft_olower('a'+i)) +// printf("%2d :%c -> %c\n", i,(char)('a'+i),(char)olower('a'+i)) +// } +// printf("\n"); +// for (int i = 0; i < 26; i++) +// { +// printf("%2d :%c -> %c\n", i,(char)('A'+i),(char)ft_olower('A'+i)) +// printf("%2d :%c -> %c\n", i,(char)('A'+i),(char)olower('A'+i)) +// } +// return (0); +// } diff --git a/minishell/libft/conversion/ft_toupper.c b/minishell/libft/conversion/ft_toupper.c new file mode 100644 index 0000000..9fdf60b --- /dev/null +++ b/minishell/libft/conversion/ft_toupper.c @@ -0,0 +1,39 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_toupper.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/25 18:47:23 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 11:36:10 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_toupper(int c) +{ + if ('a' <= c && c <= 'z') + return (c + 'A' - 'a'); + return (c); +} + +// #include +// #include + +// int main(void) +// { +// for (int i = 0; i < 26; i++) +// { +// printf("%2d :%c -> %c\n", i, (char)('a'+i),(char)ft_toupper('a'+i)) +// printf("%2d :%c -> %c\n", i, (char)('a'+i),(char)toupper('a'+i)) +// } +// printf("\n"); +// for (int i = 0; i < 26; i++) +// { +// printf("%2d :%c -> %c\n", i, (char)('A'+i),(char)ft_toupper('A'+i)) +// printf("%2d :%c -> %c\n", i, (char)('A'+i),(char)toupper('A'+i)) +// } +// return (0); +// } diff --git a/minishell/libft/judge/ft_isalnum.c b/minishell/libft/judge/ft_isalnum.c new file mode 100644 index 0000000..067882f --- /dev/null +++ b/minishell/libft/judge/ft_isalnum.c @@ -0,0 +1,30 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_isalnum.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/24 21:20:17 by kjikuhar #+# #+# */ +/* Updated: 2025/05/18 17:49:11 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_isalnum(int c) +{ + return (ft_isalpha(c) || ft_isdigit(c)); +} + +// #include + +// int main(void) +// { +// for (int i = -5; i <= 258; i++) +// { +// char *str = (ft_isalnum(i) == 1) ? "OKKKK" : "NG"; +// printf("%3i, %4c : %2s\n", i,(char)i, str); +// } +// return (0); +// } diff --git a/minishell/libft/judge/ft_isalpha.c b/minishell/libft/judge/ft_isalpha.c new file mode 100644 index 0000000..7394da8 --- /dev/null +++ b/minishell/libft/judge/ft_isalpha.c @@ -0,0 +1,71 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_isalpha.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/24 21:11:06 by kjikuhar #+# #+# */ +/* Updated: 2025/05/05 13:13:04 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +int ft_isalpha(int c) +{ + return ((unsigned)(c | 0x20) - 'a' < 26); +} + +// int ft_isalpha_uc(int c) +// { +// return (((unsigned char)c | 32) - 'a' < 26); +// } + +// #include + +// int main(void) +// { +// for (int i = -5; i <= 130; i++) +// { +// char *str = (ft_isalpha(i) == 1) ? "OKKKKK" : "NG"; +// printf("%3i, %4c : %2s\n", i,(char)i, str); +// } +// // for (int i = -5; i <= 130; i++) +// // { +// // char *str = (ft_isalpha_u(i) == 1) ? "OKKKKK" : "NG"; +// // printf("%3i, %4c : %2s\n", i,(char)i, str); +// // } +// return (0); +// } +// Optimize processing through bit operations. + +// #include +// #include + +// int ft_ft_isalpha(int c) { +// return (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')); +// } + +// int main() { +// clock_t start, end; +// int count = 1000000000; // Loop 100 million times +// int result = 0; + +// // Test ft_isalpha +// start = clock(); +// for (int i = 0; i < count; i++) { +// result += ft_isalpha(i % 256); +// } +// end = clock(); +// printf("ft_isalpha: %f seconds\n", (double)(end - start) / CLOCKS_PER_SEC); + +// // Test ft_ft_isalpha +// start = clock(); +// for (int i = 0; i < count; i++) { +// result += ft_ft_isalpha(i % 256); +// } +// end = clock(); +// printf("ft_ft_isalpha: %f seconds\n", (double)(end - start) +// / CLOCKS_PER_SEC); + +// return (result); // Prevent compiler optimization +// } diff --git a/minishell/libft/judge/ft_isascii.c b/minishell/libft/judge/ft_isascii.c new file mode 100644 index 0000000..ef320bb --- /dev/null +++ b/minishell/libft/judge/ft_isascii.c @@ -0,0 +1,100 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_isascii.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/24 21:20:17 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 22:03:04 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#define ASCII_MAX 0x7F /* 127 */ + +int ft_isascii(int c) +{ + return ((unsigned)c <= ASCII_MAX); +} + +// bit mask +// int ft_ft_isascii(int c) +// { +// return (!(c & ~0x7f)); +// // } +// #include + +// int ft_isascii(int c) +// { +// return ((unsigned)c <= 127); +// } + +// int isascii(int c) +// { +// return ((c >= 0 && c <= 127) ? 1 : 0); +// } + +// int main(void) +// { +// for (int i = -5; i <= 130; i++) +// { +// char *str = (ft_isascii(i) == 1) ? "OKKKKK" : "NG"; +// printf("%3i, %4c : %2s\n", i,(char)i, str); +// } +// return (0); +// } +// #include +// #include + +// // Implementation 1: Range Check +// int isascii_range(int c) +// { +// return (c >= 0 && c <= 127); +// } + +// // Implementation 2: Bit Mask +// int isascii_bitmask(int c) +// { +// return (!(c & ~0x7f)); +// } + +// // Implementation 3: Constant Comparison +// int isascii_unsigned(int c) +// { +// return ((unsigned)c <= 127); +// } + +// // Implementation 4: Table Lookup +// int isascii_table(int c) +// { +// static const char ascii_table[128] = {[0 ... 127] = 1}; +// // Set ASCII range to 1 +// return ((c >= 0 && c < 128) ? ascii_table[c] : 0); +// } + +// #define ITERATIONS 1000000000 // 1 billion iterations + +// void benchmark(const char *name, int (*func)(int)) +// { +// int result; + +// clock_t start, end; +// result = 0; +// start = clock(); +// for (int i = 0; i < ITERATIONS; i++) +// { +// result += func(i % 256); // Loop through range of 256 +// } +// end = clock(); +// printf("%s: %f seconds\n", name, (double)(end - start) / CLOCKS_PER_SEC); +// } + +// int main(void) +// { +// printf("Benchmarking isascii implementations...\n"); +// benchmark("Range Check", isascii_range); +// benchmark("Bitmask", isascii_bitmask); +// benchmark("Unsigned Comparison", isascii_unsigned); +// benchmark("Table Lookup", isascii_table); +// return (0); +// } diff --git a/minishell/libft/judge/ft_isdigit.c b/minishell/libft/judge/ft_isdigit.c new file mode 100644 index 0000000..7b3869c --- /dev/null +++ b/minishell/libft/judge/ft_isdigit.c @@ -0,0 +1,84 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_isdigit.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/24 21:20:17 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 21:53:07 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +/* ASCII only */ +int ft_isdigit(int c) +{ + return ((unsigned)c - '0' < 10); +} + +// #include +// #include + +// int ft_isdigit_uc(int c) +// { +// unsigned char uc; + +// uc = (unsigned char)c; +// return ('0' <= uc && uc <= '9'); +// } + +// int ft_isdigit_bit(int c) +// { +// return ((unsigned)c - '0' < 10); +// } + +// int ft_isdigit_bit_u(int c) +// { +// return ((unsigned char)c - '0' < 10); +// } + +// int main(void) +// { +// for (int i = -5; i <= 130; i++) +// { +// char *str = (ft_isdigit_uc(i) == 1) ? "OKKKKK" : "NG"; +// printf("%3i, %4c : %2s\n", i,(char)i, str); +// } +// for (int i = -5; i <= 130; i++) +// { +// char *str = (ft_isdigit_bit(i) == 1) ? "OKKKKK" : "NG"; +// printf("%3i, %4c : %2s\n", i,(char)i, str); +// } +// for (int i = -5; i <= 130; i++) +// { +// char *str = (ft_isdigit_bit_u(i) == 1) ? "OKKKKK" : "NG"; +// printf("%3i, %4c : %2s\n", i,(char)i, str); +// } +// return (0); +// } + +// #define ITERATIONS 1000000000 // billion times loop + +// void benchmark(const char *name, int (*func)(int)) +// { +// int result; + +// clock_t start, end; +// result = 0; +// start = clock(); +// for (int i = 0; i < ITERATIONS; i++) +// { +// result += func(i % 256); // loop to 256 +// } +// end = clock(); +// printf("%s: %f seconds\n", name, (double)(end - start) / CLOCKS_PER_SEC); +// } + +// int main(void) +// { +// printf("Benchmarking isdigit implementations...\n"); +// benchmark("ft_isdigit_uc", ft_isdigit_uc); +// benchmark("ft_isdigit_bit", ft_isdigit_bit); +// benchmark("ft_isdigit_bit_u", ft_isdigit_bit_u); +// return (0); +// } diff --git a/minishell/libft/judge/ft_isprint.c b/minishell/libft/judge/ft_isprint.c new file mode 100644 index 0000000..af47f04 --- /dev/null +++ b/minishell/libft/judge/ft_isprint.c @@ -0,0 +1,28 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_isprint.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/24 21:20:17 by kjikuhar #+# #+# */ +/* Updated: 2025/05/02 23:13:00 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +int ft_isprint(int c) +{ + return ((unsigned)c - 0x20 < 0x5f); +} + +// #include + +// int main(void) +// { +// for (int i = -5; i <= 258; i++) +// { +// char *str = (ft_isprint(i) == 1) ? "OKKK" : "NG"; +// printf("%3i, %4c : %2s\n", i,(char)i, str); +// } +// return (0); +// } diff --git a/minishell/libft/libft.h b/minishell/libft/libft.h new file mode 100644 index 0000000..f375e84 --- /dev/null +++ b/minishell/libft/libft.h @@ -0,0 +1,74 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* libft.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/25 14:55:13 by kjikuhar #+# #+# */ +/* Updated: 2025/05/05 20:02:11 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef LIBFT_H +# define LIBFT_H + +# include +# include +# include +# include + +typedef struct s_list +{ + void *content; + struct s_list *next; +} t_list; + +int ft_atoi(const char *str); +void ft_bzero(void *s, size_t n); +void *ft_calloc(size_t count, size_t size); +int ft_isalnum(int c); +int ft_isalpha(int c); +int ft_isascii(int c); +int ft_isdigit(int c); +int ft_isprint(int c); +char *ft_itoa(int n); +void *ft_memchr(const void *s, int c, size_t n); +int ft_memcmp(const void *s1, const void *s2, size_t n); +void *ft_memcpy(void *dest, const void *src, size_t n); +void *ft_memmove(void *dest, const void *src, size_t len); +void *ft_memset(void *s, int c, size_t n); +void ft_putchar_fd(char c, int fd); +void ft_putendl_fd(char *s, int fd); +void ft_putnbr_fd(int n, int fd); +void ft_putstr_fd(char *s, int fd); +char **ft_split(char const *s, char c); +char *ft_strchr(const char *s, int c); +char *ft_strdup(const char *s); +void ft_striteri(char *s, void (*f)(unsigned int, char *)); +char *ft_strjoin(char const *s1, char const *s2); +size_t ft_strlcat(char *dst, const char *src, size_t size); +size_t ft_strlcpy(char *dst, const char *src, size_t size); +size_t ft_strlen(const char *s); +char *ft_strmapi(char const *s, char (*f)(unsigned int, char)); +int ft_strncmp(const char *s1, const char *s2, size_t n); +char *ft_strnstr(const char *big, const char *little, size_t len); +char *ft_strrchr(const char *s, int c); +char *ft_strtrim(char const *s1, char const *set); +char *ft_substr(char const *s, unsigned int start, size_t len); +int ft_tolower(int c); +int ft_toupper(int c); +void *ft_memrchr(const void *s, int c, size_t n); + +// Bonus +t_list *ft_lstnew(void *content); +void ft_lstadd_front(t_list **lst, t_list *new); +t_list *ft_lstlast(t_list *lst); +int ft_lstsize(t_list *lst); +void ft_lstadd_back(t_list **lst, t_list *new); +void ft_lstdelone(t_list *lst, void (*del)(void *)); +void ft_lstclear(t_list **lst, void (*del)(void *)); +void ft_lstiter(t_list *lst, void (*f)(void *)); +t_list *ft_lstmap(t_list *lst, void *(*f)(void *), void (*del)(void *)); + +#endif diff --git a/minishell/libft/list/ft_lstadd_back.c b/minishell/libft/list/ft_lstadd_back.c new file mode 100644 index 0000000..62ef492 --- /dev/null +++ b/minishell/libft/list/ft_lstadd_back.c @@ -0,0 +1,91 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstadd_back_bonus.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/28 15:40:06 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 22:10:55 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +/* Adds the node new at the end of the list */ +void ft_lstadd_back(t_list **lst, t_list *new) +{ + t_list *last; + + if (!lst || !new) + return ; + if (!*lst) + *lst = new; + else + { + last = ft_lstlast(*lst); + last->next = new; + } +} + +// #include +// #include + +// t_list *listMake(char *content) +// { +// t_list *new; + +// new = malloc(sizeof(t_list)); +// if (!new) +// return (NULL); +// new->content = (char *)malloc(sizeof(char) * (strlen(content))); +// strcpy((char *)(new->content), (const char *)content); +// new->next = NULL; +// return (new); +// } + +// int main(void) +// { +// t_list *lst1, *lst2, *lst3; +// t_list *head; + +// lst1 = listMake("Hello World!1"); +// lst2 = listMake("Hello World!2"); +// lst3 = listMake("Hello World!3"); + +// head = lst1; +// lst1->next = lst2; +// lst2->next = NULL; +// lst3->next = NULL; + +// printf("%s\n", (char *)(lst1->content)); +// printf("%s\n", (char *)(lst2->content)); +// printf("%s\n", (char *)(lst3->content)); +// printf("\n"); + +// t_list *current = head; +// for (int i = 0; i < 5; i++) +// { +// if (!current) +// { +// printf("%p\n", current); +// break ; +// } +// printf("%s\n", (char *)(current->content)); +// current = current->next; +// } + +// ft_lstadd_back(&head, lst3); +// current = head; +// for (int i = 0; i < 5; i++) +// { +// if (!current) +// { +// printf("%p\n", current); +// break ; +// } +// printf("%s\n", (char *)(current->content)); +// current = current->next; +// } +// return (0); +// } diff --git a/minishell/libft/list/ft_lstadd_front.c b/minishell/libft/list/ft_lstadd_front.c new file mode 100644 index 0000000..af8ee04 --- /dev/null +++ b/minishell/libft/list/ft_lstadd_front.c @@ -0,0 +1,85 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstadd_front_bonus.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/27 12:47:59 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 18:52:16 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +/* Adds the given node to the beginning of the list. Works with empty lists. */ +void ft_lstadd_front(t_list **lst, t_list *new) +{ + if (!lst || !new) + return ; + new->next = *lst; + *lst = new; +} + +// #include +// #include + +// t_list *listMake(char *content) +// { +// t_list *new; + +// new = malloc(sizeof(t_list)); +// if (!new) +// return (NULL); +// new->content = (char *)malloc(sizeof(char) * (strlen(content))); +// strcpy((char *)(new->content), (const char *)content); +// new->next = NULL; +// return (new); +// } + +// int main(void) +// { +// t_list *lst1, *lst2, *lst3; +// t_list *head; + +// lst1 = listMake("Hello World!1"); +// lst2 = listMake("Hello World!2"); +// lst3 = listMake("Hello World!3"); + +// head = lst1; +// lst1->next = lst2; +// lst2->next = NULL; +// lst3->next = NULL; + +// printf("%s\n", (char *)(lst1->content)); +// printf("%s\n", (char *)(lst2->content)); +// printf("%s\n", (char *)(lst3->content)); + +// t_list *current = head; +// for (int i = 0; i < 3; i++) +// { +// if (!current) +// { +// printf("%p\n", current); +// break ; +// } +// printf("%s\n", (char *)(current->content)); +// current = current->next; +// } +// printf("\n"); + +// head = NULL; +// ft_lstadd_front(&head, lst3); +// current = head; +// for (int i = 0; i < 3; i++) +// { +// if (!current) +// { +// printf("%p\n", current); +// break ; +// } +// printf("%s\n", (char *)(current->content)); +// current = current->next; +// } +// return (0); +// } diff --git a/minishell/libft/list/ft_lstclear.c b/minishell/libft/list/ft_lstclear.c new file mode 100644 index 0000000..c4e6c2f --- /dev/null +++ b/minishell/libft/list/ft_lstclear.c @@ -0,0 +1,33 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstclear_bonus.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/28 15:40:38 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 18:38:55 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +/* Deletes and frees the given list and its content */ +void ft_lstclear(t_list **lst, void (*del)(void *)) +{ + t_list *current; + t_list *next_list; + + if (!lst || !*lst || !del) + return ; + current = *lst; + while (current) + { + if (current->content) + (*del)(current->content); + next_list = current->next; + free(current); + current = next_list; + } + *lst = NULL; +} diff --git a/minishell/libft/list/ft_lstdelone.c b/minishell/libft/list/ft_lstdelone.c new file mode 100644 index 0000000..7932333 --- /dev/null +++ b/minishell/libft/list/ft_lstdelone.c @@ -0,0 +1,91 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstdelone_bonus.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/28 15:40:38 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 18:36:50 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +/* This function frees the memory of a list node using the given function */ +void ft_lstdelone(t_list *lst, void (*del)(void *)) +{ + if (!lst || !del) + return ; + if (lst->content) + (*del)(lst->content); + free(lst); +} + +// #include +// #include + +// void delete_content(void *content) +// { +// free(content); + +// } + +// t_list *listMake(char *content) +// { +// t_list *new; + +// new = malloc(sizeof(t_list)); +// if (!new) +// return (NULL); +// new->content = (char *)malloc(sizeof(char) * (strlen(content))); +// strcpy((char *)(new->content), (const char *)content); +// new->next = NULL; +// return (new); +// } + +// int main(void) +// { +// t_list *lst1, *lst2, *lst3; +// t_list *head; + +// lst1 = listMake("Hello World!1"); +// lst2 = listMake("Hello World!2"); +// lst3 = listMake("Hello World!3"); + +// head = lst1; +// lst1->next = lst2; +// lst2->next = NULL; +// lst3->next = NULL; + +// printf("%s\n", (char *)(lst1->content)); +// printf("%s\n", (char *)(lst2->content)); +// printf("%s\n", (char *)(lst3->content)); +// printf("\n"); + +// t_list *current = head; +// for (int i = 0; i < 5; i++) +// { +// if (!current) +// { +// printf("%p\n", current); +// break ; +// } +// printf("%s\n", (char *)(current->content)); +// current = current->next; +// } + +// ft_lstdelone(lst2, *delete_content); +// current = head; +// for (int i = 0; i < 5; i++) +// { +// if (!current) +// { +// printf("%p\n", current); +// break ; +// } +// printf("%s\n", (char *)(current->content)); +// current = current->next; +// } +// return (0); +// } diff --git a/minishell/libft/list/ft_lstiter.c b/minishell/libft/list/ft_lstiter.c new file mode 100644 index 0000000..ea1e925 --- /dev/null +++ b/minishell/libft/list/ft_lstiter.c @@ -0,0 +1,26 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstiter_bonus.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/28 15:40:38 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 19:00:25 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +/* Iterates the list and applies the function f on the content of each node */ +void ft_lstiter(t_list *lst, void (*f)(void *)) +{ + if (!f) + return ; + while (lst) + { + if (lst->content) + (*f)(lst->content); + lst = lst->next; + } +} diff --git a/minishell/libft/list/ft_lstlast.c b/minishell/libft/list/ft_lstlast.c new file mode 100644 index 0000000..59e56e4 --- /dev/null +++ b/minishell/libft/list/ft_lstlast.c @@ -0,0 +1,84 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstlast_bonus.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/28 15:38:00 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 19:01:49 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +/* Returns the last node of the list */ +t_list *ft_lstlast(t_list *lst) +{ + if (!lst) + return (NULL); + while (lst->next) + lst = lst->next; + return (lst); +} + +// #include +// #include + +// t_list *listMake(char *content) +// { +// t_list *new; + +// new = malloc(sizeof(t_list)); +// if (!new) +// return (NULL); +// new->content = (char *)malloc(sizeof(char) * (strlen(content))); +// strcpy((char *)(new->content), (const char *)content); +// new->next = NULL; +// return (new); +// } + +// int main(void) +// { +// t_list *lst1, *lst2, *lst3; +// t_list *head; + +// lst1 = listMake("Hello World!1"); +// lst2 = listMake("Hello World!2"); +// lst3 = listMake("Hello World!3"); + +// head = lst1; +// lst1->next = lst2; +// lst2->next = NULL; +// lst3->next = NULL; + +// printf("%s\n", (char *)(lst1->content)); +// printf("%s\n", (char *)(lst2->content)); +// printf("%s\n", (char *)(lst3->content)); + +// t_list *current = head; +// for (int i = 0; i < 3; i++) +// { +// if (!current) +// { +// printf("%p\n", current); +// break ; +// } +// printf("%s\n", (char *)(current->content)); +// current = current->next; +// } + +// printf("%s\n", (char *)(ft_lstlast(head)->content)); +// current = head; +// for (int i = 0; i < 3; i++) +// { +// if (!current) +// { +// printf("%p\n", current); +// break ; +// } +// printf("%s\n", (char *)(current->content)); +// current = current->next; +// } +// return (0); +// } diff --git a/minishell/libft/list/ft_lstmap.c b/minishell/libft/list/ft_lstmap.c new file mode 100644 index 0000000..0b0842f --- /dev/null +++ b/minishell/libft/list/ft_lstmap.c @@ -0,0 +1,222 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstmap_bonus.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/28 15:40:38 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 21:54:47 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +static t_list *init_head(t_list *lst, void *(*f)(void *), void (*del)(void *)) +{ + void *tmp; + t_list *head; + + tmp = (*f)(lst->content); + if (!tmp) + return (NULL); + head = ft_lstnew(tmp); + if (!head) + return (del(tmp), NULL); + return (head); +} + +t_list *ft_lstmap(t_list *lst, void *(*f)(void *), void (*del)(void *)) +{ + t_list *head; + t_list *cur; + t_list *tmp_node; + void *tmp; + + if (!lst || !f || !del) + return (NULL); + head = init_head(lst, f, del); + if (!head) + return (NULL); + cur = head; + lst = lst->next; + while (lst) + { + tmp = (*f)(lst->content); + if (!tmp) + return (ft_lstclear(&head, del), NULL); + tmp_node = ft_lstnew(tmp); + if (!tmp_node) + return (del(tmp), ft_lstclear(&head, del), NULL); + cur->next = tmp_node; + cur = tmp_node; + lst = lst->next; + } + return (head); +} +// /* ---- Add this to the end of source file ---- */ +// #include +// #include /* ← For debugging (optional) */ +// #include +// #include + +// /* ====== Helpers ====== */ +// static int g_del_count = 0; + +// static void *dup_int_times2(void *p) +// { +// int *src; +// int *dst; + +// src = (int *)p; +// dst = malloc(sizeof(int)); +// if (!dst) +// return (NULL); +// *dst = (*src) * 2; +// return (dst); +// } + +// static void *dup_int_fail_on_2(void *p) +// { +// int *src; + +// src = (int *)p; +// if (*src == 2) +// return (NULL); /* Intentionally fail */ +// return (dup_int_times2(p)); /* Succeed otherwise */ +// } + +// static void del_int(void *p) +// { +// printf("del_int called: %p\n", p); +// free(p); +// g_del_count++; +// } + +// static t_list *make_int_node(int v) +// { +// int *p; + +// p = malloc(sizeof(int)); +// assert(p); /* Simplified for testing */ +// *p = v; +// return (ft_lstnew(p)); +// } + +// static int list_equals(t_list *a, t_list *b) +// { +// while (a && b) +// { +// if (*(int *)a->content != *(int *)b->content) +// return (0); +// a = a->next; +// b = b->next; +// } +// return (a == NULL && b == NULL); +// } + +// /* ====== ft_lstnew ====== */ +// static void test_ft_lstnew_content(void) +// { +// char *s; +// t_list *n; + +// s = "hello"; +// n = ft_lstnew(s); +// assert(n && n->content == s && n->next == NULL); +// free(n); +// } + +// static void test_ft_lstnew_null(void) +// { +// t_list *n; + +// n = ft_lstnew(NULL); +// assert(n && n->content == NULL && n->next == NULL); +// free(n); +// } + +// /* ====== ft_lstclear ====== */ +// static void test_ft_lstclear_multi(void) +// { +// t_list *a; + +// g_del_count = 0; +// a = make_int_node(1); +// a->next = make_int_node(2); +// a->next->next = make_int_node(3); +// ft_lstclear(&a, del_int); +// assert(a == NULL); +// assert(g_del_count == 3); +// } + +// static void test_ft_lstclear_nullptr(void) +// { +// t_list *head; + +// /* lst == NULL */ +// ft_lstclear(NULL, del_int); +// /* *lst == NULL */ +// head = NULL; +// ft_lstclear(&head, del_int); +// } + +// /* ====== ft_lstmap ====== */ +// static void test_ft_lstmap_success(void) +// { +// t_list *src; +// t_list *dst; + +// src = make_int_node(1); +// src->next = make_int_node(2); +// src->next->next = make_int_node(3); +// dst = ft_lstmap(src, dup_int_times2, del_int); +// assert(dst && list_equals(dst, ((t_list[]){{.content = &(int){2}, +// .next = &(t_list){.content = &(int){4}, +// .next = &(t_list){.content = &(int){6}, .next = NULL}}}}))); +// /* Original list is unchanged */ +// assert(*(int *)src->content == 1); +// ft_lstclear(&src, del_int); +// ft_lstclear(&dst, del_int); +// } + +// static void test_ft_lstmap_fail_midway(void) +// { +// t_list *src; +// t_list *dst; + +// g_del_count = 0; +// src = make_int_node(1); +// src->next = make_int_node(2); +// src->next->next = make_int_node(3); +// dst = ft_lstmap(src, dup_int_fail_on_2, del_int); +// assert(dst == NULL); +// assert(g_del_count == 1); /* Only node 1 should have been freed */ +// ft_lstclear(&src, del_int); /* Cleanup */ +// } + +// static void test_ft_lstmap_nullsrc(void) +// { +// t_list *dst; + +// dst = ft_lstmap(NULL, dup_int_times2, del_int); +// assert(dst == NULL); +// } + +// /* ====== main ====== */ +// int main(void) +// { +// /* ft_lstnew */ +// test_ft_lstnew_content(); +// test_ft_lstnew_null(); +// /* ft_lstclear */ +// test_ft_lstclear_multi(); +// test_ft_lstclear_nullptr(); +// /* ft_lstmap */ +// test_ft_lstmap_success(); +// test_ft_lstmap_fail_midway(); +// printf("Final g_del_count = %d\n", g_del_count); +// test_ft_lstmap_nullsrc(); +// puts("All tests passed!"); +// return (0); +// } diff --git a/minishell/libft/list/ft_lstnew.c b/minishell/libft/list/ft_lstnew.c new file mode 100644 index 0000000..6662b47 --- /dev/null +++ b/minishell/libft/list/ft_lstnew.c @@ -0,0 +1,37 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstnew_bonus.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/27 12:42:16 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 19:03:20 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +/* Allocates and returns a new node with the given content */ +t_list *ft_lstnew(void *content) +{ + t_list *new; + + new = malloc(sizeof(t_list)); + if (!new) + return (NULL); + new->content = content; + new->next = NULL; + return (new); +} + +// #include + +// int main(void) +// { +// t_list *new_list; + +// new_list = ft_lstnew("Hello World!"); +// printf("%s : %p", (char *)new_list->content, new_list->next); +// return (0); +// } diff --git a/minishell/libft/list/ft_lstsize.c b/minishell/libft/list/ft_lstsize.c new file mode 100644 index 0000000..85f4557 --- /dev/null +++ b/minishell/libft/list/ft_lstsize.c @@ -0,0 +1,88 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstsize_bonus.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/28 15:34:58 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 19:03:32 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +/* Counts the number of nodes in a list */ +int ft_lstsize(t_list *lst) +{ + int i; + + i = 0; + while (lst) + { + i++; + lst = lst->next; + } + return (i); +} + +// #include +// #include + +// t_list *listMake(char *content) +// { +// t_list *new; + +// new = malloc(sizeof(t_list)); +// if (!new) +// return (NULL); +// new->content = (char *)malloc(sizeof(char) * (strlen(content))); +// strcpy((char *)(new->content), (const char *)content); +// new->next = NULL; +// return (new); +// } + +// int main(void) +// { +// t_list *lst1, *lst2, *lst3; +// t_list *head; + +// lst1 = listMake("Hello World!1"); +// lst2 = listMake("Hello World!2"); +// lst3 = listMake("Hello World!3"); + +// head = lst1; +// lst1->next = lst2; +// lst2->next = lst3; +// lst3->next = NULL; + +// printf("%s\n", (char *)(lst1->content)); +// printf("%s\n", (char *)(lst2->content)); +// printf("%s\n", (char *)(lst3->content)); +// printf("\n"); + +// t_list *current = head; +// for (int i = 0; i < 5; i++) +// { +// if (!current) +// { +// printf("%p : %d\n", current, ft_lstsize(current)); +// break ; +// } +// printf("%s : %d\n", (char *)(current->content), ft_lstsize(current)); +// current = current->next; +// } + +// current = head; +// for (int i = 0; i < 5; i++) +// { +// if (!current) +// { +// printf("%p : %d\n", current, ft_lstsize(current)); +// break ; +// } +// printf("%s : %d\n", (char *)(current->content), ft_lstsize(current)); +// current = current->next; +// } +// return (0); +// } diff --git a/minishell/libft/memory/ft_bzero.c b/minishell/libft/memory/ft_bzero.c new file mode 100644 index 0000000..3c0b51e --- /dev/null +++ b/minishell/libft/memory/ft_bzero.c @@ -0,0 +1,43 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_bzero.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/25 15:46:17 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 11:36:10 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_bzero(void *s, size_t n) +{ + ft_memset(s, 0, n); +} + +// #include +// #include +// #include + +// int main(void) +// { +// char strs[][30] = {"Hello World 42 Tokyo!"}; + +// for (size_t i = 0; i < sizeof(strs) / sizeof(strs[0]); i++) +// { +// printf("%s\n", strs[i]); +// // bzero(strs[i], 2); +// ft_bzero(strs[i], 5); +// for (size_t j = 0; j < 30; j++) +// { +// if (strs[i][j] == '\0') +// printf("%s", "\\0"); +// else +// printf("%c", strs[i][j]); +// } +// printf("%c", '\n'); +// } +// return (0); +// } diff --git a/minishell/libft/memory/ft_calloc.c b/minishell/libft/memory/ft_calloc.c new file mode 100644 index 0000000..18ca355 --- /dev/null +++ b/minishell/libft/memory/ft_calloc.c @@ -0,0 +1,61 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_calloc.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/25 17:26:53 by kjikuhar #+# #+# */ +/* Updated: 2025/05/05 13:27:01 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void *ft_calloc(size_t count, size_t size) +{ + void *p; + size_t total_size; + + if (count == 0 || size == 0) + return (malloc(0)); + if (count > __SIZE_MAX__ / size) + return (NULL); + total_size = count * size; + p = malloc(total_size); + if (!p) + return (NULL); + ft_bzero(p, total_size); + return (p); +} + +// #include +// #include + +// int main(void) +// { +// int *p; +// char *str[10]; + +// p = (int *)ft_calloc(10, sizeof(int)); +// for (size_t i = 0; i < 10; i++) +// { +// printf("%d\n", p[i]); +// } +// printf("\n"); +// str = (char **)ft_calloc(10, sizeof(char *)); +// for (size_t i = 0; i < 10; i++) +// { +// str[i] = "0123456789"; +// printf("%s\n", str[i]); +// } +// free(p); +// free(str); +// return (0); +// } +// // % gcc -fsanitize=address -g ft_calloc.c ft_bzero.c -o test_calloc +// // gcc -g ft_calloc.c ft_bzero.c -o test_calloc_valgrind # ASanなしでコンパイル +// // valgrind --leak-check=full --track-origins=yes ./test_calloc_valgrind +// gcc -Wall -Wextra -Werror -Wpedantic -Wconversion -Wshadow -Wundef +// -Wcast-align -Wwrite-strings -Wformat=2 +// -g ft_calloc.c ft_bzero.c -o test_calloc_debug diff --git a/minishell/libft/memory/ft_memchr.c b/minishell/libft/memory/ft_memchr.c new file mode 100644 index 0000000..5f55f60 --- /dev/null +++ b/minishell/libft/memory/ft_memchr.c @@ -0,0 +1,74 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_memchr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/25 18:30:44 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 22:02:33 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void *ft_memchr(const void *s, int c, size_t n) +{ + const unsigned char *us; + + us = (const unsigned char *)s; + while (n--) + { + if (*us == (unsigned char)c) + return ((void *)us); + us++; + } + return (NULL); +} +// #include "libft.h" +// #include +// #include + +// void test_ft_memchr(const void *s, int c, size_t n, const char *test_name) +// { +// void *ft_result; +// void *std_result; + +// ft_result = ft_memchr(s, c, n); +// std_result = memchr(s, c, n); +// printf("Test: %s\n", test_name); +// printf("ft_memchr result: %p\n", ft_result); +// printf("memchr result: %p\n", std_result); +// printf("Match: %s\n\n", (ft_result == std_result) ? "Yes" : "No"); +// } + +// int main(void) +// { +// char str1[] = "Hello, world!"; +// unsigned char binary[] = {0x10, 0x20, 0x30, 0x40, 0x50}; +// char str2[] = "Hello\0world"; + +// // Test case 1: Search for a character in a string +// test_ft_memchr(str1, 'w', strlen(str1), "Search for 'w' in 'Hello, +// world!'"); +// // Test case 2: Search for a non-existent character +// test_ft_memchr(str1, 'z', strlen(str1), "Search for 'z' in 'Hello, +// world!' (non-existent)"); +// // Test case 3: Search for a character within limited length +// test_ft_memchr(str1, 'o', 5, "Search for 'o' in 'Hello, world!' with n=5"); +// // Test case 4: Search for a character within limited length (not in range) +// test_ft_memchr(str1, 'o', 4, "Search for 'o' in 'Hello, +// world!' with n=4 (out of range)"); +// // Test case 5: Search for NULL byte +// test_ft_memchr(str1, '\0', strlen(str1) + 1, "Search for '\\0' in 'Hello, +// world!'"); +// // Test case 6: Binary data +// test_ft_memchr(binary, 0x30, sizeof(binary), +// "Search for 0x30 in binary data"); +// // Test case 7: Case with n=0 +// test_ft_memchr("", 'a', 0, "Search for 'a' with n=0"); +// // Test case 8: Search for character after NULL byte +// test_ft_memchr(str2, 'w', 12, +// "Search for 'w' after NULL byte in 'Hello\\0world'"); +// return (0); +// } diff --git a/minishell/libft/memory/ft_memcmp.c b/minishell/libft/memory/ft_memcmp.c new file mode 100644 index 0000000..48e61d8 --- /dev/null +++ b/minishell/libft/memory/ft_memcmp.c @@ -0,0 +1,78 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_memcmp.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/25 18:41:27 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 22:02:43 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_memcmp(const void *s1, const void *s2, size_t n) +{ + const unsigned char *s1_str; + const unsigned char *s2_str; + + s1_str = (unsigned char *)s1; + s2_str = (unsigned char *)s2; + while (n--) + { + if (*s1_str != *s2_str) + return (*s1_str - *s2_str); + s1_str++; + s2_str++; + } + return (0); +} +// #include +// #include + +// void test_ft_memcmp(const void *s1, const void *s2, size_t n, +// const char *test_name) +// { +// int ft_result; +// int std_result; +// int ft_sign; +// int std_sign; + +// ft_result = ft_memcmp(s1, s2, n); +// std_result = memcmp(s1, s2, n); +// printf("Test: %s\n", test_name); +// printf("ft_memcmp result: %d\n", ft_result); +// printf("memcmp result: %d\n", std_result); +// // Check if the result signs are the same +// ft_sign = (ft_result > 0) ? 1 : ((ft_result < 0) ? -1 : 0); +// std_sign = (std_result > 0) ? 1 : ((std_result < 0) ? -1 : 0); +// printf("Match: %s\n\n", (ft_sign == std_sign) ? "Yes" : "No"); +// } + +// int main(void) +// { +// char str1[] = "Hello, world!"; +// char str3[] = "Hello\0world"; +// char str4[] = "Hello\0WORLD"; +// unsigned char bin1[] = {0x10, 0x20, 0x30, 0x40}; +// unsigned char bin2[] = {0x10, 0x20, 0x50, 0x40}; + +// // Test case 1: Compare identical strings +// test_ft_memcmp(str1, str1, strlen(str1), "Comparing identical strings"); +// // Test case 2: Compare different strings +// char str2[] = "Hello, World!"; // 'w' changed to 'W' +// test_ft_memcmp(str1, str2, strlen(str1), "Comparing different strings"); +// // Test case 3: Strings differing within specified bytes +// test_ft_memcmp("abcdef", "abcDef", 4, "Strings differing within 4 bytes"); +// // Test case 4: Strings differing outside of specified bytes +// test_ft_memcmp("abcdef", "abcDef", 3, +// "Comparing within 3 bytes (before the difference)"); +// // Test case 5: When byte count is zero +// test_ft_memcmp("abc", "def", 0, "Comparison with zero bytes"); +// // Test case 6: Comparison including NULL bytes +// test_ft_memcmp(str3, str4, 12, "Strings containing NULL characters"); +// // Test case 7: Binary data +// test_ft_memcmp(bin1, bin2, 4, "Comparing binary data"); +// return (0); +// } diff --git a/minishell/libft/memory/ft_memcpy.c b/minishell/libft/memory/ft_memcpy.c new file mode 100644 index 0000000..4e2dfd7 --- /dev/null +++ b/minishell/libft/memory/ft_memcpy.c @@ -0,0 +1,128 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_memcpy.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/25 15:45:59 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 21:58:55 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +/* When memory regions may overlap, you should use memmove instead of memcpy */ +void *ft_memcpy(void *dest, const void *src, size_t n) +{ + unsigned char *dest_str; + const unsigned char *src_str; + + if (n == 0 || dest == src) + return (dest); + dest_str = (unsigned char *)dest; + src_str = (const unsigned char *)src; + while (n--) + *(dest_str++) = *(src_str++); + return (dest); +} +// #include +// #include +// #include + +// /* MEMCPY_01: Regular copy (5 bytes) */ +// static void test_memcpy_short(void) +// { +// const char *src = "abcde"; +// char dest[8] = {0}; + +// assert(ft_memcpy(dest, src, 5) == dest); +// assert(memcmp(dest, src, 5) == 0); +// } + +// /* MEMCPY_02: No change when n==0 */ +// static void test_memcpy_n_zero(void) +// { +// const char *src = "xyz"; +// char dest[8] = "XXXX"; + +// assert(ft_memcpy(dest, src, 0) == dest); +// assert(strcmp(dest, "XXXX") == 0); /* content unchanged */ +// } + +// /* MEMCPY_03: Copy including '\0' */ +// static void test_memcpy_with_nullbyte(void) +// { +// const char *src = "Hello\0World"; +// char dest[12] = {0}; + +// size_t n = strlen(src) + 1; /* up to '\0' */ +// assert(ft_memcpy(dest, src, n) == dest); +// assert(memcmp(dest, src, n) == 0); +// } + +// /* MEMCPY_04: dest == src */ +// static void test_memcpy_same_pointer(void) +// { +// char buffer[6] = "ABCDE"; + +// assert(ft_memcpy(buffer, buffer, 5) == buffer); +// assert(memcmp(buffer, "ABCDE", 5) == 0); +// } + +// /* MEMCPY_05: Large capacity 2048 bytes */ +// static void test_memcpy_large_block(void) +// { +// size_t n; +// unsigned char *src; +// unsigned char *dest; + +// n = 2048; +// src = malloc(n); +// dest = malloc(n); +// assert(src && dest); +// memset(src, 0xAA, n); +// memset(dest, 0x00, n); +// assert(ft_memcpy(dest, src, n) == dest); +// assert(memcmp(dest, src, n) == 0); +// free(src); +// free(dest); +// } + +// /* MEMCPY_06: dest==NULL && src==NULL && n==0 */ +// static void test_memcpy_null_null_zero(void) +// { +// assert(ft_memcpy(NULL, NULL, 0) == NULL); +// } + +// // /* MEMCPY_07: dest==NULL && src!=NULL && n==0 */ +// // static void test_memcpy_null_nonull_zero(void) +// // { +// // assert(ft_memcpy(NULL, "a", 0) == NULL); +// // } + +// // /* MEMCPY_08: dest!=NULL && src==NULL && n==0 */ +// // static void test_memcpy_nonull_null_zero(void) +// // { +// // char *dst; +// // dst = malloc(32); +// // assert(ft_memcpy(dst, NULL, 0) == NULL); +// // free(dst); +// // } + +// int main(void) +// { +// // ft_memcpy(NULL, NULL, 1); +// // memcpy(NULL, NULL, 1); +// // ft_memcpy(NULL, NULL, 0); +// // memcpy(NULL, NULL, 0); +// test_memcpy_short(); +// test_memcpy_n_zero(); +// test_memcpy_with_nullbyte(); +// test_memcpy_same_pointer(); +// test_memcpy_large_block(); +// test_memcpy_null_null_zero(); +// // test_memcpy_null_nonull_zero(); +// // test_memcpy_nonull_null_zero(); +// return (0); +// } diff --git a/minishell/libft/memory/ft_memmove.c b/minishell/libft/memory/ft_memmove.c new file mode 100644 index 0000000..f3a0473 --- /dev/null +++ b/minishell/libft/memory/ft_memmove.c @@ -0,0 +1,59 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_memmove.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/25 19:28:19 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 21:59:54 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void *ft_memmove(void *dest, const void *src, size_t n) +{ + unsigned char *dest_str; + const unsigned char *src_str; + + if (!dest && !src) + return (NULL); + dest_str = (unsigned char *)dest; + src_str = (const unsigned char *)src; + if (dest < src) + while (n--) + *dest_str++ = *src_str++; + else + { + src_str += n; + dest_str += n; + while (n--) + *--dest_str = *--src_str; + } + return (dest); +} +// #include +// #include + +// int main(void) +// { +// char str[] = "Hello, World!"; +// char overlap1[] = "abcdefghijkl"; +// char overlap2[] = "0123456789"; + +// // Copy without overlap +// printf("Original string: %s\n", str); +// ft_memmove(str + 7, "42Tokyo", 7); +// printf("After memmove: %s\n", str); + +// // Copy with overlap (forward copy) +// ft_memmove(overlap1 + 3, overlap1, 4); +// printf("Overlapping copy (forward): %s\n", overlap1); + +// // Copy with overlap (backward copy) +// ft_memmove(overlap2, overlap2 + 2, 5); +// printf("Overlapping copy (backward): %s\n", overlap2); + +// return (0); +// } diff --git a/minishell/libft/memory/ft_memrchr.c b/minishell/libft/memory/ft_memrchr.c new file mode 100644 index 0000000..fbb1fe3 --- /dev/null +++ b/minishell/libft/memory/ft_memrchr.c @@ -0,0 +1,82 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_memrchr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/05/05 18:16:23 by kjikuhar #+# #+# */ +/* Updated: 2025/05/05 20:02:01 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +/* search by decrement loop */ +void *ft_memrchr(const void *s, int c, size_t n) +{ + const unsigned char *us; + + us = (unsigned char *)s; + while (n--) + if (us[n] == (unsigned char)c) + return ((void *)(us + n)); + return (NULL); +} + +// #include +// #include +// #include + +// static void test_ft_memrchr_a_found(void) +// { +// const char s[] = "abcabc"; + +// assert(ft_memrchr(s, 'a', 6) == s + 3); +// } + +// static void test_ft_memrchr_c_found(void) +// { +// const char s[] = "abcabc"; + +// assert(ft_memrchr(s, 'c', 6) == s + 5); +// } + +// static void test_ft_memrchr_n_zero(void) +// { +// const char s[] = "abcabc"; + +// assert(ft_memrchr(s, 'a', 0) == NULL); +// } + +// static void test_ft_memrchr_tail_only(void) +// { +// const char s[] = "abcabc"; + +// assert(ft_memrchr(s + 5, 'c', 1) == s + 5); +// } + +// static void test_ft_memrchr_not_found(void) +// { +// const char s[] = "abcabc"; + +// assert(ft_memrchr(s, 'x', 6) == NULL); +// } + +// static void test_ft_memrchr_binary(void) +// { +// const unsigned char s[] = {0x00, 0xff, 0x00, 0xff}; + +// assert(ft_memrchr(s, 0xff, 4) == s + 3); +// } + +// int main(void) +// { +// test_ft_memrchr_a_found(); +// test_ft_memrchr_c_found(); +// test_ft_memrchr_n_zero(); +// test_ft_memrchr_tail_only(); +// test_ft_memrchr_not_found(); +// test_ft_memrchr_binary(); +// return (0); +// } diff --git a/minishell/libft/memory/ft_memset.c b/minishell/libft/memory/ft_memset.c new file mode 100644 index 0000000..91c67dc --- /dev/null +++ b/minishell/libft/memory/ft_memset.c @@ -0,0 +1,40 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_memset.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/24 22:36:41 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 21:59:35 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +/* Undefined if s == NULL && n > 0. */ +void *ft_memset(void *s, int c, size_t n) +{ + unsigned char *uc_dst; + + if (!n) + return (s); + uc_dst = (unsigned char *)s; + while (n--) + *uc_dst++ = (unsigned char)c; + return (s); +} + +// #include +// #include + +// int main(int argc, char const *argv[]) +// { +// char str[50] = "Hello World 42 Tokyo!"; +// printf("First string:%s\n", str); + +// ft_memset(str + 2, '-', 2); +// memset(str + 4, '*', 2); +// printf("%s\n", str); +// return (0); +// } diff --git a/minishell/libft/original/ft_isspace.c b/minishell/libft/original/ft_isspace.c new file mode 100644 index 0000000..cb27822 --- /dev/null +++ b/minishell/libft/original/ft_isspace.c @@ -0,0 +1,18 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_isspace.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/05/11 18:12:36 by kjikuhar #+# #+# */ +/* Updated: 2025/05/11 18:14:44 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_isspace(const char c) +{ + return ((9 <= c && c <= 13) || c == 32); +} diff --git a/minishell/libft/original/ft_max.c b/minishell/libft/original/ft_max.c new file mode 100644 index 0000000..23a5f46 --- /dev/null +++ b/minishell/libft/original/ft_max.c @@ -0,0 +1,55 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_max.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/05/11 18:09:27 by kjikuhar #+# #+# */ +/* Updated: 2025/05/18 19:32:11 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_max_int(int a, int b, int *m) +{ + if (a <= b) + *m = b; + else + *m = a; + return (*m); +} + +long ft_max_long(long a, long b) +{ + if (a <= b) + return (b); + else + return (a); +} + +long long ft_max_long_long(long long a, long long b) +{ + if (a <= b) + return (b); + else + return (a); +} + +size_t ft_max_size_t(size_t a, size_t b) +{ + if (a <= b) + return (b); + else + return (a); +} + +// #include + +// int main(void) +// { +// int tabs[] = {0, 1, 2, 3, 4, 5}; + +// printf("%d\n", ft_max_int(tabs[3], tabs[1])); +// } diff --git a/minishell/libft/original/ft_min.c b/minishell/libft/original/ft_min.c new file mode 100644 index 0000000..443948d --- /dev/null +++ b/minishell/libft/original/ft_min.c @@ -0,0 +1,54 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_min.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/05/11 18:05:03 by kjikuhar #+# #+# */ +/* Updated: 2025/05/11 18:09:12 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_min_int(int a, int b) +{ + if (a >= b) + return (b); + else + return (a); +} + +long ft_min_long(long a, long b) +{ + if (a >= b) + return (b); + else + return (a); +} + +long long ft_min_long_long(long long a, long long b) +{ + if (a >= b) + return (b); + else + return (a); +} + +size_t ft_min_size_t(size_t a, size_t b) +{ + if (a >= b) + return (b); + else + return (a); +} + +// #include + +// int main(void) +// { +// int tabs[] = {0, 1, 2, 3, 4, 5}; + +// printf("%d\n", ft_min_int(tabs[3], tabs[1])); +// } diff --git a/minishell/libft/original/ft_swap.c b/minishell/libft/original/ft_swap.c new file mode 100644 index 0000000..8e5794d --- /dev/null +++ b/minishell/libft/original/ft_swap.c @@ -0,0 +1,33 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_swap.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/05/07 20:23:04 by kjikuhar #+# #+# */ +/* Updated: 2025/05/07 20:26:44 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_swap(int *a, int *b) +{ + int tmp; + + tmp = *a; + *a = *b; + *b = tmp; +} + +// int main(void) +// { +// int a = 42; +// int b = 24; + +// printf("Before: a = %2d, b = %2d\n", a, b); +// ft_swap(&a, &b); +// printf("After : a = %2d, b = %2d\n", a, b); +// return (0); +// } diff --git a/minishell/libft/output/ft_putchar_fd.c b/minishell/libft/output/ft_putchar_fd.c new file mode 100644 index 0000000..25ed686 --- /dev/null +++ b/minishell/libft/output/ft_putchar_fd.c @@ -0,0 +1,79 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_putchar_fd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/26 14:16:34 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 22:00:41 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_putchar_fd(char c, int fd) +{ + write(fd, &c, 1); +} +// #include "libft.h" +// #include // for open() +// #include // for printf() +// #include // for close(), read() + +// int main(void) +// { +// int fd; +// char buffer[10]; +// int bytes_read; + +// // Test Case 1: Output character to standard output +// printf("Test Case 1: Output character 'A' to standard output: "); +// ft_putchar_fd('A', 1); +// printf("\n"); +// // Test Case 2: Output character to standard error +// fprintf(stderr, "Test Case 2: Output character 'B' to standard error: "); +// ft_putchar_fd('B', 2); +// fprintf(stderr, "\n"); +// // Test Case 3: Output character to a file +// printf("Test Case 3: Output character 'C' to a file\n"); +// fd = open("test_putchar.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); +// if (fd == -1) +// { +// printf("Error: Could not open file\n"); +// return (1); +// } +// ft_putchar_fd('C', fd); +// close(fd); +// // Open the file and check its contents +// fd = open("test_putchar.txt", O_RDONLY); +// if (fd == -1) +// { +// printf("Error: Could not read file\n"); +// return (1); +// } +// bytes_read = read(fd, buffer, sizeof(buffer) - 1); +// buffer[bytes_read] = '\0'; +// printf("File contents: %s\n", buffer); +// close(fd); +// // Test Case 4: Output multiple characters to a file consecutively +// printf("Test Case 4: Consecutive output of multiple characters\n"); +// fd = open("test_multiple.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); +// if (fd != -1) +// { +// ft_putchar_fd('4', fd); +// ft_putchar_fd('2', fd); +// ft_putchar_fd('T', fd); +// ft_putchar_fd('o', fd); +// ft_putchar_fd('k', fd); +// ft_putchar_fd('y', fd); +// ft_putchar_fd('o', fd); +// close(fd); +// fd = open("test_multiple.txt", O_RDONLY); +// bytes_read = read(fd, buffer, sizeof(buffer) - 1); +// buffer[bytes_read] = '\0'; +// printf("Result of consecutive output: %s\n", buffer); +// close(fd); +// } +// return (0); +// } diff --git a/minishell/libft/output/ft_putendl_fd.c b/minishell/libft/output/ft_putendl_fd.c new file mode 100644 index 0000000..2cdb0d8 --- /dev/null +++ b/minishell/libft/output/ft_putendl_fd.c @@ -0,0 +1,98 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_putendl_fd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/26 14:29:52 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 22:01:16 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_putendl_fd(char *s, int fd) +{ + if (!s) + return ; + ft_putstr_fd(s, fd); + write(fd, "\n", 1); + return ; +} +// #include "libft.h" +// #include // for open() +// #include // for printf() +// #include // for close(), read() + +// int main(void) +// { +// int fd; +// char buffer[100]; +// int bytes_read; + +// // Test Case 1: Output string with newline to standard output +// printf("Test Case 1: Output string with newline to standard output:\n"); +// ft_putendl_fd("Hello, World!", 1); +// printf("↑ 'Hello, World!' with a newline should appear above\n"); +// // Test Case 2: Output string with newline to standard error +// fprintf(stderr, +// "Test Case 2: Output string with newline to standard error:\n"); +// ft_putendl_fd("Error message", 2); +// fprintf(stderr, "↑ 'Error message' with a newline should appear above\n"); +// // Test Case 3: Output string with newline to a file +// printf("Test Case 3: Output string with newline to a file\n"); +// fd = open("test_putendl.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); +// if (fd == -1) +// { +// printf("Error: Could not open file\n"); +// return (1); +// } +// ft_putendl_fd("42Tokyo", fd); +// close(fd); +// // Open the file and check its contents +// fd = open("test_putendl.txt", O_RDONLY); +// if (fd == -1) +// { +// printf("Error: Could not read file\n"); +// return (1); +// } +// bytes_read = read(fd, buffer, sizeof(buffer) - 1); +// buffer[bytes_read] = '\0'; +// printf("File contents: "); +// for (int i = 0; i < bytes_read; i++) +// { +// if (buffer[i] == '\n') +// printf("\\n"); +// else +// printf("%c", buffer[i]); +// } +// printf("\n"); +// close(fd); +// // Test Case 4: Empty string +// printf("Test Case 4: Output an empty string (only newline)\n"); +// fd = open("test_empty_endl.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); +// if (fd != -1) +// { +// ft_putendl_fd("", fd); +// close(fd); +// fd = open("test_empty_endl.txt", O_RDONLY); +// bytes_read = read(fd, buffer, sizeof(buffer) - 1); +// buffer[bytes_read] = '\0'; +// printf("Result of empty string (only newline): "); +// for (int i = 0; i < bytes_read; i++) +// { +// if (buffer[i] == '\n') +// printf("\\n"); +// else +// printf("%c", buffer[i]); +// } +// printf("\n"); +// close(fd); +// } +// // Test Case 5: NULL pointer +// printf("Test Case 5: NULL pointer (confirming no crash)\n"); +// ft_putendl_fd(NULL, 1); +// printf("NULL test complete\n"); +// return (0); +// } diff --git a/minishell/libft/output/ft_putnbr_fd.c b/minishell/libft/output/ft_putnbr_fd.c new file mode 100644 index 0000000..eaf53ae --- /dev/null +++ b/minishell/libft/output/ft_putnbr_fd.c @@ -0,0 +1,155 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_putnbr_fd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/26 14:33:56 by kjikuhar #+# #+# */ +/* Updated: 2025/05/05 18:12:05 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_putnbr_fd(int n, int fd) +{ + if (n == -2147483648) + return (write(fd, "-2147483648", 11), (void)0); + if (n < 0) + { + write(fd, "-", 1); + n *= -1; + } + if (n > 9) + ft_putnbr_fd(n / 10, fd); + write(fd, &(char){n % 10 + '0'}, 1); +} + +// int main(void) +// { +// int number_set[] = {0, 42, -42, 123, 2147483647, -2147483648}; +// int fd = 1; +// for (int i = 0; i < 10; i++) +// { +// ft_putnbr_fd(number_set[i], fd); +// write(fd, "\n", 1); +// } +// return (0); +// } + +// /* == tester == */ +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include + +// void ft_putnbr_fd(int n, int fd); + +// static void test_ft_putnbr_fd_basic(void) +// { +// int fd; +// char buf[256] = {0}; + +// fd = open("test_output.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); +// assert(fd != -1); +// ft_putnbr_fd(2, fd); +// write(fd, "\n", 1); +// ft_putnbr_fd(42, fd); +// write(fd, "\n", 1); +// ft_putnbr_fd(-42, fd); +// write(fd, "\n", 1); +// ft_putnbr_fd(2147483647, fd); +// write(fd, "\n", 1); +// ft_putnbr_fd(-2147483648, fd); +// write(fd, "\n", 1); +// close(fd); +// fd = open("test_output.txt", O_RDONLY); +// assert(fd != -1); +// read(fd, buf, sizeof(buf) - 1); +// close(fd); +// assert(!strcmp(buf, "2\n42\n-42\n2147483647\n-2147483648\n")); +// printf("Basic tests passed.\n"); +// } + +// static void test_ft_putnbr_fd_invalid_fd(void) +// { +// errno = 0; +// ft_putnbr_fd(123, -1); +// assert(errno != 0); +// printf("Invalid fd test passed.\n"); +// } + +// static void test_ft_putnbr_fd_stderr(void) +// { +// ft_putnbr_fd(42, 2); // should print to stderr +// printf("Stderr test ran (check manually).\n"); +// } + +// static int check_output_file(int n) +// { +// char expected[32]; +// char buf[64] = {0}; +// int fd; +// char *newline; + +// snprintf(expected, sizeof(expected), "%d", n); +// fd = open("test_output.txt", O_RDONLY); +// if (fd == -1) +// return (0); +// read(fd, buf, sizeof(buf) - 1); +// close(fd); +// // remove trailing newline if any +// newline = strchr(buf, '\n'); +// if (newline) +// *newline = '\0'; +// return (strcmp(buf, expected) == 0); +// } + +// static void test_ft_putnbr_fd_random(void) +// { +// int success_count; +// int n; +// int fd; + +// srand((unsigned int)time(NULL)); +// success_count = 0; +// for (int i = 1; i <= 200; i++) +// { +// n = (rand() % (INT_MAX)) - (rand() % (INT_MAX)); +// fd = open("test_output.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); +// if (fd == -1) +// { +// perror("open"); +// continue ; +// } +// ft_putnbr_fd(n, fd); +// write(fd, "\n", 1); +// close(fd); +// if (check_output_file(n)) +// { +// printf("%3d : %11d : Good\n", i, n); +// success_count++; +// } +// else +// { +// printf("%3d : %11d : NG\n", i, n); +// } +// } +// unlink("test_output.txt"); +// printf("Random tests passed %d / 200.\n", success_count); +// } + +// int main(void) +// { +// test_ft_putnbr_fd_basic(); +// test_ft_putnbr_fd_invalid_fd(); +// test_ft_putnbr_fd_stderr(); +// test_ft_putnbr_fd_random(); +// return (0); +// } diff --git a/minishell/libft/output/ft_putstr_fd.c b/minishell/libft/output/ft_putstr_fd.c new file mode 100644 index 0000000..ce0b271 --- /dev/null +++ b/minishell/libft/output/ft_putstr_fd.c @@ -0,0 +1,81 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_putstr_fd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/26 14:23:51 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 22:02:10 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_putstr_fd(char *s, int fd) +{ + if (!s) + return ; + write(fd, s, ft_strlen(s)); + return ; +} + +// #include "libft.h" +// #include // for open() +// #include // for printf() +// #include // for close(), read() + +// int main(void) +// { +// int fd; +// char buffer[100]; +// int bytes_read; + +// // Test Case 1: Output string to standard output +// printf("Test Case 1: Output string to standard output: "); +// ft_putstr_fd("Hello, World!", 1); +// printf("\n"); +// // Test Case 2: Output string to standard error +// fprintf(stderr, "Test Case 2: Output string to standard error: "); +// ft_putstr_fd("Error message", 2); +// fprintf(stderr, "\n"); +// // Test Case 3: Output string to a file +// printf("Test Case 3: Output string to a file\n"); +// fd = open("test_putstr.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); +// if (fd == -1) +// { +// printf("Error: Could not open file\n"); +// return (1); +// } +// ft_putstr_fd("42Tokyo", fd); +// close(fd); +// // Open the file and check its contents +// fd = open("test_putstr.txt", O_RDONLY); +// if (fd == -1) +// { +// printf("Error: Could not read file\n"); +// return (1); +// } +// bytes_read = read(fd, buffer, sizeof(buffer) - 1); +// buffer[bytes_read] = '\0'; +// printf("File contents: %s\n", buffer); +// close(fd); +// // Test Case 4: Empty string +// printf("Test Case 4: Output empty string\n"); +// fd = open("test_empty.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); +// if (fd != -1) +// { +// ft_putstr_fd("", fd); +// close(fd); +// fd = open("test_empty.txt", O_RDONLY); +// bytes_read = read(fd, buffer, sizeof(buffer) - 1); +// buffer[bytes_read] = '\0'; +// printf("Result of empty string: \"%s\"\n", buffer); +// close(fd); +// } +// // Test Case 5: NULL pointer +// printf("Test Case 5: NULL pointer (check no crash occurs)\n"); +// ft_putstr_fd(NULL, 1); +// printf("NULL test complete\n"); +// return (0); +// } diff --git a/minishell/libft/string/ft_split.c b/minishell/libft/string/ft_split.c new file mode 100644 index 0000000..63ac92d --- /dev/null +++ b/minishell/libft/string/ft_split.c @@ -0,0 +1,130 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_split.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/01 21:07:26 by kjikuhar #+# #+# */ +/* Updated: 2025/05/05 13:14:10 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +static int ft_strlen_for_split_(char const *target_str, char delimiter) +{ + int i; + + i = 0; + while (target_str[i] != delimiter && target_str[i]) + i++; + return (i); +} + +static int count_words_(char const *target_str, char delimiter) +{ + int in_word_flag; + int count; + + in_word_flag = 0; + count = 0; + while (*target_str) + { + if (in_word_flag == 0) + { + if (*target_str == delimiter) + in_word_flag = 0; + else + { + in_word_flag = 1; + count++; + } + } + else if (in_word_flag == 1) + { + if (*target_str == delimiter) + in_word_flag = 0; + } + target_str++; + } + return (count); +} + +static char *ft_strdup_for_split(char const **src, char delimiter) +{ + char *dest; + int i; + + i = 0; + dest = malloc(ft_strlen_for_split_(*src, delimiter) + 1); + if (!dest) + return (NULL); + while (**src && **src != delimiter) + { + dest[i] = **src; + i++; + (*src)++; + } + dest[i] = '\0'; + return (dest); +} + +/* Helper function to free allocated strings in case of error */ +static void free_split_result(char **arr) +{ + char **temp; + + if (!arr) + return ; + temp = arr; + while (*temp) + { + free(*temp); + temp++; + } + free(arr); +} + +char **ft_split(char const *s, char c) +{ + char **splitted; + char **p; + + splitted = malloc(sizeof(char *) * (count_words_(s, c) + 1)); + if (!splitted) + return (NULL); + p = splitted; + while (*s) + { + while (*s == c) + s++; + if (!*s) + break ; + *splitted = ft_strdup_for_split(&s, c); + if (!*splitted) + return (free_split_result(p), NULL); + splitted++; + } + *splitted = NULL; + return (p); +} +// #include + +// int main(void) +// { +// char *target_str = "//Hello/World /42/ Tok/yo!.../.."; +// char delimiter = '/'; +// int n = count_words_(target_str, delimiter); +// char **strs = ft_split(target_str, delimiter); + +// printf("%d\n", n); +// printf("%d\n", ft_strlen_for_split_(target_str, delimiter)); +// for (int i = 0; i <= n; i++) +// { +// printf("[%d] : %s\n", i, strs[i]); +// free(strs[i]); +// } +// free(strs); +// return (0); +// } diff --git a/minishell/libft/string/ft_strchr.c b/minishell/libft/string/ft_strchr.c new file mode 100644 index 0000000..5677a18 --- /dev/null +++ b/minishell/libft/string/ft_strchr.c @@ -0,0 +1,77 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strchr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/25 21:03:19 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 22:50:08 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +/* Locate first occurrence of character in string */ +char *ft_strchr(const char *s, int c) +{ + unsigned char uc; + + uc = (unsigned char)c; + while (*s) + { + if (*s == uc) + return ((char *)s); + s++; + } + if (uc == 0) + return ((char *)s); + return (NULL); +} + +// #include "libft.h" +// #include +// #include + +// void test_strchr(const char *s, int c, const char *test_name) +// { +// char *ft_result; +// char *std_result; + +// ft_result = ft_strchr(s, c); +// std_result = strchr(s, c); +// printf("Test: %s\n", test_name); +// printf("Search string: \"%s\", Search character: '%c' (ASCII: %d)\n", s, +// c >= 32 && c <= 126 ? c : ' ', c); +// if (ft_result == NULL && std_result == NULL) +// printf("Result: Both NULL (match)\n"); +// else if (ft_result != NULL && std_result != NULL) +// printf("Result: ft_strchr = %p, strchr = %p (Match: %s)\n", +// (void *)ft_result, (void *)std_result, +// ft_result == std_result ? "Yes" : "No"); +// else +// printf("Result: ft_strchr = %p, strchr = %p (Mismatch!)\n", +// (void *)ft_result, (void *)std_result); +// printf("\n"); +// } + +// int main(void) +// { +// // Test Case 1: Normal character search +// test_strchr("Hello, world!", 'w', "Normal character search"); +// // Test Case 2: First character of the string +// test_strchr("Hello, world!", 'H', "First character of the string"); +// // Test Case 3: Last character of the string +// test_strchr("Hello, world!", '!', "Last character of the string"); +// // Test Case 4: Character not present in the string +// test_strchr("Hello, world!", 'z', "Character not present"); +// // Test Case 5: NULL terminator search +// test_strchr("Hello, world!", '\0', "NULL terminator search"); +// // Test Case 6: Character appearing multiple times +// test_strchr("Hello, world!", 'l', "Character appearing multiple times"); +// // Test Case 7: Search in an empty string +// test_strchr("", 'a', "Search in an empty string"); +// // Test Case 8: Search for NULL character in an empty string +// test_strchr("", '\0', "Search for NULL character in an empty string"); +// return (0); +// } diff --git a/minishell/libft/string/ft_strdup.c b/minishell/libft/string/ft_strdup.c new file mode 100644 index 0000000..36fec73 --- /dev/null +++ b/minishell/libft/string/ft_strdup.c @@ -0,0 +1,47 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strdup.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/03/27 05:14:00 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 11:36:10 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_strdup(const char *s) +{ + char *tmp ; + char *p; + + tmp = (char *)malloc(sizeof(s[0]) * (ft_strlen(s) + 1)); + if (tmp == NULL) + return (NULL); + p = tmp; + while (*s) + { + *tmp = *s; + s++; + tmp++; + } + *tmp = '\0'; + return (p); +} + +// #include +// #include + +// int main(void) +// { +// char *c; +// char *d; + +// c = "1234567890"; +// d = ft_strdup(c); +// printf("%s", ft_strdup(c)); +// free(d); +// return (0); +// } diff --git a/minishell/libft/string/ft_striteri.c b/minishell/libft/string/ft_striteri.c new file mode 100644 index 0000000..8c999e7 --- /dev/null +++ b/minishell/libft/string/ft_striteri.c @@ -0,0 +1,80 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_striteri.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/26 14:04:33 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 22:04:53 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +void ft_striteri(char *s, void (*f)(unsigned int, char *)) +{ + unsigned int index; + + if (!s || !f) + return ; + index = 0; + while (s[index]) + { + f(index, &s[index]); + index++; + } +} +// #include "libft.h" +// #include +// #include + +// // Function to convert all lowercase letters to uppercase +// void convert_to_upper(unsigned int i, char *c) +// { +// (void)i; // Index is not used +// if (*c >= 'a' && *c <= 'z') +// *c = *c - 'a' + 'A'; +// } + +// // Function to convert only even-indexed characters to uppercase +// void convert_even_index_to_upper(unsigned int i, char *c) +// { +// if (i % 2 == 0 && *c >= 'a' && *c <= 'z') +// *c = *c - 'a' + 'A'; +// } + +// // Function to print each character with its index (for debugging) +// void print_with_index(unsigned int i, char *c) +// { +// printf("[%u]:%c ", i, *c); +// } + +// int main(void) +// { +// char str1[] = "hello world"; +// char str2[] = "abcdefghij"; +// char str3[] = "42tokyo"; +// char str4[] = ""; + +// // Test Case 1: Normal string +// printf("Original string: %s\n", str1); +// ft_striteri(str1, convert_to_upper); +// printf("After converting to uppercase: %s\n", str1); +// // Test Case 2: Using another conversion function +// printf("\nOriginal string: %s\n", str2); +// ft_striteri(str2, convert_even_index_to_upper); +// printf("After converting only even indices to uppercase: %s\n", str2); +// // Test Case 3: Debugging function +// printf("\nOriginal string: %s\n", str3); +// printf("Each character with its index: "); +// ft_striteri(str3, print_with_index); +// printf("\n"); +// // Test Case 4: Empty string +// printf("\nEmpty string test: "); +// ft_striteri(str4, convert_to_upper); +// printf("Result: \"%s\"\n", str4); +// // Test Case 5: NULL pointer and function (should handle gracefully) +// printf("\nNULL pointer test (nothing should happen)\n"); +// ft_striteri(NULL, convert_to_upper); +// ft_striteri(str1, NULL); +// return (0); +// } diff --git a/minishell/libft/string/ft_strjoin.c b/minishell/libft/string/ft_strjoin.c new file mode 100644 index 0000000..58a18dd --- /dev/null +++ b/minishell/libft/string/ft_strjoin.c @@ -0,0 +1,131 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strjoin.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/03/28 20:47:54 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 22:05:33 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +static char *ft_strcat(char *dest, const char *src) +{ + size_t i; + size_t j; + + i = 0; + while (dest[i]) + i++; + j = 0; + while (src[j]) + { + dest[j + i] = src[j]; + j++; + } + dest[j + i] = '\0'; + return (dest); +} + +static char *ft_strcpy(char *dest, const char *src) +{ + size_t i; + + i = 0; + while (src[i]) + { + dest[i] = src[i]; + i++; + } + dest[i] = '\0'; + return (dest); +} + +char *ft_strjoin(char const *s1, char const *s2) +{ + char *dest; + size_t sum_len; + + if (!s1 || !s2) + return (NULL); + sum_len = ft_strlen(s1) + ft_strlen(s2); + dest = malloc(sizeof(char) * (sum_len + 1)); + if (!dest) + return (NULL); + ft_strcpy(dest, s1); + ft_strcat(dest, s2); + return (dest); +} + +// #include "libft.h" +// #include +// #include +// #include + +// void test_strjoin(char const *s1, char const *s2, const char *test_name) +// { +// char *result; +// char *expected; + +// result = ft_strjoin(s1, s2); +// expected = NULL; +// printf("Test: %s\n", test_name); +// printf("String 1: \"%s\"\n", s1 ? s1 : "(null)"); +// printf("String 2: \"%s\"\n", s2 ? s2 : "(null)"); +// printf("Result: \"%s\"\n", result ? result : "(null)"); +// if (s1 && s2) +// { +// expected = malloc(strlen(s1) + strlen(s2) + 1); +// if (expected) +// { +// strcpy(expected, s1); +// strcat(expected, s2); +// printf("Expected: \"%s\"\n", expected); +// printf("Match: %s\n", (result && strcmp(result, +// expected) == 0) ? "Yes" : "No"); +// free(expected); +// } +// } +// else +// { +// printf("Expected: NULL\n"); +// printf("Match: %s\n", (!result) ? "Yes" : "No"); +// } +// printf("\n"); +// if (result) +// free(result); +// } + +// int main(void) +// { +// char long_str1[500], long_str2[500]; + +// // 1. Basic string concatenation +// test_strjoin("Hello, ", "world!", "Basic string concatenation"); +// // 2. Concatenation with empty string +// test_strjoin("", "Test", "Concatenation with empty and normal string"); +// // 3. Both strings empty +// test_strjoin("", "", "Both strings empty"); +// // 4. Concatenation including special characters (newline) +// test_strjoin("Hello\n", "World", "Concatenation including newline"); +// // 5. Concatenation including tab character +// test_strjoin("Hello\t", "World", "Concatenation including tab"); +// // 6. Concatenation of long strings +// memset(long_str1, 'A', 499); +// long_str1[499] = '\0'; +// memset(long_str2, 'B', 499); +// long_str2[499] = '\0'; +// test_strjoin(long_str1, long_str2, "Concatenation of long strings"); +// // 7. Concatenation of Japanese (multibyte) strings +// test_strjoin("こんにちは", "世界", "Concatenation of Japanese strings"); +// // 8. Concatenation of numbers and symbols +// test_strjoin("12345", "!@#$%", "Concatenation of numbers and symbols"); +// // 9. Handling NULL pointer in s1 +// test_strjoin(NULL, "Test", "Handling NULL for s1"); +// // 10. Handling both NULL +// test_strjoin(NULL, NULL, "Handling both NULL"); +// return (0); +// } diff --git a/minishell/libft/string/ft_strlcat.c b/minishell/libft/string/ft_strlcat.c new file mode 100644 index 0000000..073e5c7 --- /dev/null +++ b/minishell/libft/string/ft_strlcat.c @@ -0,0 +1,59 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strlcat.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/03/18 11:41:28 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 11:54:38 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +static size_t ft_strnlen(const char *str, size_t n) +{ + size_t i; + + i = 0; + while (str[i] && i < n) + i++; + return (i); +} + +size_t ft_strlcat(char *dst, const char *src, size_t size) +{ + size_t i; + size_t dst_length; + size_t src_length; + + dst_length = ft_strnlen(dst, size); + src_length = ft_strlen(src); + i = 0; + if (dst_length >= size) + return (dst_length + src_length); + while (src[i] && dst_length + i + 1 < size) + { + dst[dst_length + i] = src[i]; + i++; + } + dst[dst_length + i] = '\0'; + return (dst_length + src_length); +} + +// #include +// #include + +// int main(void) +// { +// char dest[200] = "12345"; +// char src[200] = "1234567890"; +// size_t result; + +// printf("%zu\n", ft_strnlen(dest, 3)); +// result = ft_strlcat(dest, src, 3); +// printf("dest = %s\n", dest); +// printf("result = %zu\n", result); +// return (0); +// } diff --git a/minishell/libft/string/ft_strlcpy.c b/minishell/libft/string/ft_strlcpy.c new file mode 100644 index 0000000..813e864 --- /dev/null +++ b/minishell/libft/string/ft_strlcpy.c @@ -0,0 +1,50 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strlcpy.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/03/19 20:28:11 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 22:56:27 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +size_t ft_strlcpy(char *dst, const char *src, size_t size) +{ + size_t i; + size_t src_len; + + if (!dst || !src) + return (0); + src_len = ft_strlen(src); + if (size == 0) + return (src_len); + i = 0; + while (src[i] && i + 1 < size) + { + dst[i] = src[i]; + i++; + } + dst[i] = '\0'; + return (src_len); +} + +// #include + +// #include + +// int main(void) +// { +// char str1[8] = "Tokyo"; +// char strs[10][20] = {"Hello","World1234567890", "42", "Tokyo", "24", +// "Kyoto"}; + +// printf("%i\n", ft_strlcpy(str1, strs[1], 0)); +// printf("%s\n", str1); +// printf("%i\n", str_len(strs[1])); + +// return (0); +// } diff --git a/minishell/libft/string/ft_strlen.c b/minishell/libft/string/ft_strlen.c new file mode 100644 index 0000000..778a382 --- /dev/null +++ b/minishell/libft/string/ft_strlen.c @@ -0,0 +1,38 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strlen.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/24 22:06:53 by kjikuhar #+# #+# */ +/* Updated: 2025/05/16 20:20:20 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +size_t ft_strlen(const char *s) +{ + size_t length; + + if (!s) + return (0); + length = 0; + while (s[length]) + length++; + return (length); +} + +// #include + +// int main(void) +// { +// char *strs[] = {"Hello World 42 Tokyo!", "1234567890", +// "abcdefghijklmnopqrstuvwxyz"}; +// for (int i = 0; i < sizeof(strs) / sizeof(strs[0]); i++) +// { +// printf("%10s : %zu\n", strs[i], ft_strlen((const char *)strs[i])); +// } +// return (0); +// } diff --git a/minishell/libft/string/ft_strmapi.c b/minishell/libft/string/ft_strmapi.c new file mode 100644 index 0000000..3bfc2cf --- /dev/null +++ b/minishell/libft/string/ft_strmapi.c @@ -0,0 +1,56 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strmapi.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/26 12:57:28 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 11:36:10 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_strmapi(char const *s, char (*f)(unsigned int, char)) +{ + unsigned int index; + size_t s_length; + char *rtv_str; + + if (!s || !f) + return (NULL); + index = 0; + s_length = ft_strlen(s); + rtv_str = malloc(sizeof(char) * (s_length + 1)); + if (!rtv_str) + return (NULL); + while (s[index]) + { + rtv_str[index] = (*f)(index, s[index]); + index++; + } + rtv_str[index] = '\0'; + return (rtv_str); +} + +// #include + +// char convert_to_upper(unsigned int index, char c) +// { +// (void)index; +// if ('a' <= c && c <= 'z') +// return (c - 'a' + 'A'); +// return (c); +// } + +// int main(void) +// { +// char *str = "42Tokyo"; +// printf("%zu\n", ft_strlen_(str)); + +// char *convert_str = ft_strmapi(str, convert_to_upper); +// printf("%s\n", convert_str); +// free(convert_str); +// return (0); +// } diff --git a/minishell/libft/string/ft_strncmp.c b/minishell/libft/string/ft_strncmp.c new file mode 100644 index 0000000..88fb5f9 --- /dev/null +++ b/minishell/libft/string/ft_strncmp.c @@ -0,0 +1,43 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strncmp.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/24 22:22:54 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 22:17:52 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +/* Compare two strings up to n characters */ +int ft_strncmp(const char *s1, const char *s2, size_t n) +{ + size_t i; + + i = 0; + while (i < n && (s1[i] || s2[i])) + { + if (s1[i] != s2[i]) + return ((unsigned char)s1[i] - (unsigned char)s2[i]); + i++; + } + return (0); +} + +// #include + +// int main(void) +// { +// char *str[] = {"Hello World 42 Tokyo!", "0123456789", +// "abcdefghijklmnopqrstuvwxyz", "01234556789"}; +// printf("%i\n", ft_strncmp((const char *)str[1], (const char *)str[3], 7)); +// printf("%i\n", ft_strncmp((const char *)str[1], (const char *)str[3], 7)); +// printf("%i\n", ft_strncmp((const char *)str[1], (const char *)str[3], 7)); +// printf("%i\n", ft_strncmp((const char *)str[1], (const char *)str[3], 7)); +// printf("%i\n", ft_strncmp((const char *)str[1], (const char *)str[3], 7)); + +// return (0); +// } diff --git a/minishell/libft/string/ft_strnstr.c b/minishell/libft/string/ft_strnstr.c new file mode 100644 index 0000000..fecd98b --- /dev/null +++ b/minishell/libft/string/ft_strnstr.c @@ -0,0 +1,95 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strnstr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/25 21:07:45 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 22:54:06 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +/* Locate substring in a string with length limit */ +char *ft_strnstr(const char *big, const char *little, size_t len) +{ + size_t i; + size_t j; + size_t little_len; + + if (!little || !big) + return (NULL); + little_len = ft_strlen(little); + if (little_len == 0) + return ((char *)big); + if (len == 0 || little_len > len) + return (NULL); + i = 0; + while (big[i] && i < len) + { + j = 0; + while (i + j < len && little[j] && big[i + j] == little[j]) + j++; + if (little[j] == '\0') + return ((char *)&big[i]); + i++; + } + return (NULL); +} + +// #include "libft.h" +// #include +// #include +// #include + +// // Function to display test results +// void test_strnstr(const char *big, const char *little, size_t len, +// const char *test_name) +// { +// char *ft_result; +// char *org_result; + +// ft_result = ft_strnstr(big, little, len); +// org_result = strnstr(big, little, len); +// printf("Test: %s\n", test_name); +// printf("Target string: \"%s\"\n", big); +// printf("Search string: \"%s\"\n", little); +// printf("Search length: %zu\n", len); +// // Display result pointer as string, or "(null)" if NULL +// printf("ft_strnstr result: %s\n", ft_result ? ft_result : "(null)"); +// printf("strnstr result: %s\n", org_result ? org_result : "(null)"); +// printf("Pointer match: %s\n\n", (ft_result == org_result) ? "Yes" : "No"); +// } + +// int main(void) +// { +// char str_with_null[] = "Hello\0world"; +// unsigned char binary[] = {0x10, 0x20, 0x30, 0x40, 0x50}; +// unsigned char pattern[] = {0x30, 0x40}; + +// // Test case 1: Basic search +// test_strnstr("Hello, world!", "world", 13, "Basic search"); +// // Test case 2: Partial search (within limit) +// test_strnstr("Hello, world!", "world", 13, "Partial search within limit"); +// // Test case 3: Partial search (outside limit) +// test_strnstr("Hello, world!", "world", 8, "Partial search outside limit"); +// // Test case 4: Match at beginning +// test_strnstr("Hello, world!", "Hello", 13, "Match at beginning"); +// // Test case 5: Match at end +// test_strnstr("Hello, world!", "ld!", 13, "Match at end"); +// // Test case 6: Non-existent string +// test_strnstr("Hello, world!", "xyz", 13, "Non-existent string"); +// // Test case 7: Empty search string +// test_strnstr("Hello, world!", "", 13, "Empty search string"); +// // Test case 8: Search after NULL character +// test_strnstr(str_with_null, "world", 11, "Search after NULL character"); +// // Test case 9: Binary data +// test_strnstr((char *)binary, (char *)pattern, 5, "Binary data"); +// // Test case 10: Search with length 0 +// test_strnstr("Hello, world!", "Hello", 0, "Search with length 0"); +// // Test case 11: Duplicate pattern +// test_strnstr("abababab", "abab", 8, "Duplicate pattern"); +// return (0); +// } diff --git a/minishell/libft/string/ft_strrchr.c b/minishell/libft/string/ft_strrchr.c new file mode 100644 index 0000000..0e26db5 --- /dev/null +++ b/minishell/libft/string/ft_strrchr.c @@ -0,0 +1,65 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strrchr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/25 21:03:19 by kjikuhar #+# #+# */ +/* Updated: 2025/05/05 18:16:21 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +/* Why: +1 so that '\0' is also searched per strrchr spec */ +char *ft_strrchr(const char *s, int c) +{ + return (ft_memrchr(s, c, ft_strlen(s) + 1)); +} +// #include "libft.h" +// #include +// #include + +// void test_strrchr(const char *s, int c, const char *test_name) +// { +// char *ft_result; +// char *std_result; + +// ft_result = ft_strrchr(s, c); +// std_result = strrchr(s, c); +// printf("Test: %s\n", test_name); +// printf("Search string: \"%s\", Search character: '%c' (ASCII: %d)\n", s, +// c >= 32 && c <= 126 ? c : ' ', c); +// if (ft_result == NULL && std_result == NULL) +// printf("Result: Both NULL (match)\n"); +// else if (ft_result != NULL && std_result != NULL) +// printf("Result: ft_strrchr = %p, strrchr = %p (Match: %s)\n", +// (void *)ft_result, (void *)std_result, +// ft_result == std_result ? "Yes" : "No"); +// else +// printf("Result: ft_strrchr = %p, strrchr = %p (Mismatch!)\n", +// (void *)ft_result, (void *)std_result); +// printf("\n"); +// } + +// int main(void) +// { +// // Test Case 1: Normal character search +// test_strrchr("Hello, world!", 'w', "Normal character search"); +// // Test Case 2: First character of the string +// test_strrchr("Hello, world!", 'H', "First character of the string"); +// // Test Case 3: Last character of the string +// test_strrchr("Hello, world!", '!', "Last character of the string"); +// // Test Case 4: Character not present in the string +// test_strrchr("Hello, world!", 'z', "Character not present"); +// // Test Case 5: NULL terminator search +// test_strrchr("Hello, world!", '\0', "NULL terminator search"); +// // Test Case 6: Character appearing multiple times +// test_strrchr("Hello, world!", 'l', "Character appearing multiple times"); +// // Test Case 7: Search in an empty string +// test_strrchr("", 'a', "Search in an empty string"); +// // Test Case 8: Search for NULL character in an empty string +// test_strrchr("", '\0', "Search for NULL character in an empty string"); +// return (0); +// } diff --git a/minishell/libft/string/ft_strtrim.c b/minishell/libft/string/ft_strtrim.c new file mode 100644 index 0000000..759c8fd --- /dev/null +++ b/minishell/libft/string/ft_strtrim.c @@ -0,0 +1,133 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strtrim.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/25 22:58:35 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 22:07:09 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +static size_t get_trimmed_length(char const *s1, char const *set) +{ + size_t start; + size_t end; + + start = 0; + end = ft_strlen(s1); + while (s1[start] && ft_strchr(set, (unsigned char)s1[start])) + start++; + while (end > start && ft_strchr(set, (unsigned char)s1[end - 1])) + end--; + return (end - start); +} + +char *ft_strtrim(char const *s1, char const *set) +{ + char *dest; + size_t dest_len; + + if (!s1 || !set) + return (NULL); + dest_len = get_trimmed_length(s1, set); + dest = malloc(dest_len + 1); + if (!dest) + return (NULL); + while (*s1 && ft_strchr(set, (unsigned char)*s1)) + s1++; + ft_strlcpy(dest, s1, dest_len + 1); + return (dest); +} + +// #include +// #include +// #include + +// // テスト関数 +// void run_test(const char *test_name, const char *input, const char *set, +// const char *expected_output) +// { +// char *result; + +// result = ft_strtrim(input, set); +// printf("Test: %s\n", test_name); +// printf("Input: \"%s\"\n", input); +// printf("Set: \"%s\"\n", set); +// printf("Expected: \"%s\"\n", expected_output); +// printf("Result: \"%s\"\n", result); +// if ((result == NULL && expected_output == NULL) || (result +// && expected_output && strcmp((const char *)result, +// expected_output) == 0)) +// { +// printf("Status: ✅ Passed\n"); +// } +// else +// { +// printf("Status: ❌ Failed\n"); +// } +// free(result); +// printf("\n"); +// // } +// int main(void) +// { +// // Test Case 1: Normal trim +// run_test("Normal Trim", " Hello World! ", " ", "Hello World!"); +// // Test Case 2: Empty input string +// run_test("Empty Input", "", " ", ""); +// // Test Case 3: No trim characters present +// run_test("No Trim Characters", "HelloWorld", " ", "HelloWorld"); +// // Test Case 4: Entire input string is trim target +// run_test("Full Trim", ".....", ".", ""); +// // Test Case 5: Empty set +// run_test("Empty Set", " Hello World! ", "", " Hello World! "); +// // Test Case 6: Trim only at both ends +// run_test("Trim Both Ends", "xxHello World!xx", "x", "Hello World!"); +// // Test Case 7: Trim including special characters +// run_test("Special Characters", "\t\nHello World!\n\t", "\t\n", +// "Hello World!"); +// // Test Case 8: NULL pointer (input string) +// run_test("NULL Input", NULL, " ", NULL); +// // Test Case 9: NULL pointer (set) +// run_test("NULL Set", " Hello World! ", NULL, NULL); +// // Test Case 10: Partial trim at both ends +// run_test("Partial Trim", "xyHello World!yz", "xyz", "Hello World!"); +// // Test Case 11: Set with numbers +// run_test("Numeric Set", "12345Hello12345", "12345", "Hello"); +// // Test Case 12: Multiple types of trim characters at both ends +// run_test("Multiple Trim Characters", " ***Hello*** ", " *", "Hello"); +// // Test Case 13: NULL set with non-NULL input +// run_test("NULL Set with Non-NULL Input", "Hello World!", NULL, NULL); +// // Test Case 14: NULL input with non-NULL set +// run_test("NULL Input with Non-NULL Set", NULL, " ", NULL); +// // Test Case 15: Different trim characters at each end +// run_test("Different Trim Characters", "abcHello World!xyz", "abcxyz", +// "Hello World!"); +// // Test Case 16: Input fully composed of set characters +// run_test("Input Fully Matches Set", "aaaaa", "a", ""); +// // Test Case 17: Set does not overlap with input string +// run_test("Set Does Not Match Input", "Hello World!", "xyz", "Hello World!"); +// // Test Case 18: NULL input and NULL set +// run_test("NULL Input and NULL Set", NULL, NULL, NULL); +// // Test Case 19: Empty string as set +// run_test("Empty Set", "Hello World!", "", "Hello World!"); +// // Test Case 20: Empty input with non-empty set +// run_test("Empty Input with Non-Empty Set", "", "abc", ""); +// // Test Case 21: Long input string and set +// run_test("Long String and Set", +// " This is a very long string for testing purposes. ", " ", +// "This is a very long string for testing purposes."); +// // Test Case 22: All characters are trimmed +// run_test("All Characters are Trimmed", "xxxxxxxxxx", "x", ""); +// // Test Case 23: Set includes special characters and numbers +// run_test("Set Includes Special Characters", "123Hello World!321", "123!", +// "Hello World"); +// // Test Case 24: Input contains only whitespace +// run_test("Whitespace Only Input", " ", " ", ""); +// // Test Case 25: Both input string and set are empty +// run_test("Empty Input and Empty Set", "", "", ""); +// return (0); +// } diff --git a/minishell/libft/string/ft_substr.c b/minishell/libft/string/ft_substr.c new file mode 100644 index 0000000..65b0f4c --- /dev/null +++ b/minishell/libft/string/ft_substr.c @@ -0,0 +1,105 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_substr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/25 22:00:05 by kjikuhar #+# #+# */ +/* Updated: 2025/05/04 22:08:53 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_substr(char const *s, unsigned int start, size_t len) +{ + size_t s_len; + char *substr; + size_t i; + + if (!s) + return (NULL); + s_len = ft_strlen(s); + if (!(start < s_len)) + return (ft_strdup("")); + if (!(start + len < s_len)) + len = s_len - start; + substr = malloc(sizeof(char) * (len + 1)); + if (!substr) + return (NULL); + i = 0; + while (i < len) + { + substr[i] = s[start + i]; + i++; + } + substr[i] = '\0'; + return (substr); +} + +// #include "libft.h" +// #include +// #include + +// void test_substr(char const *s, unsigned int start, size_t len, +// const char *test_name) +// { +// char *result; + +// result = ft_substr(s, start, len); +// printf("Test: %s\n", test_name); +// printf("Original string: \"%s\"\n", s ? s : "(null)"); +// printf("Start position: %u, Length: %zu\n", start, len); +// printf("Result: \"%s\"\n", result ? result : "(null)"); +// printf("Result length: %zu\n", result ? strlen(result) : 0); +// printf("\n"); +// if (result) +// free(result); +// } + +// int main(void) +// { +// char long_str[1000]; + +// // Test Case 1: Basic substring extraction +// test_substr("Hello, world!", 7, 5, "Basic substring extraction"); +// // Test Case 2: Start position beyond string length +// test_substr("Hello", 10, 5, "Start position beyond string length"); +// // Test Case 3: Length longer than remaining string +// test_substr("Hello", 2, 10, "Length longer than remaining string"); +// // Test Case 4: Empty string +// test_substr("", 0, 5, "Empty string"); +// // Test Case 5: Start position at last character +// test_substr("Hello", 4, 1, "Start position at last character"); +// // Test Case 6: Length is zero +// test_substr("Hello", 2, 0, "Length zero"); +// // Test Case 7: Very large length specified +// test_substr("Hello", 0, 1000, "Very large length specified"); +// // Additional test cases +// test_substr("Hello, world!", 0, 5, "Extract from start of string"); +// test_substr("Hello\nworld", 5, 6, "String including newline"); +// test_substr("Hello\tworld", 5, 6, "String including tab"); +// test_substr(" Hello ", 3, 5, "String including spaces"); +// test_substr("Hello", 0, 0, "Extract zero length from start"); +// // Boundary tests on string length +// test_substr("A", 0, 1, "Extract entire one-character string"); +// test_substr("AB", 0, 1, +// "Extract first character from two-character string"); +// test_substr("AB", 1, 1, +// "Extract second character from two-character string"); +// // Very long string (memory efficiency test) +// memset(long_str, 'X', 999); +// long_str[999] = '\0'; +// test_substr(long_str, 500, 100, "Extract part of very long string"); +// // Special index cases +// test_substr("Hello, world!", 7, 0, "Valid start but zero length"); +// test_substr("Hello, world!", 12, 1, "Extract last character ('!')"); +// test_substr("Hello, world!", 13, 0, "Extract zero length at string end"); +// // String including special characters +// test_substr("Hello\"quotes\"", 5, 8, "String including quotes"); +// test_substr("Hello\\escape", 5, 7, "String including escape character"); +// // NULL pointer case +// test_substr(NULL, 0, 5, "NULL pointer"); +// return (0); +// } From 21cf1c07ad8f8eeb28114f1f8b5290dbb93148e4 Mon Sep 17 00:00:00 2001 From: Jikuhara Date: Mon, 29 Sep 2025 14:46:21 +0900 Subject: [PATCH 002/173] add pull_request_template.md --- .github/pull_request_template.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..6c51f4a --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,21 @@ +## やったこと + +- +- + +## 懸念点 / レビューしてほしいポイント + +- + +## ひとこと + From 52ca353cd6ad8682c9592648a92146a0ea52f4bb Mon Sep 17 00:00:00 2001 From: Jikuhara Date: Mon, 29 Sep 2025 15:01:25 +0900 Subject: [PATCH 003/173] delete comment_outted test_code --- minishell/libft/conversion/ft_atoi.c | 21 +-- minishell/libft/conversion/ft_itoa.c | 19 +-- minishell/libft/conversion/ft_tolower.c | 21 +-- minishell/libft/conversion/ft_toupper.c | 21 +-- minishell/libft/judge/ft_isalnum.c | 14 +- minishell/libft/judge/ft_isalpha.c | 57 +------- minishell/libft/judge/ft_isascii.c | 84 +----------- minishell/libft/judge/ft_isdigit.c | 69 +--------- minishell/libft/judge/ft_isprint.c | 14 +- minishell/libft/list/ft_lstadd_back.c | 66 +-------- minishell/libft/list/ft_lstadd_front.c | 67 +--------- minishell/libft/list/ft_lstdelone.c | 72 +--------- minishell/libft/list/ft_lstlast.c | 65 +-------- minishell/libft/list/ft_lstmap.c | 170 +----------------------- minishell/libft/list/ft_lstnew.c | 15 +-- minishell/libft/list/ft_lstsize.c | 65 +-------- minishell/libft/memory/ft_bzero.c | 27 +--- minishell/libft/memory/ft_calloc.c | 33 +---- minishell/libft/memory/ft_memchr.c | 49 +------ minishell/libft/memory/ft_memcmp.c | 50 +------ minishell/libft/memory/ft_memcpy.c | 102 +------------- minishell/libft/memory/ft_memmove.c | 26 +--- minishell/libft/memory/ft_memrchr.c | 59 +------- minishell/libft/memory/ft_memset.c | 16 +-- minishell/libft/original/ft_max.c | 11 +- minishell/libft/original/ft_min.c | 11 +- minishell/libft/original/ft_swap.c | 13 +- minishell/libft/output/ft_putchar_fd.c | 63 +-------- minishell/libft/output/ft_putendl_fd.c | 78 +---------- minishell/libft/output/ft_putnbr_fd.c | 130 +----------------- minishell/libft/output/ft_putstr_fd.c | 62 +-------- minishell/libft/string/ft_split.c | 21 +-- minishell/libft/string/ft_strchr.c | 49 +------ minishell/libft/string/ft_strdup.c | 17 +-- minishell/libft/string/ft_striteri.c | 57 +------- minishell/libft/string/ft_strjoin.c | 72 +--------- minishell/libft/string/ft_strlcat.c | 18 +-- minishell/libft/string/ft_strlcpy.c | 19 +-- minishell/libft/string/ft_strlen.c | 15 +-- minishell/libft/string/ft_strmapi.c | 23 +--- minishell/libft/string/ft_strncmp.c | 17 +-- minishell/libft/string/ft_strnstr.c | 57 +------- minishell/libft/string/ft_strrchr.c | 48 +------ minishell/libft/string/ft_strtrim.c | 91 +------------ minishell/libft/string/ft_substr.c | 68 +--------- 45 files changed, 52 insertions(+), 2090 deletions(-) diff --git a/minishell/libft/conversion/ft_atoi.c b/minishell/libft/conversion/ft_atoi.c index ddca3db..2206b5e 100644 --- a/minishell/libft/conversion/ft_atoi.c +++ b/minishell/libft/conversion/ft_atoi.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/24 21:08:27 by kjikuhar #+# #+# */ -/* Updated: 2025/05/16 16:54:10 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:57:08 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -28,22 +28,3 @@ int ft_atoi(const char *str) num = 10 * num + (*str++ - '0'); return (sign * num); } - -// #include - -// int main(void) -// { -// char *str[] = {"123", "-3456789", " -112", "123", "0123456789", -// "10123456789", "10101010101010101010101", "10101010101010", -// "10010101010101010101", "9910101010101010101", -// "9010101010101010101", "9510101010101010101", "9210101010101010101", -// "2147483648", "18446744073709551615"}; - -// for (unsigned int i = 0; i < sizeof(str) / sizeof(str[0]); i++) -// { -// printf("%i : %20s : %d\n", i, str[i], atoi(str[i])); -// printf("%i : %20s : %d\n", i, str[i], ft_atoi(str[i])); -// printf("\n"); -// } -// return (0); -// } diff --git a/minishell/libft/conversion/ft_itoa.c b/minishell/libft/conversion/ft_itoa.c index a1f0b14..727e305 100644 --- a/minishell/libft/conversion/ft_itoa.c +++ b/minishell/libft/conversion/ft_itoa.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/26 11:55:06 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 21:19:09 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:57:13 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -77,20 +77,3 @@ char *ft_itoa(int n) dest_str[i] = n % 10 + '0'; return (dest_str); } - -// #include - -// int main(void) -// { -// int number_set[] = {0, 1, -1, -10, 10, -11, 2147483647, 2147483647, -// -2147483648, -2147483648, 1234567}; -// for (int i = 0; i < (sizeof(number_set) / sizeof(number_set[0])); i++) -// { -// char *number_char = ft_itoa(number_set[i]); -// printf("%d : %11d : %d\n",i, number_set[i], number_len(number_set[i])); -// printf("%d : %11d : %s\n\n",i, number_set[i], number_char); -// free(number_char); -// } - -// return (0); -// } diff --git a/minishell/libft/conversion/ft_tolower.c b/minishell/libft/conversion/ft_tolower.c index e074da2..9861545 100644 --- a/minishell/libft/conversion/ft_tolower.c +++ b/minishell/libft/conversion/ft_tolower.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/25 18:47:23 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 11:36:10 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:57:17 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,22 +18,3 @@ int ft_tolower(int c) return (c + 'a' - 'A'); return (c); } - -// #include -// #include - -// int main(void) -// { -// for (int i = 0; i < 26; i++) -// { -// printf("%2d :%c -> %c\n", i,(char)('a'+i),(char)ft_olower('a'+i)) -// printf("%2d :%c -> %c\n", i,(char)('a'+i),(char)olower('a'+i)) -// } -// printf("\n"); -// for (int i = 0; i < 26; i++) -// { -// printf("%2d :%c -> %c\n", i,(char)('A'+i),(char)ft_olower('A'+i)) -// printf("%2d :%c -> %c\n", i,(char)('A'+i),(char)olower('A'+i)) -// } -// return (0); -// } diff --git a/minishell/libft/conversion/ft_toupper.c b/minishell/libft/conversion/ft_toupper.c index 9fdf60b..0758da3 100644 --- a/minishell/libft/conversion/ft_toupper.c +++ b/minishell/libft/conversion/ft_toupper.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/25 18:47:23 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 11:36:10 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:57:19 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,22 +18,3 @@ int ft_toupper(int c) return (c + 'A' - 'a'); return (c); } - -// #include -// #include - -// int main(void) -// { -// for (int i = 0; i < 26; i++) -// { -// printf("%2d :%c -> %c\n", i, (char)('a'+i),(char)ft_toupper('a'+i)) -// printf("%2d :%c -> %c\n", i, (char)('a'+i),(char)toupper('a'+i)) -// } -// printf("\n"); -// for (int i = 0; i < 26; i++) -// { -// printf("%2d :%c -> %c\n", i, (char)('A'+i),(char)ft_toupper('A'+i)) -// printf("%2d :%c -> %c\n", i, (char)('A'+i),(char)toupper('A'+i)) -// } -// return (0); -// } diff --git a/minishell/libft/judge/ft_isalnum.c b/minishell/libft/judge/ft_isalnum.c index 067882f..315ae0e 100644 --- a/minishell/libft/judge/ft_isalnum.c +++ b/minishell/libft/judge/ft_isalnum.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/24 21:20:17 by kjikuhar #+# #+# */ -/* Updated: 2025/05/18 17:49:11 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:57:23 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,15 +16,3 @@ int ft_isalnum(int c) { return (ft_isalpha(c) || ft_isdigit(c)); } - -// #include - -// int main(void) -// { -// for (int i = -5; i <= 258; i++) -// { -// char *str = (ft_isalnum(i) == 1) ? "OKKKK" : "NG"; -// printf("%3i, %4c : %2s\n", i,(char)i, str); -// } -// return (0); -// } diff --git a/minishell/libft/judge/ft_isalpha.c b/minishell/libft/judge/ft_isalpha.c index 7394da8..26b373e 100644 --- a/minishell/libft/judge/ft_isalpha.c +++ b/minishell/libft/judge/ft_isalpha.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/24 21:11:06 by kjikuhar #+# #+# */ -/* Updated: 2025/05/05 13:13:04 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:57:26 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,58 +14,3 @@ int ft_isalpha(int c) { return ((unsigned)(c | 0x20) - 'a' < 26); } - -// int ft_isalpha_uc(int c) -// { -// return (((unsigned char)c | 32) - 'a' < 26); -// } - -// #include - -// int main(void) -// { -// for (int i = -5; i <= 130; i++) -// { -// char *str = (ft_isalpha(i) == 1) ? "OKKKKK" : "NG"; -// printf("%3i, %4c : %2s\n", i,(char)i, str); -// } -// // for (int i = -5; i <= 130; i++) -// // { -// // char *str = (ft_isalpha_u(i) == 1) ? "OKKKKK" : "NG"; -// // printf("%3i, %4c : %2s\n", i,(char)i, str); -// // } -// return (0); -// } -// Optimize processing through bit operations. - -// #include -// #include - -// int ft_ft_isalpha(int c) { -// return (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')); -// } - -// int main() { -// clock_t start, end; -// int count = 1000000000; // Loop 100 million times -// int result = 0; - -// // Test ft_isalpha -// start = clock(); -// for (int i = 0; i < count; i++) { -// result += ft_isalpha(i % 256); -// } -// end = clock(); -// printf("ft_isalpha: %f seconds\n", (double)(end - start) / CLOCKS_PER_SEC); - -// // Test ft_ft_isalpha -// start = clock(); -// for (int i = 0; i < count; i++) { -// result += ft_ft_isalpha(i % 256); -// } -// end = clock(); -// printf("ft_ft_isalpha: %f seconds\n", (double)(end - start) -// / CLOCKS_PER_SEC); - -// return (result); // Prevent compiler optimization -// } diff --git a/minishell/libft/judge/ft_isascii.c b/minishell/libft/judge/ft_isascii.c index ef320bb..10ca1f7 100644 --- a/minishell/libft/judge/ft_isascii.c +++ b/minishell/libft/judge/ft_isascii.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/24 21:20:17 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 22:03:04 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:57:29 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,85 +16,3 @@ int ft_isascii(int c) { return ((unsigned)c <= ASCII_MAX); } - -// bit mask -// int ft_ft_isascii(int c) -// { -// return (!(c & ~0x7f)); -// // } -// #include - -// int ft_isascii(int c) -// { -// return ((unsigned)c <= 127); -// } - -// int isascii(int c) -// { -// return ((c >= 0 && c <= 127) ? 1 : 0); -// } - -// int main(void) -// { -// for (int i = -5; i <= 130; i++) -// { -// char *str = (ft_isascii(i) == 1) ? "OKKKKK" : "NG"; -// printf("%3i, %4c : %2s\n", i,(char)i, str); -// } -// return (0); -// } -// #include -// #include - -// // Implementation 1: Range Check -// int isascii_range(int c) -// { -// return (c >= 0 && c <= 127); -// } - -// // Implementation 2: Bit Mask -// int isascii_bitmask(int c) -// { -// return (!(c & ~0x7f)); -// } - -// // Implementation 3: Constant Comparison -// int isascii_unsigned(int c) -// { -// return ((unsigned)c <= 127); -// } - -// // Implementation 4: Table Lookup -// int isascii_table(int c) -// { -// static const char ascii_table[128] = {[0 ... 127] = 1}; -// // Set ASCII range to 1 -// return ((c >= 0 && c < 128) ? ascii_table[c] : 0); -// } - -// #define ITERATIONS 1000000000 // 1 billion iterations - -// void benchmark(const char *name, int (*func)(int)) -// { -// int result; - -// clock_t start, end; -// result = 0; -// start = clock(); -// for (int i = 0; i < ITERATIONS; i++) -// { -// result += func(i % 256); // Loop through range of 256 -// } -// end = clock(); -// printf("%s: %f seconds\n", name, (double)(end - start) / CLOCKS_PER_SEC); -// } - -// int main(void) -// { -// printf("Benchmarking isascii implementations...\n"); -// benchmark("Range Check", isascii_range); -// benchmark("Bitmask", isascii_bitmask); -// benchmark("Unsigned Comparison", isascii_unsigned); -// benchmark("Table Lookup", isascii_table); -// return (0); -// } diff --git a/minishell/libft/judge/ft_isdigit.c b/minishell/libft/judge/ft_isdigit.c index 7b3869c..0cfdf31 100644 --- a/minishell/libft/judge/ft_isdigit.c +++ b/minishell/libft/judge/ft_isdigit.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/24 21:20:17 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 21:53:07 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:57:34 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,70 +15,3 @@ int ft_isdigit(int c) { return ((unsigned)c - '0' < 10); } - -// #include -// #include - -// int ft_isdigit_uc(int c) -// { -// unsigned char uc; - -// uc = (unsigned char)c; -// return ('0' <= uc && uc <= '9'); -// } - -// int ft_isdigit_bit(int c) -// { -// return ((unsigned)c - '0' < 10); -// } - -// int ft_isdigit_bit_u(int c) -// { -// return ((unsigned char)c - '0' < 10); -// } - -// int main(void) -// { -// for (int i = -5; i <= 130; i++) -// { -// char *str = (ft_isdigit_uc(i) == 1) ? "OKKKKK" : "NG"; -// printf("%3i, %4c : %2s\n", i,(char)i, str); -// } -// for (int i = -5; i <= 130; i++) -// { -// char *str = (ft_isdigit_bit(i) == 1) ? "OKKKKK" : "NG"; -// printf("%3i, %4c : %2s\n", i,(char)i, str); -// } -// for (int i = -5; i <= 130; i++) -// { -// char *str = (ft_isdigit_bit_u(i) == 1) ? "OKKKKK" : "NG"; -// printf("%3i, %4c : %2s\n", i,(char)i, str); -// } -// return (0); -// } - -// #define ITERATIONS 1000000000 // billion times loop - -// void benchmark(const char *name, int (*func)(int)) -// { -// int result; - -// clock_t start, end; -// result = 0; -// start = clock(); -// for (int i = 0; i < ITERATIONS; i++) -// { -// result += func(i % 256); // loop to 256 -// } -// end = clock(); -// printf("%s: %f seconds\n", name, (double)(end - start) / CLOCKS_PER_SEC); -// } - -// int main(void) -// { -// printf("Benchmarking isdigit implementations...\n"); -// benchmark("ft_isdigit_uc", ft_isdigit_uc); -// benchmark("ft_isdigit_bit", ft_isdigit_bit); -// benchmark("ft_isdigit_bit_u", ft_isdigit_bit_u); -// return (0); -// } diff --git a/minishell/libft/judge/ft_isprint.c b/minishell/libft/judge/ft_isprint.c index af47f04..58df58c 100644 --- a/minishell/libft/judge/ft_isprint.c +++ b/minishell/libft/judge/ft_isprint.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/24 21:20:17 by kjikuhar #+# #+# */ -/* Updated: 2025/05/02 23:13:00 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:57:37 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,15 +14,3 @@ int ft_isprint(int c) { return ((unsigned)c - 0x20 < 0x5f); } - -// #include - -// int main(void) -// { -// for (int i = -5; i <= 258; i++) -// { -// char *str = (ft_isprint(i) == 1) ? "OKKK" : "NG"; -// printf("%3i, %4c : %2s\n", i,(char)i, str); -// } -// return (0); -// } diff --git a/minishell/libft/list/ft_lstadd_back.c b/minishell/libft/list/ft_lstadd_back.c index 62ef492..d1e81c4 100644 --- a/minishell/libft/list/ft_lstadd_back.c +++ b/minishell/libft/list/ft_lstadd_back.c @@ -1,12 +1,12 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* ft_lstadd_back_bonus.c :+: :+: :+: */ +/* ft_lstadd_back.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/28 15:40:06 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 22:10:55 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:57:41 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -27,65 +27,3 @@ void ft_lstadd_back(t_list **lst, t_list *new) last->next = new; } } - -// #include -// #include - -// t_list *listMake(char *content) -// { -// t_list *new; - -// new = malloc(sizeof(t_list)); -// if (!new) -// return (NULL); -// new->content = (char *)malloc(sizeof(char) * (strlen(content))); -// strcpy((char *)(new->content), (const char *)content); -// new->next = NULL; -// return (new); -// } - -// int main(void) -// { -// t_list *lst1, *lst2, *lst3; -// t_list *head; - -// lst1 = listMake("Hello World!1"); -// lst2 = listMake("Hello World!2"); -// lst3 = listMake("Hello World!3"); - -// head = lst1; -// lst1->next = lst2; -// lst2->next = NULL; -// lst3->next = NULL; - -// printf("%s\n", (char *)(lst1->content)); -// printf("%s\n", (char *)(lst2->content)); -// printf("%s\n", (char *)(lst3->content)); -// printf("\n"); - -// t_list *current = head; -// for (int i = 0; i < 5; i++) -// { -// if (!current) -// { -// printf("%p\n", current); -// break ; -// } -// printf("%s\n", (char *)(current->content)); -// current = current->next; -// } - -// ft_lstadd_back(&head, lst3); -// current = head; -// for (int i = 0; i < 5; i++) -// { -// if (!current) -// { -// printf("%p\n", current); -// break ; -// } -// printf("%s\n", (char *)(current->content)); -// current = current->next; -// } -// return (0); -// } diff --git a/minishell/libft/list/ft_lstadd_front.c b/minishell/libft/list/ft_lstadd_front.c index af8ee04..5a60399 100644 --- a/minishell/libft/list/ft_lstadd_front.c +++ b/minishell/libft/list/ft_lstadd_front.c @@ -1,12 +1,12 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* ft_lstadd_front_bonus.c :+: :+: :+: */ +/* ft_lstadd_front.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/27 12:47:59 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 18:52:16 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:57:44 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -20,66 +20,3 @@ void ft_lstadd_front(t_list **lst, t_list *new) new->next = *lst; *lst = new; } - -// #include -// #include - -// t_list *listMake(char *content) -// { -// t_list *new; - -// new = malloc(sizeof(t_list)); -// if (!new) -// return (NULL); -// new->content = (char *)malloc(sizeof(char) * (strlen(content))); -// strcpy((char *)(new->content), (const char *)content); -// new->next = NULL; -// return (new); -// } - -// int main(void) -// { -// t_list *lst1, *lst2, *lst3; -// t_list *head; - -// lst1 = listMake("Hello World!1"); -// lst2 = listMake("Hello World!2"); -// lst3 = listMake("Hello World!3"); - -// head = lst1; -// lst1->next = lst2; -// lst2->next = NULL; -// lst3->next = NULL; - -// printf("%s\n", (char *)(lst1->content)); -// printf("%s\n", (char *)(lst2->content)); -// printf("%s\n", (char *)(lst3->content)); - -// t_list *current = head; -// for (int i = 0; i < 3; i++) -// { -// if (!current) -// { -// printf("%p\n", current); -// break ; -// } -// printf("%s\n", (char *)(current->content)); -// current = current->next; -// } -// printf("\n"); - -// head = NULL; -// ft_lstadd_front(&head, lst3); -// current = head; -// for (int i = 0; i < 3; i++) -// { -// if (!current) -// { -// printf("%p\n", current); -// break ; -// } -// printf("%s\n", (char *)(current->content)); -// current = current->next; -// } -// return (0); -// } diff --git a/minishell/libft/list/ft_lstdelone.c b/minishell/libft/list/ft_lstdelone.c index 7932333..ea51172 100644 --- a/minishell/libft/list/ft_lstdelone.c +++ b/minishell/libft/list/ft_lstdelone.c @@ -1,12 +1,12 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* ft_lstdelone_bonus.c :+: :+: :+: */ +/* ft_lstdelone.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/28 15:40:38 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 18:36:50 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:57:48 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -21,71 +21,3 @@ void ft_lstdelone(t_list *lst, void (*del)(void *)) (*del)(lst->content); free(lst); } - -// #include -// #include - -// void delete_content(void *content) -// { -// free(content); - -// } - -// t_list *listMake(char *content) -// { -// t_list *new; - -// new = malloc(sizeof(t_list)); -// if (!new) -// return (NULL); -// new->content = (char *)malloc(sizeof(char) * (strlen(content))); -// strcpy((char *)(new->content), (const char *)content); -// new->next = NULL; -// return (new); -// } - -// int main(void) -// { -// t_list *lst1, *lst2, *lst3; -// t_list *head; - -// lst1 = listMake("Hello World!1"); -// lst2 = listMake("Hello World!2"); -// lst3 = listMake("Hello World!3"); - -// head = lst1; -// lst1->next = lst2; -// lst2->next = NULL; -// lst3->next = NULL; - -// printf("%s\n", (char *)(lst1->content)); -// printf("%s\n", (char *)(lst2->content)); -// printf("%s\n", (char *)(lst3->content)); -// printf("\n"); - -// t_list *current = head; -// for (int i = 0; i < 5; i++) -// { -// if (!current) -// { -// printf("%p\n", current); -// break ; -// } -// printf("%s\n", (char *)(current->content)); -// current = current->next; -// } - -// ft_lstdelone(lst2, *delete_content); -// current = head; -// for (int i = 0; i < 5; i++) -// { -// if (!current) -// { -// printf("%p\n", current); -// break ; -// } -// printf("%s\n", (char *)(current->content)); -// current = current->next; -// } -// return (0); -// } diff --git a/minishell/libft/list/ft_lstlast.c b/minishell/libft/list/ft_lstlast.c index 59e56e4..3b5dc0f 100644 --- a/minishell/libft/list/ft_lstlast.c +++ b/minishell/libft/list/ft_lstlast.c @@ -1,12 +1,12 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* ft_lstlast_bonus.c :+: :+: :+: */ +/* ft_lstlast.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/28 15:38:00 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 19:01:49 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:57:53 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -21,64 +21,3 @@ t_list *ft_lstlast(t_list *lst) lst = lst->next; return (lst); } - -// #include -// #include - -// t_list *listMake(char *content) -// { -// t_list *new; - -// new = malloc(sizeof(t_list)); -// if (!new) -// return (NULL); -// new->content = (char *)malloc(sizeof(char) * (strlen(content))); -// strcpy((char *)(new->content), (const char *)content); -// new->next = NULL; -// return (new); -// } - -// int main(void) -// { -// t_list *lst1, *lst2, *lst3; -// t_list *head; - -// lst1 = listMake("Hello World!1"); -// lst2 = listMake("Hello World!2"); -// lst3 = listMake("Hello World!3"); - -// head = lst1; -// lst1->next = lst2; -// lst2->next = NULL; -// lst3->next = NULL; - -// printf("%s\n", (char *)(lst1->content)); -// printf("%s\n", (char *)(lst2->content)); -// printf("%s\n", (char *)(lst3->content)); - -// t_list *current = head; -// for (int i = 0; i < 3; i++) -// { -// if (!current) -// { -// printf("%p\n", current); -// break ; -// } -// printf("%s\n", (char *)(current->content)); -// current = current->next; -// } - -// printf("%s\n", (char *)(ft_lstlast(head)->content)); -// current = head; -// for (int i = 0; i < 3; i++) -// { -// if (!current) -// { -// printf("%p\n", current); -// break ; -// } -// printf("%s\n", (char *)(current->content)); -// current = current->next; -// } -// return (0); -// } diff --git a/minishell/libft/list/ft_lstmap.c b/minishell/libft/list/ft_lstmap.c index 0b0842f..904327f 100644 --- a/minishell/libft/list/ft_lstmap.c +++ b/minishell/libft/list/ft_lstmap.c @@ -1,12 +1,12 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* ft_lstmap_bonus.c :+: :+: :+: */ +/* ft_lstmap.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/28 15:40:38 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 21:54:47 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:57:58 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -54,169 +54,3 @@ t_list *ft_lstmap(t_list *lst, void *(*f)(void *), void (*del)(void *)) } return (head); } -// /* ---- Add this to the end of source file ---- */ -// #include -// #include /* ← For debugging (optional) */ -// #include -// #include - -// /* ====== Helpers ====== */ -// static int g_del_count = 0; - -// static void *dup_int_times2(void *p) -// { -// int *src; -// int *dst; - -// src = (int *)p; -// dst = malloc(sizeof(int)); -// if (!dst) -// return (NULL); -// *dst = (*src) * 2; -// return (dst); -// } - -// static void *dup_int_fail_on_2(void *p) -// { -// int *src; - -// src = (int *)p; -// if (*src == 2) -// return (NULL); /* Intentionally fail */ -// return (dup_int_times2(p)); /* Succeed otherwise */ -// } - -// static void del_int(void *p) -// { -// printf("del_int called: %p\n", p); -// free(p); -// g_del_count++; -// } - -// static t_list *make_int_node(int v) -// { -// int *p; - -// p = malloc(sizeof(int)); -// assert(p); /* Simplified for testing */ -// *p = v; -// return (ft_lstnew(p)); -// } - -// static int list_equals(t_list *a, t_list *b) -// { -// while (a && b) -// { -// if (*(int *)a->content != *(int *)b->content) -// return (0); -// a = a->next; -// b = b->next; -// } -// return (a == NULL && b == NULL); -// } - -// /* ====== ft_lstnew ====== */ -// static void test_ft_lstnew_content(void) -// { -// char *s; -// t_list *n; - -// s = "hello"; -// n = ft_lstnew(s); -// assert(n && n->content == s && n->next == NULL); -// free(n); -// } - -// static void test_ft_lstnew_null(void) -// { -// t_list *n; - -// n = ft_lstnew(NULL); -// assert(n && n->content == NULL && n->next == NULL); -// free(n); -// } - -// /* ====== ft_lstclear ====== */ -// static void test_ft_lstclear_multi(void) -// { -// t_list *a; - -// g_del_count = 0; -// a = make_int_node(1); -// a->next = make_int_node(2); -// a->next->next = make_int_node(3); -// ft_lstclear(&a, del_int); -// assert(a == NULL); -// assert(g_del_count == 3); -// } - -// static void test_ft_lstclear_nullptr(void) -// { -// t_list *head; - -// /* lst == NULL */ -// ft_lstclear(NULL, del_int); -// /* *lst == NULL */ -// head = NULL; -// ft_lstclear(&head, del_int); -// } - -// /* ====== ft_lstmap ====== */ -// static void test_ft_lstmap_success(void) -// { -// t_list *src; -// t_list *dst; - -// src = make_int_node(1); -// src->next = make_int_node(2); -// src->next->next = make_int_node(3); -// dst = ft_lstmap(src, dup_int_times2, del_int); -// assert(dst && list_equals(dst, ((t_list[]){{.content = &(int){2}, -// .next = &(t_list){.content = &(int){4}, -// .next = &(t_list){.content = &(int){6}, .next = NULL}}}}))); -// /* Original list is unchanged */ -// assert(*(int *)src->content == 1); -// ft_lstclear(&src, del_int); -// ft_lstclear(&dst, del_int); -// } - -// static void test_ft_lstmap_fail_midway(void) -// { -// t_list *src; -// t_list *dst; - -// g_del_count = 0; -// src = make_int_node(1); -// src->next = make_int_node(2); -// src->next->next = make_int_node(3); -// dst = ft_lstmap(src, dup_int_fail_on_2, del_int); -// assert(dst == NULL); -// assert(g_del_count == 1); /* Only node 1 should have been freed */ -// ft_lstclear(&src, del_int); /* Cleanup */ -// } - -// static void test_ft_lstmap_nullsrc(void) -// { -// t_list *dst; - -// dst = ft_lstmap(NULL, dup_int_times2, del_int); -// assert(dst == NULL); -// } - -// /* ====== main ====== */ -// int main(void) -// { -// /* ft_lstnew */ -// test_ft_lstnew_content(); -// test_ft_lstnew_null(); -// /* ft_lstclear */ -// test_ft_lstclear_multi(); -// test_ft_lstclear_nullptr(); -// /* ft_lstmap */ -// test_ft_lstmap_success(); -// test_ft_lstmap_fail_midway(); -// printf("Final g_del_count = %d\n", g_del_count); -// test_ft_lstmap_nullsrc(); -// puts("All tests passed!"); -// return (0); -// } diff --git a/minishell/libft/list/ft_lstnew.c b/minishell/libft/list/ft_lstnew.c index 6662b47..e45823f 100644 --- a/minishell/libft/list/ft_lstnew.c +++ b/minishell/libft/list/ft_lstnew.c @@ -1,12 +1,12 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* ft_lstnew_bonus.c :+: :+: :+: */ +/* ft_lstnew.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/27 12:42:16 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 19:03:20 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:58:04 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -24,14 +24,3 @@ t_list *ft_lstnew(void *content) new->next = NULL; return (new); } - -// #include - -// int main(void) -// { -// t_list *new_list; - -// new_list = ft_lstnew("Hello World!"); -// printf("%s : %p", (char *)new_list->content, new_list->next); -// return (0); -// } diff --git a/minishell/libft/list/ft_lstsize.c b/minishell/libft/list/ft_lstsize.c index 85f4557..ebc98ac 100644 --- a/minishell/libft/list/ft_lstsize.c +++ b/minishell/libft/list/ft_lstsize.c @@ -1,12 +1,12 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* ft_lstsize_bonus.c :+: :+: :+: */ +/* ft_lstsize.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/28 15:34:58 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 19:03:32 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:58:07 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -25,64 +25,3 @@ int ft_lstsize(t_list *lst) } return (i); } - -// #include -// #include - -// t_list *listMake(char *content) -// { -// t_list *new; - -// new = malloc(sizeof(t_list)); -// if (!new) -// return (NULL); -// new->content = (char *)malloc(sizeof(char) * (strlen(content))); -// strcpy((char *)(new->content), (const char *)content); -// new->next = NULL; -// return (new); -// } - -// int main(void) -// { -// t_list *lst1, *lst2, *lst3; -// t_list *head; - -// lst1 = listMake("Hello World!1"); -// lst2 = listMake("Hello World!2"); -// lst3 = listMake("Hello World!3"); - -// head = lst1; -// lst1->next = lst2; -// lst2->next = lst3; -// lst3->next = NULL; - -// printf("%s\n", (char *)(lst1->content)); -// printf("%s\n", (char *)(lst2->content)); -// printf("%s\n", (char *)(lst3->content)); -// printf("\n"); - -// t_list *current = head; -// for (int i = 0; i < 5; i++) -// { -// if (!current) -// { -// printf("%p : %d\n", current, ft_lstsize(current)); -// break ; -// } -// printf("%s : %d\n", (char *)(current->content), ft_lstsize(current)); -// current = current->next; -// } - -// current = head; -// for (int i = 0; i < 5; i++) -// { -// if (!current) -// { -// printf("%p : %d\n", current, ft_lstsize(current)); -// break ; -// } -// printf("%s : %d\n", (char *)(current->content), ft_lstsize(current)); -// current = current->next; -// } -// return (0); -// } diff --git a/minishell/libft/memory/ft_bzero.c b/minishell/libft/memory/ft_bzero.c index 3c0b51e..e2fc6f7 100644 --- a/minishell/libft/memory/ft_bzero.c +++ b/minishell/libft/memory/ft_bzero.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/25 15:46:17 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 11:36:10 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:58:11 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,28 +16,3 @@ void ft_bzero(void *s, size_t n) { ft_memset(s, 0, n); } - -// #include -// #include -// #include - -// int main(void) -// { -// char strs[][30] = {"Hello World 42 Tokyo!"}; - -// for (size_t i = 0; i < sizeof(strs) / sizeof(strs[0]); i++) -// { -// printf("%s\n", strs[i]); -// // bzero(strs[i], 2); -// ft_bzero(strs[i], 5); -// for (size_t j = 0; j < 30; j++) -// { -// if (strs[i][j] == '\0') -// printf("%s", "\\0"); -// else -// printf("%c", strs[i][j]); -// } -// printf("%c", '\n'); -// } -// return (0); -// } diff --git a/minishell/libft/memory/ft_calloc.c b/minishell/libft/memory/ft_calloc.c index 18ca355..f76fc2f 100644 --- a/minishell/libft/memory/ft_calloc.c +++ b/minishell/libft/memory/ft_calloc.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/25 17:26:53 by kjikuhar #+# #+# */ -/* Updated: 2025/05/05 13:27:01 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:58:15 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -28,34 +28,3 @@ void *ft_calloc(size_t count, size_t size) ft_bzero(p, total_size); return (p); } - -// #include -// #include - -// int main(void) -// { -// int *p; -// char *str[10]; - -// p = (int *)ft_calloc(10, sizeof(int)); -// for (size_t i = 0; i < 10; i++) -// { -// printf("%d\n", p[i]); -// } -// printf("\n"); -// str = (char **)ft_calloc(10, sizeof(char *)); -// for (size_t i = 0; i < 10; i++) -// { -// str[i] = "0123456789"; -// printf("%s\n", str[i]); -// } -// free(p); -// free(str); -// return (0); -// } -// // % gcc -fsanitize=address -g ft_calloc.c ft_bzero.c -o test_calloc -// // gcc -g ft_calloc.c ft_bzero.c -o test_calloc_valgrind # ASanなしでコンパイル -// // valgrind --leak-check=full --track-origins=yes ./test_calloc_valgrind -// gcc -Wall -Wextra -Werror -Wpedantic -Wconversion -Wshadow -Wundef -// -Wcast-align -Wwrite-strings -Wformat=2 -// -g ft_calloc.c ft_bzero.c -o test_calloc_debug diff --git a/minishell/libft/memory/ft_memchr.c b/minishell/libft/memory/ft_memchr.c index 5f55f60..bf87470 100644 --- a/minishell/libft/memory/ft_memchr.c +++ b/minishell/libft/memory/ft_memchr.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/25 18:30:44 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 22:02:33 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:58:19 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -25,50 +25,3 @@ void *ft_memchr(const void *s, int c, size_t n) } return (NULL); } -// #include "libft.h" -// #include -// #include - -// void test_ft_memchr(const void *s, int c, size_t n, const char *test_name) -// { -// void *ft_result; -// void *std_result; - -// ft_result = ft_memchr(s, c, n); -// std_result = memchr(s, c, n); -// printf("Test: %s\n", test_name); -// printf("ft_memchr result: %p\n", ft_result); -// printf("memchr result: %p\n", std_result); -// printf("Match: %s\n\n", (ft_result == std_result) ? "Yes" : "No"); -// } - -// int main(void) -// { -// char str1[] = "Hello, world!"; -// unsigned char binary[] = {0x10, 0x20, 0x30, 0x40, 0x50}; -// char str2[] = "Hello\0world"; - -// // Test case 1: Search for a character in a string -// test_ft_memchr(str1, 'w', strlen(str1), "Search for 'w' in 'Hello, -// world!'"); -// // Test case 2: Search for a non-existent character -// test_ft_memchr(str1, 'z', strlen(str1), "Search for 'z' in 'Hello, -// world!' (non-existent)"); -// // Test case 3: Search for a character within limited length -// test_ft_memchr(str1, 'o', 5, "Search for 'o' in 'Hello, world!' with n=5"); -// // Test case 4: Search for a character within limited length (not in range) -// test_ft_memchr(str1, 'o', 4, "Search for 'o' in 'Hello, -// world!' with n=4 (out of range)"); -// // Test case 5: Search for NULL byte -// test_ft_memchr(str1, '\0', strlen(str1) + 1, "Search for '\\0' in 'Hello, -// world!'"); -// // Test case 6: Binary data -// test_ft_memchr(binary, 0x30, sizeof(binary), -// "Search for 0x30 in binary data"); -// // Test case 7: Case with n=0 -// test_ft_memchr("", 'a', 0, "Search for 'a' with n=0"); -// // Test case 8: Search for character after NULL byte -// test_ft_memchr(str2, 'w', 12, -// "Search for 'w' after NULL byte in 'Hello\\0world'"); -// return (0); -// } diff --git a/minishell/libft/memory/ft_memcmp.c b/minishell/libft/memory/ft_memcmp.c index 48e61d8..29013d3 100644 --- a/minishell/libft/memory/ft_memcmp.c +++ b/minishell/libft/memory/ft_memcmp.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/25 18:41:27 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 22:02:43 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:58:26 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -28,51 +28,3 @@ int ft_memcmp(const void *s1, const void *s2, size_t n) } return (0); } -// #include -// #include - -// void test_ft_memcmp(const void *s1, const void *s2, size_t n, -// const char *test_name) -// { -// int ft_result; -// int std_result; -// int ft_sign; -// int std_sign; - -// ft_result = ft_memcmp(s1, s2, n); -// std_result = memcmp(s1, s2, n); -// printf("Test: %s\n", test_name); -// printf("ft_memcmp result: %d\n", ft_result); -// printf("memcmp result: %d\n", std_result); -// // Check if the result signs are the same -// ft_sign = (ft_result > 0) ? 1 : ((ft_result < 0) ? -1 : 0); -// std_sign = (std_result > 0) ? 1 : ((std_result < 0) ? -1 : 0); -// printf("Match: %s\n\n", (ft_sign == std_sign) ? "Yes" : "No"); -// } - -// int main(void) -// { -// char str1[] = "Hello, world!"; -// char str3[] = "Hello\0world"; -// char str4[] = "Hello\0WORLD"; -// unsigned char bin1[] = {0x10, 0x20, 0x30, 0x40}; -// unsigned char bin2[] = {0x10, 0x20, 0x50, 0x40}; - -// // Test case 1: Compare identical strings -// test_ft_memcmp(str1, str1, strlen(str1), "Comparing identical strings"); -// // Test case 2: Compare different strings -// char str2[] = "Hello, World!"; // 'w' changed to 'W' -// test_ft_memcmp(str1, str2, strlen(str1), "Comparing different strings"); -// // Test case 3: Strings differing within specified bytes -// test_ft_memcmp("abcdef", "abcDef", 4, "Strings differing within 4 bytes"); -// // Test case 4: Strings differing outside of specified bytes -// test_ft_memcmp("abcdef", "abcDef", 3, -// "Comparing within 3 bytes (before the difference)"); -// // Test case 5: When byte count is zero -// test_ft_memcmp("abc", "def", 0, "Comparison with zero bytes"); -// // Test case 6: Comparison including NULL bytes -// test_ft_memcmp(str3, str4, 12, "Strings containing NULL characters"); -// // Test case 7: Binary data -// test_ft_memcmp(bin1, bin2, 4, "Comparing binary data"); -// return (0); -// } diff --git a/minishell/libft/memory/ft_memcpy.c b/minishell/libft/memory/ft_memcpy.c index 4e2dfd7..3e0d542 100644 --- a/minishell/libft/memory/ft_memcpy.c +++ b/minishell/libft/memory/ft_memcpy.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/25 15:45:59 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 21:58:55 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:58:30 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -26,103 +26,3 @@ void *ft_memcpy(void *dest, const void *src, size_t n) *(dest_str++) = *(src_str++); return (dest); } -// #include -// #include -// #include - -// /* MEMCPY_01: Regular copy (5 bytes) */ -// static void test_memcpy_short(void) -// { -// const char *src = "abcde"; -// char dest[8] = {0}; - -// assert(ft_memcpy(dest, src, 5) == dest); -// assert(memcmp(dest, src, 5) == 0); -// } - -// /* MEMCPY_02: No change when n==0 */ -// static void test_memcpy_n_zero(void) -// { -// const char *src = "xyz"; -// char dest[8] = "XXXX"; - -// assert(ft_memcpy(dest, src, 0) == dest); -// assert(strcmp(dest, "XXXX") == 0); /* content unchanged */ -// } - -// /* MEMCPY_03: Copy including '\0' */ -// static void test_memcpy_with_nullbyte(void) -// { -// const char *src = "Hello\0World"; -// char dest[12] = {0}; - -// size_t n = strlen(src) + 1; /* up to '\0' */ -// assert(ft_memcpy(dest, src, n) == dest); -// assert(memcmp(dest, src, n) == 0); -// } - -// /* MEMCPY_04: dest == src */ -// static void test_memcpy_same_pointer(void) -// { -// char buffer[6] = "ABCDE"; - -// assert(ft_memcpy(buffer, buffer, 5) == buffer); -// assert(memcmp(buffer, "ABCDE", 5) == 0); -// } - -// /* MEMCPY_05: Large capacity 2048 bytes */ -// static void test_memcpy_large_block(void) -// { -// size_t n; -// unsigned char *src; -// unsigned char *dest; - -// n = 2048; -// src = malloc(n); -// dest = malloc(n); -// assert(src && dest); -// memset(src, 0xAA, n); -// memset(dest, 0x00, n); -// assert(ft_memcpy(dest, src, n) == dest); -// assert(memcmp(dest, src, n) == 0); -// free(src); -// free(dest); -// } - -// /* MEMCPY_06: dest==NULL && src==NULL && n==0 */ -// static void test_memcpy_null_null_zero(void) -// { -// assert(ft_memcpy(NULL, NULL, 0) == NULL); -// } - -// // /* MEMCPY_07: dest==NULL && src!=NULL && n==0 */ -// // static void test_memcpy_null_nonull_zero(void) -// // { -// // assert(ft_memcpy(NULL, "a", 0) == NULL); -// // } - -// // /* MEMCPY_08: dest!=NULL && src==NULL && n==0 */ -// // static void test_memcpy_nonull_null_zero(void) -// // { -// // char *dst; -// // dst = malloc(32); -// // assert(ft_memcpy(dst, NULL, 0) == NULL); -// // free(dst); -// // } - -// int main(void) -// { -// // ft_memcpy(NULL, NULL, 1); -// // memcpy(NULL, NULL, 1); -// // ft_memcpy(NULL, NULL, 0); -// // memcpy(NULL, NULL, 0); -// test_memcpy_short(); -// test_memcpy_n_zero(); -// test_memcpy_with_nullbyte(); -// test_memcpy_same_pointer(); -// test_memcpy_large_block(); -// test_memcpy_null_null_zero(); -// // test_memcpy_null_nonull_zero(); -// // test_memcpy_nonull_null_zero(); -// return (0); -// } diff --git a/minishell/libft/memory/ft_memmove.c b/minishell/libft/memory/ft_memmove.c index f3a0473..c4a9e9f 100644 --- a/minishell/libft/memory/ft_memmove.c +++ b/minishell/libft/memory/ft_memmove.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/25 19:28:19 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 21:59:54 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:58:34 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -33,27 +33,3 @@ void *ft_memmove(void *dest, const void *src, size_t n) } return (dest); } -// #include -// #include - -// int main(void) -// { -// char str[] = "Hello, World!"; -// char overlap1[] = "abcdefghijkl"; -// char overlap2[] = "0123456789"; - -// // Copy without overlap -// printf("Original string: %s\n", str); -// ft_memmove(str + 7, "42Tokyo", 7); -// printf("After memmove: %s\n", str); - -// // Copy with overlap (forward copy) -// ft_memmove(overlap1 + 3, overlap1, 4); -// printf("Overlapping copy (forward): %s\n", overlap1); - -// // Copy with overlap (backward copy) -// ft_memmove(overlap2, overlap2 + 2, 5); -// printf("Overlapping copy (backward): %s\n", overlap2); - -// return (0); -// } diff --git a/minishell/libft/memory/ft_memrchr.c b/minishell/libft/memory/ft_memrchr.c index fbb1fe3..e766d30 100644 --- a/minishell/libft/memory/ft_memrchr.c +++ b/minishell/libft/memory/ft_memrchr.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/05 18:16:23 by kjikuhar #+# #+# */ -/* Updated: 2025/05/05 20:02:01 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:58:37 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -23,60 +23,3 @@ void *ft_memrchr(const void *s, int c, size_t n) return ((void *)(us + n)); return (NULL); } - -// #include -// #include -// #include - -// static void test_ft_memrchr_a_found(void) -// { -// const char s[] = "abcabc"; - -// assert(ft_memrchr(s, 'a', 6) == s + 3); -// } - -// static void test_ft_memrchr_c_found(void) -// { -// const char s[] = "abcabc"; - -// assert(ft_memrchr(s, 'c', 6) == s + 5); -// } - -// static void test_ft_memrchr_n_zero(void) -// { -// const char s[] = "abcabc"; - -// assert(ft_memrchr(s, 'a', 0) == NULL); -// } - -// static void test_ft_memrchr_tail_only(void) -// { -// const char s[] = "abcabc"; - -// assert(ft_memrchr(s + 5, 'c', 1) == s + 5); -// } - -// static void test_ft_memrchr_not_found(void) -// { -// const char s[] = "abcabc"; - -// assert(ft_memrchr(s, 'x', 6) == NULL); -// } - -// static void test_ft_memrchr_binary(void) -// { -// const unsigned char s[] = {0x00, 0xff, 0x00, 0xff}; - -// assert(ft_memrchr(s, 0xff, 4) == s + 3); -// } - -// int main(void) -// { -// test_ft_memrchr_a_found(); -// test_ft_memrchr_c_found(); -// test_ft_memrchr_n_zero(); -// test_ft_memrchr_tail_only(); -// test_ft_memrchr_not_found(); -// test_ft_memrchr_binary(); -// return (0); -// } diff --git a/minishell/libft/memory/ft_memset.c b/minishell/libft/memory/ft_memset.c index 91c67dc..68e7931 100644 --- a/minishell/libft/memory/ft_memset.c +++ b/minishell/libft/memory/ft_memset.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/24 22:36:41 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 21:59:35 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:58:41 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -24,17 +24,3 @@ void *ft_memset(void *s, int c, size_t n) *uc_dst++ = (unsigned char)c; return (s); } - -// #include -// #include - -// int main(int argc, char const *argv[]) -// { -// char str[50] = "Hello World 42 Tokyo!"; -// printf("First string:%s\n", str); - -// ft_memset(str + 2, '-', 2); -// memset(str + 4, '*', 2); -// printf("%s\n", str); -// return (0); -// } diff --git a/minishell/libft/original/ft_max.c b/minishell/libft/original/ft_max.c index 23a5f46..8df788c 100644 --- a/minishell/libft/original/ft_max.c +++ b/minishell/libft/original/ft_max.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/11 18:09:27 by kjikuhar #+# #+# */ -/* Updated: 2025/05/18 19:32:11 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:58:47 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -44,12 +44,3 @@ size_t ft_max_size_t(size_t a, size_t b) else return (a); } - -// #include - -// int main(void) -// { -// int tabs[] = {0, 1, 2, 3, 4, 5}; - -// printf("%d\n", ft_max_int(tabs[3], tabs[1])); -// } diff --git a/minishell/libft/original/ft_min.c b/minishell/libft/original/ft_min.c index 443948d..d0d5722 100644 --- a/minishell/libft/original/ft_min.c +++ b/minishell/libft/original/ft_min.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/11 18:05:03 by kjikuhar #+# #+# */ -/* Updated: 2025/05/11 18:09:12 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:58:50 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -43,12 +43,3 @@ size_t ft_min_size_t(size_t a, size_t b) else return (a); } - -// #include - -// int main(void) -// { -// int tabs[] = {0, 1, 2, 3, 4, 5}; - -// printf("%d\n", ft_min_int(tabs[3], tabs[1])); -// } diff --git a/minishell/libft/original/ft_swap.c b/minishell/libft/original/ft_swap.c index 8e5794d..9c645c3 100644 --- a/minishell/libft/original/ft_swap.c +++ b/minishell/libft/original/ft_swap.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/07 20:23:04 by kjikuhar #+# #+# */ -/* Updated: 2025/05/07 20:26:44 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:58:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -20,14 +20,3 @@ void ft_swap(int *a, int *b) *a = *b; *b = tmp; } - -// int main(void) -// { -// int a = 42; -// int b = 24; - -// printf("Before: a = %2d, b = %2d\n", a, b); -// ft_swap(&a, &b); -// printf("After : a = %2d, b = %2d\n", a, b); -// return (0); -// } diff --git a/minishell/libft/output/ft_putchar_fd.c b/minishell/libft/output/ft_putchar_fd.c index 25ed686..3e0bae9 100644 --- a/minishell/libft/output/ft_putchar_fd.c +++ b/minishell/libft/output/ft_putchar_fd.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/26 14:16:34 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 22:00:41 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:58:58 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,64 +16,3 @@ void ft_putchar_fd(char c, int fd) { write(fd, &c, 1); } -// #include "libft.h" -// #include // for open() -// #include // for printf() -// #include // for close(), read() - -// int main(void) -// { -// int fd; -// char buffer[10]; -// int bytes_read; - -// // Test Case 1: Output character to standard output -// printf("Test Case 1: Output character 'A' to standard output: "); -// ft_putchar_fd('A', 1); -// printf("\n"); -// // Test Case 2: Output character to standard error -// fprintf(stderr, "Test Case 2: Output character 'B' to standard error: "); -// ft_putchar_fd('B', 2); -// fprintf(stderr, "\n"); -// // Test Case 3: Output character to a file -// printf("Test Case 3: Output character 'C' to a file\n"); -// fd = open("test_putchar.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); -// if (fd == -1) -// { -// printf("Error: Could not open file\n"); -// return (1); -// } -// ft_putchar_fd('C', fd); -// close(fd); -// // Open the file and check its contents -// fd = open("test_putchar.txt", O_RDONLY); -// if (fd == -1) -// { -// printf("Error: Could not read file\n"); -// return (1); -// } -// bytes_read = read(fd, buffer, sizeof(buffer) - 1); -// buffer[bytes_read] = '\0'; -// printf("File contents: %s\n", buffer); -// close(fd); -// // Test Case 4: Output multiple characters to a file consecutively -// printf("Test Case 4: Consecutive output of multiple characters\n"); -// fd = open("test_multiple.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); -// if (fd != -1) -// { -// ft_putchar_fd('4', fd); -// ft_putchar_fd('2', fd); -// ft_putchar_fd('T', fd); -// ft_putchar_fd('o', fd); -// ft_putchar_fd('k', fd); -// ft_putchar_fd('y', fd); -// ft_putchar_fd('o', fd); -// close(fd); -// fd = open("test_multiple.txt", O_RDONLY); -// bytes_read = read(fd, buffer, sizeof(buffer) - 1); -// buffer[bytes_read] = '\0'; -// printf("Result of consecutive output: %s\n", buffer); -// close(fd); -// } -// return (0); -// } diff --git a/minishell/libft/output/ft_putendl_fd.c b/minishell/libft/output/ft_putendl_fd.c index 2cdb0d8..b28858b 100644 --- a/minishell/libft/output/ft_putendl_fd.c +++ b/minishell/libft/output/ft_putendl_fd.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/26 14:29:52 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 22:01:16 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:59:03 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -20,79 +20,3 @@ void ft_putendl_fd(char *s, int fd) write(fd, "\n", 1); return ; } -// #include "libft.h" -// #include // for open() -// #include // for printf() -// #include // for close(), read() - -// int main(void) -// { -// int fd; -// char buffer[100]; -// int bytes_read; - -// // Test Case 1: Output string with newline to standard output -// printf("Test Case 1: Output string with newline to standard output:\n"); -// ft_putendl_fd("Hello, World!", 1); -// printf("↑ 'Hello, World!' with a newline should appear above\n"); -// // Test Case 2: Output string with newline to standard error -// fprintf(stderr, -// "Test Case 2: Output string with newline to standard error:\n"); -// ft_putendl_fd("Error message", 2); -// fprintf(stderr, "↑ 'Error message' with a newline should appear above\n"); -// // Test Case 3: Output string with newline to a file -// printf("Test Case 3: Output string with newline to a file\n"); -// fd = open("test_putendl.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); -// if (fd == -1) -// { -// printf("Error: Could not open file\n"); -// return (1); -// } -// ft_putendl_fd("42Tokyo", fd); -// close(fd); -// // Open the file and check its contents -// fd = open("test_putendl.txt", O_RDONLY); -// if (fd == -1) -// { -// printf("Error: Could not read file\n"); -// return (1); -// } -// bytes_read = read(fd, buffer, sizeof(buffer) - 1); -// buffer[bytes_read] = '\0'; -// printf("File contents: "); -// for (int i = 0; i < bytes_read; i++) -// { -// if (buffer[i] == '\n') -// printf("\\n"); -// else -// printf("%c", buffer[i]); -// } -// printf("\n"); -// close(fd); -// // Test Case 4: Empty string -// printf("Test Case 4: Output an empty string (only newline)\n"); -// fd = open("test_empty_endl.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); -// if (fd != -1) -// { -// ft_putendl_fd("", fd); -// close(fd); -// fd = open("test_empty_endl.txt", O_RDONLY); -// bytes_read = read(fd, buffer, sizeof(buffer) - 1); -// buffer[bytes_read] = '\0'; -// printf("Result of empty string (only newline): "); -// for (int i = 0; i < bytes_read; i++) -// { -// if (buffer[i] == '\n') -// printf("\\n"); -// else -// printf("%c", buffer[i]); -// } -// printf("\n"); -// close(fd); -// } -// // Test Case 5: NULL pointer -// printf("Test Case 5: NULL pointer (confirming no crash)\n"); -// ft_putendl_fd(NULL, 1); -// printf("NULL test complete\n"); -// return (0); -// } diff --git a/minishell/libft/output/ft_putnbr_fd.c b/minishell/libft/output/ft_putnbr_fd.c index eaf53ae..598da7e 100644 --- a/minishell/libft/output/ft_putnbr_fd.c +++ b/minishell/libft/output/ft_putnbr_fd.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/26 14:33:56 by kjikuhar #+# #+# */ -/* Updated: 2025/05/05 18:12:05 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:59:06 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -25,131 +25,3 @@ void ft_putnbr_fd(int n, int fd) ft_putnbr_fd(n / 10, fd); write(fd, &(char){n % 10 + '0'}, 1); } - -// int main(void) -// { -// int number_set[] = {0, 42, -42, 123, 2147483647, -2147483648}; -// int fd = 1; -// for (int i = 0; i < 10; i++) -// { -// ft_putnbr_fd(number_set[i], fd); -// write(fd, "\n", 1); -// } -// return (0); -// } - -// /* == tester == */ -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include - -// void ft_putnbr_fd(int n, int fd); - -// static void test_ft_putnbr_fd_basic(void) -// { -// int fd; -// char buf[256] = {0}; - -// fd = open("test_output.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); -// assert(fd != -1); -// ft_putnbr_fd(2, fd); -// write(fd, "\n", 1); -// ft_putnbr_fd(42, fd); -// write(fd, "\n", 1); -// ft_putnbr_fd(-42, fd); -// write(fd, "\n", 1); -// ft_putnbr_fd(2147483647, fd); -// write(fd, "\n", 1); -// ft_putnbr_fd(-2147483648, fd); -// write(fd, "\n", 1); -// close(fd); -// fd = open("test_output.txt", O_RDONLY); -// assert(fd != -1); -// read(fd, buf, sizeof(buf) - 1); -// close(fd); -// assert(!strcmp(buf, "2\n42\n-42\n2147483647\n-2147483648\n")); -// printf("Basic tests passed.\n"); -// } - -// static void test_ft_putnbr_fd_invalid_fd(void) -// { -// errno = 0; -// ft_putnbr_fd(123, -1); -// assert(errno != 0); -// printf("Invalid fd test passed.\n"); -// } - -// static void test_ft_putnbr_fd_stderr(void) -// { -// ft_putnbr_fd(42, 2); // should print to stderr -// printf("Stderr test ran (check manually).\n"); -// } - -// static int check_output_file(int n) -// { -// char expected[32]; -// char buf[64] = {0}; -// int fd; -// char *newline; - -// snprintf(expected, sizeof(expected), "%d", n); -// fd = open("test_output.txt", O_RDONLY); -// if (fd == -1) -// return (0); -// read(fd, buf, sizeof(buf) - 1); -// close(fd); -// // remove trailing newline if any -// newline = strchr(buf, '\n'); -// if (newline) -// *newline = '\0'; -// return (strcmp(buf, expected) == 0); -// } - -// static void test_ft_putnbr_fd_random(void) -// { -// int success_count; -// int n; -// int fd; - -// srand((unsigned int)time(NULL)); -// success_count = 0; -// for (int i = 1; i <= 200; i++) -// { -// n = (rand() % (INT_MAX)) - (rand() % (INT_MAX)); -// fd = open("test_output.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); -// if (fd == -1) -// { -// perror("open"); -// continue ; -// } -// ft_putnbr_fd(n, fd); -// write(fd, "\n", 1); -// close(fd); -// if (check_output_file(n)) -// { -// printf("%3d : %11d : Good\n", i, n); -// success_count++; -// } -// else -// { -// printf("%3d : %11d : NG\n", i, n); -// } -// } -// unlink("test_output.txt"); -// printf("Random tests passed %d / 200.\n", success_count); -// } - -// int main(void) -// { -// test_ft_putnbr_fd_basic(); -// test_ft_putnbr_fd_invalid_fd(); -// test_ft_putnbr_fd_stderr(); -// test_ft_putnbr_fd_random(); -// return (0); -// } diff --git a/minishell/libft/output/ft_putstr_fd.c b/minishell/libft/output/ft_putstr_fd.c index ce0b271..70aa6cb 100644 --- a/minishell/libft/output/ft_putstr_fd.c +++ b/minishell/libft/output/ft_putstr_fd.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/26 14:23:51 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 22:02:10 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:59:09 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,63 +19,3 @@ void ft_putstr_fd(char *s, int fd) write(fd, s, ft_strlen(s)); return ; } - -// #include "libft.h" -// #include // for open() -// #include // for printf() -// #include // for close(), read() - -// int main(void) -// { -// int fd; -// char buffer[100]; -// int bytes_read; - -// // Test Case 1: Output string to standard output -// printf("Test Case 1: Output string to standard output: "); -// ft_putstr_fd("Hello, World!", 1); -// printf("\n"); -// // Test Case 2: Output string to standard error -// fprintf(stderr, "Test Case 2: Output string to standard error: "); -// ft_putstr_fd("Error message", 2); -// fprintf(stderr, "\n"); -// // Test Case 3: Output string to a file -// printf("Test Case 3: Output string to a file\n"); -// fd = open("test_putstr.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); -// if (fd == -1) -// { -// printf("Error: Could not open file\n"); -// return (1); -// } -// ft_putstr_fd("42Tokyo", fd); -// close(fd); -// // Open the file and check its contents -// fd = open("test_putstr.txt", O_RDONLY); -// if (fd == -1) -// { -// printf("Error: Could not read file\n"); -// return (1); -// } -// bytes_read = read(fd, buffer, sizeof(buffer) - 1); -// buffer[bytes_read] = '\0'; -// printf("File contents: %s\n", buffer); -// close(fd); -// // Test Case 4: Empty string -// printf("Test Case 4: Output empty string\n"); -// fd = open("test_empty.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); -// if (fd != -1) -// { -// ft_putstr_fd("", fd); -// close(fd); -// fd = open("test_empty.txt", O_RDONLY); -// bytes_read = read(fd, buffer, sizeof(buffer) - 1); -// buffer[bytes_read] = '\0'; -// printf("Result of empty string: \"%s\"\n", buffer); -// close(fd); -// } -// // Test Case 5: NULL pointer -// printf("Test Case 5: NULL pointer (check no crash occurs)\n"); -// ft_putstr_fd(NULL, 1); -// printf("NULL test complete\n"); -// return (0); -// } diff --git a/minishell/libft/string/ft_split.c b/minishell/libft/string/ft_split.c index 63ac92d..37be22e 100644 --- a/minishell/libft/string/ft_split.c +++ b/minishell/libft/string/ft_split.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/01 21:07:26 by kjikuhar #+# #+# */ -/* Updated: 2025/05/05 13:14:10 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:59:18 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -109,22 +109,3 @@ char **ft_split(char const *s, char c) *splitted = NULL; return (p); } -// #include - -// int main(void) -// { -// char *target_str = "//Hello/World /42/ Tok/yo!.../.."; -// char delimiter = '/'; -// int n = count_words_(target_str, delimiter); -// char **strs = ft_split(target_str, delimiter); - -// printf("%d\n", n); -// printf("%d\n", ft_strlen_for_split_(target_str, delimiter)); -// for (int i = 0; i <= n; i++) -// { -// printf("[%d] : %s\n", i, strs[i]); -// free(strs[i]); -// } -// free(strs); -// return (0); -// } diff --git a/minishell/libft/string/ft_strchr.c b/minishell/libft/string/ft_strchr.c index 5677a18..1193436 100644 --- a/minishell/libft/string/ft_strchr.c +++ b/minishell/libft/string/ft_strchr.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/25 21:03:19 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 22:50:08 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:59:21 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -28,50 +28,3 @@ char *ft_strchr(const char *s, int c) return ((char *)s); return (NULL); } - -// #include "libft.h" -// #include -// #include - -// void test_strchr(const char *s, int c, const char *test_name) -// { -// char *ft_result; -// char *std_result; - -// ft_result = ft_strchr(s, c); -// std_result = strchr(s, c); -// printf("Test: %s\n", test_name); -// printf("Search string: \"%s\", Search character: '%c' (ASCII: %d)\n", s, -// c >= 32 && c <= 126 ? c : ' ', c); -// if (ft_result == NULL && std_result == NULL) -// printf("Result: Both NULL (match)\n"); -// else if (ft_result != NULL && std_result != NULL) -// printf("Result: ft_strchr = %p, strchr = %p (Match: %s)\n", -// (void *)ft_result, (void *)std_result, -// ft_result == std_result ? "Yes" : "No"); -// else -// printf("Result: ft_strchr = %p, strchr = %p (Mismatch!)\n", -// (void *)ft_result, (void *)std_result); -// printf("\n"); -// } - -// int main(void) -// { -// // Test Case 1: Normal character search -// test_strchr("Hello, world!", 'w', "Normal character search"); -// // Test Case 2: First character of the string -// test_strchr("Hello, world!", 'H', "First character of the string"); -// // Test Case 3: Last character of the string -// test_strchr("Hello, world!", '!', "Last character of the string"); -// // Test Case 4: Character not present in the string -// test_strchr("Hello, world!", 'z', "Character not present"); -// // Test Case 5: NULL terminator search -// test_strchr("Hello, world!", '\0', "NULL terminator search"); -// // Test Case 6: Character appearing multiple times -// test_strchr("Hello, world!", 'l', "Character appearing multiple times"); -// // Test Case 7: Search in an empty string -// test_strchr("", 'a', "Search in an empty string"); -// // Test Case 8: Search for NULL character in an empty string -// test_strchr("", '\0', "Search for NULL character in an empty string"); -// return (0); -// } diff --git a/minishell/libft/string/ft_strdup.c b/minishell/libft/string/ft_strdup.c index 36fec73..77fab6c 100644 --- a/minishell/libft/string/ft_strdup.c +++ b/minishell/libft/string/ft_strdup.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/03/27 05:14:00 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 11:36:10 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:59:23 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -30,18 +30,3 @@ char *ft_strdup(const char *s) *tmp = '\0'; return (p); } - -// #include -// #include - -// int main(void) -// { -// char *c; -// char *d; - -// c = "1234567890"; -// d = ft_strdup(c); -// printf("%s", ft_strdup(c)); -// free(d); -// return (0); -// } diff --git a/minishell/libft/string/ft_striteri.c b/minishell/libft/string/ft_striteri.c index 8c999e7..daa3ea8 100644 --- a/minishell/libft/string/ft_striteri.c +++ b/minishell/libft/string/ft_striteri.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/26 14:04:33 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 22:04:53 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:59:28 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -23,58 +23,3 @@ void ft_striteri(char *s, void (*f)(unsigned int, char *)) index++; } } -// #include "libft.h" -// #include -// #include - -// // Function to convert all lowercase letters to uppercase -// void convert_to_upper(unsigned int i, char *c) -// { -// (void)i; // Index is not used -// if (*c >= 'a' && *c <= 'z') -// *c = *c - 'a' + 'A'; -// } - -// // Function to convert only even-indexed characters to uppercase -// void convert_even_index_to_upper(unsigned int i, char *c) -// { -// if (i % 2 == 0 && *c >= 'a' && *c <= 'z') -// *c = *c - 'a' + 'A'; -// } - -// // Function to print each character with its index (for debugging) -// void print_with_index(unsigned int i, char *c) -// { -// printf("[%u]:%c ", i, *c); -// } - -// int main(void) -// { -// char str1[] = "hello world"; -// char str2[] = "abcdefghij"; -// char str3[] = "42tokyo"; -// char str4[] = ""; - -// // Test Case 1: Normal string -// printf("Original string: %s\n", str1); -// ft_striteri(str1, convert_to_upper); -// printf("After converting to uppercase: %s\n", str1); -// // Test Case 2: Using another conversion function -// printf("\nOriginal string: %s\n", str2); -// ft_striteri(str2, convert_even_index_to_upper); -// printf("After converting only even indices to uppercase: %s\n", str2); -// // Test Case 3: Debugging function -// printf("\nOriginal string: %s\n", str3); -// printf("Each character with its index: "); -// ft_striteri(str3, print_with_index); -// printf("\n"); -// // Test Case 4: Empty string -// printf("\nEmpty string test: "); -// ft_striteri(str4, convert_to_upper); -// printf("Result: \"%s\"\n", str4); -// // Test Case 5: NULL pointer and function (should handle gracefully) -// printf("\nNULL pointer test (nothing should happen)\n"); -// ft_striteri(NULL, convert_to_upper); -// ft_striteri(str1, NULL); -// return (0); -// } diff --git a/minishell/libft/string/ft_strjoin.c b/minishell/libft/string/ft_strjoin.c index 58a18dd..84c3609 100644 --- a/minishell/libft/string/ft_strjoin.c +++ b/minishell/libft/string/ft_strjoin.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/03/28 20:47:54 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 22:05:33 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:59:34 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -59,73 +59,3 @@ char *ft_strjoin(char const *s1, char const *s2) ft_strcat(dest, s2); return (dest); } - -// #include "libft.h" -// #include -// #include -// #include - -// void test_strjoin(char const *s1, char const *s2, const char *test_name) -// { -// char *result; -// char *expected; - -// result = ft_strjoin(s1, s2); -// expected = NULL; -// printf("Test: %s\n", test_name); -// printf("String 1: \"%s\"\n", s1 ? s1 : "(null)"); -// printf("String 2: \"%s\"\n", s2 ? s2 : "(null)"); -// printf("Result: \"%s\"\n", result ? result : "(null)"); -// if (s1 && s2) -// { -// expected = malloc(strlen(s1) + strlen(s2) + 1); -// if (expected) -// { -// strcpy(expected, s1); -// strcat(expected, s2); -// printf("Expected: \"%s\"\n", expected); -// printf("Match: %s\n", (result && strcmp(result, -// expected) == 0) ? "Yes" : "No"); -// free(expected); -// } -// } -// else -// { -// printf("Expected: NULL\n"); -// printf("Match: %s\n", (!result) ? "Yes" : "No"); -// } -// printf("\n"); -// if (result) -// free(result); -// } - -// int main(void) -// { -// char long_str1[500], long_str2[500]; - -// // 1. Basic string concatenation -// test_strjoin("Hello, ", "world!", "Basic string concatenation"); -// // 2. Concatenation with empty string -// test_strjoin("", "Test", "Concatenation with empty and normal string"); -// // 3. Both strings empty -// test_strjoin("", "", "Both strings empty"); -// // 4. Concatenation including special characters (newline) -// test_strjoin("Hello\n", "World", "Concatenation including newline"); -// // 5. Concatenation including tab character -// test_strjoin("Hello\t", "World", "Concatenation including tab"); -// // 6. Concatenation of long strings -// memset(long_str1, 'A', 499); -// long_str1[499] = '\0'; -// memset(long_str2, 'B', 499); -// long_str2[499] = '\0'; -// test_strjoin(long_str1, long_str2, "Concatenation of long strings"); -// // 7. Concatenation of Japanese (multibyte) strings -// test_strjoin("こんにちは", "世界", "Concatenation of Japanese strings"); -// // 8. Concatenation of numbers and symbols -// test_strjoin("12345", "!@#$%", "Concatenation of numbers and symbols"); -// // 9. Handling NULL pointer in s1 -// test_strjoin(NULL, "Test", "Handling NULL for s1"); -// // 10. Handling both NULL -// test_strjoin(NULL, NULL, "Handling both NULL"); -// return (0); -// } diff --git a/minishell/libft/string/ft_strlcat.c b/minishell/libft/string/ft_strlcat.c index 073e5c7..ae136f1 100644 --- a/minishell/libft/string/ft_strlcat.c +++ b/minishell/libft/string/ft_strlcat.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/03/18 11:41:28 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 11:54:38 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:59:36 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -41,19 +41,3 @@ size_t ft_strlcat(char *dst, const char *src, size_t size) dst[dst_length + i] = '\0'; return (dst_length + src_length); } - -// #include -// #include - -// int main(void) -// { -// char dest[200] = "12345"; -// char src[200] = "1234567890"; -// size_t result; - -// printf("%zu\n", ft_strnlen(dest, 3)); -// result = ft_strlcat(dest, src, 3); -// printf("dest = %s\n", dest); -// printf("result = %zu\n", result); -// return (0); -// } diff --git a/minishell/libft/string/ft_strlcpy.c b/minishell/libft/string/ft_strlcpy.c index 813e864..079f8bd 100644 --- a/minishell/libft/string/ft_strlcpy.c +++ b/minishell/libft/string/ft_strlcpy.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/03/19 20:28:11 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 22:56:27 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:59:40 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -31,20 +31,3 @@ size_t ft_strlcpy(char *dst, const char *src, size_t size) dst[i] = '\0'; return (src_len); } - -// #include - -// #include - -// int main(void) -// { -// char str1[8] = "Tokyo"; -// char strs[10][20] = {"Hello","World1234567890", "42", "Tokyo", "24", -// "Kyoto"}; - -// printf("%i\n", ft_strlcpy(str1, strs[1], 0)); -// printf("%s\n", str1); -// printf("%i\n", str_len(strs[1])); - -// return (0); -// } diff --git a/minishell/libft/string/ft_strlen.c b/minishell/libft/string/ft_strlen.c index 778a382..6ee613d 100644 --- a/minishell/libft/string/ft_strlen.c +++ b/minishell/libft/string/ft_strlen.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/24 22:06:53 by kjikuhar #+# #+# */ -/* Updated: 2025/05/16 20:20:20 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:59:42 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -23,16 +23,3 @@ size_t ft_strlen(const char *s) length++; return (length); } - -// #include - -// int main(void) -// { -// char *strs[] = {"Hello World 42 Tokyo!", "1234567890", -// "abcdefghijklmnopqrstuvwxyz"}; -// for (int i = 0; i < sizeof(strs) / sizeof(strs[0]); i++) -// { -// printf("%10s : %zu\n", strs[i], ft_strlen((const char *)strs[i])); -// } -// return (0); -// } diff --git a/minishell/libft/string/ft_strmapi.c b/minishell/libft/string/ft_strmapi.c index 3bfc2cf..0c4d100 100644 --- a/minishell/libft/string/ft_strmapi.c +++ b/minishell/libft/string/ft_strmapi.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/26 12:57:28 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 11:36:10 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:59:45 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -33,24 +33,3 @@ char *ft_strmapi(char const *s, char (*f)(unsigned int, char)) rtv_str[index] = '\0'; return (rtv_str); } - -// #include - -// char convert_to_upper(unsigned int index, char c) -// { -// (void)index; -// if ('a' <= c && c <= 'z') -// return (c - 'a' + 'A'); -// return (c); -// } - -// int main(void) -// { -// char *str = "42Tokyo"; -// printf("%zu\n", ft_strlen_(str)); - -// char *convert_str = ft_strmapi(str, convert_to_upper); -// printf("%s\n", convert_str); -// free(convert_str); -// return (0); -// } diff --git a/minishell/libft/string/ft_strncmp.c b/minishell/libft/string/ft_strncmp.c index 88fb5f9..d34b479 100644 --- a/minishell/libft/string/ft_strncmp.c +++ b/minishell/libft/string/ft_strncmp.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/24 22:22:54 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 22:17:52 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:59:51 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -26,18 +26,3 @@ int ft_strncmp(const char *s1, const char *s2, size_t n) } return (0); } - -// #include - -// int main(void) -// { -// char *str[] = {"Hello World 42 Tokyo!", "0123456789", -// "abcdefghijklmnopqrstuvwxyz", "01234556789"}; -// printf("%i\n", ft_strncmp((const char *)str[1], (const char *)str[3], 7)); -// printf("%i\n", ft_strncmp((const char *)str[1], (const char *)str[3], 7)); -// printf("%i\n", ft_strncmp((const char *)str[1], (const char *)str[3], 7)); -// printf("%i\n", ft_strncmp((const char *)str[1], (const char *)str[3], 7)); -// printf("%i\n", ft_strncmp((const char *)str[1], (const char *)str[3], 7)); - -// return (0); -// } diff --git a/minishell/libft/string/ft_strnstr.c b/minishell/libft/string/ft_strnstr.c index fecd98b..cd2bc59 100644 --- a/minishell/libft/string/ft_strnstr.c +++ b/minishell/libft/string/ft_strnstr.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/25 21:07:45 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 22:54:06 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:59:54 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -38,58 +38,3 @@ char *ft_strnstr(const char *big, const char *little, size_t len) } return (NULL); } - -// #include "libft.h" -// #include -// #include -// #include - -// // Function to display test results -// void test_strnstr(const char *big, const char *little, size_t len, -// const char *test_name) -// { -// char *ft_result; -// char *org_result; - -// ft_result = ft_strnstr(big, little, len); -// org_result = strnstr(big, little, len); -// printf("Test: %s\n", test_name); -// printf("Target string: \"%s\"\n", big); -// printf("Search string: \"%s\"\n", little); -// printf("Search length: %zu\n", len); -// // Display result pointer as string, or "(null)" if NULL -// printf("ft_strnstr result: %s\n", ft_result ? ft_result : "(null)"); -// printf("strnstr result: %s\n", org_result ? org_result : "(null)"); -// printf("Pointer match: %s\n\n", (ft_result == org_result) ? "Yes" : "No"); -// } - -// int main(void) -// { -// char str_with_null[] = "Hello\0world"; -// unsigned char binary[] = {0x10, 0x20, 0x30, 0x40, 0x50}; -// unsigned char pattern[] = {0x30, 0x40}; - -// // Test case 1: Basic search -// test_strnstr("Hello, world!", "world", 13, "Basic search"); -// // Test case 2: Partial search (within limit) -// test_strnstr("Hello, world!", "world", 13, "Partial search within limit"); -// // Test case 3: Partial search (outside limit) -// test_strnstr("Hello, world!", "world", 8, "Partial search outside limit"); -// // Test case 4: Match at beginning -// test_strnstr("Hello, world!", "Hello", 13, "Match at beginning"); -// // Test case 5: Match at end -// test_strnstr("Hello, world!", "ld!", 13, "Match at end"); -// // Test case 6: Non-existent string -// test_strnstr("Hello, world!", "xyz", 13, "Non-existent string"); -// // Test case 7: Empty search string -// test_strnstr("Hello, world!", "", 13, "Empty search string"); -// // Test case 8: Search after NULL character -// test_strnstr(str_with_null, "world", 11, "Search after NULL character"); -// // Test case 9: Binary data -// test_strnstr((char *)binary, (char *)pattern, 5, "Binary data"); -// // Test case 10: Search with length 0 -// test_strnstr("Hello, world!", "Hello", 0, "Search with length 0"); -// // Test case 11: Duplicate pattern -// test_strnstr("abababab", "abab", 8, "Duplicate pattern"); -// return (0); -// } diff --git a/minishell/libft/string/ft_strrchr.c b/minishell/libft/string/ft_strrchr.c index 0e26db5..21485a1 100644 --- a/minishell/libft/string/ft_strrchr.c +++ b/minishell/libft/string/ft_strrchr.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/25 21:03:19 by kjikuhar #+# #+# */ -/* Updated: 2025/05/05 18:16:21 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 14:59:58 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,49 +17,3 @@ char *ft_strrchr(const char *s, int c) { return (ft_memrchr(s, c, ft_strlen(s) + 1)); } -// #include "libft.h" -// #include -// #include - -// void test_strrchr(const char *s, int c, const char *test_name) -// { -// char *ft_result; -// char *std_result; - -// ft_result = ft_strrchr(s, c); -// std_result = strrchr(s, c); -// printf("Test: %s\n", test_name); -// printf("Search string: \"%s\", Search character: '%c' (ASCII: %d)\n", s, -// c >= 32 && c <= 126 ? c : ' ', c); -// if (ft_result == NULL && std_result == NULL) -// printf("Result: Both NULL (match)\n"); -// else if (ft_result != NULL && std_result != NULL) -// printf("Result: ft_strrchr = %p, strrchr = %p (Match: %s)\n", -// (void *)ft_result, (void *)std_result, -// ft_result == std_result ? "Yes" : "No"); -// else -// printf("Result: ft_strrchr = %p, strrchr = %p (Mismatch!)\n", -// (void *)ft_result, (void *)std_result); -// printf("\n"); -// } - -// int main(void) -// { -// // Test Case 1: Normal character search -// test_strrchr("Hello, world!", 'w', "Normal character search"); -// // Test Case 2: First character of the string -// test_strrchr("Hello, world!", 'H', "First character of the string"); -// // Test Case 3: Last character of the string -// test_strrchr("Hello, world!", '!', "Last character of the string"); -// // Test Case 4: Character not present in the string -// test_strrchr("Hello, world!", 'z', "Character not present"); -// // Test Case 5: NULL terminator search -// test_strrchr("Hello, world!", '\0', "NULL terminator search"); -// // Test Case 6: Character appearing multiple times -// test_strrchr("Hello, world!", 'l', "Character appearing multiple times"); -// // Test Case 7: Search in an empty string -// test_strrchr("", 'a', "Search in an empty string"); -// // Test Case 8: Search for NULL character in an empty string -// test_strrchr("", '\0', "Search for NULL character in an empty string"); -// return (0); -// } diff --git a/minishell/libft/string/ft_strtrim.c b/minishell/libft/string/ft_strtrim.c index 759c8fd..0f709e0 100644 --- a/minishell/libft/string/ft_strtrim.c +++ b/minishell/libft/string/ft_strtrim.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/25 22:58:35 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 22:07:09 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 15:00:04 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -42,92 +42,3 @@ char *ft_strtrim(char const *s1, char const *set) ft_strlcpy(dest, s1, dest_len + 1); return (dest); } - -// #include -// #include -// #include - -// // テスト関数 -// void run_test(const char *test_name, const char *input, const char *set, -// const char *expected_output) -// { -// char *result; - -// result = ft_strtrim(input, set); -// printf("Test: %s\n", test_name); -// printf("Input: \"%s\"\n", input); -// printf("Set: \"%s\"\n", set); -// printf("Expected: \"%s\"\n", expected_output); -// printf("Result: \"%s\"\n", result); -// if ((result == NULL && expected_output == NULL) || (result -// && expected_output && strcmp((const char *)result, -// expected_output) == 0)) -// { -// printf("Status: ✅ Passed\n"); -// } -// else -// { -// printf("Status: ❌ Failed\n"); -// } -// free(result); -// printf("\n"); -// // } -// int main(void) -// { -// // Test Case 1: Normal trim -// run_test("Normal Trim", " Hello World! ", " ", "Hello World!"); -// // Test Case 2: Empty input string -// run_test("Empty Input", "", " ", ""); -// // Test Case 3: No trim characters present -// run_test("No Trim Characters", "HelloWorld", " ", "HelloWorld"); -// // Test Case 4: Entire input string is trim target -// run_test("Full Trim", ".....", ".", ""); -// // Test Case 5: Empty set -// run_test("Empty Set", " Hello World! ", "", " Hello World! "); -// // Test Case 6: Trim only at both ends -// run_test("Trim Both Ends", "xxHello World!xx", "x", "Hello World!"); -// // Test Case 7: Trim including special characters -// run_test("Special Characters", "\t\nHello World!\n\t", "\t\n", -// "Hello World!"); -// // Test Case 8: NULL pointer (input string) -// run_test("NULL Input", NULL, " ", NULL); -// // Test Case 9: NULL pointer (set) -// run_test("NULL Set", " Hello World! ", NULL, NULL); -// // Test Case 10: Partial trim at both ends -// run_test("Partial Trim", "xyHello World!yz", "xyz", "Hello World!"); -// // Test Case 11: Set with numbers -// run_test("Numeric Set", "12345Hello12345", "12345", "Hello"); -// // Test Case 12: Multiple types of trim characters at both ends -// run_test("Multiple Trim Characters", " ***Hello*** ", " *", "Hello"); -// // Test Case 13: NULL set with non-NULL input -// run_test("NULL Set with Non-NULL Input", "Hello World!", NULL, NULL); -// // Test Case 14: NULL input with non-NULL set -// run_test("NULL Input with Non-NULL Set", NULL, " ", NULL); -// // Test Case 15: Different trim characters at each end -// run_test("Different Trim Characters", "abcHello World!xyz", "abcxyz", -// "Hello World!"); -// // Test Case 16: Input fully composed of set characters -// run_test("Input Fully Matches Set", "aaaaa", "a", ""); -// // Test Case 17: Set does not overlap with input string -// run_test("Set Does Not Match Input", "Hello World!", "xyz", "Hello World!"); -// // Test Case 18: NULL input and NULL set -// run_test("NULL Input and NULL Set", NULL, NULL, NULL); -// // Test Case 19: Empty string as set -// run_test("Empty Set", "Hello World!", "", "Hello World!"); -// // Test Case 20: Empty input with non-empty set -// run_test("Empty Input with Non-Empty Set", "", "abc", ""); -// // Test Case 21: Long input string and set -// run_test("Long String and Set", -// " This is a very long string for testing purposes. ", " ", -// "This is a very long string for testing purposes."); -// // Test Case 22: All characters are trimmed -// run_test("All Characters are Trimmed", "xxxxxxxxxx", "x", ""); -// // Test Case 23: Set includes special characters and numbers -// run_test("Set Includes Special Characters", "123Hello World!321", "123!", -// "Hello World"); -// // Test Case 24: Input contains only whitespace -// run_test("Whitespace Only Input", " ", " ", ""); -// // Test Case 25: Both input string and set are empty -// run_test("Empty Input and Empty Set", "", "", ""); -// return (0); -// } diff --git a/minishell/libft/string/ft_substr.c b/minishell/libft/string/ft_substr.c index 65b0f4c..e136db7 100644 --- a/minishell/libft/string/ft_substr.c +++ b/minishell/libft/string/ft_substr.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/25 22:00:05 by kjikuhar #+# #+# */ -/* Updated: 2025/05/04 22:08:53 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 15:00:09 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -37,69 +37,3 @@ char *ft_substr(char const *s, unsigned int start, size_t len) substr[i] = '\0'; return (substr); } - -// #include "libft.h" -// #include -// #include - -// void test_substr(char const *s, unsigned int start, size_t len, -// const char *test_name) -// { -// char *result; - -// result = ft_substr(s, start, len); -// printf("Test: %s\n", test_name); -// printf("Original string: \"%s\"\n", s ? s : "(null)"); -// printf("Start position: %u, Length: %zu\n", start, len); -// printf("Result: \"%s\"\n", result ? result : "(null)"); -// printf("Result length: %zu\n", result ? strlen(result) : 0); -// printf("\n"); -// if (result) -// free(result); -// } - -// int main(void) -// { -// char long_str[1000]; - -// // Test Case 1: Basic substring extraction -// test_substr("Hello, world!", 7, 5, "Basic substring extraction"); -// // Test Case 2: Start position beyond string length -// test_substr("Hello", 10, 5, "Start position beyond string length"); -// // Test Case 3: Length longer than remaining string -// test_substr("Hello", 2, 10, "Length longer than remaining string"); -// // Test Case 4: Empty string -// test_substr("", 0, 5, "Empty string"); -// // Test Case 5: Start position at last character -// test_substr("Hello", 4, 1, "Start position at last character"); -// // Test Case 6: Length is zero -// test_substr("Hello", 2, 0, "Length zero"); -// // Test Case 7: Very large length specified -// test_substr("Hello", 0, 1000, "Very large length specified"); -// // Additional test cases -// test_substr("Hello, world!", 0, 5, "Extract from start of string"); -// test_substr("Hello\nworld", 5, 6, "String including newline"); -// test_substr("Hello\tworld", 5, 6, "String including tab"); -// test_substr(" Hello ", 3, 5, "String including spaces"); -// test_substr("Hello", 0, 0, "Extract zero length from start"); -// // Boundary tests on string length -// test_substr("A", 0, 1, "Extract entire one-character string"); -// test_substr("AB", 0, 1, -// "Extract first character from two-character string"); -// test_substr("AB", 1, 1, -// "Extract second character from two-character string"); -// // Very long string (memory efficiency test) -// memset(long_str, 'X', 999); -// long_str[999] = '\0'; -// test_substr(long_str, 500, 100, "Extract part of very long string"); -// // Special index cases -// test_substr("Hello, world!", 7, 0, "Valid start but zero length"); -// test_substr("Hello, world!", 12, 1, "Extract last character ('!')"); -// test_substr("Hello, world!", 13, 0, "Extract zero length at string end"); -// // String including special characters -// test_substr("Hello\"quotes\"", 5, 8, "String including quotes"); -// test_substr("Hello\\escape", 5, 7, "String including escape character"); -// // NULL pointer case -// test_substr(NULL, 0, 5, "NULL pointer"); -// return (0); -// } From fe95557079f7dd7875694b62c93178ded632392f Mon Sep 17 00:00:00 2001 From: Jikuhara Date: Mon, 29 Sep 2025 15:01:55 +0900 Subject: [PATCH 004/173] delete .vscode/settings.json --- minishell/libft/.vscode/settings.json | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 minishell/libft/.vscode/settings.json diff --git a/minishell/libft/.vscode/settings.json b/minishell/libft/.vscode/settings.json deleted file mode 100644 index 2bdaf25..0000000 --- a/minishell/libft/.vscode/settings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "files.associations": { - "stdbool.h": "c", - "libft.h": "c", - "string": "c" - } -} From ce5d17927237d1b2735fc502eb27aa6df91e4203 Mon Sep 17 00:00:00 2001 From: Jikuhara Date: Mon, 29 Sep 2025 15:06:43 +0900 Subject: [PATCH 005/173] revise Makefile and header file --- minishell/libft/Makefile | 4 +- minishell/libft/libft.h | 116 +++++++++++++++++++++++---------------- 2 files changed, 71 insertions(+), 49 deletions(-) diff --git a/minishell/libft/Makefile b/minishell/libft/Makefile index 1e45f5a..b74c873 100644 --- a/minishell/libft/Makefile +++ b/minishell/libft/Makefile @@ -6,13 +6,13 @@ # By: kjikuhar +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/04/04 16:00:02 by kjikuhar #+# #+# # -# Updated: 2025/06/02 20:46:59 by kjikuhar ### ########.fr # +# Updated: 2025/09/29 15:03:45 by kjikuhar ### ########.fr # # # # **************************************************************************** # CC = cc RM = rm -f -CFLAGS = -Wall -Wextra -Werror -I../includes/ +CFLAGS = -Wall -Wextra -Werror -I. NAME = libft.a SRCS = conversion/ft_atoi.c \ diff --git a/minishell/libft/libft.h b/minishell/libft/libft.h index f375e84..556dd50 100644 --- a/minishell/libft/libft.h +++ b/minishell/libft/libft.h @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/25 14:55:13 by kjikuhar #+# #+# */ -/* Updated: 2025/05/05 20:02:11 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 15:05:15 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,9 +14,10 @@ # define LIBFT_H # include +# include +# include # include # include -# include typedef struct s_list { @@ -24,51 +25,72 @@ typedef struct s_list struct s_list *next; } t_list; -int ft_atoi(const char *str); -void ft_bzero(void *s, size_t n); -void *ft_calloc(size_t count, size_t size); -int ft_isalnum(int c); -int ft_isalpha(int c); -int ft_isascii(int c); -int ft_isdigit(int c); -int ft_isprint(int c); -char *ft_itoa(int n); -void *ft_memchr(const void *s, int c, size_t n); -int ft_memcmp(const void *s1, const void *s2, size_t n); -void *ft_memcpy(void *dest, const void *src, size_t n); -void *ft_memmove(void *dest, const void *src, size_t len); -void *ft_memset(void *s, int c, size_t n); -void ft_putchar_fd(char c, int fd); -void ft_putendl_fd(char *s, int fd); -void ft_putnbr_fd(int n, int fd); -void ft_putstr_fd(char *s, int fd); -char **ft_split(char const *s, char c); -char *ft_strchr(const char *s, int c); -char *ft_strdup(const char *s); -void ft_striteri(char *s, void (*f)(unsigned int, char *)); -char *ft_strjoin(char const *s1, char const *s2); -size_t ft_strlcat(char *dst, const char *src, size_t size); -size_t ft_strlcpy(char *dst, const char *src, size_t size); -size_t ft_strlen(const char *s); -char *ft_strmapi(char const *s, char (*f)(unsigned int, char)); -int ft_strncmp(const char *s1, const char *s2, size_t n); -char *ft_strnstr(const char *big, const char *little, size_t len); -char *ft_strrchr(const char *s, int c); -char *ft_strtrim(char const *s1, char const *set); -char *ft_substr(char const *s, unsigned int start, size_t len); -int ft_tolower(int c); -int ft_toupper(int c); -void *ft_memrchr(const void *s, int c, size_t n); +// conversion +int ft_atoi(const char *str); +char *ft_itoa(int n); +int ft_tolower(int c); +int ft_toupper(int c); + +// judge +int ft_isalnum(int c); +int ft_isalpha(int c); +int ft_isascii(int c); +int ft_isdigit(int c); +int ft_isprint(int c); + +// list +t_list *ft_lstnew(void *content); +void ft_lstadd_front(t_list **lst, t_list *new); +t_list *ft_lstlast(t_list *lst); +int ft_lstsize(t_list *lst); +void ft_lstadd_back(t_list **lst, t_list *new); +void ft_lstdelone(t_list *lst, void (*del)(void *)); +void ft_lstclear(t_list **lst, void (*del)(void *)); +void ft_lstiter(t_list *lst, void (*f)(void *)); +t_list *ft_lstmap(t_list *lst, void *(*f)(void *), void (*del)(void *)); + +// memory +void ft_bzero(void *s, size_t n); +void *ft_calloc(size_t count, size_t size); +void *ft_memchr(const void *s, int c, size_t n); +int ft_memcmp(const void *s1, const void *s2, size_t n); +void *ft_memcpy(void *dest, const void *src, size_t n); +void *ft_memmove(void *dest, const void *src, size_t len); +void *ft_memrchr(const void *s, int c, size_t n); +void *ft_memset(void *s, int c, size_t n); + +// original functions +void ft_swap(int *a, int *b); +int ft_isspace(const char c); +int ft_max_int(int a, int b, int *m); +long ft_max_long(long a, long b); +long long ft_max_long_long(long long a, long long b); +size_t ft_max_size_t(size_t a, size_t b); +int ft_min_int(int a, int b); +long ft_min_long(long a, long b); +long long ft_min_long_long(long long a, long long b); +size_t ft_min_size_t(size_t a, size_t b); + +// output +void ft_putchar_fd(char c, int fd); +void ft_putendl_fd(char *s, int fd); +void ft_putnbr_fd(int n, int fd); +void ft_putstr_fd(char *s, int fd); -// Bonus -t_list *ft_lstnew(void *content); -void ft_lstadd_front(t_list **lst, t_list *new); -t_list *ft_lstlast(t_list *lst); -int ft_lstsize(t_list *lst); -void ft_lstadd_back(t_list **lst, t_list *new); -void ft_lstdelone(t_list *lst, void (*del)(void *)); -void ft_lstclear(t_list **lst, void (*del)(void *)); -void ft_lstiter(t_list *lst, void (*f)(void *)); -t_list *ft_lstmap(t_list *lst, void *(*f)(void *), void (*del)(void *)); +// string +char **ft_split(char const *s, char c); +char *ft_strchr(const char *s, int c); +char *ft_strdup(const char *s); +void ft_striteri(char *s, void (*f)(unsigned int, char *)); +char *ft_strjoin(char const *s1, char const *s2); +size_t ft_strlcat(char *dst, const char *src, size_t size); +size_t ft_strlcpy(char *dst, const char *src, size_t size); +size_t ft_strlen(const char *s); +char *ft_strmapi(char const *s, char (*f)(unsigned int, char)); +int ft_strncmp(const char *s1, const char *s2, size_t n); +char *ft_strnstr(const char *big, const char *little, size_t len); +char *ft_strrchr(const char *s, int c); +char *ft_strtrim(char const *s1, char const *set); +char *ft_substr(char const *s, unsigned int start, size_t len); #endif From a37dd34290703b7ad7e726ec20344faad75c00f3 Mon Sep 17 00:00:00 2001 From: Jikuhara Date: Mon, 29 Sep 2025 15:20:28 +0900 Subject: [PATCH 006/173] add Makefile template --- minishell/Makefile | 115 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 minishell/Makefile diff --git a/minishell/Makefile b/minishell/Makefile new file mode 100644 index 0000000..d058975 --- /dev/null +++ b/minishell/Makefile @@ -0,0 +1,115 @@ +# **************************************************************************** # +# # +# ::: :::::::: # +# Makefile :+: :+: :+: # +# +:+ +:+ +:+ # +# By: kjikuhar +#+ +:+ +#+ # +# +#+#+#+#+#+ +#+ # +# Created: 2025/05/18 21:11:39 by kjikuhar #+# #+# # +# Updated: 2025/09/29 15:17:10 by kjikuhar ### ########.fr # +# # +# **************************************************************************** # + +#----------------------------------------------------------------------------- +#> options +#----------------------------------------------------------------------------- +BLACK := \033[30m +RED := \033[31m +GREEN := \033[32m +YELLOW := \033[33m +BLUE := \033[96m +MAGENTA := \033[38;5;206m +CYAN := \033[36m +WHITE := \033[37m +RESET := \033[0m +BOLD := \033[1m +DIM := \033[2m +ITALIC := \033[3m +UNDER := \033[4m +BLINK := \033[5m +REVERSE := \033[7m +HIDDEN := \033[8m +PINK := \033[35m + +#----------------------------------------------------------------------------- + +#▸ variables + +#----------------------------------------------------------------------------- + +NAME := minishell + +#─ compile config ──────────────────────────────────────────────────────────── + +CC := cc +CFLAGS := -Wall -Wextra -Werror -Iincludes -Ilibft + +#─ directory name ──────────────────────────────────────────────────────────── + +SRCDIR := src +MAND := mandatory +OBJDIR := obj +LIBFT_DIR := libft +LIBFT_A := $(LIBFT_DIR)/libft.a + +#─ sources & objects ───────────────────────────────────────────────────────── + +#mandatory sources +SRCS_MAND := src/main.c + +#bonus sources + +SRCS_BONUS := + +#object files + +OBJS_MAND := $(SRCS_MAND:$(SRCDIR)/%.c=$(OBJDIR)/%.o) +OBJS_BONUS := $(SRCS_BONUS:$(SRCDIR)/%.c=$(OBJDIR)/%.o) +# OBJS := $(OBJS_MAND) $(OBJS_BONUS) + +#----------------------------------------------------------------------------- + +#▸ rules + +#----------------------------------------------------------------------------- + +all: $(NAME) + +$(NAME): $(LIBFT_A) $(OBJS_MAND) + @echo "Compiled with $(GREEN)$(BOLD)$(CFLAGS)$(RESET)" + @$(CC) $(CFLAGS) $(OBJS_MAND) -o $@ $(LIBFT_A) + @echo "$(YELLOW)$(BOLD)=========================================" + @echo " You can use My $(NAME)!!" + @echo "=========================================$(RESET)" + +# compile object files + +$(OBJDIR)/%.o: $(SRCDIR)/%.c + @mkdir -p $(dir $@) + @echo "Compiled ✅ $(WHITE) $(BOLD) $^ $(RESET)" + @$(CC) $(CFLAGS) -c -o $@ $^ + +# libft +$(LIBFT_A): + @$(MAKE) -C $(LIBFT_DIR) + +# clean targets +clean: + @$(MAKE) -C $(LIBFT_DIR) clean + @rm -rf $(OBJDIR) + +fclean: clean + @$(MAKE) -C $(LIBFT_DIR) fclean + @rm -f $(NAME) + +re: fclean all + +# bonus: $(LIBFT_A) $(OBJS_BONUS) +# @cp $(LIBFT_A) $(NAME) +# @echo "Compiled with $(GREEN)$(BOLD)$(CFLAGS)$(RESET)" +# @ar rcs $(NAME) $(OBJS_BONUS) +# @echo "$(YELLOW)$(BOLD)=========================================" +# @echo " You can use My Bonus_$(NAME)!!" +# @echo "=========================================$(RESET)" + +.PHONY: all clean fclean re bonus From 68c5cc4c72e249455eba5163828156f583af3bc9 Mon Sep 17 00:00:00 2001 From: Jikuhara Date: Mon, 29 Sep 2025 15:20:49 +0900 Subject: [PATCH 007/173] add src directory template --- minishell/src/main.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 minishell/src/main.c diff --git a/minishell/src/main.c b/minishell/src/main.c new file mode 100644 index 0000000..780544d --- /dev/null +++ b/minishell/src/main.c @@ -0,0 +1,21 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* main.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/09/29 15:13:47 by kjikuhar #+# #+# */ +/* Updated: 2025/09/29 15:17:54 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +int main(int argc, char const *argv[]) +{ + (void)argc; + (void)argv; + printf("test\n"); + return (0); +} From fb7a050c16a4201363cb351b57405c31da98076d Mon Sep 17 00:00:00 2001 From: Jikuhara Date: Mon, 29 Sep 2025 15:21:05 +0900 Subject: [PATCH 008/173] add includes template --- minishell/includes/minishell.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 minishell/includes/minishell.h diff --git a/minishell/includes/minishell.h b/minishell/includes/minishell.h new file mode 100644 index 0000000..b20ba43 --- /dev/null +++ b/minishell/includes/minishell.h @@ -0,0 +1,17 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* minishell.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/09/29 15:14:22 by kjikuhar #+# #+# */ +/* Updated: 2025/09/29 15:17:31 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef MINISHELL_H +# define MINISHELL_H + +#include "../libft/libft.h" +#endif From 7a1357900a91587529d824044cc005f414396879 Mon Sep 17 00:00:00 2001 From: Jikuhara Date: Mon, 29 Sep 2025 15:43:05 +0900 Subject: [PATCH 009/173] revise some --- minishell/libft/conversion/ft_atoi.c | 5 ++++- minishell/libft/original/ft_isspace.c | 5 +++-- minishell/libft/string/ft_strdup.c | 4 ++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/minishell/libft/conversion/ft_atoi.c b/minishell/libft/conversion/ft_atoi.c index 2206b5e..b992826 100644 --- a/minishell/libft/conversion/ft_atoi.c +++ b/minishell/libft/conversion/ft_atoi.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/24 21:08:27 by kjikuhar #+# #+# */ -/* Updated: 2025/09/29 14:57:08 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 15:37:25 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -21,8 +21,11 @@ int ft_atoi(const char *str) str++; sign = 1; if (*str == '+' || *str == '-') + { if (*str == '-') sign *= -1; + str++; + } num = 0; while (ft_isdigit((int)*str)) num = 10 * num + (*str++ - '0'); diff --git a/minishell/libft/original/ft_isspace.c b/minishell/libft/original/ft_isspace.c index cb27822..24c731e 100644 --- a/minishell/libft/original/ft_isspace.c +++ b/minishell/libft/original/ft_isspace.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/11 18:12:36 by kjikuhar #+# #+# */ -/* Updated: 2025/05/11 18:14:44 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 15:41:22 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,5 +14,6 @@ int ft_isspace(const char c) { - return ((9 <= c && c <= 13) || c == 32); + return (c == '\a' || c == '\b' || c == '\t' || c == '\n' || c == '\v' + || c == '\f' || c == '\r' || c == ' '); } diff --git a/minishell/libft/string/ft_strdup.c b/minishell/libft/string/ft_strdup.c index 77fab6c..0f27d67 100644 --- a/minishell/libft/string/ft_strdup.c +++ b/minishell/libft/string/ft_strdup.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/03/27 05:14:00 by kjikuhar #+# #+# */ -/* Updated: 2025/09/29 14:59:23 by kjikuhar ### ########.fr */ +/* Updated: 2025/09/29 15:42:45 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,7 +14,7 @@ char *ft_strdup(const char *s) { - char *tmp ; + char *tmp; char *p; tmp = (char *)malloc(sizeof(s[0]) * (ft_strlen(s) + 1)); From 88b065c3652106a78d575374d0621b8aaacba061 Mon Sep 17 00:00:00 2001 From: urassh Date: Wed, 1 Oct 2025 17:06:04 +0900 Subject: [PATCH 010/173] =?UTF-8?q?minishell=E3=83=87=E3=82=A3=E3=83=AC?= =?UTF-8?q?=E3=82=AF=E3=83=88=E3=83=AA=E3=81=8B=E3=82=89=E5=B9=B3=E5=9D=A6?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- minishell/Makefile => Makefile | 0 {minishell/includes => includes}/minishell.h | 0 {minishell/libft => libft}/Makefile | 0 {minishell/libft => libft}/conversion/ft_atoi.c | 0 {minishell/libft => libft}/conversion/ft_itoa.c | 0 {minishell/libft => libft}/conversion/ft_tolower.c | 0 {minishell/libft => libft}/conversion/ft_toupper.c | 0 {minishell/libft => libft}/judge/ft_isalnum.c | 0 {minishell/libft => libft}/judge/ft_isalpha.c | 0 {minishell/libft => libft}/judge/ft_isascii.c | 0 {minishell/libft => libft}/judge/ft_isdigit.c | 0 {minishell/libft => libft}/judge/ft_isprint.c | 0 {minishell/libft => libft}/libft.h | 0 {minishell/libft => libft}/list/ft_lstadd_back.c | 0 {minishell/libft => libft}/list/ft_lstadd_front.c | 0 {minishell/libft => libft}/list/ft_lstclear.c | 0 {minishell/libft => libft}/list/ft_lstdelone.c | 0 {minishell/libft => libft}/list/ft_lstiter.c | 0 {minishell/libft => libft}/list/ft_lstlast.c | 0 {minishell/libft => libft}/list/ft_lstmap.c | 0 {minishell/libft => libft}/list/ft_lstnew.c | 0 {minishell/libft => libft}/list/ft_lstsize.c | 0 {minishell/libft => libft}/memory/ft_bzero.c | 0 {minishell/libft => libft}/memory/ft_calloc.c | 0 {minishell/libft => libft}/memory/ft_memchr.c | 0 {minishell/libft => libft}/memory/ft_memcmp.c | 0 {minishell/libft => libft}/memory/ft_memcpy.c | 0 {minishell/libft => libft}/memory/ft_memmove.c | 0 {minishell/libft => libft}/memory/ft_memrchr.c | 0 {minishell/libft => libft}/memory/ft_memset.c | 0 {minishell/libft => libft}/original/ft_isspace.c | 0 {minishell/libft => libft}/original/ft_max.c | 0 {minishell/libft => libft}/original/ft_min.c | 0 {minishell/libft => libft}/original/ft_swap.c | 0 {minishell/libft => libft}/output/ft_putchar_fd.c | 0 {minishell/libft => libft}/output/ft_putendl_fd.c | 0 {minishell/libft => libft}/output/ft_putnbr_fd.c | 0 {minishell/libft => libft}/output/ft_putstr_fd.c | 0 {minishell/libft => libft}/string/ft_split.c | 0 {minishell/libft => libft}/string/ft_strchr.c | 0 {minishell/libft => libft}/string/ft_strdup.c | 0 {minishell/libft => libft}/string/ft_striteri.c | 0 {minishell/libft => libft}/string/ft_strjoin.c | 0 {minishell/libft => libft}/string/ft_strlcat.c | 0 {minishell/libft => libft}/string/ft_strlcpy.c | 0 {minishell/libft => libft}/string/ft_strlen.c | 0 {minishell/libft => libft}/string/ft_strmapi.c | 0 {minishell/libft => libft}/string/ft_strncmp.c | 0 {minishell/libft => libft}/string/ft_strnstr.c | 0 {minishell/libft => libft}/string/ft_strrchr.c | 0 {minishell/libft => libft}/string/ft_strtrim.c | 0 {minishell/libft => libft}/string/ft_substr.c | 0 {minishell/src => src}/main.c | 0 53 files changed, 0 insertions(+), 0 deletions(-) rename minishell/Makefile => Makefile (100%) rename {minishell/includes => includes}/minishell.h (100%) rename {minishell/libft => libft}/Makefile (100%) rename {minishell/libft => libft}/conversion/ft_atoi.c (100%) rename {minishell/libft => libft}/conversion/ft_itoa.c (100%) rename {minishell/libft => libft}/conversion/ft_tolower.c (100%) rename {minishell/libft => libft}/conversion/ft_toupper.c (100%) rename {minishell/libft => libft}/judge/ft_isalnum.c (100%) rename {minishell/libft => libft}/judge/ft_isalpha.c (100%) rename {minishell/libft => libft}/judge/ft_isascii.c (100%) rename {minishell/libft => libft}/judge/ft_isdigit.c (100%) rename {minishell/libft => libft}/judge/ft_isprint.c (100%) rename {minishell/libft => libft}/libft.h (100%) rename {minishell/libft => libft}/list/ft_lstadd_back.c (100%) rename {minishell/libft => libft}/list/ft_lstadd_front.c (100%) rename {minishell/libft => libft}/list/ft_lstclear.c (100%) rename {minishell/libft => libft}/list/ft_lstdelone.c (100%) rename {minishell/libft => libft}/list/ft_lstiter.c (100%) rename {minishell/libft => libft}/list/ft_lstlast.c (100%) rename {minishell/libft => libft}/list/ft_lstmap.c (100%) rename {minishell/libft => libft}/list/ft_lstnew.c (100%) rename {minishell/libft => libft}/list/ft_lstsize.c (100%) rename {minishell/libft => libft}/memory/ft_bzero.c (100%) rename {minishell/libft => libft}/memory/ft_calloc.c (100%) rename {minishell/libft => libft}/memory/ft_memchr.c (100%) rename {minishell/libft => libft}/memory/ft_memcmp.c (100%) rename {minishell/libft => libft}/memory/ft_memcpy.c (100%) rename {minishell/libft => libft}/memory/ft_memmove.c (100%) rename {minishell/libft => libft}/memory/ft_memrchr.c (100%) rename {minishell/libft => libft}/memory/ft_memset.c (100%) rename {minishell/libft => libft}/original/ft_isspace.c (100%) rename {minishell/libft => libft}/original/ft_max.c (100%) rename {minishell/libft => libft}/original/ft_min.c (100%) rename {minishell/libft => libft}/original/ft_swap.c (100%) rename {minishell/libft => libft}/output/ft_putchar_fd.c (100%) rename {minishell/libft => libft}/output/ft_putendl_fd.c (100%) rename {minishell/libft => libft}/output/ft_putnbr_fd.c (100%) rename {minishell/libft => libft}/output/ft_putstr_fd.c (100%) rename {minishell/libft => libft}/string/ft_split.c (100%) rename {minishell/libft => libft}/string/ft_strchr.c (100%) rename {minishell/libft => libft}/string/ft_strdup.c (100%) rename {minishell/libft => libft}/string/ft_striteri.c (100%) rename {minishell/libft => libft}/string/ft_strjoin.c (100%) rename {minishell/libft => libft}/string/ft_strlcat.c (100%) rename {minishell/libft => libft}/string/ft_strlcpy.c (100%) rename {minishell/libft => libft}/string/ft_strlen.c (100%) rename {minishell/libft => libft}/string/ft_strmapi.c (100%) rename {minishell/libft => libft}/string/ft_strncmp.c (100%) rename {minishell/libft => libft}/string/ft_strnstr.c (100%) rename {minishell/libft => libft}/string/ft_strrchr.c (100%) rename {minishell/libft => libft}/string/ft_strtrim.c (100%) rename {minishell/libft => libft}/string/ft_substr.c (100%) rename {minishell/src => src}/main.c (100%) diff --git a/minishell/Makefile b/Makefile similarity index 100% rename from minishell/Makefile rename to Makefile diff --git a/minishell/includes/minishell.h b/includes/minishell.h similarity index 100% rename from minishell/includes/minishell.h rename to includes/minishell.h diff --git a/minishell/libft/Makefile b/libft/Makefile similarity index 100% rename from minishell/libft/Makefile rename to libft/Makefile diff --git a/minishell/libft/conversion/ft_atoi.c b/libft/conversion/ft_atoi.c similarity index 100% rename from minishell/libft/conversion/ft_atoi.c rename to libft/conversion/ft_atoi.c diff --git a/minishell/libft/conversion/ft_itoa.c b/libft/conversion/ft_itoa.c similarity index 100% rename from minishell/libft/conversion/ft_itoa.c rename to libft/conversion/ft_itoa.c diff --git a/minishell/libft/conversion/ft_tolower.c b/libft/conversion/ft_tolower.c similarity index 100% rename from minishell/libft/conversion/ft_tolower.c rename to libft/conversion/ft_tolower.c diff --git a/minishell/libft/conversion/ft_toupper.c b/libft/conversion/ft_toupper.c similarity index 100% rename from minishell/libft/conversion/ft_toupper.c rename to libft/conversion/ft_toupper.c diff --git a/minishell/libft/judge/ft_isalnum.c b/libft/judge/ft_isalnum.c similarity index 100% rename from minishell/libft/judge/ft_isalnum.c rename to libft/judge/ft_isalnum.c diff --git a/minishell/libft/judge/ft_isalpha.c b/libft/judge/ft_isalpha.c similarity index 100% rename from minishell/libft/judge/ft_isalpha.c rename to libft/judge/ft_isalpha.c diff --git a/minishell/libft/judge/ft_isascii.c b/libft/judge/ft_isascii.c similarity index 100% rename from minishell/libft/judge/ft_isascii.c rename to libft/judge/ft_isascii.c diff --git a/minishell/libft/judge/ft_isdigit.c b/libft/judge/ft_isdigit.c similarity index 100% rename from minishell/libft/judge/ft_isdigit.c rename to libft/judge/ft_isdigit.c diff --git a/minishell/libft/judge/ft_isprint.c b/libft/judge/ft_isprint.c similarity index 100% rename from minishell/libft/judge/ft_isprint.c rename to libft/judge/ft_isprint.c diff --git a/minishell/libft/libft.h b/libft/libft.h similarity index 100% rename from minishell/libft/libft.h rename to libft/libft.h diff --git a/minishell/libft/list/ft_lstadd_back.c b/libft/list/ft_lstadd_back.c similarity index 100% rename from minishell/libft/list/ft_lstadd_back.c rename to libft/list/ft_lstadd_back.c diff --git a/minishell/libft/list/ft_lstadd_front.c b/libft/list/ft_lstadd_front.c similarity index 100% rename from minishell/libft/list/ft_lstadd_front.c rename to libft/list/ft_lstadd_front.c diff --git a/minishell/libft/list/ft_lstclear.c b/libft/list/ft_lstclear.c similarity index 100% rename from minishell/libft/list/ft_lstclear.c rename to libft/list/ft_lstclear.c diff --git a/minishell/libft/list/ft_lstdelone.c b/libft/list/ft_lstdelone.c similarity index 100% rename from minishell/libft/list/ft_lstdelone.c rename to libft/list/ft_lstdelone.c diff --git a/minishell/libft/list/ft_lstiter.c b/libft/list/ft_lstiter.c similarity index 100% rename from minishell/libft/list/ft_lstiter.c rename to libft/list/ft_lstiter.c diff --git a/minishell/libft/list/ft_lstlast.c b/libft/list/ft_lstlast.c similarity index 100% rename from minishell/libft/list/ft_lstlast.c rename to libft/list/ft_lstlast.c diff --git a/minishell/libft/list/ft_lstmap.c b/libft/list/ft_lstmap.c similarity index 100% rename from minishell/libft/list/ft_lstmap.c rename to libft/list/ft_lstmap.c diff --git a/minishell/libft/list/ft_lstnew.c b/libft/list/ft_lstnew.c similarity index 100% rename from minishell/libft/list/ft_lstnew.c rename to libft/list/ft_lstnew.c diff --git a/minishell/libft/list/ft_lstsize.c b/libft/list/ft_lstsize.c similarity index 100% rename from minishell/libft/list/ft_lstsize.c rename to libft/list/ft_lstsize.c diff --git a/minishell/libft/memory/ft_bzero.c b/libft/memory/ft_bzero.c similarity index 100% rename from minishell/libft/memory/ft_bzero.c rename to libft/memory/ft_bzero.c diff --git a/minishell/libft/memory/ft_calloc.c b/libft/memory/ft_calloc.c similarity index 100% rename from minishell/libft/memory/ft_calloc.c rename to libft/memory/ft_calloc.c diff --git a/minishell/libft/memory/ft_memchr.c b/libft/memory/ft_memchr.c similarity index 100% rename from minishell/libft/memory/ft_memchr.c rename to libft/memory/ft_memchr.c diff --git a/minishell/libft/memory/ft_memcmp.c b/libft/memory/ft_memcmp.c similarity index 100% rename from minishell/libft/memory/ft_memcmp.c rename to libft/memory/ft_memcmp.c diff --git a/minishell/libft/memory/ft_memcpy.c b/libft/memory/ft_memcpy.c similarity index 100% rename from minishell/libft/memory/ft_memcpy.c rename to libft/memory/ft_memcpy.c diff --git a/minishell/libft/memory/ft_memmove.c b/libft/memory/ft_memmove.c similarity index 100% rename from minishell/libft/memory/ft_memmove.c rename to libft/memory/ft_memmove.c diff --git a/minishell/libft/memory/ft_memrchr.c b/libft/memory/ft_memrchr.c similarity index 100% rename from minishell/libft/memory/ft_memrchr.c rename to libft/memory/ft_memrchr.c diff --git a/minishell/libft/memory/ft_memset.c b/libft/memory/ft_memset.c similarity index 100% rename from minishell/libft/memory/ft_memset.c rename to libft/memory/ft_memset.c diff --git a/minishell/libft/original/ft_isspace.c b/libft/original/ft_isspace.c similarity index 100% rename from minishell/libft/original/ft_isspace.c rename to libft/original/ft_isspace.c diff --git a/minishell/libft/original/ft_max.c b/libft/original/ft_max.c similarity index 100% rename from minishell/libft/original/ft_max.c rename to libft/original/ft_max.c diff --git a/minishell/libft/original/ft_min.c b/libft/original/ft_min.c similarity index 100% rename from minishell/libft/original/ft_min.c rename to libft/original/ft_min.c diff --git a/minishell/libft/original/ft_swap.c b/libft/original/ft_swap.c similarity index 100% rename from minishell/libft/original/ft_swap.c rename to libft/original/ft_swap.c diff --git a/minishell/libft/output/ft_putchar_fd.c b/libft/output/ft_putchar_fd.c similarity index 100% rename from minishell/libft/output/ft_putchar_fd.c rename to libft/output/ft_putchar_fd.c diff --git a/minishell/libft/output/ft_putendl_fd.c b/libft/output/ft_putendl_fd.c similarity index 100% rename from minishell/libft/output/ft_putendl_fd.c rename to libft/output/ft_putendl_fd.c diff --git a/minishell/libft/output/ft_putnbr_fd.c b/libft/output/ft_putnbr_fd.c similarity index 100% rename from minishell/libft/output/ft_putnbr_fd.c rename to libft/output/ft_putnbr_fd.c diff --git a/minishell/libft/output/ft_putstr_fd.c b/libft/output/ft_putstr_fd.c similarity index 100% rename from minishell/libft/output/ft_putstr_fd.c rename to libft/output/ft_putstr_fd.c diff --git a/minishell/libft/string/ft_split.c b/libft/string/ft_split.c similarity index 100% rename from minishell/libft/string/ft_split.c rename to libft/string/ft_split.c diff --git a/minishell/libft/string/ft_strchr.c b/libft/string/ft_strchr.c similarity index 100% rename from minishell/libft/string/ft_strchr.c rename to libft/string/ft_strchr.c diff --git a/minishell/libft/string/ft_strdup.c b/libft/string/ft_strdup.c similarity index 100% rename from minishell/libft/string/ft_strdup.c rename to libft/string/ft_strdup.c diff --git a/minishell/libft/string/ft_striteri.c b/libft/string/ft_striteri.c similarity index 100% rename from minishell/libft/string/ft_striteri.c rename to libft/string/ft_striteri.c diff --git a/minishell/libft/string/ft_strjoin.c b/libft/string/ft_strjoin.c similarity index 100% rename from minishell/libft/string/ft_strjoin.c rename to libft/string/ft_strjoin.c diff --git a/minishell/libft/string/ft_strlcat.c b/libft/string/ft_strlcat.c similarity index 100% rename from minishell/libft/string/ft_strlcat.c rename to libft/string/ft_strlcat.c diff --git a/minishell/libft/string/ft_strlcpy.c b/libft/string/ft_strlcpy.c similarity index 100% rename from minishell/libft/string/ft_strlcpy.c rename to libft/string/ft_strlcpy.c diff --git a/minishell/libft/string/ft_strlen.c b/libft/string/ft_strlen.c similarity index 100% rename from minishell/libft/string/ft_strlen.c rename to libft/string/ft_strlen.c diff --git a/minishell/libft/string/ft_strmapi.c b/libft/string/ft_strmapi.c similarity index 100% rename from minishell/libft/string/ft_strmapi.c rename to libft/string/ft_strmapi.c diff --git a/minishell/libft/string/ft_strncmp.c b/libft/string/ft_strncmp.c similarity index 100% rename from minishell/libft/string/ft_strncmp.c rename to libft/string/ft_strncmp.c diff --git a/minishell/libft/string/ft_strnstr.c b/libft/string/ft_strnstr.c similarity index 100% rename from minishell/libft/string/ft_strnstr.c rename to libft/string/ft_strnstr.c diff --git a/minishell/libft/string/ft_strrchr.c b/libft/string/ft_strrchr.c similarity index 100% rename from minishell/libft/string/ft_strrchr.c rename to libft/string/ft_strrchr.c diff --git a/minishell/libft/string/ft_strtrim.c b/libft/string/ft_strtrim.c similarity index 100% rename from minishell/libft/string/ft_strtrim.c rename to libft/string/ft_strtrim.c diff --git a/minishell/libft/string/ft_substr.c b/libft/string/ft_substr.c similarity index 100% rename from minishell/libft/string/ft_substr.c rename to libft/string/ft_substr.c diff --git a/minishell/src/main.c b/src/main.c similarity index 100% rename from minishell/src/main.c rename to src/main.c From 8251be59293caee7abe5ea1cb8229a40d868e644 Mon Sep 17 00:00:00 2001 From: urassh Date: Wed, 1 Oct 2025 17:55:35 +0900 Subject: [PATCH 011/173] =?UTF-8?q?fix:=20minishell.h=E3=81=AEnorminette?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- includes/minishell.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/includes/minishell.h b/includes/minishell.h index b20ba43..c3ab83f 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -13,5 +13,6 @@ #ifndef MINISHELL_H # define MINISHELL_H -#include "../libft/libft.h" +# include "../libft/libft.h" + #endif From c1c3bcc0d47a33fca17b6e63745f088fe2d3ef6d Mon Sep 17 00:00:00 2001 From: urassh Date: Wed, 1 Oct 2025 17:13:12 +0900 Subject: [PATCH 012/173] =?UTF-8?q?feat:=20=E3=83=97=E3=83=AD=E3=83=B3?= =?UTF-8?q?=E3=83=97=E3=83=88=E6=A9=9F=E8=83=BD=E3=81=AE=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 3 ++- includes/minishell.h | 3 ++- includes/prompt.h | 26 +++++++++++++++++++ src/main.c | 22 ++++++++++++---- src/prompt/prompt.c | 61 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+), 7 deletions(-) create mode 100644 includes/prompt.h create mode 100644 src/prompt/prompt.c diff --git a/Makefile b/Makefile index d058975..80ccbeb 100644 --- a/Makefile +++ b/Makefile @@ -55,7 +55,8 @@ LIBFT_A := $(LIBFT_DIR)/libft.a #─ sources & objects ───────────────────────────────────────────────────────── #mandatory sources -SRCS_MAND := src/main.c +SRCS_MAND := src/main.c \ + src/prompt/prompt.c #bonus sources diff --git a/includes/minishell.h b/includes/minishell.h index c3ab83f..5d1cf06 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -13,6 +13,7 @@ #ifndef MINISHELL_H # define MINISHELL_H -# include "../libft/libft.h" +#include "../libft/libft.h" +#include "prompt.h" #endif diff --git a/includes/prompt.h b/includes/prompt.h new file mode 100644 index 0000000..067b601 --- /dev/null +++ b/includes/prompt.h @@ -0,0 +1,26 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* prompt.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/10/01 15:35:18 by urassh #+# #+# */ +/* Updated: 2025/10/01 16:50:03 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef PROMPT_H +# define PROMPT_H + +# include "../libft/libft.h" +# include +# include +# include + +int prompt(int (*handler)(char *input)); + +# define PROMPT_BUFFER_SIZE 1024 +# define PROMPT "minishell$ " + +#endif diff --git a/src/main.c b/src/main.c index 780544d..f61f9dc 100644 --- a/src/main.c +++ b/src/main.c @@ -10,12 +10,24 @@ /* */ /* ************************************************************************** */ -#include "minishell.h" +#include "../includes/minishell.h" -int main(int argc, char const *argv[]) +int on_input(char *input) { - (void)argc; - (void)argv; - printf("test\n"); + if (!input) + return (0); + if (ft_strncmp(input, "exit", 4) == 0 && (input[4] == '\0' + || ft_isspace(input[4]))) + { + write(STDOUT_FILENO, "exit", 4); + return (0); + } + write(STDOUT_FILENO, input, ft_strlen(input)); + return (1); +} + +int main(void) +{ + prompt(on_input); return (0); } diff --git a/src/prompt/prompt.c b/src/prompt/prompt.c new file mode 100644 index 0000000..9543174 --- /dev/null +++ b/src/prompt/prompt.c @@ -0,0 +1,61 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* prompt.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/10/01 15:35:00 by urassh #+# #+# */ +/* Updated: 2025/10/01 16:49:19 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../../includes/prompt.h" + +static char *read_line(void); + +int prompt(int (*handler)(char *input)) +{ + char *input; + int should_continue; + + while (1) + { + write(STDOUT_FILENO, PROMPT, ft_strlen(PROMPT)); + input = read_line(); + if (!input) + break ; + should_continue = 1; + if (handler) + should_continue = handler(input); + write(STDOUT_FILENO, "\n", 1); + free(input); + input = NULL; + if (!should_continue) + break ; + } + return (0); +} + +static char *read_line(void) +{ + char *buffer; + char *line; + ssize_t bytes_read; + + buffer = malloc(PROMPT_BUFFER_SIZE); + if (!buffer) + return (NULL); + bytes_read = read(STDIN_FILENO, buffer, PROMPT_BUFFER_SIZE - 1); + if (bytes_read <= 0) + { + free(buffer); + return (NULL); + } + buffer[bytes_read] = '\0'; + if (buffer[bytes_read - 1] == '\n') + buffer[bytes_read - 1] = '\0'; + line = ft_strdup(buffer); + free(buffer); + return (line); +} From cfebedcde826656f0aa0c030b38edcab4822575e Mon Sep 17 00:00:00 2001 From: jiku0730 Date: Wed, 1 Oct 2025 17:28:23 +0900 Subject: [PATCH 013/173] revise prompt --- Makefile | 210 ++++++++++++++++++++++---------------------- src/prompt/prompt.c | 82 +++++++++++------ src/prompt/prompt.h | 28 ++++++ 3 files changed, 188 insertions(+), 132 deletions(-) create mode 100644 src/prompt/prompt.h diff --git a/Makefile b/Makefile index 80ccbeb..286d2db 100644 --- a/Makefile +++ b/Makefile @@ -1,116 +1,120 @@ -# **************************************************************************** # -# # -# ::: :::::::: # -# Makefile :+: :+: :+: # -# +:+ +:+ +:+ # -# By: kjikuhar +#+ +:+ +#+ # -# +#+#+#+#+#+ +#+ # -# Created: 2025/05/18 21:11:39 by kjikuhar #+# #+# # -# Updated: 2025/09/29 15:17:10 by kjikuhar ### ########.fr # -# # -# **************************************************************************** # - -#----------------------------------------------------------------------------- -#> options -#----------------------------------------------------------------------------- -BLACK := \033[30m -RED := \033[31m -GREEN := \033[32m -YELLOW := \033[33m -BLUE := \033[96m -MAGENTA := \033[38;5;206m -CYAN := \033[36m -WHITE := \033[37m -RESET := \033[0m -BOLD := \033[1m -DIM := \033[2m -ITALIC := \033[3m -UNDER := \033[4m -BLINK := \033[5m -REVERSE := \033[7m -HIDDEN := \033[8m -PINK := \033[35m - -#----------------------------------------------------------------------------- - -#▸ variables - -#----------------------------------------------------------------------------- - -NAME := minishell - -#─ compile config ──────────────────────────────────────────────────────────── - -CC := cc -CFLAGS := -Wall -Wextra -Werror -Iincludes -Ilibft - -#─ directory name ──────────────────────────────────────────────────────────── - -SRCDIR := src -MAND := mandatory -OBJDIR := obj -LIBFT_DIR := libft -LIBFT_A := $(LIBFT_DIR)/libft.a - -#─ sources & objects ───────────────────────────────────────────────────────── - -#mandatory sources -SRCS_MAND := src/main.c \ - src/prompt/prompt.c - -#bonus sources - -SRCS_BONUS := - -#object files - -OBJS_MAND := $(SRCS_MAND:$(SRCDIR)/%.c=$(OBJDIR)/%.o) -OBJS_BONUS := $(SRCS_BONUS:$(SRCDIR)/%.c=$(OBJDIR)/%.o) -# OBJS := $(OBJS_MAND) $(OBJS_BONUS) - -#----------------------------------------------------------------------------- - -#▸ rules - -#----------------------------------------------------------------------------- +NAME = minishell + +SRCDIR = src +INCDIR = src +OBJDIR = obj + +CC = cc +CFLAGS = -Wall -Wextra -Werror +INCLUDES = -I$(INCDIR) -I$(INCDIR)/libft -I$(INCDIR)/prompt + +LIBFT_SRCS = $(SRCDIR)/libft/conversion/ft_atoi.c \ + $(SRCDIR)/libft/conversion/ft_itoa.c \ + $(SRCDIR)/libft/conversion/ft_tolower.c \ + $(SRCDIR)/libft/conversion/ft_toupper.c \ + $(SRCDIR)/libft/judge/ft_isalnum.c \ + $(SRCDIR)/libft/judge/ft_isalpha.c \ + $(SRCDIR)/libft/judge/ft_isascii.c \ + $(SRCDIR)/libft/judge/ft_isdigit.c \ + $(SRCDIR)/libft/judge/ft_isprint.c \ + $(SRCDIR)/libft/list/ft_lstadd_back.c \ + $(SRCDIR)/libft/list/ft_lstadd_front.c \ + $(SRCDIR)/libft/list/ft_lstclear.c \ + $(SRCDIR)/libft/list/ft_lstdelone.c \ + $(SRCDIR)/libft/list/ft_lstiter.c \ + $(SRCDIR)/libft/list/ft_lstlast.c \ + $(SRCDIR)/libft/list/ft_lstmap.c \ + $(SRCDIR)/libft/list/ft_lstnew.c \ + $(SRCDIR)/libft/list/ft_lstsize.c \ + $(SRCDIR)/libft/memory/ft_bzero.c \ + $(SRCDIR)/libft/memory/ft_calloc.c \ + $(SRCDIR)/libft/memory/ft_memchr.c \ + $(SRCDIR)/libft/memory/ft_memcmp.c \ + $(SRCDIR)/libft/memory/ft_memcpy.c \ + $(SRCDIR)/libft/memory/ft_memmove.c \ + $(SRCDIR)/libft/memory/ft_memrchr.c \ + $(SRCDIR)/libft/memory/ft_memset.c \ + $(SRCDIR)/libft/original/ft_isspace.c \ + $(SRCDIR)/libft/original/ft_max.c \ + $(SRCDIR)/libft/original/ft_min.c \ + $(SRCDIR)/libft/original/ft_swap.c \ + $(SRCDIR)/libft/output/ft_putchar_fd.c \ + $(SRCDIR)/libft/output/ft_putendl_fd.c \ + $(SRCDIR)/libft/output/ft_putnbr_fd.c \ + $(SRCDIR)/libft/output/ft_putstr_fd.c \ + $(SRCDIR)/libft/string/ft_split.c \ + $(SRCDIR)/libft/string/ft_strchr.c \ + $(SRCDIR)/libft/string/ft_strdup.c \ + $(SRCDIR)/libft/string/ft_striteri.c \ + $(SRCDIR)/libft/string/ft_strjoin.c \ + $(SRCDIR)/libft/string/ft_strlcat.c \ + $(SRCDIR)/libft/string/ft_strlcpy.c \ + $(SRCDIR)/libft/string/ft_strlen.c \ + $(SRCDIR)/libft/string/ft_strmapi.c \ + $(SRCDIR)/libft/string/ft_strncmp.c \ + $(SRCDIR)/libft/string/ft_strnstr.c \ + $(SRCDIR)/libft/string/ft_strrchr.c \ + $(SRCDIR)/libft/string/ft_strtrim.c \ + $(SRCDIR)/libft/string/ft_substr.c + +PROMPT_SRCS = $(SRCDIR)/prompt/prompt.c + +MAIN_SRCS = $(SRCDIR)/main.c + +SRCS = $(MAIN_SRCS) $(LIBFT_SRCS) $(PROMPT_SRCS) + +OBJS = $(SRCS:$(SRCDIR)/%.c=$(OBJDIR)/%.o) + +HEADERS = $(INCDIR)/minishell.h \ + $(INCDIR)/libft/libft.h \ + $(INCDIR)/prompt/prompt.h + +GREEN = \033[0;32m +YELLOW = \033[0;33m +RED = \033[0;31m +NC = \033[0m all: $(NAME) -$(NAME): $(LIBFT_A) $(OBJS_MAND) - @echo "Compiled with $(GREEN)$(BOLD)$(CFLAGS)$(RESET)" - @$(CC) $(CFLAGS) $(OBJS_MAND) -o $@ $(LIBFT_A) - @echo "$(YELLOW)$(BOLD)=========================================" - @echo " You can use My $(NAME)!!" - @echo "=========================================$(RESET)" +$(NAME): $(OBJS) + @echo "$(YELLOW)Linking $(NAME)...$(NC)" + @$(CC) $(CFLAGS) $(OBJS) -lreadline -o $(NAME) + @echo "$(GREEN) $(NAME) created successfully!$(NC)" -# compile object files - -$(OBJDIR)/%.o: $(SRCDIR)/%.c +$(OBJDIR)/%.o: $(SRCDIR)/%.c $(HEADERS) | $(OBJDIR) @mkdir -p $(dir $@) - @echo "Compiled ✅ $(WHITE) $(BOLD) $^ $(RESET)" - @$(CC) $(CFLAGS) -c -o $@ $^ - -# libft -$(LIBFT_A): - @$(MAKE) -C $(LIBFT_DIR) + @echo "$(YELLOW)Compiling $<...$(NC)" + @$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ + +$(OBJDIR): + @mkdir -p $(OBJDIR)/prompt + @mkdir -p $(OBJDIR)/libft/conversion + @mkdir -p $(OBJDIR)/libft/judge + @mkdir -p $(OBJDIR)/libft/list + @mkdir -p $(OBJDIR)/libft/memory + @mkdir -p $(OBJDIR)/libft/original + @mkdir -p $(OBJDIR)/libft/output + @mkdir -p $(OBJDIR)/libft/string + +%: + @: -# clean targets clean: - @$(MAKE) -C $(LIBFT_DIR) clean - @rm -rf $(OBJDIR) + @if [ -d $(OBJDIR) ]; then \ + echo "$(RED)Removing object files...$(NC)"; \ + rm -rf $(OBJDIR); \ + echo "$(GREEN) Object files removed!$(NC)"; \ + fi fclean: clean - @$(MAKE) -C $(LIBFT_DIR) fclean - @rm -f $(NAME) + @if [ -f $(NAME) ]; then \ + echo "$(RED)Removing $(NAME)...$(NC)"; \ + rm -f $(NAME); \ + echo "$(GREEN) $(NAME) removed!$(NC)"; \ + fi re: fclean all -# bonus: $(LIBFT_A) $(OBJS_BONUS) -# @cp $(LIBFT_A) $(NAME) -# @echo "Compiled with $(GREEN)$(BOLD)$(CFLAGS)$(RESET)" -# @ar rcs $(NAME) $(OBJS_BONUS) -# @echo "$(YELLOW)$(BOLD)=========================================" -# @echo " You can use My Bonus_$(NAME)!!" -# @echo "=========================================$(RESET)" +.PHONY: all clean fclean re -.PHONY: all clean fclean re bonus +.PRECIOUS: $(OBJDIR)/%.o diff --git a/src/prompt/prompt.c b/src/prompt/prompt.c index 9543174..9213ba4 100644 --- a/src/prompt/prompt.c +++ b/src/prompt/prompt.c @@ -10,9 +10,57 @@ /* */ /* ************************************************************************** */ -#include "../../includes/prompt.h" +#include "prompt.h" -static char *read_line(void); +// static char *read_line(void); + +// int prompt(int (*handler)(char *input)) +// { +// char *input; +// int should_continue ; + +// while (1) +// { +// write(STDOUT_FILENO, PROMPT, ft_strlen(PROMPT)); +// input = read_line(); +// if (!input) +// break ; +// should_continue = 1; +// if (handler) +// should_continue = handler(input); +// write(STDOUT_FILENO, "\n", 1); +// free(input); +// input = NULL; +// if (!should_continue) +// break ; +// } +// return (0); +// } + +// static char *read_line(void) +// { +// char *buffer; +// char *line; +// ssize_t bytes_read; + +// buffer = malloc(PROMPT_BUFFER_SIZE); +// if (!buffer) +// return (NULL); +// bytes_read = read(STDIN_FILENO, buffer, PROMPT_BUFFER_SIZE - 1); +// if (bytes_read <= 0) +// { +// free(buffer); +// return (NULL); +// } +// buffer[bytes_read] = '\0'; +// if (buffer[bytes_read - 1] == '\n') +// buffer[bytes_read - 1] = '\0'; +// line = ft_strdup(buffer); +// free(buffer); +// return (line); +// } + +#include "prompt.h" int prompt(int (*handler)(char *input)) { @@ -21,41 +69,17 @@ int prompt(int (*handler)(char *input)) while (1) { - write(STDOUT_FILENO, PROMPT, ft_strlen(PROMPT)); - input = read_line(); + input = readline(PROMPT); if (!input) break ; + if (*input) + add_history(input); should_continue = 1; if (handler) should_continue = handler(input); - write(STDOUT_FILENO, "\n", 1); free(input); - input = NULL; if (!should_continue) break ; } return (0); } - -static char *read_line(void) -{ - char *buffer; - char *line; - ssize_t bytes_read; - - buffer = malloc(PROMPT_BUFFER_SIZE); - if (!buffer) - return (NULL); - bytes_read = read(STDIN_FILENO, buffer, PROMPT_BUFFER_SIZE - 1); - if (bytes_read <= 0) - { - free(buffer); - return (NULL); - } - buffer[bytes_read] = '\0'; - if (buffer[bytes_read - 1] == '\n') - buffer[bytes_read - 1] = '\0'; - line = ft_strdup(buffer); - free(buffer); - return (line); -} diff --git a/src/prompt/prompt.h b/src/prompt/prompt.h new file mode 100644 index 0000000..4a56094 --- /dev/null +++ b/src/prompt/prompt.h @@ -0,0 +1,28 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* prompt.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/10/01 15:35:18 by urassh #+# #+# */ +/* Updated: 2025/10/01 16:50:03 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef PROMPT_H +# define PROMPT_H + +# include "libft.h" +# include +# include +# include +# include +# include + +int prompt(int (*handler)(char *input)); + +# define PROMPT_BUFFER_SIZE 1024 +# define PROMPT "minishell$ " + +#endif From 1fee2dc8a36b01178b692a685b91d36b220d2998 Mon Sep 17 00:00:00 2001 From: urassh Date: Wed, 1 Oct 2025 17:45:42 +0900 Subject: [PATCH 014/173] =?UTF-8?q?fix:=20readline=E9=96=A2=E6=95=B0?= =?UTF-8?q?=E3=82=92=E4=BD=BF=E3=81=86=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 117 +++++++++++++++++++++++--------------------- includes/prompt.h | 3 +- src/main.c | 3 +- src/prompt/prompt.c | 50 ------------------- src/prompt/prompt.h | 28 ----------- 5 files changed, 66 insertions(+), 135 deletions(-) delete mode 100644 src/prompt/prompt.h diff --git a/Makefile b/Makefile index 286d2db..8a54ff6 100644 --- a/Makefile +++ b/Makefile @@ -6,68 +6,70 @@ OBJDIR = obj CC = cc CFLAGS = -Wall -Wextra -Werror -INCLUDES = -I$(INCDIR) -I$(INCDIR)/libft -I$(INCDIR)/prompt - -LIBFT_SRCS = $(SRCDIR)/libft/conversion/ft_atoi.c \ - $(SRCDIR)/libft/conversion/ft_itoa.c \ - $(SRCDIR)/libft/conversion/ft_tolower.c \ - $(SRCDIR)/libft/conversion/ft_toupper.c \ - $(SRCDIR)/libft/judge/ft_isalnum.c \ - $(SRCDIR)/libft/judge/ft_isalpha.c \ - $(SRCDIR)/libft/judge/ft_isascii.c \ - $(SRCDIR)/libft/judge/ft_isdigit.c \ - $(SRCDIR)/libft/judge/ft_isprint.c \ - $(SRCDIR)/libft/list/ft_lstadd_back.c \ - $(SRCDIR)/libft/list/ft_lstadd_front.c \ - $(SRCDIR)/libft/list/ft_lstclear.c \ - $(SRCDIR)/libft/list/ft_lstdelone.c \ - $(SRCDIR)/libft/list/ft_lstiter.c \ - $(SRCDIR)/libft/list/ft_lstlast.c \ - $(SRCDIR)/libft/list/ft_lstmap.c \ - $(SRCDIR)/libft/list/ft_lstnew.c \ - $(SRCDIR)/libft/list/ft_lstsize.c \ - $(SRCDIR)/libft/memory/ft_bzero.c \ - $(SRCDIR)/libft/memory/ft_calloc.c \ - $(SRCDIR)/libft/memory/ft_memchr.c \ - $(SRCDIR)/libft/memory/ft_memcmp.c \ - $(SRCDIR)/libft/memory/ft_memcpy.c \ - $(SRCDIR)/libft/memory/ft_memmove.c \ - $(SRCDIR)/libft/memory/ft_memrchr.c \ - $(SRCDIR)/libft/memory/ft_memset.c \ - $(SRCDIR)/libft/original/ft_isspace.c \ - $(SRCDIR)/libft/original/ft_max.c \ - $(SRCDIR)/libft/original/ft_min.c \ - $(SRCDIR)/libft/original/ft_swap.c \ - $(SRCDIR)/libft/output/ft_putchar_fd.c \ - $(SRCDIR)/libft/output/ft_putendl_fd.c \ - $(SRCDIR)/libft/output/ft_putnbr_fd.c \ - $(SRCDIR)/libft/output/ft_putstr_fd.c \ - $(SRCDIR)/libft/string/ft_split.c \ - $(SRCDIR)/libft/string/ft_strchr.c \ - $(SRCDIR)/libft/string/ft_strdup.c \ - $(SRCDIR)/libft/string/ft_striteri.c \ - $(SRCDIR)/libft/string/ft_strjoin.c \ - $(SRCDIR)/libft/string/ft_strlcat.c \ - $(SRCDIR)/libft/string/ft_strlcpy.c \ - $(SRCDIR)/libft/string/ft_strlen.c \ - $(SRCDIR)/libft/string/ft_strmapi.c \ - $(SRCDIR)/libft/string/ft_strncmp.c \ - $(SRCDIR)/libft/string/ft_strnstr.c \ - $(SRCDIR)/libft/string/ft_strrchr.c \ - $(SRCDIR)/libft/string/ft_strtrim.c \ - $(SRCDIR)/libft/string/ft_substr.c +INCLUDES = -Iincludes -Ilibft + +LIBFT_SRCS = libft/conversion/ft_atoi.c \ + libft/conversion/ft_itoa.c \ + libft/conversion/ft_tolower.c \ + libft/conversion/ft_toupper.c \ + libft/judge/ft_isalnum.c \ + libft/judge/ft_isalpha.c \ + libft/judge/ft_isascii.c \ + libft/judge/ft_isdigit.c \ + libft/judge/ft_isprint.c \ + libft/list/ft_lstadd_back.c \ + libft/list/ft_lstadd_front.c \ + libft/list/ft_lstclear.c \ + libft/list/ft_lstdelone.c \ + libft/list/ft_lstiter.c \ + libft/list/ft_lstlast.c \ + libft/list/ft_lstmap.c \ + libft/list/ft_lstnew.c \ + libft/list/ft_lstsize.c \ + libft/memory/ft_bzero.c \ + libft/memory/ft_calloc.c \ + libft/memory/ft_memchr.c \ + libft/memory/ft_memcmp.c \ + libft/memory/ft_memcpy.c \ + libft/memory/ft_memmove.c \ + libft/memory/ft_memrchr.c \ + libft/memory/ft_memset.c \ + libft/original/ft_isspace.c \ + libft/original/ft_max.c \ + libft/original/ft_min.c \ + libft/original/ft_swap.c \ + libft/output/ft_putchar_fd.c \ + libft/output/ft_putendl_fd.c \ + libft/output/ft_putnbr_fd.c \ + libft/output/ft_putstr_fd.c \ + libft/string/ft_split.c \ + libft/string/ft_strchr.c \ + libft/string/ft_strdup.c \ + libft/string/ft_striteri.c \ + libft/string/ft_strjoin.c \ + libft/string/ft_strlcat.c \ + libft/string/ft_strlcpy.c \ + libft/string/ft_strlen.c \ + libft/string/ft_strmapi.c \ + libft/string/ft_strncmp.c \ + libft/string/ft_strnstr.c \ + libft/string/ft_strrchr.c \ + libft/string/ft_strtrim.c \ + libft/string/ft_substr.c PROMPT_SRCS = $(SRCDIR)/prompt/prompt.c MAIN_SRCS = $(SRCDIR)/main.c -SRCS = $(MAIN_SRCS) $(LIBFT_SRCS) $(PROMPT_SRCS) +SRCS = $(MAIN_SRCS) $(PROMPT_SRCS) $(LIBFT_SRCS) -OBJS = $(SRCS:$(SRCDIR)/%.c=$(OBJDIR)/%.o) +OBJS = $(MAIN_SRCS:$(SRCDIR)/%.c=$(OBJDIR)/%.o) \ + $(PROMPT_SRCS:$(SRCDIR)/%.c=$(OBJDIR)/%.o) \ + $(LIBFT_SRCS:%.c=$(OBJDIR)/%.o) -HEADERS = $(INCDIR)/minishell.h \ - $(INCDIR)/libft/libft.h \ - $(INCDIR)/prompt/prompt.h +HEADERS = includes/minishell.h \ + includes/prompt.h \ + libft/libft.h GREEN = \033[0;32m YELLOW = \033[0;33m @@ -86,6 +88,11 @@ $(OBJDIR)/%.o: $(SRCDIR)/%.c $(HEADERS) | $(OBJDIR) @echo "$(YELLOW)Compiling $<...$(NC)" @$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ +$(OBJDIR)/%.o: %.c $(HEADERS) | $(OBJDIR) + @mkdir -p $(dir $@) + @echo "$(YELLOW)Compiling $<...$(NC)" + @$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ + $(OBJDIR): @mkdir -p $(OBJDIR)/prompt @mkdir -p $(OBJDIR)/libft/conversion diff --git a/includes/prompt.h b/includes/prompt.h index 067b601..aa242a2 100644 --- a/includes/prompt.h +++ b/includes/prompt.h @@ -14,13 +14,14 @@ # define PROMPT_H # include "../libft/libft.h" +# include +# include # include # include # include int prompt(int (*handler)(char *input)); -# define PROMPT_BUFFER_SIZE 1024 # define PROMPT "minishell$ " #endif diff --git a/src/main.c b/src/main.c index f61f9dc..882e931 100644 --- a/src/main.c +++ b/src/main.c @@ -10,7 +10,7 @@ /* */ /* ************************************************************************** */ -#include "../includes/minishell.h" +#include "minishell.h" int on_input(char *input) { @@ -23,6 +23,7 @@ int on_input(char *input) return (0); } write(STDOUT_FILENO, input, ft_strlen(input)); + write(STDOUT_FILENO, "\n", 1); return (1); } diff --git a/src/prompt/prompt.c b/src/prompt/prompt.c index 9213ba4..20c5a8c 100644 --- a/src/prompt/prompt.c +++ b/src/prompt/prompt.c @@ -12,56 +12,6 @@ #include "prompt.h" -// static char *read_line(void); - -// int prompt(int (*handler)(char *input)) -// { -// char *input; -// int should_continue ; - -// while (1) -// { -// write(STDOUT_FILENO, PROMPT, ft_strlen(PROMPT)); -// input = read_line(); -// if (!input) -// break ; -// should_continue = 1; -// if (handler) -// should_continue = handler(input); -// write(STDOUT_FILENO, "\n", 1); -// free(input); -// input = NULL; -// if (!should_continue) -// break ; -// } -// return (0); -// } - -// static char *read_line(void) -// { -// char *buffer; -// char *line; -// ssize_t bytes_read; - -// buffer = malloc(PROMPT_BUFFER_SIZE); -// if (!buffer) -// return (NULL); -// bytes_read = read(STDIN_FILENO, buffer, PROMPT_BUFFER_SIZE - 1); -// if (bytes_read <= 0) -// { -// free(buffer); -// return (NULL); -// } -// buffer[bytes_read] = '\0'; -// if (buffer[bytes_read - 1] == '\n') -// buffer[bytes_read - 1] = '\0'; -// line = ft_strdup(buffer); -// free(buffer); -// return (line); -// } - -#include "prompt.h" - int prompt(int (*handler)(char *input)) { char *input; diff --git a/src/prompt/prompt.h b/src/prompt/prompt.h deleted file mode 100644 index 4a56094..0000000 --- a/src/prompt/prompt.h +++ /dev/null @@ -1,28 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* prompt.h :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/10/01 15:35:18 by urassh #+# #+# */ -/* Updated: 2025/10/01 16:50:03 by urassh ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#ifndef PROMPT_H -# define PROMPT_H - -# include "libft.h" -# include -# include -# include -# include -# include - -int prompt(int (*handler)(char *input)); - -# define PROMPT_BUFFER_SIZE 1024 -# define PROMPT "minishell$ " - -#endif From c4346897b0326a2716665c8e87928952a467cea7 Mon Sep 17 00:00:00 2001 From: urassh Date: Wed, 1 Oct 2025 18:32:28 +0900 Subject: [PATCH 015/173] =?UTF-8?q?add:=20=E5=8B=95=E4=BD=9C=E7=A2=BA?= =?UTF-8?q?=E8=AA=8D=E3=81=AE=E9=A0=85=E7=9B=AE=E3=82=92=E8=BF=BD=E5=8A=A0?= =?UTF-8?q?=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/pull_request_template.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 6c51f4a..bc51a04 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -15,6 +15,18 @@ --> - +## 動作確認 + +- [] norminetteを通過している。 +- [] makeコマンドでビルドできる。 +- [] valgrindでリークチェックをした。(`valgrind --leak-check=full --show-leak-kinds=all -s -q `) +- [] ~~~ +- [] ~~~ +- [] ~~~ + ## ひとこと - [] norminetteを通過している。 - [] makeコマンドでビルドできる。 -- [] valgrindでリークチェックをした。(`valgrind --leak-check=full --show-leak-kinds=all -s -q `) +- [] valgrindでリークチェックをした。(`valgrind --leak-check=full --suppressions=readline.supp --show-leak-kinds=all -s -q ./minishell`) - [] ~~~ - [] ~~~ - [] ~~~ diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6177a42..bd9e072 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,8 +1,6 @@ name: Build on: - push: - branches: [ "master", "develop", "urassh/*", "jiku/*" ] pull_request: branches: [ "master", "develop" ] diff --git a/.github/workflows/leak-check.yml b/.github/workflows/leak-check.yml new file mode 100644 index 0000000..73cd084 --- /dev/null +++ b/.github/workflows/leak-check.yml @@ -0,0 +1,113 @@ +name: Memory Leak Check + +on: + pull_request: + branches: [ "master", "develop" ] + push: + branches: [ "master", "develop" ] + +jobs: + leak-check: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y build-essential libreadline-dev valgrind + + - name: Build project + run: | + echo "Building minishell..." + make + + - name: Verify binary exists + run: | + if [ ! -f "./minishell" ]; then + echo "❌ ERROR: minishell binary not found" + exit 1 + fi + echo "✅ minishell binary found" + ls -la ./minishell + + - name: Create test script + run: | + cat << 'EOF' > test_input.sh + #!/bin/bash + + # minishellにコマンドを送信してメモリリークをチェック + echo "Starting memory leak test..." + + # expectスタイルでインタラクティブな入力をシミュレート + ( + sleep 0.5 + echo "ec'c'o \"hello\"&&cat -e" + sleep 0.5 + echo "exit" + sleep 0.5 + ) | valgrind --leak-check=full \ + --show-leak-kinds=all \ + --track-origins=yes \ + --suppressions=./readline.supp \ + --error-exitcode=42 \ + --log-file=valgrind_output.txt \ + ./minishell 2>&1 + + VALGRIND_EXIT=$? + + echo "" + echo "==========================================" + echo "Valgrind Output:" + echo "==========================================" + cat valgrind_output.txt + echo "==========================================" + + # Valgrindの結果を解析 + if [ $VALGRIND_EXIT -eq 42 ]; then + echo "" + echo "❌ MEMORY LEAK DETECTED!" + echo "" + echo "Summary of leaks:" + grep "definitely lost" valgrind_output.txt || echo "No definitely lost blocks" + grep "indirectly lost" valgrind_output.txt || echo "No indirectly lost blocks" + grep "possibly lost" valgrind_output.txt || echo "No possibly lost blocks" + exit 1 + else + echo "" + echo "✅ NO MEMORY LEAKS DETECTED" + + # リークサマリーを表示 + echo "" + echo "Leak Summary:" + grep "LEAK SUMMARY" valgrind_output.txt -A 5 || true + + # 全てのヒープブロックが解放されたかチェック + if grep -q "All heap blocks were freed -- no leaks are possible" valgrind_output.txt; then + echo "✅ All heap blocks were freed" + elif grep -q "definitely lost: 0 bytes in 0 blocks" valgrind_output.txt && \ + grep -q "indirectly lost: 0 bytes in 0 blocks" valgrind_output.txt && \ + grep -q "possibly lost: 0 bytes in 0 blocks" valgrind_output.txt; then + echo "✅ No definite, indirect, or possible leaks" + else + echo "⚠️ Warning: Some reachable memory detected (this is usually OK for readline)" + fi + + exit 0 + fi + EOF + + chmod +x test_input.sh + + - name: Run memory leak test + run: | + ./test_input.sh + + - name: Upload valgrind output as artifact + if: always() + uses: actions/upload-artifact@v4 + with: + name: valgrind-report + path: valgrind_output.txt + retention-days: 30 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bd0ad5e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +FROM ubuntu:22.04 + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + build-essential \ + libreadline-dev \ + clang \ + git \ + valgrind \ + python3 \ + python3-pip \ + && apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN python3 -m pip install --upgrade pip && \ + python3 -m pip install norminette diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..4360743 --- /dev/null +++ b/compose.yml @@ -0,0 +1,7 @@ +services: + minishell: + build: . + volumes: + - .:/cursus + working_dir: /cursus + tty: true From b475af5fd955a84f6294948caa7ada473245f498 Mon Sep 17 00:00:00 2001 From: jiku <134150757+jiku0730@users.noreply.github.com> Date: Wed, 5 Nov 2025 12:58:32 +0900 Subject: [PATCH 064/173] feature: add test command to Makefile (#19) (#20) * feature: add test command to Makefile * add: docker command to Makefile --- Makefile | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 38c1d39..f501203 100644 --- a/Makefile +++ b/Makefile @@ -3,10 +3,10 @@ # ::: :::::::: # # Makefile :+: :+: :+: # # +:+ +:+ +:+ # -# By: urassh +#+ +:+ +#+ # +# By: kjikuhar +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/05/18 21:11:39 by kjikuhar #+# #+# # -# Updated: 2025/10/10 17:16:16 by urassh ### ########.fr # +# Updated: 2025/11/04 22:30:29 by kjikuhar ### ########.fr # # # # **************************************************************************** # @@ -126,3 +126,22 @@ re: fclean all # @echo "=========================================$(RESET)" .PHONY: all clean fclean re bonus + +#----------------------------------------------------------------------------- + +#▸ original rules + +#----------------------------------------------------------------------------- + +norm: + norminette src/* includes/* libft/ + +valgrind: all + valgrind --leak-check=full --suppressions=readline.supp ./$(NAME) + +test: norm valgrind + +docker: + docker compose up -d && docker compose exec minishell bash + +.PHONY: norm valgrind test docker From a8e483c5f6642a2b2fd300a11e855cb8b039976f Mon Sep 17 00:00:00 2001 From: urassh Date: Wed, 5 Nov 2025 15:14:20 +0900 Subject: [PATCH 065/173] =?UTF-8?q?HashTable=E3=82=92=E5=AE=9A=E7=BE=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libft/Makefile | 6 +++ libft/hash_table/hash_delete.c | 51 ++++++++++++++++++++++ libft/hash_table/hash_destroy.c | 46 ++++++++++++++++++++ libft/hash_table/hash_function.c | 30 +++++++++++++ libft/hash_table/hash_insert.c | 74 ++++++++++++++++++++++++++++++++ libft/hash_table/hash_search.c | 31 +++++++++++++ libft/hash_table/hash_table.c | 40 +++++++++++++++++ libft/libft.h | 25 ++++++++++- 8 files changed, 302 insertions(+), 1 deletion(-) create mode 100644 libft/hash_table/hash_delete.c create mode 100644 libft/hash_table/hash_destroy.c create mode 100644 libft/hash_table/hash_function.c create mode 100644 libft/hash_table/hash_insert.c create mode 100644 libft/hash_table/hash_search.c create mode 100644 libft/hash_table/hash_table.c diff --git a/libft/Makefile b/libft/Makefile index a416e66..7f17871 100644 --- a/libft/Makefile +++ b/libft/Makefile @@ -19,6 +19,12 @@ SRCS = conversion/ft_atoi.c \ conversion/ft_itoa.c \ conversion/ft_tolower.c \ conversion/ft_toupper.c \ + hash_table/hash_table.c \ + hash_table/hash_function.c \ + hash_table/hash_insert.c \ + hash_table/hash_search.c \ + hash_table/hash_delete.c \ + hash_table/hash_destroy.c \ judge/ft_isalnum.c \ judge/ft_isalpha.c \ judge/ft_isascii.c \ diff --git a/libft/hash_table/hash_delete.c b/libft/hash_table/hash_delete.c new file mode 100644 index 0000000..9df5e23 --- /dev/null +++ b/libft/hash_table/hash_delete.c @@ -0,0 +1,51 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* hash_delete.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/05 00:00:00 by urassh #+# #+# */ +/* Updated: 2025/11/05 00:00:00 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +static void free_node(t_hash_node *node) +{ + if (!node) + return ; + free(node->key); + free(node->value); + free(node); +} + +int ht_delete(t_hash_table *table, const char *key) +{ + size_t index; + t_hash_node *node; + t_hash_node *prev; + + if (!table || !key) + return (0); + index = ht_hash(key, table->size); + node = table->buckets[index]; + prev = NULL; + while (node) + { + if (ft_strncmp(node->key, key, ft_strlen(key) + 1) == 0) + { + if (prev) + prev->next = node->next; + else + table->buckets[index] = node->next; + free_node(node); + table->n_nodes--; + return (1); + } + prev = node; + node = node->next; + } + return (0); +} diff --git a/libft/hash_table/hash_destroy.c b/libft/hash_table/hash_destroy.c new file mode 100644 index 0000000..ec9c502 --- /dev/null +++ b/libft/hash_table/hash_destroy.c @@ -0,0 +1,46 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* hash_destroy.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/05 00:00:00 by urassh #+# #+# */ +/* Updated: 2025/11/05 00:00:00 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +static void free_chain(t_hash_node *node) +{ + t_hash_node *next; + + while (node) + { + next = node->next; + free(node->key); + free(node->value); + free(node); + node = next; + } +} + +void ht_destroy(t_hash_table *table) +{ + size_t i; + + if (!table) + return ; + if (table->buckets) + { + i = 0; + while (i < table->size) + { + free_chain(table->buckets[i]); + i++; + } + free(table->buckets); + } + free(table); +} diff --git a/libft/hash_table/hash_function.c b/libft/hash_table/hash_function.c new file mode 100644 index 0000000..e9e4745 --- /dev/null +++ b/libft/hash_table/hash_function.c @@ -0,0 +1,30 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* hash_function.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/05 00:00:00 by urassh #+# #+# */ +/* Updated: 2025/11/05 00:00:00 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +size_t ht_hash(const char *key, size_t table_size) +{ + size_t hash; + size_t i; + + if (!key || table_size == 0) + return (0); + hash = 5381; + i = 0; + while (key[i]) + { + hash = ((hash << 5) + hash) + (unsigned char)key[i]; + i++; + } + return (hash % table_size); +} diff --git a/libft/hash_table/hash_insert.c b/libft/hash_table/hash_insert.c new file mode 100644 index 0000000..09099fe --- /dev/null +++ b/libft/hash_table/hash_insert.c @@ -0,0 +1,74 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* hash_insert.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/05 00:00:00 by urassh #+# #+# */ +/* Updated: 2025/11/05 00:00:00 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +static t_hash_node *create_node(const char *key, const char *value) +{ + t_hash_node *node; + + node = (t_hash_node *)malloc(sizeof(t_hash_node)); + if (!node) + return (NULL); + node->key = ft_strdup(key); + if (!node->key) + { + free(node); + return (NULL); + } + node->value = ft_strdup(value); + if (!node->value) + { + free(node->key); + free(node); + return (NULL); + } + node->next = NULL; + return (node); +} + +static int update_existing_node(t_hash_node *node, const char *value) +{ + char *new_value; + + new_value = ft_strdup(value); + if (!new_value) + return (0); + free(node->value); + node->value = new_value; + return (1); +} + +int ht_insert(t_hash_table *table, const char *key, const char *value) +{ + size_t index; + t_hash_node *node; + t_hash_node *new_node; + + if (!table || !key || !value) + return (0); + index = ht_hash(key, table->size); + node = table->buckets[index]; + while (node) + { + if (ft_strncmp(node->key, key, ft_strlen(key) + 1) == 0) + return (update_existing_node(node, value)); + node = node->next; + } + new_node = create_node(key, value); + if (!new_node) + return (0); + new_node->next = table->buckets[index]; + table->buckets[index] = new_node; + table->n_nodes++; + return (1); +} diff --git a/libft/hash_table/hash_search.c b/libft/hash_table/hash_search.c new file mode 100644 index 0000000..cb0818d --- /dev/null +++ b/libft/hash_table/hash_search.c @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* hash_search.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/05 00:00:00 by urassh #+# #+# */ +/* Updated: 2025/11/05 00:00:00 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ht_search(t_hash_table *table, const char *key) +{ + size_t index; + t_hash_node *node; + + if (!table || !key) + return (NULL); + index = ht_hash(key, table->size); + node = table->buckets[index]; + while (node) + { + if (ft_strncmp(node->key, key, ft_strlen(key) + 1) == 0) + return (node->value); + node = node->next; + } + return (NULL); +} diff --git a/libft/hash_table/hash_table.c b/libft/hash_table/hash_table.c new file mode 100644 index 0000000..e3df790 --- /dev/null +++ b/libft/hash_table/hash_table.c @@ -0,0 +1,40 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* hash_table.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/05 00:00:00 by urassh #+# #+# */ +/* Updated: 2025/11/05 00:00:00 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../libft.h" + +t_hash_table *ht_create(size_t size) +{ + t_hash_table *table; + size_t i; + + if (size == 0) + return (NULL); + table = (t_hash_table *)malloc(sizeof(t_hash_table)); + if (!table) + return (NULL); + table->buckets = (t_hash_node **)malloc(sizeof(t_hash_node *) * size); + if (!table->buckets) + { + free(table); + return (NULL); + } + table->size = size; + table->n_nodes = 0; + i = 0; + while (i < size) + { + table->buckets[i] = NULL; + i++; + } + return (table); +} diff --git a/libft/libft.h b/libft/libft.h index c0b86e0..9652c3b 100644 --- a/libft/libft.h +++ b/libft/libft.h @@ -6,7 +6,7 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/25 14:55:13 by kjikuhar #+# #+# */ -/* Updated: 2025/10/15 01:37:33 by urassh ### ########.fr */ +/* Updated: 2025/11/05 14:49:40 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -24,6 +24,20 @@ typedef struct s_list struct s_list *next; } t_list; +typedef struct s_hash_node +{ + char *key; + char *value; + struct s_hash_node *next; +} t_hash_node; + +typedef struct s_hash_table +{ + t_hash_node **buckets; + size_t size; + size_t n_nodes; +} t_hash_table; + // conversion int ft_atoi(const char *str); char *ft_itoa(int n); @@ -49,6 +63,15 @@ void ft_lstiter(t_list *lst, void (*f)(void *)); t_list *ft_lstmap(t_list *lst, void *(*f)(void *), void (*del)(void *)); +// hash_table +t_hash_table *ht_create(size_t size); +size_t ht_hash(const char *key, size_t table_size); +int ht_insert(t_hash_table *table, const char *key, + const char *value); +char *ht_search(t_hash_table *table, const char *key); +int ht_delete(t_hash_table *table, const char *key); +void ht_destroy(t_hash_table *table); + // memory void ft_bzero(void *s, size_t n); void *ft_calloc(size_t count, size_t size); From 3ad6237d01526c73457e4f6220225fd980b2c6d6 Mon Sep 17 00:00:00 2001 From: jiku0730 Date: Thu, 20 Nov 2025 11:52:55 +0900 Subject: [PATCH 066/173] finish: make parser --- Makefile | 14 +++- includes/minishell.h | 5 +- includes/parser.h | 98 ++++++++++++++++++++++++++ src/callback/on_input.c | 8 ++- src/parser/parser.c | 104 ++++++++++++++++++++++++++++ src/parser/utils/add_to_cmd.c | 50 +++++++++++++ src/parser/utils/free_ast.c | 50 +++++++++++++ src/parser/utils/new_ast_node.c | 27 ++++++++ src/parser/utils/new_cmd.c | 25 +++++++ src/parser/utils/new_redir.c | 30 ++++++++ src/parser/utils/print_ast.c | 67 ++++++++++++++++++ src/parser/utils/print_ast_utils.c | 57 +++++++++++++++ src/parser/utils/print_ast_utils2.c | 99 ++++++++++++++++++++++++++ src/parser/utils/token_check.c | 64 +++++++++++++++++ 14 files changed, 692 insertions(+), 6 deletions(-) create mode 100644 includes/parser.h create mode 100644 src/parser/parser.c create mode 100644 src/parser/utils/add_to_cmd.c create mode 100644 src/parser/utils/free_ast.c create mode 100644 src/parser/utils/new_ast_node.c create mode 100644 src/parser/utils/new_cmd.c create mode 100644 src/parser/utils/new_redir.c create mode 100644 src/parser/utils/print_ast.c create mode 100644 src/parser/utils/print_ast_utils.c create mode 100644 src/parser/utils/print_ast_utils2.c create mode 100644 src/parser/utils/token_check.c diff --git a/Makefile b/Makefile index f501203..e01172a 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # By: kjikuhar +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/05/18 21:11:39 by kjikuhar #+# #+# # -# Updated: 2025/11/04 22:30:29 by kjikuhar ### ########.fr # +# Updated: 2025/11/20 11:49:13 by kjikuhar ### ########.fr # # # # **************************************************************************** # @@ -69,6 +69,16 @@ SRCS_MAND := src/main.c \ src/tokenize/store/free_store.c \ src/tokenize/store/push_token.c \ src/tokenize/store/add_buffer.c \ + src/parser/parser.c \ + src/parser/utils/add_to_cmd.c \ + src/parser/utils/new_ast_node.c \ + src/parser/utils/new_cmd.c \ + src/parser/utils/new_redir.c \ + src/parser/utils/token_check.c \ + src/parser/utils/free_ast.c \ + src/parser/utils/print_ast.c \ + src/parser/utils/print_ast_utils.c \ + src/parser/utils/print_ast_utils2.c #bonus sources @@ -136,7 +146,7 @@ re: fclean all norm: norminette src/* includes/* libft/ -valgrind: all +valgrind: re valgrind --leak-check=full --suppressions=readline.supp ./$(NAME) test: norm valgrind diff --git a/includes/minishell.h b/includes/minishell.h index 3f889f7..312029f 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* minishell.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:14:22 by kjikuhar #+# #+# */ -/* Updated: 2025/10/17 02:36:03 by urassh ### ########.fr */ +/* Updated: 2025/11/19 23:53:23 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,6 +17,7 @@ # include "libft.h" # include "prompt.h" # include "tokenize.h" +# include "parser.h" // callbacks void on_input(char *input); diff --git a/includes/parser.h b/includes/parser.h new file mode 100644 index 0000000..8f3bc7b --- /dev/null +++ b/includes/parser.h @@ -0,0 +1,98 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parser.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/09/30 16:38:39 by kjikuhar #+# #+# */ +/* Updated: 2025/11/20 11:50:13 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef PARSER_H +# define PARSER_H + +# include "libft.h" +# include +# include +# include +# include +# include +# include +# include + +/* define part--------------------------------------------------------------- */ +typedef enum e_ast_type +{ + PIPE, + CMD +} t_ast_type; + +typedef enum e_redir_kind +{ + R_IN, + R_IN_HEREDOC, + R_OUT_TRUNC, + R_OUT_APPEND +} t_redir_kind; + +typedef struct s_redir +{ + t_redir_kind kind; + char *filename; +} t_redir; + +typedef struct s_cmd +{ + t_list *argv; + t_list *redirs; +} t_cmd; + +typedef struct s_ast +{ + t_ast_type type; + t_cmd *cmd; + struct s_ast *left; + struct s_ast *right; +} t_ast; + +/* main function------------------------------------------------------------- */ +t_ast *parser(t_list *head); + +/* AST's token utils--------------------------------------------------------- */ +bool is_word(const t_list *node); +bool is_symbol(const t_list *node, const char *literal); +bool is_eof(const t_list *node); +bool is_redir(const t_list *node); +const char *get_content(const t_list *node); + +/* AST's Utils--------------------------------------------------------------- */ +t_ast *new_ast_node(t_ast_type type); +t_cmd *new_cmd(void); +t_redir *new_redir(t_redir_kind kind, const char *filename); +bool add_redir_to_cmd(t_cmd *cmd, t_redir_kind kind, + const char *file); +bool add_argv_to_cmd(t_cmd *cmd, const char *arg); + +/* free utils function------------------------------------------------------- */ +void free_cmd(t_cmd *cmd); +void free_ast(t_ast *node); + +/* test print function------------------------------------------------------- */ +void print_branch_line(const char *prefix, bool is_last, + const char *text); +void build_child_prefix(const char *prefix, bool is_last, + char *buffer, size_t size); +void print_argv_item(t_list *node, int index); +const char *get_redir_symbol(t_redir *redir); +void print_redir_entry(t_redir *redir, int index); +void print_argv_line(const char *prefix, bool is_last, + t_list *argv); +void print_redir_line(const char *prefix, bool is_last, + t_list *redirs); +void print_pipe_children(t_ast *node, const char *prefix); +void print_pipe_node(t_ast *node, const char *prefix, bool is_last); +void print_ast_node(t_ast *node, const char *prefix, bool is_last); +void print_ast(t_ast *ast_root); +#endif diff --git a/src/callback/on_input.c b/src/callback/on_input.c index a6d9bf2..857868a 100644 --- a/src/callback/on_input.c +++ b/src/callback/on_input.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* on_input.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/10 17:04:25 by urassh #+# #+# */ -/* Updated: 2025/10/15 01:50:30 by urassh ### ########.fr */ +/* Updated: 2025/11/20 00:07:32 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -23,6 +23,7 @@ void on_input(char *input) void tokenize_checker(char *input) { t_list *token_list; + t_ast *ast_root; token_list = tokenize(input); if (!token_list) @@ -33,6 +34,9 @@ void tokenize_checker(char *input) if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) on_exit_token(token_list); print_tokens(token_list); + ast_root = parser(token_list); + print_ast(ast_root); + free_ast(ast_root); ft_lstclear(&token_list, free); } diff --git a/src/parser/parser.c b/src/parser/parser.c new file mode 100644 index 0000000..efc9261 --- /dev/null +++ b/src/parser/parser.c @@ -0,0 +1,104 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parser.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/14 18:30:40 by kjikuhar #+# #+# */ +/* Updated: 2025/11/19 23:51:59 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser.h" + +static bool parse_redir(t_list **cursor, t_cmd *cmd) +{ + if (is_symbol(*cursor, "<")) + { + *cursor = (*cursor)->next; + if (!*cursor || !add_redir_to_cmd(cmd, R_IN, get_content(*cursor))) + return (false); + } + else if (is_symbol(*cursor, ">")) + { + *cursor = (*cursor)->next; + if (!*cursor) + return (false); + if (!add_redir_to_cmd(cmd, R_OUT_TRUNC, get_content(*cursor))) + return (false); + } + else if (is_symbol(*cursor, ">>")) + { + *cursor = (*cursor)->next; + if (!*cursor) + return (false); + if (!add_redir_to_cmd(cmd, R_OUT_APPEND, get_content(*cursor))) + return (false); + } + else + return (false); + return (true); +} + +static t_ast *parse_cmd(t_list **cursor) +{ + t_ast *ast; + t_cmd *cmd; + + cmd = new_cmd(); + if (!cmd) + return (NULL); + while (*cursor && !is_symbol(*cursor, "|") && !is_eof(*cursor)) + { + if (is_redir(*cursor)) + { + if (!parse_redir(cursor, cmd)) + return (free_cmd(cmd), NULL); + } + else if (is_word(*cursor)) + { + if (!add_argv_to_cmd(cmd, get_content(*cursor))) + return (free_cmd(cmd), NULL); + } + *cursor = (*cursor)->next; + } + ast = new_ast_node(CMD); + if (!ast) + return (free_cmd(cmd), NULL); + ast->cmd = cmd; + return (ast); +} + +static t_ast *parse_pipeline(t_list **cursor) +{ + t_ast *left; + t_ast *pipe_node; + + left = parse_cmd(cursor); + if (!left) + return (NULL); + if (*cursor && is_symbol(*cursor, "|")) + { + *cursor = (*cursor)->next; + pipe_node = new_ast_node(PIPE); + if (!pipe_node) + return (free_ast(left), NULL); + pipe_node->left = left; + pipe_node->right = parse_pipeline(cursor); + if (!pipe_node->right) + return (free_ast(pipe_node), NULL); + return (pipe_node); + } + return (left); +} + +t_ast *parser(t_list *head) +{ + t_list *cursor; + t_ast *root; + + cursor = head; + root = parse_pipeline(&cursor); + return (root); +} diff --git a/src/parser/utils/add_to_cmd.c b/src/parser/utils/add_to_cmd.c new file mode 100644 index 0000000..dbfa85a --- /dev/null +++ b/src/parser/utils/add_to_cmd.c @@ -0,0 +1,50 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* add_to_cmd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/14 18:29:22 by kjikuhar #+# #+# */ +/* Updated: 2025/11/19 23:39:17 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser.h" + +bool add_redir_to_cmd(t_cmd *cmd, t_redir_kind kind, const char *file) +{ + t_redir *redir; + t_list *node; + + redir = new_redir(kind, file); + if (!redir) + return (false); + node = ft_lstnew(redir); + if (!node) + { + free(redir->filename); + free(redir); + return (false); + } + ft_lstadd_back(&cmd->redirs, node); + return (true); +} + +bool add_argv_to_cmd(t_cmd *cmd, const char *arg) +{ + char *dup; + t_list *node; + + dup = ft_strdup(arg); + if (!dup) + return (false); + node = ft_lstnew(dup); + if (!node) + { + free(dup); + return (false); + } + ft_lstadd_back(&cmd->argv, node); + return (true); +} diff --git a/src/parser/utils/free_ast.c b/src/parser/utils/free_ast.c new file mode 100644 index 0000000..58e7281 --- /dev/null +++ b/src/parser/utils/free_ast.c @@ -0,0 +1,50 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* free_ast.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/01 14:38:13 by kjikuhar #+# #+# */ +/* Updated: 2025/11/19 23:52:47 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser.h" + +static void free_redir(void *ptr) +{ + t_redir *redir; + + redir = (t_redir *)ptr; + if (!redir) + return ; + if (redir->filename) + free(redir->filename); + free(redir); +} + +void free_cmd(t_cmd *cmd) +{ + if (!cmd) + return ; + ft_lstclear(&cmd->argv, free); + ft_lstclear(&cmd->redirs, free_redir); + free(cmd); +} + +void free_ast(t_ast *ast) +{ + if (!ast) + return ; + if (ast->type == PIPE) + { + free_ast(ast->left); + free_ast(ast->right); + } + else if (ast->type == CMD) + { + free_cmd(ast->cmd); + } + free(ast); +} diff --git a/src/parser/utils/new_ast_node.c b/src/parser/utils/new_ast_node.c new file mode 100644 index 0000000..123bf37 --- /dev/null +++ b/src/parser/utils/new_ast_node.c @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* new_ast_node.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/14 18:29:33 by kjikuhar #+# #+# */ +/* Updated: 2025/11/19 23:39:24 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser.h" + +t_ast *new_ast_node(t_ast_type type) +{ + t_ast *node; + + node = malloc(sizeof(t_ast)); + if (!node) + return (NULL); + node->type = type; + node->cmd = NULL; + node->left = NULL; + node->right = NULL; + return (node); +} diff --git a/src/parser/utils/new_cmd.c b/src/parser/utils/new_cmd.c new file mode 100644 index 0000000..65cad92 --- /dev/null +++ b/src/parser/utils/new_cmd.c @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* new_cmd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/14 18:29:38 by kjikuhar #+# #+# */ +/* Updated: 2025/11/19 23:39:34 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser.h" + +t_cmd *new_cmd(void) +{ + t_cmd *cmd; + + cmd = malloc(sizeof(t_cmd)); + if (!cmd) + return (NULL); + cmd->argv = NULL; + cmd->redirs = NULL; + return (cmd); +} diff --git a/src/parser/utils/new_redir.c b/src/parser/utils/new_redir.c new file mode 100644 index 0000000..f3b608c --- /dev/null +++ b/src/parser/utils/new_redir.c @@ -0,0 +1,30 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* new_redir.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/14 17:40:45 by kjikuhar #+# #+# */ +/* Updated: 2025/11/19 23:39:39 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser.h" + +t_redir *new_redir(t_redir_kind kind, const char *filename) +{ + t_redir *redir; + + redir = malloc(sizeof(t_redir)); + if (!redir) + return (NULL); + redir->kind = kind; + redir->filename = ft_strdup(filename); + if (!redir->filename) + { + free(redir); + return (NULL); + } + return (redir); +} diff --git a/src/parser/utils/print_ast.c b/src/parser/utils/print_ast.c new file mode 100644 index 0000000..f4215d0 --- /dev/null +++ b/src/parser/utils/print_ast.c @@ -0,0 +1,67 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* print_ast.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/19 23:57:42 by kjikuhar #+# #+# */ +/* Updated: 2025/11/20 11:49:39 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser.h" + +void print_pipe_node(t_ast *node, const char *prefix, bool is_last) +{ + char child_prefix[256]; + + print_branch_line(prefix, is_last, "PIPE"); + build_child_prefix(prefix, is_last, child_prefix, sizeof(child_prefix)); + print_pipe_children(node, child_prefix); +} + +void print_cmd_node(t_ast *node, const char *prefix, bool is_last) +{ + char child_prefix[256]; + t_list *argv_list; + t_list *redir_list; + + argv_list = NULL; + redir_list = NULL; + if (node->cmd) + { + argv_list = node->cmd->argv; + redir_list = node->cmd->redirs; + } + print_branch_line(prefix, is_last, "CMD"); + build_child_prefix(prefix, is_last, child_prefix, sizeof(child_prefix)); + print_argv_line(child_prefix, false, argv_list); + print_redir_line(child_prefix, true, redir_list); +} + +void print_ast_node(t_ast *node, const char *prefix, bool is_last) +{ + if (!node) + { + print_branch_line(prefix, is_last, "(null)"); + return ; + } + if (node->type == PIPE) + { + print_pipe_node(node, prefix, is_last); + return ; + } + if (node->type == CMD) + { + print_cmd_node(node, prefix, is_last); + return ; + } + return ; +} + +void print_ast(t_ast *ast_root) +{ + printf("AST\n"); + print_ast_node(ast_root, "", true); +} diff --git a/src/parser/utils/print_ast_utils.c b/src/parser/utils/print_ast_utils.c new file mode 100644 index 0000000..2ae1b57 --- /dev/null +++ b/src/parser/utils/print_ast_utils.c @@ -0,0 +1,57 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* print_ast_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/19 23:57:42 by kjikuhar #+# #+# */ +/* Updated: 2025/11/20 11:46:29 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser.h" + +void print_branch_line(const char *prefix, bool is_last, const char *text) +{ + printf("%s", prefix); + if (is_last) + printf("`-- %s\n", text); + else + printf("|-- %s\n", text); +} + +void build_child_prefix(const char *prefix, bool is_last, + char *buffer, size_t size) +{ + ft_strlcpy(buffer, prefix, size); + if (is_last) + ft_strlcat(buffer, " ", size); + else + ft_strlcat(buffer, "| ", size); +} + +static const char *get_argv_value(t_list *node) +{ + if (node && node->content) + return ((const char *)node->content); + return (""); +} + +const char *get_redir_symbol(t_redir *redir) +{ + static const char *kind_str[] = {"<", "<<", ">", ">>"}; + + if (!redir) + return ("?"); + if (R_IN <= redir->kind && redir->kind <= R_OUT_APPEND) + return (kind_str[redir->kind]); + return ("?"); +} + +void print_argv_item(t_list *node, int index) +{ + if (index > 0) + printf(" "); + printf("[%d].%s", index + 1, get_argv_value(node)); +} diff --git a/src/parser/utils/print_ast_utils2.c b/src/parser/utils/print_ast_utils2.c new file mode 100644 index 0000000..b71327c --- /dev/null +++ b/src/parser/utils/print_ast_utils2.c @@ -0,0 +1,99 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* print_ast_utils2.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/20 11:39:03 by kjikuhar #+# #+# */ +/* Updated: 2025/11/20 11:49:54 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser.h" + +void print_redir_entry(t_redir *redir, int index) +{ + const char *symbol; + const char *filename; + + symbol = get_redir_symbol(redir); + filename = ""; + if (redir && redir->filename) + filename = redir->filename; + printf("[%d].%s%s", index + 1, symbol, filename); +} + +void print_argv_line(const char *prefix, bool is_last, t_list *argv) +{ + t_list *current; + int index; + + printf("%s", prefix); + if (is_last) + printf("`-- argv: "); + else + printf("|-- argv: "); + if (!argv) + { + printf("(empty)\n"); + return ; + } + current = argv; + index = 0; + while (current) + { + print_argv_item(current, index); + current = current->next; + index++; + } + printf("\n"); +} + +void print_redir_line(const char *prefix, bool is_last, t_list *redirs) +{ + t_list *current; + int index; + + printf("%s", prefix); + if (is_last) + printf("`-- redirs: "); + else + printf("|-- redirs: "); + if (!redirs) + { + printf("(empty)\n"); + return ; + } + current = redirs; + index = 0; + while (current) + { + print_redir_entry((t_redir *)current->content, index); + current = current->next; + index++; + } + printf("\n"); +} + +void print_pipe_children(t_ast *node, const char *prefix) +{ + bool has_right; + + has_right = false; + if (node->right) + has_right = true; + if (node->left) + { + if (has_right) + print_ast_node(node->left, prefix, false); + else + print_ast_node(node->left, prefix, true); + } + else if (has_right) + print_ast_node(NULL, prefix, false); + if (has_right) + print_ast_node(node->right, prefix, true); + else if (!node->left) + print_ast_node(NULL, prefix, true); +} diff --git a/src/parser/utils/token_check.c b/src/parser/utils/token_check.c new file mode 100644 index 0000000..b5bce4c --- /dev/null +++ b/src/parser/utils/token_check.c @@ -0,0 +1,64 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* token_check.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/14 18:29:48 by kjikuhar #+# #+# */ +/* Updated: 2025/11/19 23:39:47 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser.h" + +bool is_word(const t_list *node) +{ + const char *s; + + if (!node || !node->content) + return (false); + s = (const char *)node->content; + if (ft_strncmp(s, "<", 2) == 0 || \ + ft_strncmp(s, ">", 2) == 0 || \ + ft_strncmp(s, ">>", 3) == 0 || \ + ft_strncmp(s, "|", 2) == 0 || \ + ft_strncmp(s, "EOF", 4) == 0) + return (false); + return (true); +} + +bool is_symbol(const t_list *node, const char *literal) +{ + size_t len; + + if (!node || \ + !node->content || \ + !literal) + return (false); + len = ft_strlen(literal); + return (ft_strncmp((const char *)node->content, literal, len + 1) == 0); +} + +bool is_eof(const t_list *node) +{ + if (!node || !node->content) + return (true); + return (ft_strncmp((const char *)node->content, "EOF", 4) == 0); +} + +bool is_redir(const t_list *node) +{ + if (!node) + return (false); + return (is_symbol(node, "<") || \ + is_symbol(node, ">") || \ + is_symbol(node, ">>")); +} + +const char *get_content(const t_list *node) +{ + if (!node) + return (NULL); + return ((const char *)node->content); +} From 4c0fcf876b52d453902347c3e7020fc32aceb226 Mon Sep 17 00:00:00 2001 From: jiku0730 Date: Thu, 20 Nov 2025 11:57:48 +0900 Subject: [PATCH 067/173] revise: norminette --- src/parser/utils/print_ast_utils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/parser/utils/print_ast_utils.c b/src/parser/utils/print_ast_utils.c index 2ae1b57..fbe5e19 100644 --- a/src/parser/utils/print_ast_utils.c +++ b/src/parser/utils/print_ast_utils.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/19 23:57:42 by kjikuhar #+# #+# */ -/* Updated: 2025/11/20 11:46:29 by kjikuhar ### ########.fr */ +/* Updated: 2025/11/20 11:57:27 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,7 +22,7 @@ void print_branch_line(const char *prefix, bool is_last, const char *text) } void build_child_prefix(const char *prefix, bool is_last, - char *buffer, size_t size) + char *buffer, size_t size) { ft_strlcpy(buffer, prefix, size); if (is_last) From 3ea13fc9c25609a93f9a2912f498a316bce445a5 Mon Sep 17 00:00:00 2001 From: jiku0730 Date: Thu, 20 Nov 2025 12:04:47 +0900 Subject: [PATCH 068/173] revise: norminette --- includes/parser.h | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/includes/parser.h b/includes/parser.h index 8f3bc7b..5d9d8fe 100644 --- a/includes/parser.h +++ b/includes/parser.h @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/30 16:38:39 by kjikuhar #+# #+# */ -/* Updated: 2025/11/20 11:50:13 by kjikuhar ### ########.fr */ +/* Updated: 2025/11/20 11:57:10 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -58,39 +58,39 @@ typedef struct s_ast } t_ast; /* main function------------------------------------------------------------- */ -t_ast *parser(t_list *head); +t_ast *parser(t_list *head); /* AST's token utils--------------------------------------------------------- */ -bool is_word(const t_list *node); -bool is_symbol(const t_list *node, const char *literal); -bool is_eof(const t_list *node); -bool is_redir(const t_list *node); -const char *get_content(const t_list *node); +bool is_word(const t_list *node); +bool is_symbol(const t_list *node, const char *literal); +bool is_eof(const t_list *node); +bool is_redir(const t_list *node); +const char *get_content(const t_list *node); /* AST's Utils--------------------------------------------------------------- */ -t_ast *new_ast_node(t_ast_type type); -t_cmd *new_cmd(void); -t_redir *new_redir(t_redir_kind kind, const char *filename); -bool add_redir_to_cmd(t_cmd *cmd, t_redir_kind kind, - const char *file); -bool add_argv_to_cmd(t_cmd *cmd, const char *arg); +t_ast *new_ast_node(t_ast_type type); +t_cmd *new_cmd(void); +t_redir *new_redir(t_redir_kind kind, const char *filename); +bool add_redir_to_cmd(t_cmd *cmd, t_redir_kind kind, + const char *file); +bool add_argv_to_cmd(t_cmd *cmd, const char *arg); /* free utils function------------------------------------------------------- */ -void free_cmd(t_cmd *cmd); -void free_ast(t_ast *node); +void free_cmd(t_cmd *cmd); +void free_ast(t_ast *node); /* test print function------------------------------------------------------- */ void print_branch_line(const char *prefix, bool is_last, - const char *text); + const char *text); void build_child_prefix(const char *prefix, bool is_last, - char *buffer, size_t size); + char *buffer, size_t size); void print_argv_item(t_list *node, int index); const char *get_redir_symbol(t_redir *redir); void print_redir_entry(t_redir *redir, int index); void print_argv_line(const char *prefix, bool is_last, - t_list *argv); + t_list *argv); void print_redir_line(const char *prefix, bool is_last, - t_list *redirs); + t_list *redirs); void print_pipe_children(t_ast *node, const char *prefix); void print_pipe_node(t_ast *node, const char *prefix, bool is_last); void print_ast_node(t_ast *node, const char *prefix, bool is_last); From c26a18a9e62c39a27949e80d560a114343363aa8 Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Thu, 20 Nov 2025 13:34:43 +0900 Subject: [PATCH 069/173] =?UTF-8?q?tokenize=E6=99=82=E3=81=AB=E3=82=AF?= =?UTF-8?q?=E3=82=A9=E3=83=BC=E3=83=88=E3=82=92=E6=B6=88=E3=81=95=E3=81=AA?= =?UTF-8?q?=E3=81=84=E3=82=88=E3=81=86=E3=81=AB=20(#25)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: tokenize_checkerをcheckerに移動 * fix: tokenize時にクォートを消さないように * delete: is_operatorは使われていないので削除 * rename: is_*_char -> is_* --- Makefile | 10 ++-- includes/tokenize.h | 15 ++--- src/callback/on_input.c | 49 +-------------- src/checker/tokenize_checker.c | 60 +++++++++++++++++++ src/tokenize/{is_operator.c => is_specific.c} | 38 ++++-------- src/tokenize/state/in_normal.c | 24 ++++---- src/tokenize/state/in_operator.c | 4 +- .../state/{in_double_quote.c => in_quote.c} | 13 ++-- src/tokenize/state/in_single_quote.c | 24 -------- src/tokenize/tokenize.c | 8 +-- 10 files changed, 107 insertions(+), 138 deletions(-) create mode 100644 src/checker/tokenize_checker.c rename src/tokenize/{is_operator.c => is_specific.c} (62%) rename src/tokenize/state/{in_double_quote.c => in_quote.c} (73%) delete mode 100644 src/tokenize/state/in_single_quote.c diff --git a/Makefile b/Makefile index f501203..4debb5e 100644 --- a/Makefile +++ b/Makefile @@ -3,10 +3,10 @@ # ::: :::::::: # # Makefile :+: :+: :+: # # +:+ +:+ +:+ # -# By: kjikuhar +#+ +:+ +#+ # +# By: urassh +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/05/18 21:11:39 by kjikuhar #+# #+# # -# Updated: 2025/11/04 22:30:29 by kjikuhar ### ########.fr # +# Updated: 2025/11/05 14:02:34 by urassh ### ########.fr # # # # **************************************************************************** # @@ -58,11 +58,11 @@ LIBFT_A := $(LIBFT_DIR)/libft.a SRCS_MAND := src/main.c \ src/prompt/prompt.c \ src/callback/on_input.c \ + src/checker/tokenize_checker.c \ src/tokenize/tokenize.c \ - src/tokenize/is_operator.c \ + src/tokenize/is_specific.c \ src/tokenize/state/in_normal.c \ - src/tokenize/state/in_double_quote.c \ - src/tokenize/state/in_single_quote.c \ + src/tokenize/state/in_quote.c \ src/tokenize/state/in_operator.c \ src/tokenize/state/on_success.c \ src/tokenize/state/on_error.c \ diff --git a/includes/tokenize.h b/includes/tokenize.h index f07d44e..8009461 100644 --- a/includes/tokenize.h +++ b/includes/tokenize.h @@ -6,7 +6,7 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/10 17:09:25 by urassh #+# #+# */ -/* Updated: 2025/10/17 22:49:29 by urassh ### ########.fr */ +/* Updated: 2025/11/05 14:21:43 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -20,8 +20,7 @@ typedef enum e_token_state { IN_NORMAL, - IN_DOUBLE_QUOTE, - IN_SINGLE_QUOTE, + IN_QUOTE, IN_OPERATOR, ON_SUCCESS, ON_ERROR, @@ -35,9 +34,9 @@ typedef struct s_token_store t_list *tokenize(char *input); -// operator -bool is_operator(const char *str); -bool is_operator_char(const char c); +// is specific +bool is_quote(const char c); +bool is_operator(const char c); // store int push_token(t_token_store *store); @@ -47,9 +46,7 @@ void free_store(t_token_store *store); // state handler void in_normal(t_token_store *store, t_token_state *state, const char current); -void in_double_quote(t_token_store *store, t_token_state *state, - const char current); -void in_single_quote(t_token_store *store, t_token_state *state, +void in_quote(t_token_store *store, t_token_state *state, const char current); void in_operator(t_token_store *store, t_token_state *state, const char current); diff --git a/src/callback/on_input.c b/src/callback/on_input.c index a6d9bf2..44d4585 100644 --- a/src/callback/on_input.c +++ b/src/callback/on_input.c @@ -6,60 +6,13 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/10 17:04:25 by urassh #+# #+# */ -/* Updated: 2025/10/15 01:50:30 by urassh ### ########.fr */ +/* Updated: 2025/11/05 13:48:51 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -static void on_exit_token(t_list *token_list); -static void print_tokens(t_list *token_list); - void on_input(char *input) { free(input); } - -void tokenize_checker(char *input) -{ - t_list *token_list; - - token_list = tokenize(input); - if (!token_list) - { - write(STDOUT_FILENO, "Error: tokenize failed\n", 23); - return ; - } - if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) - on_exit_token(token_list); - print_tokens(token_list); - ft_lstclear(&token_list, free); -} - -static void print_tokens(t_list *token_list) -{ - t_list *current; - int index; - - index = 0; - current = token_list; - write(STDOUT_FILENO, "Tokens:\n", 8); - while (current) - { - write(STDOUT_FILENO, "[", 1); - ft_putnbr_fd(index, STDOUT_FILENO); - write(STDOUT_FILENO, "] \"", 3); - if (current->content) - write(STDOUT_FILENO, current->content, ft_strlen(current->content)); - write(STDOUT_FILENO, "\"\n", 2); - current = current->next; - index++; - } -} - -static void on_exit_token(t_list *token_list) -{ - write(STDOUT_FILENO, "exit\n", 5); - ft_lstclear(&token_list, free); - exit(0); -} diff --git a/src/checker/tokenize_checker.c b/src/checker/tokenize_checker.c new file mode 100644 index 0000000..18e6859 --- /dev/null +++ b/src/checker/tokenize_checker.c @@ -0,0 +1,60 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* tokenize_checker.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/05 13:47:35 by urassh #+# #+# */ +/* Updated: 2025/11/05 13:48:56 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +static void on_exit_token(t_list *token_list); +static void print_tokens(t_list *token_list); + +void tokenize_checker(char *input) +{ + t_list *token_list; + + token_list = tokenize(input); + if (!token_list) + { + write(STDOUT_FILENO, "Error: tokenize failed\n", 23); + return ; + } + if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) + on_exit_token(token_list); + print_tokens(token_list); + ft_lstclear(&token_list, free); +} + +static void print_tokens(t_list *token_list) +{ + t_list *current; + int index; + + index = 0; + current = token_list; + write(STDOUT_FILENO, "Tokens:\n", 8); + while (current) + { + write(STDOUT_FILENO, "[", 1); + ft_putnbr_fd(index, STDOUT_FILENO); + write(STDOUT_FILENO, "] \"", 3); + if (current->content) + write(STDOUT_FILENO, current->content, ft_strlen(current->content)); + write(STDOUT_FILENO, "\"\n", 2); + current = current->next; + index++; + } +} + +static void on_exit_token(t_list *token_list) +{ + write(STDOUT_FILENO, "exit\n", 5); + ft_lstclear(&token_list, free); + exit(0); +} diff --git a/src/tokenize/is_operator.c b/src/tokenize/is_specific.c similarity index 62% rename from src/tokenize/is_operator.c rename to src/tokenize/is_specific.c index 0294ded..380bfcf 100644 --- a/src/tokenize/is_operator.c +++ b/src/tokenize/is_specific.c @@ -1,53 +1,39 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* is_operator.c :+: :+: :+: */ +/* is_specific.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/13 01:15:00 by urassh #+# #+# */ -/* Updated: 2025/10/17 01:56:50 by urassh ### ########.fr */ +/* Updated: 2025/11/05 14:21:43 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ #include "tokenize.h" -bool is_operator_char(const char c) +bool is_quote(const char c) { - if (c == '&') - return (true); - if (c == '|') - return (true); - if (c == '<') + if (c == '"') return (true); - if (c == '>') - return (true); - if (c == '(') - return (true); - if (c == ')') + if (c == '\'') return (true); return (false); } -bool is_operator(const char *str) +bool is_operator(const char c) { - if (ft_strncmp(str, "&&", 2) == 0) - return (true); - if (ft_strncmp(str, "||", 2) == 0) - return (true); - if (ft_strncmp(str, "<<", 2) == 0) - return (true); - if (ft_strncmp(str, ">>", 2) == 0) + if (c == '&') return (true); - if (ft_strncmp(str, "|", 1) == 0) + if (c == '|') return (true); - if (ft_strncmp(str, "<", 1) == 0) + if (c == '<') return (true); - if (ft_strncmp(str, ">", 1) == 0) + if (c == '>') return (true); - if (ft_strncmp(str, "(", 1) == 0) + if (c == '(') return (true); - if (ft_strncmp(str, ")", 1) == 0) + if (c == ')') return (true); return (false); } diff --git a/src/tokenize/state/in_normal.c b/src/tokenize/state/in_normal.c index cec2354..ea67e98 100644 --- a/src/tokenize/state/in_normal.c +++ b/src/tokenize/state/in_normal.c @@ -6,7 +6,7 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/13 00:30:00 by urassh #+# #+# */ -/* Updated: 2025/10/23 00:27:32 by urassh ### ########.fr */ +/* Updated: 2025/11/05 14:21:43 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -28,9 +28,9 @@ void in_normal(t_token_store *store, t_token_state *state, by_last(store, state, current); else if (ft_isspace(current)) by_space(store, state, current); - else if (is_operator_char(current)) + else if (is_operator(current)) by_operator(store, state, current); - else if (current == '\"' || current == '\'') + else if (is_quote(current)) by_quote(store, state, current); else if (add_buffer(store, current) == ERROR) *state = ON_ERROR; @@ -56,21 +56,21 @@ static void by_space(t_token_store *store, t_token_state *state, *state = IN_NORMAL; } -static void by_quote(t_token_store *store, t_token_state *state, +static void by_operator(t_token_store *store, t_token_state *state, const char current) { - (void)store; - if (current == '\"') - *state = IN_DOUBLE_QUOTE; - else if (current == '\'') - *state = IN_SINGLE_QUOTE; + if (push_token(store) == ERROR || add_buffer(store, current) == ERROR) + *state = ON_ERROR; + else + *state = IN_OPERATOR; } -static void by_operator(t_token_store *store, t_token_state *state, +static void by_quote(t_token_store *store, t_token_state *state, const char current) { - if (push_token(store) == ERROR || add_buffer(store, current) == ERROR) + (void)store; + if (add_buffer(store, current) == ERROR) *state = ON_ERROR; else - *state = IN_OPERATOR; + *state = IN_QUOTE; } diff --git a/src/tokenize/state/in_operator.c b/src/tokenize/state/in_operator.c index 75ce120..5dd519a 100644 --- a/src/tokenize/state/in_operator.c +++ b/src/tokenize/state/in_operator.c @@ -6,7 +6,7 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/13 00:30:00 by urassh #+# #+# */ -/* Updated: 2025/10/23 01:17:48 by urassh ### ########.fr */ +/* Updated: 2025/11/05 14:21:43 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,7 +22,7 @@ void in_operator(t_token_store *store, t_token_state *state, { if (current == '\0' && push_token(store)) *state = ON_SUCCESS; - else if (is_operator_char(current)) + else if (is_operator(current)) by_operator(store, state, current); else by_normal(store, state, current); diff --git a/src/tokenize/state/in_double_quote.c b/src/tokenize/state/in_quote.c similarity index 73% rename from src/tokenize/state/in_double_quote.c rename to src/tokenize/state/in_quote.c index dce0bb3..dd925c1 100644 --- a/src/tokenize/state/in_double_quote.c +++ b/src/tokenize/state/in_quote.c @@ -1,24 +1,23 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* in_double_quote.c :+: :+: :+: */ +/* in_quote.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/10/13 00:30:00 by urassh #+# #+# */ -/* Updated: 2025/10/17 01:23:03 by urassh ### ########.fr */ +/* Created: 2025/11/05 13:54:52 by urassh #+# #+# */ +/* Updated: 2025/11/05 14:21:31 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ #include "tokenize.h" -void in_double_quote(t_token_store *store, t_token_state *state, - const char current) +void in_quote(t_token_store *store, t_token_state *state, const char current) { if (current == '\0') *state = ON_ERROR; - else if (current == '"') - *state = IN_NORMAL; else if (add_buffer(store, current) == ERROR) *state = ON_ERROR; + else if (is_quote(current)) + *state = IN_NORMAL; } diff --git a/src/tokenize/state/in_single_quote.c b/src/tokenize/state/in_single_quote.c deleted file mode 100644 index b80d218..0000000 --- a/src/tokenize/state/in_single_quote.c +++ /dev/null @@ -1,24 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* in_single_quote.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/10/13 00:30:00 by urassh #+# #+# */ -/* Updated: 2025/10/17 02:27:47 by urassh ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "tokenize.h" - -void in_single_quote(t_token_store *store, t_token_state *state, - const char current) -{ - if (current == '\0') - *state = ON_ERROR; - else if (current == '\'') - *state = IN_NORMAL; - else if (add_buffer(store, current) == ERROR) - *state = ON_ERROR; -} diff --git a/src/tokenize/tokenize.c b/src/tokenize/tokenize.c index 246b438..76b08db 100644 --- a/src/tokenize/tokenize.c +++ b/src/tokenize/tokenize.c @@ -6,7 +6,7 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/10 17:14:04 by urassh #+# #+# */ -/* Updated: 2025/10/17 22:55:05 by urassh ### ########.fr */ +/* Updated: 2025/11/05 14:06:48 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -28,10 +28,8 @@ t_list *tokenize(char *input) { if (state == IN_NORMAL) in_normal(&store, &state, *current); - else if (state == IN_DOUBLE_QUOTE) - in_double_quote(&store, &state, *current); - else if (state == IN_SINGLE_QUOTE) - in_single_quote(&store, &state, *current); + else if (state == IN_QUOTE) + in_quote(&store, &state, *current); else if (state == IN_OPERATOR) in_operator(&store, &state, *current); else if (state == ON_SUCCESS) From c38568075765c79ba47f42f6dc88a56bab6c9c3e Mon Sep 17 00:00:00 2001 From: jiku0730 Date: Thu, 20 Nov 2025 23:40:34 +0900 Subject: [PATCH 070/173] change: parser's prototype declearation --- includes/parser.h | 4 ++-- src/parser/parser.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/includes/parser.h b/includes/parser.h index 5d9d8fe..628ff65 100644 --- a/includes/parser.h +++ b/includes/parser.h @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/30 16:38:39 by kjikuhar #+# #+# */ -/* Updated: 2025/11/20 11:57:10 by kjikuhar ### ########.fr */ +/* Updated: 2025/11/20 23:35:17 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -58,7 +58,7 @@ typedef struct s_ast } t_ast; /* main function------------------------------------------------------------- */ -t_ast *parser(t_list *head); +t_ast *parser(t_list *token_head); /* AST's token utils--------------------------------------------------------- */ bool is_word(const t_list *node); diff --git a/src/parser/parser.c b/src/parser/parser.c index efc9261..8ffd434 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/14 18:30:40 by kjikuhar #+# #+# */ -/* Updated: 2025/11/19 23:51:59 by kjikuhar ### ########.fr */ +/* Updated: 2025/11/20 23:40:01 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -93,12 +93,12 @@ static t_ast *parse_pipeline(t_list **cursor) return (left); } -t_ast *parser(t_list *head) +t_ast *parser(t_list *token_head) { t_list *cursor; t_ast *root; - cursor = head; + cursor = token_head; root = parse_pipeline(&cursor); return (root); } From 88690beeb6a7efdd4cb822235960c24dcc7b29c6 Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Sat, 22 Nov 2025 01:16:45 +0900 Subject: [PATCH 071/173] =?UTF-8?q?heredoc=E3=81=AE=E5=AE=9F=E8=A3=85=20(#?= =?UTF-8?q?30)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: tmpfileの生成 * feat: heredoc promptを作成 * feat: heredoc関数を実装した * refactor: heredoc * feat: heredoc_checker * feat: heredoc * revert: open_tmpfile * rename: create_tmpfile * fix: rebuild_token * tmp * fix: error * fix: rebuild_tokens * refactor: get_tmpfile_id * refactor: create_tmpfile * fix: null guard --- Makefile | 6 +- includes/heredoc.h | 34 +++++++++++ includes/minishell.h | 6 +- src/checker/heredoc_checker.c | 84 ++++++++++++++++++++++++++ src/component/heredoc/heredoc.c | 62 +++++++++++++++++++ src/component/heredoc/heredoc_prompt.c | 72 ++++++++++++++++++++++ src/component/heredoc/tmpfile.c | 76 +++++++++++++++++++++++ src/main.c | 2 +- 8 files changed, 338 insertions(+), 4 deletions(-) create mode 100644 includes/heredoc.h create mode 100644 src/checker/heredoc_checker.c create mode 100644 src/component/heredoc/heredoc.c create mode 100644 src/component/heredoc/heredoc_prompt.c create mode 100644 src/component/heredoc/tmpfile.c diff --git a/Makefile b/Makefile index 4debb5e..7828f21 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # By: urassh +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/05/18 21:11:39 by kjikuhar #+# #+# # -# Updated: 2025/11/05 14:02:34 by urassh ### ########.fr # +# Updated: 2025/11/20 17:42:22 by urassh ### ########.fr # # # # **************************************************************************** # @@ -59,6 +59,7 @@ SRCS_MAND := src/main.c \ src/prompt/prompt.c \ src/callback/on_input.c \ src/checker/tokenize_checker.c \ + src/checker/heredoc_checker.c \ src/tokenize/tokenize.c \ src/tokenize/is_specific.c \ src/tokenize/state/in_normal.c \ @@ -69,6 +70,9 @@ SRCS_MAND := src/main.c \ src/tokenize/store/free_store.c \ src/tokenize/store/push_token.c \ src/tokenize/store/add_buffer.c \ + src/component/heredoc/heredoc.c \ + src/component/heredoc/heredoc_prompt.c \ + src/component/heredoc/tmpfile.c \ #bonus sources diff --git a/includes/heredoc.h b/includes/heredoc.h new file mode 100644 index 0000000..d1b9c64 --- /dev/null +++ b/includes/heredoc.h @@ -0,0 +1,34 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* heredoc.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/20 14:12:42 by urassh #+# #+# */ +/* Updated: 2025/11/20 17:36:09 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef HEREDOC_H +# define HEREDOC_H + +# include "constants.h" +# include "libft.h" +# include +# include +# include +# include + +t_list *heredoc(t_list *tokens); +char *heredoc_prompt(const char *delimiter); + +// tmpfile +int open_tmpfile(char *tmpfile_path); +char *create_tmpfile(void); + +# define HEREDOC_PROMPT "heredoc> " +# define HEREDOC_TMP_PREFIX "/tmp/minishell_heredoc_" +# define HEREDOC_BUFFER 1024 + +#endif diff --git a/includes/minishell.h b/includes/minishell.h index 3f889f7..3d96c2a 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -6,7 +6,7 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:14:22 by kjikuhar #+# #+# */ -/* Updated: 2025/10/17 02:36:03 by urassh ### ########.fr */ +/* Updated: 2025/11/20 15:56:35 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,11 +17,13 @@ # include "libft.h" # include "prompt.h" # include "tokenize.h" +# include "heredoc.h" // callbacks void on_input(char *input); -// TEST: callbacks +// checkers void tokenize_checker(char *input); +void heredoc_checker(char *input); #endif diff --git a/src/checker/heredoc_checker.c b/src/checker/heredoc_checker.c new file mode 100644 index 0000000..2346323 --- /dev/null +++ b/src/checker/heredoc_checker.c @@ -0,0 +1,84 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* heredoc_checker.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/20 15:55:55 by urassh #+# #+# */ +/* Updated: 2025/11/20 17:40:53 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#include +#include + +static void on_exit_token(t_list *token_list); +static void print_tokens(t_list *token_list); +static void unlink_tmpfiles(t_list *token_list); + +void heredoc_checker(char *input) +{ + t_list *token_list; + t_list *heredoced_list; + + token_list = tokenize(input); + if (!token_list) + { + printf("Error: tokenize failed\n"); + return ; + } + if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) + on_exit_token(token_list); + heredoced_list = heredoc(token_list); + if (!heredoced_list) + { + printf("Error: heredoc failed\n"); + ft_lstclear(&token_list, free); + return ; + } + print_tokens(heredoced_list); + unlink_tmpfiles(heredoced_list); + ft_lstclear(&heredoced_list, free); +} + +static void print_tokens(t_list *token_list) +{ + t_list *current; + int index; + + index = 0; + current = token_list; + printf("here_doced_tokens:\n"); + while (current) + { + printf("[%d] \"", index); + if (current->content) + printf("%s", (char *)current->content); + printf("\"\n"); + current = current->next; + index++; + } +} + +static void on_exit_token(t_list *token_list) +{ + printf("exit\n"); + ft_lstclear(&token_list, free); + exit(0); +} + +static void unlink_tmpfiles(t_list *token_list) +{ + t_list *current; + + current = token_list; + while (current) + { + if (current->content && ft_strncmp(current->content, HEREDOC_TMP_PREFIX, + ft_strlen(HEREDOC_TMP_PREFIX)) == 0) + unlink((char *)current->content); + current = current->next; + } +} diff --git a/src/component/heredoc/heredoc.c b/src/component/heredoc/heredoc.c new file mode 100644 index 0000000..e62529f --- /dev/null +++ b/src/component/heredoc/heredoc.c @@ -0,0 +1,62 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* heredoc.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/20 14:13:36 by urassh #+# #+# */ +/* Updated: 2025/11/21 16:16:47 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include + +static bool is_heredoc_operator(const char *token); +static int rebuild_tokens(t_list *current, t_list *eof_node, + char *tmpfile_path); + +t_list *heredoc(t_list *tokens) +{ + t_list *current; + t_list *eof_node; + char *tmpfile_path; + + current = tokens; + while (current != NULL) + { + if (is_heredoc_operator((char *)current->content)) + { + eof_node = current->next; + if (eof_node == NULL) + return (NULL); + tmpfile_path = heredoc_prompt((char *)eof_node->content); + if (rebuild_tokens(current, eof_node, tmpfile_path) == ERROR) + return (NULL); + } + current = current->next; + } + return (tokens); +} + +static bool is_heredoc_operator(const char *token) +{ + if (token == NULL) + return (false); + return (ft_strncmp(token, "<<", 3) == 0); +} + +static int rebuild_tokens(t_list *current, t_list *eof_node, + char *tmpfile_path) +{ + char *input_redir; + + input_redir = ft_strdup("<"); + if (!current || !eof_node || !tmpfile_path || !input_redir) + return (ERROR); + free(current->content); + free(eof_node->content); + current->content = input_redir; + eof_node->content = tmpfile_path; + return (SUCCESS); +} diff --git a/src/component/heredoc/heredoc_prompt.c b/src/component/heredoc/heredoc_prompt.c new file mode 100644 index 0000000..d3e3ddc --- /dev/null +++ b/src/component/heredoc/heredoc_prompt.c @@ -0,0 +1,72 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* heredoc_prompt.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/20 15:05:31 by urassh #+# #+# */ +/* Updated: 2025/11/20 17:23:51 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#include + +static int write_line_to_file(int fd, char *line); +static char *by_found_delimiter(char *line, int fd, char *tmpfile_path); +static void *by_fail_write_line_to_file(char *line, int fd, char *tmpfile_path); + +char *heredoc_prompt(const char *delimiter) +{ + char *line; + char *tmpfile_path; + int fd; + + tmpfile_path = create_tmpfile(); + if (tmpfile_path == NULL) + return (NULL); + fd = open_tmpfile(tmpfile_path); + if (fd == -1) + return (NULL); + while (1) + { + line = readline(HEREDOC_PROMPT); + if (line == NULL) + break ; + if (ft_strncmp(line, delimiter, ft_strlen(delimiter) + 1) == 0) + return (by_found_delimiter(line, fd, tmpfile_path)); + if (write_line_to_file(fd, line) == ERROR) + return (by_fail_write_line_to_file(line, fd, tmpfile_path)); + free(line); + } + close(fd); + return (tmpfile_path); +} + +static int write_line_to_file(int fd, char *line) +{ + size_t len; + + len = ft_strlen(line); + if (write(fd, line, len) == -1) + return (ERROR); + if (write(fd, "\n", 1) == -1) + return (ERROR); + return (SUCCESS); +} + +static char *by_found_delimiter(char *line, int fd, char *tmpfile_path) +{ + free(line); + close(fd); + return (tmpfile_path); +} + +static void *by_fail_write_line_to_file(char *line, int fd, char *tmpfile_path) +{ + free(line); + close(fd); + free(tmpfile_path); + return (NULL); +} diff --git a/src/component/heredoc/tmpfile.c b/src/component/heredoc/tmpfile.c new file mode 100644 index 0000000..66b16f0 --- /dev/null +++ b/src/component/heredoc/tmpfile.c @@ -0,0 +1,76 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* tmpfile.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/20 14:28:49 by urassh #+# #+# */ +/* Updated: 2025/11/22 01:08:26 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include + +static char *get_tmpfile_id(const char *tmp_prefix); + +int open_tmpfile(char *tmpfile_path) +{ + int fd; + + fd = open(tmpfile_path, O_WRONLY | O_APPEND); + if (fd == -1) + { + free(tmpfile_path); + tmpfile_path = NULL; + return (-1); + } + return (fd); +} + +char *create_tmpfile(void) +{ + char *id; + char *path; + int tmp_file_id; + + id = get_tmpfile_id(HEREDOC_TMP_PREFIX); + if (id == NULL) + return (NULL); + path = ft_strjoin(HEREDOC_TMP_PREFIX, id); + free(id); + if (path == NULL) + return (NULL); + tmp_file_id = open(path, O_CREAT | O_EXCL | O_RDWR, 0600); + if (tmp_file_id == -1) + return (NULL); + close(tmp_file_id); + return (path); +} + +static char *get_tmpfile_id(const char *tmp_prefix) +{ + int id; + char *filename; + char *id_str; + + id = 0; + while (id < INT_MAX) + { + id_str = ft_itoa(id); + if (!id_str) + return (NULL); + filename = ft_strjoin(tmp_prefix, id_str); + free(id_str); + if (!filename) + return (NULL); + if (access(filename, F_OK) != 0) + { + free(filename); + return (ft_itoa(id)); + } + free(filename); + id++; + } + return (NULL); +} diff --git a/src/main.c b/src/main.c index bef3c27..47af15b 100644 --- a/src/main.c +++ b/src/main.c @@ -14,6 +14,6 @@ int main(void) { - prompt(tokenize_checker); + prompt(heredoc_checker); return (0); } From 2e3851504cd1c9d309f93ce7518e710478960bb0 Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Sat, 22 Nov 2025 01:22:14 +0900 Subject: [PATCH 072/173] =?UTF-8?q?NorminetteCI=E3=81=AE=E3=83=88=E3=83=AA?= =?UTF-8?q?=E3=82=AC=E3=83=BC=E3=82=92=E4=BF=AE=E6=AD=A3=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: norminette ci * fix: 3.3.55 --- .github/workflows/norminette.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/norminette.yml b/.github/workflows/norminette.yml index 5ea496f..e92a6bf 100644 --- a/.github/workflows/norminette.yml +++ b/.github/workflows/norminette.yml @@ -1,8 +1,10 @@ name: Norminette Check on: + pull_request: + branches: [ "master", "develop" ] push: - branches: [ "master", "develop", "urassh/*", "jiku/*" ] + branches: [ "master", "develop" ] jobs: norminette: @@ -19,7 +21,7 @@ jobs: - name: Install norminette run: | python -m pip install --upgrade pip - pip install norminette + pip install norminette=="3.3.55" - name: Check norminette version run: norminette --version From 1e2bc36b4f617354114b33d6e2862ee297e256dc Mon Sep 17 00:00:00 2001 From: urassh Date: Sun, 23 Nov 2025 15:15:24 +0900 Subject: [PATCH 073/173] refactor: ht_hash --- libft/hash_table/hash_function.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libft/hash_table/hash_function.c b/libft/hash_table/hash_function.c index e9e4745..f841a00 100644 --- a/libft/hash_table/hash_function.c +++ b/libft/hash_table/hash_function.c @@ -6,7 +6,7 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/05 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/11/05 00:00:00 by urassh ### ########.fr */ +/* Updated: 2025/11/23 15:09:38 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,17 +14,18 @@ size_t ht_hash(const char *key, size_t table_size) { - size_t hash; - size_t i; + const size_t inital_hash = 5381; + size_t hash_num; + size_t i; if (!key || table_size == 0) return (0); - hash = 5381; + hash_num = inital_hash; i = 0; while (key[i]) { - hash = ((hash << 5) + hash) + (unsigned char)key[i]; + hash_num = ((hash_num << 5) + hash_num) + (unsigned char)key[i]; i++; } - return (hash % table_size); + return (hash_num % table_size); } From 0b7f4810ef05a2928da0e8bf1c5b242c96882c13 Mon Sep 17 00:00:00 2001 From: urassh Date: Sun, 23 Nov 2025 15:16:59 +0900 Subject: [PATCH 074/173] =?UTF-8?q?refactor:=20create=5Fnode=E3=81=A7callo?= =?UTF-8?q?c=E3=82=92=E4=BD=BF=E3=81=86=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libft/hash_table/hash_insert.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libft/hash_table/hash_insert.c b/libft/hash_table/hash_insert.c index 09099fe..597057f 100644 --- a/libft/hash_table/hash_insert.c +++ b/libft/hash_table/hash_insert.c @@ -16,7 +16,7 @@ static t_hash_node *create_node(const char *key, const char *value) { t_hash_node *node; - node = (t_hash_node *)malloc(sizeof(t_hash_node)); + node = (t_hash_node *)ft_calloc(1, sizeof(t_hash_node)); if (!node) return (NULL); node->key = ft_strdup(key); @@ -32,7 +32,6 @@ static t_hash_node *create_node(const char *key, const char *value) free(node); return (NULL); } - node->next = NULL; return (node); } From b6e9fec3ef64ac33575d971dcbf30cafb64bfe28 Mon Sep 17 00:00:00 2001 From: urassh Date: Sun, 23 Nov 2025 15:19:03 +0900 Subject: [PATCH 075/173] =?UTF-8?q?fix:=20ht=5Fcreate=E3=81=A7calloc?= =?UTF-8?q?=E3=82=92=E4=BD=BF=E3=81=86=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libft/hash_table/hash_table.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/libft/hash_table/hash_table.c b/libft/hash_table/hash_table.c index e3df790..afc1cc0 100644 --- a/libft/hash_table/hash_table.c +++ b/libft/hash_table/hash_table.c @@ -15,14 +15,13 @@ t_hash_table *ht_create(size_t size) { t_hash_table *table; - size_t i; if (size == 0) return (NULL); - table = (t_hash_table *)malloc(sizeof(t_hash_table)); + table = (t_hash_table *)ft_calloc(1, sizeof(t_hash_table)); if (!table) return (NULL); - table->buckets = (t_hash_node **)malloc(sizeof(t_hash_node *) * size); + table->buckets = (t_hash_node **)ft_calloc(size, sizeof(t_hash_node *)); if (!table->buckets) { free(table); @@ -30,11 +29,5 @@ t_hash_table *ht_create(size_t size) } table->size = size; table->n_nodes = 0; - i = 0; - while (i < size) - { - table->buckets[i] = NULL; - i++; - } return (table); } From d0561433c742c5d06a76b84c66f88becd76d3d6b Mon Sep 17 00:00:00 2001 From: urassh Date: Wed, 26 Nov 2025 16:13:21 +0900 Subject: [PATCH 076/173] =?UTF-8?q?feat:=20env=5Ftable=E3=82=92=E4=BD=BF?= =?UTF-8?q?=E3=81=86=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- includes/minishell.h | 2 +- includes/prompt.h | 5 +++-- src/callback/on_input.c | 3 ++- src/checker/heredoc_checker.c | 5 +++-- src/checker/tokenize_checker.c | 5 +++-- src/main.c | 15 ++++++++++++--- src/prompt/prompt.c | 7 ++++--- 7 files changed, 28 insertions(+), 14 deletions(-) diff --git a/includes/minishell.h b/includes/minishell.h index 3d96c2a..317162b 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -20,7 +20,7 @@ # include "heredoc.h" // callbacks -void on_input(char *input); +void on_input(char *input, t_hash_table *env); // checkers void tokenize_checker(char *input); diff --git a/includes/prompt.h b/includes/prompt.h index fdc87f1..23ccd75 100644 --- a/includes/prompt.h +++ b/includes/prompt.h @@ -6,7 +6,7 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/01 15:35:18 by urassh #+# #+# */ -/* Updated: 2025/10/16 23:15:29 by urassh ### ########.fr */ +/* Updated: 2025/11/26 16:02:45 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -20,7 +20,8 @@ # include # include -void prompt(void (*handler)(char *input)); +void prompt(void (*handler)(char *input, t_hash_table *env), + t_hash_table *env); # define PROMPT "minishell$ " diff --git a/src/callback/on_input.c b/src/callback/on_input.c index 44d4585..eddd110 100644 --- a/src/callback/on_input.c +++ b/src/callback/on_input.c @@ -12,7 +12,8 @@ #include "minishell.h" -void on_input(char *input) +void on_input(char *input, t_hash_table *env) { + (void)env; free(input); } diff --git a/src/checker/heredoc_checker.c b/src/checker/heredoc_checker.c index 2346323..0eb3b52 100644 --- a/src/checker/heredoc_checker.c +++ b/src/checker/heredoc_checker.c @@ -6,7 +6,7 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/20 15:55:55 by urassh #+# #+# */ -/* Updated: 2025/11/20 17:40:53 by urassh ### ########.fr */ +/* Updated: 2025/11/26 16:02:02 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,11 +18,12 @@ static void on_exit_token(t_list *token_list); static void print_tokens(t_list *token_list); static void unlink_tmpfiles(t_list *token_list); -void heredoc_checker(char *input) +void heredoc_checker(char *input, t_hash_table *env) { t_list *token_list; t_list *heredoced_list; + (void)env; token_list = tokenize(input); if (!token_list) { diff --git a/src/checker/tokenize_checker.c b/src/checker/tokenize_checker.c index 18e6859..4dbf5b3 100644 --- a/src/checker/tokenize_checker.c +++ b/src/checker/tokenize_checker.c @@ -6,7 +6,7 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/05 13:47:35 by urassh #+# #+# */ -/* Updated: 2025/11/05 13:48:56 by urassh ### ########.fr */ +/* Updated: 2025/11/26 16:02:29 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,10 +15,11 @@ static void on_exit_token(t_list *token_list); static void print_tokens(t_list *token_list); -void tokenize_checker(char *input) +void tokenize_checker(char *input, t_hash_table *env) { t_list *token_list; + (void)env; token_list = tokenize(input); if (!token_list) { diff --git a/src/main.c b/src/main.c index 47af15b..42c083c 100644 --- a/src/main.c +++ b/src/main.c @@ -6,14 +6,23 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:13:47 by kjikuhar #+# #+# */ -/* Updated: 2025/10/15 01:50:50 by urassh ### ########.fr */ +/* Updated: 2025/11/26 16:01:45 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -int main(void) +int main(int argc, char **argv, char **envp) { - prompt(heredoc_checker); + t_hash_table *env; + + (void)argc; + (void)argv; + (void)envp; + env = ht_create(128); + if (!env) + return (1); + prompt(heredoc_checker, env); + ht_destroy(env); return (0); } diff --git a/src/prompt/prompt.c b/src/prompt/prompt.c index 10e0c2b..007678c 100644 --- a/src/prompt/prompt.c +++ b/src/prompt/prompt.c @@ -6,13 +6,14 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/01 15:35:00 by urassh #+# #+# */ -/* Updated: 2025/10/15 01:39:41 by urassh ### ########.fr */ +/* Updated: 2025/11/26 16:01:54 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ #include "prompt.h" -void prompt(void (*handler)(char *input)) +void prompt(void (*handler)(char *input, t_hash_table *env), + t_hash_table *env) { char *input; @@ -29,7 +30,7 @@ void prompt(void (*handler)(char *input)) if (*input) add_history(input); if (handler) - handler(input); + handler(input, env); } rl_clear_history(); } From 38c5367171243f42502ae6114f534b9479341b06 Mon Sep 17 00:00:00 2001 From: urassh Date: Wed, 26 Nov 2025 16:34:17 +0900 Subject: [PATCH 077/173] feat: build_env_table --- includes/env_table.h | 24 +++++++ src/component/env_table/build_env_table.c | 76 +++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 includes/env_table.h create mode 100644 src/component/env_table/build_env_table.c diff --git a/includes/env_table.h b/includes/env_table.h new file mode 100644 index 0000000..fc6a6ec --- /dev/null +++ b/includes/env_table.h @@ -0,0 +1,24 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* env_table.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/26 16:13:33 by urassh #+# #+# */ +/* Updated: 2025/11/26 16:31:31 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef ENV_TABLE_H +# define ENV_TABLE_H + +# include +# include + +# define ENV_TABLE_INIT_SIZE 256 + +t_hash_table *build_env_table(char **envp); +char **export_envp(t_hash_table *env_table); + +#endif diff --git a/src/component/env_table/build_env_table.c b/src/component/env_table/build_env_table.c new file mode 100644 index 0000000..488591a --- /dev/null +++ b/src/component/env_table/build_env_table.c @@ -0,0 +1,76 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* build_env_table.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/26 16:15:23 by urassh #+# #+# */ +/* Updated: 2025/11/26 16:31:37 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include + +static int insert_env_entries(char **envp, t_hash_table *table); +static int parse_env_entry(char *env, char **key, char **value); + +t_hash_table *build_env_table(char **envp) +{ + t_hash_table *table; + + if (!envp) + return (NULL); + table = ht_create(ENV_TABLE_INIT_SIZE); + if (!table) + return (NULL); + if (insert_env_entries(envp, table) == ERROR) + return (NULL); + return (table); +} + +static int insert_env_entries(char **envp, t_hash_table *table) +{ + size_t i; + char *key_tmp; + char *value_tmp; + + while (envp[i]) + { + if (parse_env_entry(envp[i], &key_tmp, &value_tmp) == ERROR) + return (ERROR); + if (!ht_insert(table, key_tmp, value_tmp)) + { + free(key_tmp); + free(value_tmp); + ht_destroy(table); + return (NULL); + } + free(key_tmp); + free(value_tmp); + i++; + } + return (SUCCESS); +} + +static int parse_env_entry(char *env, char **key, char **value) +{ + char *eq_ptr; + size_t key_len; + + eq_ptr = ft_strchr(env, '='); + if (!eq_ptr) + return (ERROR); + key_len = eq_ptr - env; + *key = (char *)malloc(key_len + 1); + if (!*key) + return (ERROR); + ft_strlcpy(*key, env, key_len + 1); + *value = ft_strdup(eq_ptr + 1); + if (!*value) + { + free(*key); + return (ERROR); + } + return (SUCCESS); +} From 684d27f96c86e25a58f2cfc276b02b5a4e3c923e Mon Sep 17 00:00:00 2001 From: urassh Date: Wed, 26 Nov 2025 16:47:27 +0900 Subject: [PATCH 078/173] feat: export_envp.c --- src/component/env_table/export_envp.c | 88 +++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/component/env_table/export_envp.c diff --git a/src/component/env_table/export_envp.c b/src/component/env_table/export_envp.c new file mode 100644 index 0000000..b704770 --- /dev/null +++ b/src/component/env_table/export_envp.c @@ -0,0 +1,88 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* export_envp.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/26 16:15:41 by urassh #+# #+# */ +/* Updated: 2025/11/26 16:45:48 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include + +static int export_envp_entries(char **envp, t_hash_table *env_table); +static char *export_envp_str(t_hash_node *node); +static void free_envp_array(char **envp, size_t count); + +char **export_envp(t_hash_table *env_table) +{ + char **envp; + + if (!env_table) + return (NULL); + envp = (char **)ft_calloc(env_table->n_nodes + 1, sizeof(char *)); + if (!envp) + return (NULL); + if (export_envp_entries(envp, env_table) == ERROR) + return (NULL); + return (envp); +} + +static int export_envp_entries(char **envp, t_hash_table *env_table) +{ + size_t index; + size_t env_index; + t_hash_node *node; + + env_index = 0; + index = 0; + while (index < env_table->size) + { + node = env_table->buckets[index]; + while (node) + { + envp[env_index] = export_envp_str(node); + if (!envp[env_index]) + { + free_envp_array(envp, env_index); + return (ERROR); + } + env_index++; + node = node->next; + } + index++; + } + return (SUCCESS); +} + +static char *export_envp_str(t_hash_node *node) +{ + char *result; + size_t key_len; + size_t value_len; + + key_len = ft_strlen(node->key); + value_len = ft_strlen(node->value); + result = (char *)malloc(key_len + value_len + 2); + if (!result) + return (NULL); + ft_strlcpy(result, node->key, key_len + 1); + result[key_len] = '='; + ft_strlcpy(result + key_len + 1, node->value, value_len + 1); + return (result); +} + +static void free_envp_array(char **envp, size_t count) +{ + size_t i; + + i = 0; + while (i < count) + { + free(envp[i]); + i++; + } + free(envp); +} From ab62ef2ce5381b99fef79107a300f909243ad031 Mon Sep 17 00:00:00 2001 From: urassh Date: Wed, 26 Nov 2025 16:52:14 +0900 Subject: [PATCH 079/173] =?UTF-8?q?faet:=20build=5Fenv=5Ftable=E3=82=92min?= =?UTF-8?q?ishell=E3=81=AB=E7=B5=B1=E5=90=88=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- includes/minishell.h | 11 ++++++----- includes/prompt.h | 6 +++--- src/callback/on_input.c | 6 +++--- src/checker/heredoc_checker.c | 6 +++--- src/checker/tokenize_checker.c | 6 +++--- src/main.c | 13 ++++++------- src/prompt/prompt.c | 8 ++++---- 7 files changed, 28 insertions(+), 28 deletions(-) diff --git a/includes/minishell.h b/includes/minishell.h index 317162b..8984724 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -6,7 +6,7 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:14:22 by kjikuhar #+# #+# */ -/* Updated: 2025/11/20 15:56:35 by urassh ### ########.fr */ +/* Updated: 2025/11/26 16:51:25 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,16 +14,17 @@ # define MINISHELL_H # include "constants.h" +# include "env_table.h" +# include "heredoc.h" # include "libft.h" # include "prompt.h" # include "tokenize.h" -# include "heredoc.h" // callbacks -void on_input(char *input, t_hash_table *env); +void on_input(char *input, t_hash_table *env_table); // checkers -void tokenize_checker(char *input); -void heredoc_checker(char *input); +void tokenize_checker(char *input, t_hash_table *env_table); +void heredoc_checker(char *input, t_hash_table *env_table); #endif diff --git a/includes/prompt.h b/includes/prompt.h index 23ccd75..94132e6 100644 --- a/includes/prompt.h +++ b/includes/prompt.h @@ -6,7 +6,7 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/01 15:35:18 by urassh #+# #+# */ -/* Updated: 2025/11/26 16:02:45 by urassh ### ########.fr */ +/* Updated: 2025/11/26 16:48:53 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -20,8 +20,8 @@ # include # include -void prompt(void (*handler)(char *input, t_hash_table *env), - t_hash_table *env); +void prompt(void (*handler)(char *input, t_hash_table *env_table), + t_hash_table *env_table); # define PROMPT "minishell$ " diff --git a/src/callback/on_input.c b/src/callback/on_input.c index eddd110..a3e5c03 100644 --- a/src/callback/on_input.c +++ b/src/callback/on_input.c @@ -6,14 +6,14 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/10 17:04:25 by urassh #+# #+# */ -/* Updated: 2025/11/05 13:48:51 by urassh ### ########.fr */ +/* Updated: 2025/11/26 16:50:02 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -void on_input(char *input, t_hash_table *env) +void on_input(char *input, t_hash_table *env_table) { - (void)env; + (void)env_table; free(input); } diff --git a/src/checker/heredoc_checker.c b/src/checker/heredoc_checker.c index 0eb3b52..a14621b 100644 --- a/src/checker/heredoc_checker.c +++ b/src/checker/heredoc_checker.c @@ -6,7 +6,7 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/20 15:55:55 by urassh #+# #+# */ -/* Updated: 2025/11/26 16:02:02 by urassh ### ########.fr */ +/* Updated: 2025/11/26 16:49:25 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,12 +18,12 @@ static void on_exit_token(t_list *token_list); static void print_tokens(t_list *token_list); static void unlink_tmpfiles(t_list *token_list); -void heredoc_checker(char *input, t_hash_table *env) +void heredoc_checker(char *input, t_hash_table *env_table) { t_list *token_list; t_list *heredoced_list; - (void)env; + (void)env_table; token_list = tokenize(input); if (!token_list) { diff --git a/src/checker/tokenize_checker.c b/src/checker/tokenize_checker.c index 4dbf5b3..28c823d 100644 --- a/src/checker/tokenize_checker.c +++ b/src/checker/tokenize_checker.c @@ -6,7 +6,7 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/05 13:47:35 by urassh #+# #+# */ -/* Updated: 2025/11/26 16:02:29 by urassh ### ########.fr */ +/* Updated: 2025/11/26 16:49:18 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,11 +15,11 @@ static void on_exit_token(t_list *token_list); static void print_tokens(t_list *token_list); -void tokenize_checker(char *input, t_hash_table *env) +void tokenize_checker(char *input, t_hash_table *env_table) { t_list *token_list; - (void)env; + (void)env_table; token_list = tokenize(input); if (!token_list) { diff --git a/src/main.c b/src/main.c index 42c083c..f63e66d 100644 --- a/src/main.c +++ b/src/main.c @@ -6,7 +6,7 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:13:47 by kjikuhar #+# #+# */ -/* Updated: 2025/11/26 16:01:45 by urassh ### ########.fr */ +/* Updated: 2025/11/26 16:51:41 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,15 +14,14 @@ int main(int argc, char **argv, char **envp) { - t_hash_table *env; + t_hash_table *env_table; (void)argc; (void)argv; - (void)envp; - env = ht_create(128); - if (!env) + env_table = build_env_table(envp); + if (!env_table) return (1); - prompt(heredoc_checker, env); - ht_destroy(env); + prompt(heredoc_checker, env_table); + ht_destroy(env_table); return (0); } diff --git a/src/prompt/prompt.c b/src/prompt/prompt.c index 007678c..8c43c07 100644 --- a/src/prompt/prompt.c +++ b/src/prompt/prompt.c @@ -6,14 +6,14 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/01 15:35:00 by urassh #+# #+# */ -/* Updated: 2025/11/26 16:01:54 by urassh ### ########.fr */ +/* Updated: 2025/11/26 16:50:17 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ #include "prompt.h" -void prompt(void (*handler)(char *input, t_hash_table *env), - t_hash_table *env) +void prompt(void (*handler)(char *input, t_hash_table *env_table), + t_hash_table *env_table) { char *input; @@ -30,7 +30,7 @@ void prompt(void (*handler)(char *input, t_hash_table *env), if (*input) add_history(input); if (handler) - handler(input, env); + handler(input, env_table); } rl_clear_history(); } From a03319d856ddfcc7b98d051088c9b3da698abf1e Mon Sep 17 00:00:00 2001 From: urassh Date: Wed, 26 Nov 2025 16:55:59 +0900 Subject: [PATCH 080/173] =?UTF-8?q?add:=20Makefile=E3=81=ABenv=5Ftable?= =?UTF-8?q?=E3=81=AB=E9=96=A2=E3=81=99=E3=82=8B=E5=AE=9A=E7=BE=A9=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 7828f21..5a0267a 100644 --- a/Makefile +++ b/Makefile @@ -60,6 +60,7 @@ SRCS_MAND := src/main.c \ src/callback/on_input.c \ src/checker/tokenize_checker.c \ src/checker/heredoc_checker.c \ + src/checker/exv_table_checker.c \ src/tokenize/tokenize.c \ src/tokenize/is_specific.c \ src/tokenize/state/in_normal.c \ @@ -73,6 +74,8 @@ SRCS_MAND := src/main.c \ src/component/heredoc/heredoc.c \ src/component/heredoc/heredoc_prompt.c \ src/component/heredoc/tmpfile.c \ + src/component/env_table/build_env_table.c \ + src/component/env_table/export_env.c \ #bonus sources From 841a931397e1f2f942e078ef5738122cec34cf77 Mon Sep 17 00:00:00 2001 From: urassh Date: Wed, 26 Nov 2025 17:01:17 +0900 Subject: [PATCH 081/173] add: env_table_checker.c --- Makefile | 4 +- includes/minishell.h | 1 + src/checker/env_table_checker.c | 78 +++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 src/checker/env_table_checker.c diff --git a/Makefile b/Makefile index 5a0267a..114a9b3 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # By: urassh +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/05/18 21:11:39 by kjikuhar #+# #+# # -# Updated: 2025/11/20 17:42:22 by urassh ### ########.fr # +# Updated: 2025/11/26 17:01:03 by urassh ### ########.fr # # # # **************************************************************************** # @@ -60,7 +60,7 @@ SRCS_MAND := src/main.c \ src/callback/on_input.c \ src/checker/tokenize_checker.c \ src/checker/heredoc_checker.c \ - src/checker/exv_table_checker.c \ + src/checker/env_table_checker.c \ src/tokenize/tokenize.c \ src/tokenize/is_specific.c \ src/tokenize/state/in_normal.c \ diff --git a/includes/minishell.h b/includes/minishell.h index 8984724..6994e8b 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -26,5 +26,6 @@ void on_input(char *input, t_hash_table *env_table); // checkers void tokenize_checker(char *input, t_hash_table *env_table); void heredoc_checker(char *input, t_hash_table *env_table); +void env_table_checker(char *input, t_hash_table *env_table); #endif diff --git a/src/checker/env_table_checker.c b/src/checker/env_table_checker.c new file mode 100644 index 0000000..9b3a72c --- /dev/null +++ b/src/checker/env_table_checker.c @@ -0,0 +1,78 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* env_table_checker.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/26 16:53:40 by urassh #+# #+# */ +/* Updated: 2025/11/26 17:00:37 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#include + +static void print_env_table_entries(t_hash_table *env_table); +static void print_exported_envp(t_hash_table *env_table); + +void env_table_checker(char *input, t_hash_table *env_table) +{ + (void)input; + printf("\n========== ENV TABLE ENTRIES ==========\n"); + print_env_table_entries(env_table); + printf("\n========== EXPORTED ENVP ==========\n"); + print_exported_envp(env_table); + printf("=======================================\n\n"); +} + +static void print_env_table_entries(t_hash_table *env_table) +{ + size_t i; + t_hash_node *node; + + if (!env_table) + { + printf("env_table is NULL\n"); + return ; + } + printf("Total entries: %zu\n", env_table->n_nodes); + printf("Table size: %zu\n\n", env_table->size); + i = 0; + while (i < env_table->size) + { + node = env_table->buckets[i]; + while (node) + { + printf("[%zu] %s = %s\n", i, node->key, node->value); + node = node->next; + } + i++; + } +} + +static void print_exported_envp(t_hash_table *env_table) +{ + char **envp; + size_t i; + + if (!env_table) + { + printf("env_table is NULL\n"); + return ; + } + envp = export_envp(env_table); + if (!envp) + { + printf("Failed to export envp\n"); + return ; + } + i = 0; + while (envp[i]) + { + printf("%s\n", envp[i]); + free(envp[i]); + i++; + } + free(envp); +} From 5c6d30f681115a3c6324ff9812af23f87b34ac5a Mon Sep 17 00:00:00 2001 From: urassh Date: Wed, 26 Nov 2025 17:02:18 +0900 Subject: [PATCH 082/173] =?UTF-8?q?fix:=20insert=5Fenv=5Fentries=E3=81=AE?= =?UTF-8?q?=E6=88=BB=E3=82=8A=E5=9E=8B=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/component/env_table/build_env_table.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/component/env_table/build_env_table.c b/src/component/env_table/build_env_table.c index 488591a..fde134b 100644 --- a/src/component/env_table/build_env_table.c +++ b/src/component/env_table/build_env_table.c @@ -6,7 +6,7 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/26 16:15:23 by urassh #+# #+# */ -/* Updated: 2025/11/26 16:31:37 by urassh ### ########.fr */ +/* Updated: 2025/11/26 17:01:50 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -44,7 +44,7 @@ static int insert_env_entries(char **envp, t_hash_table *table) free(key_tmp); free(value_tmp); ht_destroy(table); - return (NULL); + return (ERROR); } free(key_tmp); free(value_tmp); From 279c8d8ef47390b7ab277881b1143618ecf20668 Mon Sep 17 00:00:00 2001 From: urassh Date: Wed, 26 Nov 2025 17:03:21 +0900 Subject: [PATCH 083/173] =?UTF-8?q?fix:=20export=5Fenvp=E3=81=AE=E3=82=BF?= =?UTF-8?q?=E3=82=A4=E3=83=9D=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 114a9b3..93d268a 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # By: urassh +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/05/18 21:11:39 by kjikuhar #+# #+# # -# Updated: 2025/11/26 17:01:03 by urassh ### ########.fr # +# Updated: 2025/11/26 17:03:05 by urassh ### ########.fr # # # # **************************************************************************** # @@ -75,7 +75,7 @@ SRCS_MAND := src/main.c \ src/component/heredoc/heredoc_prompt.c \ src/component/heredoc/tmpfile.c \ src/component/env_table/build_env_table.c \ - src/component/env_table/export_env.c \ + src/component/env_table/export_envp.c \ #bonus sources From ac2952bec5d73dfa8ee6076b400b7aa1c8755b0d Mon Sep 17 00:00:00 2001 From: urassh Date: Wed, 26 Nov 2025 17:20:37 +0900 Subject: [PATCH 084/173] =?UTF-8?q?main=E3=82=92=E6=9C=AC=E7=95=AA?= =?UTF-8?q?=E3=81=A7=E5=88=86=E5=89=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/leak-check.yml | 123 ++++++++++++++++++---- includes/minishell.h | 2 +- src/checker/env_table_checker.c | 5 +- src/component/env_table/build_env_table.c | 1 + src/main.c | 27 ++++- 5 files changed, 132 insertions(+), 26 deletions(-) diff --git a/.github/workflows/leak-check.yml b/.github/workflows/leak-check.yml index 73cd084..1e4cd94 100644 --- a/.github/workflows/leak-check.yml +++ b/.github/workflows/leak-check.yml @@ -32,13 +32,17 @@ jobs: echo "✅ minishell binary found" ls -la ./minishell - - name: Create test script + - name: Create test script for production mode run: | - cat << 'EOF' > test_input.sh + cat << 'EOF' > test_prod.sh #!/bin/bash + echo "==========================================" + echo "🚀 Testing PRODUCTION mode" + echo "==========================================" + # minishellにコマンドを送信してメモリリークをチェック - echo "Starting memory leak test..." + echo "Starting memory leak test for production mode..." # expectスタイルでインタラクティブな入力をシミュレート ( @@ -52,43 +56,43 @@ jobs: --track-origins=yes \ --suppressions=./readline.supp \ --error-exitcode=42 \ - --log-file=valgrind_output.txt \ + --log-file=valgrind_prod.txt \ ./minishell 2>&1 VALGRIND_EXIT=$? echo "" echo "==========================================" - echo "Valgrind Output:" + echo "Valgrind Output (Production):" echo "==========================================" - cat valgrind_output.txt + cat valgrind_prod.txt echo "==========================================" # Valgrindの結果を解析 if [ $VALGRIND_EXIT -eq 42 ]; then echo "" - echo "❌ MEMORY LEAK DETECTED!" + echo "❌ MEMORY LEAK DETECTED in PRODUCTION mode!" echo "" echo "Summary of leaks:" - grep "definitely lost" valgrind_output.txt || echo "No definitely lost blocks" - grep "indirectly lost" valgrind_output.txt || echo "No indirectly lost blocks" - grep "possibly lost" valgrind_output.txt || echo "No possibly lost blocks" + grep "definitely lost" valgrind_prod.txt || echo "No definitely lost blocks" + grep "indirectly lost" valgrind_prod.txt || echo "No indirectly lost blocks" + grep "possibly lost" valgrind_prod.txt || echo "No possibly lost blocks" exit 1 else echo "" - echo "✅ NO MEMORY LEAKS DETECTED" + echo "✅ NO MEMORY LEAKS DETECTED in PRODUCTION mode" # リークサマリーを表示 echo "" echo "Leak Summary:" - grep "LEAK SUMMARY" valgrind_output.txt -A 5 || true + grep "LEAK SUMMARY" valgrind_prod.txt -A 5 || true # 全てのヒープブロックが解放されたかチェック - if grep -q "All heap blocks were freed -- no leaks are possible" valgrind_output.txt; then + if grep -q "All heap blocks were freed -- no leaks are possible" valgrind_prod.txt; then echo "✅ All heap blocks were freed" - elif grep -q "definitely lost: 0 bytes in 0 blocks" valgrind_output.txt && \ - grep -q "indirectly lost: 0 bytes in 0 blocks" valgrind_output.txt && \ - grep -q "possibly lost: 0 bytes in 0 blocks" valgrind_output.txt; then + elif grep -q "definitely lost: 0 bytes in 0 blocks" valgrind_prod.txt && \ + grep -q "indirectly lost: 0 bytes in 0 blocks" valgrind_prod.txt && \ + grep -q "possibly lost: 0 bytes in 0 blocks" valgrind_prod.txt; then echo "✅ No definite, indirect, or possible leaks" else echo "⚠️ Warning: Some reachable memory detected (this is usually OK for readline)" @@ -98,16 +102,95 @@ jobs: fi EOF - chmod +x test_input.sh + chmod +x test_prod.sh + + - name: Create test script for development mode + run: | + cat << 'EOF' > test_dev.sh + #!/bin/bash + + echo "" + echo "==========================================" + echo "🔧 Testing DEVELOPMENT mode" + echo "==========================================" + + # minishellにコマンドを送信してメモリリークをチェック + echo "Starting memory leak test for development mode..." + + # expectスタイルでインタラクティブな入力をシミュレート + ( + sleep 0.5 + echo "ec'c'o \"hello\"&&cat -e" + sleep 0.5 + echo "exit" + sleep 0.5 + ) | valgrind --leak-check=full \ + --show-leak-kinds=all \ + --track-origins=yes \ + --suppressions=./readline.supp \ + --error-exitcode=42 \ + --log-file=valgrind_dev.txt \ + ./minishell --dev 2>&1 + + VALGRIND_EXIT=$? + + echo "" + echo "==========================================" + echo "Valgrind Output (Development):" + echo "==========================================" + cat valgrind_dev.txt + echo "==========================================" + + # Valgrindの結果を解析 + if [ $VALGRIND_EXIT -eq 42 ]; then + echo "" + echo "❌ MEMORY LEAK DETECTED in DEVELOPMENT mode!" + echo "" + echo "Summary of leaks:" + grep "definitely lost" valgrind_dev.txt || echo "No definitely lost blocks" + grep "indirectly lost" valgrind_dev.txt || echo "No indirectly lost blocks" + grep "possibly lost" valgrind_dev.txt || echo "No possibly lost blocks" + exit 1 + else + echo "" + echo "✅ NO MEMORY LEAKS DETECTED in DEVELOPMENT mode" + + # リークサマリーを表示 + echo "" + echo "Leak Summary:" + grep "LEAK SUMMARY" valgrind_dev.txt -A 5 || true + + # 全てのヒープブロックが解放されたかチェック + if grep -q "All heap blocks were freed -- no leaks are possible" valgrind_dev.txt; then + echo "✅ All heap blocks were freed" + elif grep -q "definitely lost: 0 bytes in 0 blocks" valgrind_dev.txt && \ + grep -q "indirectly lost: 0 bytes in 0 blocks" valgrind_dev.txt && \ + grep -q "possibly lost: 0 bytes in 0 blocks" valgrind_dev.txt; then + echo "✅ No definite, indirect, or possible leaks" + else + echo "⚠️ Warning: Some reachable memory detected (this is usually OK for readline)" + fi + + exit 0 + fi + EOF + + chmod +x test_dev.sh + + - name: Run memory leak test (Production mode) + run: | + ./test_prod.sh - - name: Run memory leak test + - name: Run memory leak test (Development mode) run: | - ./test_input.sh + ./test_dev.sh - name: Upload valgrind output as artifact if: always() uses: actions/upload-artifact@v4 with: name: valgrind-report - path: valgrind_output.txt + path: | + valgrind_prod.txt + valgrind_dev.txt retention-days: 30 diff --git a/includes/minishell.h b/includes/minishell.h index 6994e8b..8d2b738 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -26,6 +26,6 @@ void on_input(char *input, t_hash_table *env_table); // checkers void tokenize_checker(char *input, t_hash_table *env_table); void heredoc_checker(char *input, t_hash_table *env_table); -void env_table_checker(char *input, t_hash_table *env_table); +void env_table_checker(t_hash_table *env_table); #endif diff --git a/src/checker/env_table_checker.c b/src/checker/env_table_checker.c index 9b3a72c..63a6111 100644 --- a/src/checker/env_table_checker.c +++ b/src/checker/env_table_checker.c @@ -6,7 +6,7 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/26 16:53:40 by urassh #+# #+# */ -/* Updated: 2025/11/26 17:00:37 by urassh ### ########.fr */ +/* Updated: 2025/11/26 17:04:38 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,9 +16,8 @@ static void print_env_table_entries(t_hash_table *env_table); static void print_exported_envp(t_hash_table *env_table); -void env_table_checker(char *input, t_hash_table *env_table) +void env_table_checker(t_hash_table *env_table) { - (void)input; printf("\n========== ENV TABLE ENTRIES ==========\n"); print_env_table_entries(env_table); printf("\n========== EXPORTED ENVP ==========\n"); diff --git a/src/component/env_table/build_env_table.c b/src/component/env_table/build_env_table.c index fde134b..2155654 100644 --- a/src/component/env_table/build_env_table.c +++ b/src/component/env_table/build_env_table.c @@ -35,6 +35,7 @@ static int insert_env_entries(char **envp, t_hash_table *table) char *key_tmp; char *value_tmp; + i = 0; while (envp[i]) { if (parse_env_entry(envp[i], &key_tmp, &value_tmp) == ERROR) diff --git a/src/main.c b/src/main.c index f63e66d..63e95b3 100644 --- a/src/main.c +++ b/src/main.c @@ -6,13 +6,13 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:13:47 by kjikuhar #+# #+# */ -/* Updated: 2025/11/26 16:51:41 by urassh ### ########.fr */ +/* Updated: 2025/11/26 17:03:43 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -int main(int argc, char **argv, char **envp) +int main_prod(int argc, char **argv, char **envp) { t_hash_table *env_table; @@ -21,7 +21,30 @@ int main(int argc, char **argv, char **envp) env_table = build_env_table(envp); if (!env_table) return (1); + prompt(on_input, env_table); + ht_destroy(env_table); + return (0); +} + +int main_dev(int argc, char **argv, char **envp) +{ + t_hash_table *env_table; + + (void)argc; + (void)argv; + env_table = build_env_table(envp); + if (!env_table) + return (1); + env_table_checker(env_table); prompt(heredoc_checker, env_table); ht_destroy(env_table); return (0); } + +int main(int argc, char **argv, char **envp) +{ + if (argc > 1 && ft_strncmp(argv[1], "--dev", 6) == 0) + return (main_dev(argc, argv, envp)); + else + return (main_prod(argc, argv, envp)); +} From 7ab1128ac936d0105d6dc01571b21ef7f5d68492 Mon Sep 17 00:00:00 2001 From: urassh Date: Wed, 26 Nov 2025 17:30:40 +0900 Subject: [PATCH 085/173] =?UTF-8?q?add:=20test=5Fexecve=5Fwith=5Fenvp?= =?UTF-8?q?=E3=82=82=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/checker/env_table_checker.c | 46 ++++++++++++++++++++++++++++++++- src/main.c | 6 ++--- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/checker/env_table_checker.c b/src/checker/env_table_checker.c index 63a6111..587177f 100644 --- a/src/checker/env_table_checker.c +++ b/src/checker/env_table_checker.c @@ -6,15 +6,18 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/26 16:53:40 by urassh #+# #+# */ -/* Updated: 2025/11/26 17:04:38 by urassh ### ########.fr */ +/* Updated: 2025/11/26 17:29:16 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ #include #include +#include +#include static void print_env_table_entries(t_hash_table *env_table); static void print_exported_envp(t_hash_table *env_table); +static void test_execve_with_envp(t_hash_table *env_table); void env_table_checker(t_hash_table *env_table) { @@ -22,6 +25,8 @@ void env_table_checker(t_hash_table *env_table) print_env_table_entries(env_table); printf("\n========== EXPORTED ENVP ==========\n"); print_exported_envp(env_table); + printf("\n========== EXECVE TEST ==========\n"); + test_execve_with_envp(env_table); printf("=======================================\n\n"); } @@ -75,3 +80,42 @@ static void print_exported_envp(t_hash_table *env_table) } free(envp); } + +static void free_envp(char **envp) +{ + char **tmp; + + tmp = envp; + while (*tmp) + free(*tmp++); + free(envp); +} + +static void test_execve_with_envp(t_hash_table *env_table) +{ + char **envp; + pid_t pid; + int status; + char *argv[2]; + + envp = export_envp(env_table); + if (!env_table || !envp) + { + printf("env_table is NULL or failed to export envp\n"); + return ; + } + pid = fork(); + if (pid == 0) + { + argv[0] = "/usr/bin/env"; + argv[1] = NULL; + execve("/usr/bin/env", argv, envp); + perror("execve failed"); + exit(1); + } + else if (pid > 0 && waitpid(pid, &status, 0) != -1 && WIFEXITED(status)) + printf("execve test completed!!\n"); + else + printf("\nFork failed or test terminated abnormally\n"); + free_envp(envp); +} diff --git a/src/main.c b/src/main.c index 63e95b3..9b4dc47 100644 --- a/src/main.c +++ b/src/main.c @@ -6,13 +6,13 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:13:47 by kjikuhar #+# #+# */ -/* Updated: 2025/11/26 17:03:43 by urassh ### ########.fr */ +/* Updated: 2025/11/26 17:27:11 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -int main_prod(int argc, char **argv, char **envp) +int main_prod(int argc, char **argv, char **envp) { t_hash_table *env_table; @@ -26,7 +26,7 @@ int main_prod(int argc, char **argv, char **envp) return (0); } -int main_dev(int argc, char **argv, char **envp) +int main_dev(int argc, char **argv, char **envp) { t_hash_table *env_table; From 829244efefa69ca3d2bf3476ead90aa178ea234f Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 27 Nov 2025 01:01:06 +0900 Subject: [PATCH 086/173] =?UTF-8?q?fix:=20free=5Fenvp=5Farray=E3=81=A7?= =?UTF-8?q?=E3=81=AENULL=E5=9F=8B=E3=82=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/component/env_table/export_envp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/component/env_table/export_envp.c b/src/component/env_table/export_envp.c index b704770..9fca268 100644 --- a/src/component/env_table/export_envp.c +++ b/src/component/env_table/export_envp.c @@ -82,6 +82,7 @@ static void free_envp_array(char **envp, size_t count) while (i < count) { free(envp[i]); + envp[i] = NULL; i++; } free(envp); From d1c6ad2ef16b3d46f2447f88ff241d26104c0cf6 Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 27 Nov 2025 01:05:37 +0900 Subject: [PATCH 087/173] fix: char *const envp[] --- includes/env_table.h | 2 +- src/component/env_table/build_env_table.c | 6 +++--- src/main.c | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/includes/env_table.h b/includes/env_table.h index fc6a6ec..0b83091 100644 --- a/includes/env_table.h +++ b/includes/env_table.h @@ -18,7 +18,7 @@ # define ENV_TABLE_INIT_SIZE 256 -t_hash_table *build_env_table(char **envp); +t_hash_table *build_env_table(char *const envp[]); char **export_envp(t_hash_table *env_table); #endif diff --git a/src/component/env_table/build_env_table.c b/src/component/env_table/build_env_table.c index 2155654..eef795a 100644 --- a/src/component/env_table/build_env_table.c +++ b/src/component/env_table/build_env_table.c @@ -12,10 +12,10 @@ #include -static int insert_env_entries(char **envp, t_hash_table *table); +static int insert_env_entries(char *const envp[], t_hash_table *table); static int parse_env_entry(char *env, char **key, char **value); -t_hash_table *build_env_table(char **envp) +t_hash_table *build_env_table(char *const envp[]) { t_hash_table *table; @@ -29,7 +29,7 @@ t_hash_table *build_env_table(char **envp) return (table); } -static int insert_env_entries(char **envp, t_hash_table *table) +static int insert_env_entries(char *const envp[], t_hash_table *table) { size_t i; char *key_tmp; diff --git a/src/main.c b/src/main.c index 9b4dc47..78655aa 100644 --- a/src/main.c +++ b/src/main.c @@ -12,7 +12,7 @@ #include "minishell.h" -int main_prod(int argc, char **argv, char **envp) +int main_prod(int argc, char const **argv, char *const envp[]) { t_hash_table *env_table; @@ -26,7 +26,7 @@ int main_prod(int argc, char **argv, char **envp) return (0); } -int main_dev(int argc, char **argv, char **envp) +int main_dev(int argc, char const **argv, char *const envp[]) { t_hash_table *env_table; @@ -41,7 +41,7 @@ int main_dev(int argc, char **argv, char **envp) return (0); } -int main(int argc, char **argv, char **envp) +int main(int argc, char const **argv, char *const envp[]) { if (argc > 1 && ft_strncmp(argv[1], "--dev", 6) == 0) return (main_dev(argc, argv, envp)); From f1df0c2eafa1242ee3ee78470c025116d66f3929 Mon Sep 17 00:00:00 2001 From: jiku0730 Date: Thu, 27 Nov 2025 02:02:03 +0900 Subject: [PATCH 088/173] add: parser_checker.c --- Makefile | 9 ++++---- includes/minishell.h | 4 ++-- src/callback/on_input.c | 50 +---------------------------------------- src/main.c | 6 ++--- 4 files changed, 11 insertions(+), 58 deletions(-) diff --git a/Makefile b/Makefile index 72abaf7..a4d7eb0 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # By: kjikuhar +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/05/18 21:11:39 by kjikuhar #+# #+# # -# Updated: 2025/11/27 01:32:06 by kjikuhar ### ########.fr # +# Updated: 2025/11/27 01:57:08 by kjikuhar ### ########.fr # # # # **************************************************************************** # @@ -61,6 +61,7 @@ SRCS_MAND := src/main.c \ src/checker/tokenize_checker.c \ src/checker/heredoc_checker.c \ src/checker/env_table_checker.c \ + src/checker/parser_checker.c \ src/tokenize/tokenize.c \ src/tokenize/is_specific.c \ src/tokenize/state/in_normal.c \ @@ -80,12 +81,12 @@ SRCS_MAND := src/main.c \ src/parser/utils/free_ast.c \ src/parser/utils/print_ast.c \ src/parser/utils/print_ast_utils.c \ - src/parser/utils/print_ast_utils2.c + src/parser/utils/print_ast_utils2.c \ src/component/heredoc/heredoc.c \ src/component/heredoc/heredoc_prompt.c \ src/component/heredoc/tmpfile.c \ src/component/env_table/build_env_table.c \ - src/component/env_table/export_envp.c \ + src/component/env_table/export_envp.c #bonus sources @@ -154,7 +155,7 @@ norm: norminette src/* includes/* libft/ valgrind: re - valgrind --leak-check=full --suppressions=readline.supp ./$(NAME) + valgrind --leak-check=full --suppressions=readline.supp ./$(NAME) --dev test: norm valgrind diff --git a/includes/minishell.h b/includes/minishell.h index 94f1356..cf1b6a4 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:14:22 by kjikuhar #+# #+# */ -/* Updated: 2025/11/27 01:31:30 by kjikuhar ### ########.fr */ +/* Updated: 2025/11/27 01:55:10 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -28,5 +28,5 @@ void on_input(char *input, t_hash_table *env_table); void tokenize_checker(char *input, t_hash_table *env_table); void heredoc_checker(char *input, t_hash_table *env_table); void env_table_checker(t_hash_table *env_table); - +void parser_checker(char *input, t_hash_table *env_table); #endif diff --git a/src/callback/on_input.c b/src/callback/on_input.c index dc7a276..2e1559a 100644 --- a/src/callback/on_input.c +++ b/src/callback/on_input.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/10 17:04:25 by urassh #+# #+# */ -/* Updated: 2025/11/27 01:31:37 by kjikuhar ### ########.fr */ +/* Updated: 2025/11/27 01:46:34 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,51 +17,3 @@ void on_input(char *input, t_hash_table *env_table) (void)env_table; free(input); } - -void tokenize_checker(char *input) -{ - t_list *token_list; - t_ast *ast_root; - - token_list = tokenize(input); - if (!token_list) - { - write(STDOUT_FILENO, "Error: tokenize failed\n", 23); - return ; - } - if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) - on_exit_token(token_list); - print_tokens(token_list); - ast_root = parser(token_list); - print_ast(ast_root); - free_ast(ast_root); - ft_lstclear(&token_list, free); -} - -static void print_tokens(t_list *token_list) -{ - t_list *current; - int index; - - index = 0; - current = token_list; - write(STDOUT_FILENO, "Tokens:\n", 8); - while (current) - { - write(STDOUT_FILENO, "[", 1); - ft_putnbr_fd(index, STDOUT_FILENO); - write(STDOUT_FILENO, "] \"", 3); - if (current->content) - write(STDOUT_FILENO, current->content, ft_strlen(current->content)); - write(STDOUT_FILENO, "\"\n", 2); - current = current->next; - index++; - } -} - -static void on_exit_token(t_list *token_list) -{ - write(STDOUT_FILENO, "exit\n", 5); - ft_lstclear(&token_list, free); - exit(0); -} diff --git a/src/main.c b/src/main.c index 78655aa..2bd8f61 100644 --- a/src/main.c +++ b/src/main.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* main.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:13:47 by kjikuhar #+# #+# */ -/* Updated: 2025/11/26 17:27:11 by urassh ### ########.fr */ +/* Updated: 2025/11/27 01:53:40 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -36,7 +36,7 @@ int main_dev(int argc, char const **argv, char *const envp[]) if (!env_table) return (1); env_table_checker(env_table); - prompt(heredoc_checker, env_table); + prompt(parser_checker, env_table); ht_destroy(env_table); return (0); } From e4cda5ab904493f1b8803856206874e9b107cb67 Mon Sep 17 00:00:00 2001 From: jiku0730 Date: Thu, 27 Nov 2025 02:06:39 +0900 Subject: [PATCH 089/173] add: parser_checker.c --- src/checker/parser_checker.c | 40 ++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/checker/parser_checker.c diff --git a/src/checker/parser_checker.c b/src/checker/parser_checker.c new file mode 100644 index 0000000..eb95b9c --- /dev/null +++ b/src/checker/parser_checker.c @@ -0,0 +1,40 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parser_checker.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/27 01:46:42 by kjikuhar #+# #+# */ +/* Updated: 2025/11/27 01:52:44 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +static void on_exit_token(t_list *token_list) +{ + write(STDOUT_FILENO, "exit\n", 5); + ft_lstclear(&token_list, free); + exit(0); +} + +void parser_checker(char *input, t_hash_table *env_table) +{ + t_list *token_list; + t_ast *ast_root; + + (void)env_table; + token_list = tokenize(input); + if (!token_list) + { + write(STDOUT_FILENO, "Error: tokenize failed\n", 23); + return ; + } + if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) + on_exit_token(token_list); + ast_root = parser(token_list); + print_ast(ast_root); + free_ast(ast_root); + ft_lstclear(&token_list, free); +} From aabbb5045a3347e0702072ae8b905f330f8c8625 Mon Sep 17 00:00:00 2001 From: jiku0730 Date: Thu, 27 Nov 2025 02:41:13 +0900 Subject: [PATCH 090/173] delete: get_content ,and change:cursor->current ,and refactor: parser_redir --- includes/parser.h | 6 +-- src/parser/parser.c | 76 +++++++++++++++++----------------- src/parser/utils/token_check.c | 9 +--- 3 files changed, 41 insertions(+), 50 deletions(-) diff --git a/includes/parser.h b/includes/parser.h index 628ff65..59b2859 100644 --- a/includes/parser.h +++ b/includes/parser.h @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/30 16:38:39 by kjikuhar #+# #+# */ -/* Updated: 2025/11/20 23:35:17 by kjikuhar ### ########.fr */ +/* Updated: 2025/11/27 02:38:13 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -34,7 +34,8 @@ typedef enum e_redir_kind R_IN, R_IN_HEREDOC, R_OUT_TRUNC, - R_OUT_APPEND + R_OUT_APPEND, + R_NOT_FOUND } t_redir_kind; typedef struct s_redir @@ -65,7 +66,6 @@ bool is_word(const t_list *node); bool is_symbol(const t_list *node, const char *literal); bool is_eof(const t_list *node); bool is_redir(const t_list *node); -const char *get_content(const t_list *node); /* AST's Utils--------------------------------------------------------------- */ t_ast *new_ast_node(t_ast_type type); diff --git a/src/parser/parser.c b/src/parser/parser.c index 8ffd434..360725d 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -6,42 +6,40 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/14 18:30:40 by kjikuhar #+# #+# */ -/* Updated: 2025/11/20 23:40:01 by kjikuhar ### ########.fr */ +/* Updated: 2025/11/27 02:38:07 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ #include "parser.h" -static bool parse_redir(t_list **cursor, t_cmd *cmd) +static t_redir_kind find_redir_kind(t_list *current) { - if (is_symbol(*cursor, "<")) - { - *cursor = (*cursor)->next; - if (!*cursor || !add_redir_to_cmd(cmd, R_IN, get_content(*cursor))) - return (false); - } - else if (is_symbol(*cursor, ">")) - { - *cursor = (*cursor)->next; - if (!*cursor) - return (false); - if (!add_redir_to_cmd(cmd, R_OUT_TRUNC, get_content(*cursor))) - return (false); - } - else if (is_symbol(*cursor, ">>")) - { - *cursor = (*cursor)->next; - if (!*cursor) - return (false); - if (!add_redir_to_cmd(cmd, R_OUT_APPEND, get_content(*cursor))) - return (false); - } + if (is_symbol(current, "<")) + return (R_IN); + else if (is_symbol(current, ">")) + return (R_OUT_TRUNC); + else if (is_symbol(current, ">>")) + return (R_OUT_APPEND); else + return (R_NOT_FOUND); +} + +static bool parse_redir(t_list **current, t_cmd *cmd) +{ + t_redir_kind kind; + + kind = find_redir_kind(*current); + if (kind == R_NOT_FOUND) + return (false); + *current = (*current)->next; + if (!*current) + return (false); + if (!add_redir_to_cmd(cmd, kind, (*current)->content)) return (false); return (true); } -static t_ast *parse_cmd(t_list **cursor) +static t_ast *parse_cmd(t_list **current) { t_ast *ast; t_cmd *cmd; @@ -49,19 +47,19 @@ static t_ast *parse_cmd(t_list **cursor) cmd = new_cmd(); if (!cmd) return (NULL); - while (*cursor && !is_symbol(*cursor, "|") && !is_eof(*cursor)) + while (*current && !is_symbol(*current, "|") && !is_eof(*current)) { - if (is_redir(*cursor)) + if (is_redir(*current)) { - if (!parse_redir(cursor, cmd)) + if (!parse_redir(current, cmd)) return (free_cmd(cmd), NULL); } - else if (is_word(*cursor)) + else if (is_word(*current)) { - if (!add_argv_to_cmd(cmd, get_content(*cursor))) + if (!add_argv_to_cmd(cmd, (*current)->content)) return (free_cmd(cmd), NULL); } - *cursor = (*cursor)->next; + *current = (*current)->next; } ast = new_ast_node(CMD); if (!ast) @@ -70,22 +68,22 @@ static t_ast *parse_cmd(t_list **cursor) return (ast); } -static t_ast *parse_pipeline(t_list **cursor) +static t_ast *parse_pipeline(t_list **current) { t_ast *left; t_ast *pipe_node; - left = parse_cmd(cursor); + left = parse_cmd(current); if (!left) return (NULL); - if (*cursor && is_symbol(*cursor, "|")) + if (*current && is_symbol(*current, "|")) { - *cursor = (*cursor)->next; + *current = (*current)->next; pipe_node = new_ast_node(PIPE); if (!pipe_node) return (free_ast(left), NULL); pipe_node->left = left; - pipe_node->right = parse_pipeline(cursor); + pipe_node->right = parse_pipeline(current); if (!pipe_node->right) return (free_ast(pipe_node), NULL); return (pipe_node); @@ -95,10 +93,10 @@ static t_ast *parse_pipeline(t_list **cursor) t_ast *parser(t_list *token_head) { - t_list *cursor; + t_list *current; t_ast *root; - cursor = token_head; - root = parse_pipeline(&cursor); + current = token_head; + root = parse_pipeline(¤t); return (root); } diff --git a/src/parser/utils/token_check.c b/src/parser/utils/token_check.c index b5bce4c..92f969c 100644 --- a/src/parser/utils/token_check.c +++ b/src/parser/utils/token_check.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/14 18:29:48 by kjikuhar #+# #+# */ -/* Updated: 2025/11/19 23:39:47 by kjikuhar ### ########.fr */ +/* Updated: 2025/11/27 02:37:36 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -55,10 +55,3 @@ bool is_redir(const t_list *node) is_symbol(node, ">") || \ is_symbol(node, ">>")); } - -const char *get_content(const t_list *node) -{ - if (!node) - return (NULL); - return ((const char *)node->content); -} From f052401298db42011a7cea923f7532cb503c5310 Mon Sep 17 00:00:00 2001 From: jiku0730 Date: Thu, 27 Nov 2025 11:47:56 +0900 Subject: [PATCH 091/173] revise: parser_redir's return value from bool to int(use macro ERROR SUCCESS) --- includes/parser.h | 3 ++- src/parser/parser.c | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/includes/parser.h b/includes/parser.h index 59b2859..bb536dc 100644 --- a/includes/parser.h +++ b/includes/parser.h @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/30 16:38:39 by kjikuhar #+# #+# */ -/* Updated: 2025/11/27 02:38:13 by kjikuhar ### ########.fr */ +/* Updated: 2025/11/27 11:46:40 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,6 +14,7 @@ # define PARSER_H # include "libft.h" +# include "constants.h" # include # include # include diff --git a/src/parser/parser.c b/src/parser/parser.c index 360725d..7e00fd9 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/14 18:30:40 by kjikuhar #+# #+# */ -/* Updated: 2025/11/27 02:38:07 by kjikuhar ### ########.fr */ +/* Updated: 2025/11/27 11:46:57 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -24,19 +24,19 @@ static t_redir_kind find_redir_kind(t_list *current) return (R_NOT_FOUND); } -static bool parse_redir(t_list **current, t_cmd *cmd) +static int parse_redir(t_list **current, t_cmd *cmd) { t_redir_kind kind; kind = find_redir_kind(*current); if (kind == R_NOT_FOUND) - return (false); + return (ERROR); *current = (*current)->next; if (!*current) - return (false); + return (ERROR); if (!add_redir_to_cmd(cmd, kind, (*current)->content)) - return (false); - return (true); + return (ERROR); + return (SUCCESS); } static t_ast *parse_cmd(t_list **current) From 9a0ed221f9fc4e4c94ae33c5548c18f5a34e72fd Mon Sep 17 00:00:00 2001 From: jiku0730 Date: Thu, 27 Nov 2025 11:51:00 +0900 Subject: [PATCH 092/173] delete: HEREDOC macro --- includes/parser.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/includes/parser.h b/includes/parser.h index bb536dc..a3cad0c 100644 --- a/includes/parser.h +++ b/includes/parser.h @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/30 16:38:39 by kjikuhar #+# #+# */ -/* Updated: 2025/11/27 11:46:40 by kjikuhar ### ########.fr */ +/* Updated: 2025/11/27 11:48:59 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -35,7 +35,6 @@ typedef enum e_redir_kind R_IN, R_IN_HEREDOC, R_OUT_TRUNC, - R_OUT_APPEND, R_NOT_FOUND } t_redir_kind; From 0fe3e76ba9190ba15d7c007162cf74b8d331f951 Mon Sep 17 00:00:00 2001 From: jiku0730 Date: Thu, 27 Nov 2025 11:52:58 +0900 Subject: [PATCH 093/173] delete: is_EOF function --- includes/parser.h | 5 ++--- src/parser/utils/token_check.c | 9 +-------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/includes/parser.h b/includes/parser.h index a3cad0c..8d1529f 100644 --- a/includes/parser.h +++ b/includes/parser.h @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/30 16:38:39 by kjikuhar #+# #+# */ -/* Updated: 2025/11/27 11:48:59 by kjikuhar ### ########.fr */ +/* Updated: 2025/11/27 11:51:05 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -33,8 +33,8 @@ typedef enum e_ast_type typedef enum e_redir_kind { R_IN, - R_IN_HEREDOC, R_OUT_TRUNC, + R_OUT_APPEND, R_NOT_FOUND } t_redir_kind; @@ -64,7 +64,6 @@ t_ast *parser(t_list *token_head); /* AST's token utils--------------------------------------------------------- */ bool is_word(const t_list *node); bool is_symbol(const t_list *node, const char *literal); -bool is_eof(const t_list *node); bool is_redir(const t_list *node); /* AST's Utils--------------------------------------------------------------- */ diff --git a/src/parser/utils/token_check.c b/src/parser/utils/token_check.c index 92f969c..60b99d7 100644 --- a/src/parser/utils/token_check.c +++ b/src/parser/utils/token_check.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/14 18:29:48 by kjikuhar #+# #+# */ -/* Updated: 2025/11/27 02:37:36 by kjikuhar ### ########.fr */ +/* Updated: 2025/11/27 11:51:11 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -40,13 +40,6 @@ bool is_symbol(const t_list *node, const char *literal) return (ft_strncmp((const char *)node->content, literal, len + 1) == 0); } -bool is_eof(const t_list *node) -{ - if (!node || !node->content) - return (true); - return (ft_strncmp((const char *)node->content, "EOF", 4) == 0); -} - bool is_redir(const t_list *node) { if (!node) From 99aaff6d64937b627f2792117fbb6d3b2f20796d Mon Sep 17 00:00:00 2001 From: jiku0730 Date: Thu, 27 Nov 2025 11:56:05 +0900 Subject: [PATCH 094/173] delete: don't use is_EOF --- src/parser/parser.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/parser/parser.c b/src/parser/parser.c index 7e00fd9..6b2f976 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/14 18:30:40 by kjikuhar #+# #+# */ -/* Updated: 2025/11/27 11:46:57 by kjikuhar ### ########.fr */ +/* Updated: 2025/11/27 11:55:22 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -47,7 +47,7 @@ static t_ast *parse_cmd(t_list **current) cmd = new_cmd(); if (!cmd) return (NULL); - while (*current && !is_symbol(*current, "|") && !is_eof(*current)) + while (*current && !is_symbol(*current, "|")) { if (is_redir(*current)) { From 55366847e5f5fe525f1a640dcfee6f5c8559f8ad Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Thu, 27 Nov 2025 13:03:28 +0900 Subject: [PATCH 095/173] =?UTF-8?q?=E3=83=91=E3=82=BF=E3=83=BC=E3=83=B3?= =?UTF-8?q?=E3=83=9E=E3=83=83=E3=83=81=E3=81=AE=E5=9F=BA=E6=9C=AC=E5=AE=9F?= =?UTF-8?q?=E8=A3=85=20(#32)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: filter_pattern * fix: mattern_matchの基本ケースのリファクタ --- Makefile | 3 +- includes/pattern.h | 23 ++++++++++ src/component/pattern/filter_pattern.c | 62 ++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 includes/pattern.h create mode 100644 src/component/pattern/filter_pattern.c diff --git a/Makefile b/Makefile index a4d7eb0..0ee9ac0 100644 --- a/Makefile +++ b/Makefile @@ -86,7 +86,8 @@ SRCS_MAND := src/main.c \ src/component/heredoc/heredoc_prompt.c \ src/component/heredoc/tmpfile.c \ src/component/env_table/build_env_table.c \ - src/component/env_table/export_envp.c + src/component/env_table/export_envp.c \ + src/component/pattern/filter_pattern.c \ #bonus sources diff --git a/includes/pattern.h b/includes/pattern.h new file mode 100644 index 0000000..0310b6e --- /dev/null +++ b/includes/pattern.h @@ -0,0 +1,23 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* pattern.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/27 11:36:50 by urassh #+# #+# */ +/* Updated: 2025/11/27 12:02:52 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef PATTERN_H +# define PATTERN_H + +# include +# include + +# define WILDCARD '*' + +t_list *filter_pattern(t_list *source, const char *pattern); + +#endif diff --git a/src/component/pattern/filter_pattern.c b/src/component/pattern/filter_pattern.c new file mode 100644 index 0000000..dc14406 --- /dev/null +++ b/src/component/pattern/filter_pattern.c @@ -0,0 +1,62 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* filter_by_pattern.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/27 11:40:49 by urassh #+# #+# */ +/* Updated: 2025/11/27 12:10:33 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#include + +static bool match_pattern(const char *str, const char *pattern); + +t_list *filter_pattern(t_list *source, const char *pattern) +{ + t_list *result; + t_list *current; + t_list *new_node; + + if (!source || !pattern) + return (NULL); + result = NULL; + current = source; + while (current) + { + if (match_pattern((const char *)current->content, pattern)) + { + new_node = ft_lstnew(ft_strdup((const char *)current->content)); + if (!new_node) + { + ft_lstclear(&result, free); + return (NULL); + } + ft_lstadd_back(&result, new_node); + } + current = current->next; + } + return (result); +} + +static bool match_pattern(const char *str, const char *pattern) +{ + if (*pattern == '\0') + return (*str == '\0'); + if (*pattern == WILDCARD) + { + while (*str) + { + if (match_pattern(str, pattern + 1)) + return (true); + str++; + } + return (match_pattern(str, pattern + 1)); + } + if (*str == *pattern) + return (match_pattern(str + 1, pattern + 1)); + return (false); +} From fefeb164bf40120b38a8eb6500c604d7cf46b628 Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Thu, 27 Nov 2025 15:09:15 +0900 Subject: [PATCH 096/173] =?UTF-8?q?=E3=82=B7=E3=82=A7=E3=83=AB=E3=83=86?= =?UTF-8?q?=E3=83=BC=E3=83=96=E3=83=AB=E3=82=92=E5=AE=9A=E7=BE=A9=E3=81=97?= =?UTF-8?q?=E3=81=9F=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: filter_pattern * fix: mattern_matchの基本ケースのリファクタ * env_tablekからexportedフラグを含むshell_tableにrename --- Makefile | 17 +++-- includes/env_table.h | 24 ------- includes/minishell.h | 16 ++--- includes/prompt.h | 7 +- includes/shell_table.h | 49 +++++++++++++ libft/Makefile | 6 -- libft/hash_table/hash_table.c | 33 --------- libft/libft.h | 23 ------ src/callback/on_input.c | 8 +-- src/checker/heredoc_checker.c | 6 +- src/checker/parser_checker.c | 8 +-- ..._table_checker.c => shell_table_checker.c} | 52 +++++++------- src/checker/tokenize_checker.c | 6 +- .../build_shell_table.c} | 44 +++++++++--- .../{env_table => shell_table}/export_envp.c | 70 +++++++++++++------ .../component/shell_table/shell_delete.c | 20 +++--- .../component/shell_table/shell_destroy.c | 14 ++-- .../component/shell_table/shell_hash.c | 10 +-- .../component/shell_table/shell_insert.c | 31 ++++---- .../component/shell_table/shell_search.c | 16 ++--- src/main.c | 26 +++---- src/prompt/prompt.c | 8 +-- 22 files changed, 256 insertions(+), 238 deletions(-) delete mode 100644 includes/env_table.h create mode 100644 includes/shell_table.h delete mode 100644 libft/hash_table/hash_table.c rename src/checker/{env_table_checker.c => shell_table_checker.c} (63%) rename src/component/{env_table/build_env_table.c => shell_table/build_shell_table.c} (61%) rename src/component/{env_table => shell_table}/export_envp.c (52%) rename libft/hash_table/hash_delete.c => src/component/shell_table/shell_delete.c (73%) rename libft/hash_table/hash_destroy.c => src/component/shell_table/shell_destroy.c (75%) rename libft/hash_table/hash_function.c => src/component/shell_table/shell_hash.c (78%) rename libft/hash_table/hash_insert.c => src/component/shell_table/shell_insert.c (67%) rename libft/hash_table/hash_search.c => src/component/shell_table/shell_search.c (72%) diff --git a/Makefile b/Makefile index 0ee9ac0..972a83a 100644 --- a/Makefile +++ b/Makefile @@ -3,10 +3,10 @@ # ::: :::::::: # # Makefile :+: :+: :+: # # +:+ +:+ +:+ # -# By: kjikuhar +#+ +:+ +#+ # +# By: urassh +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/05/18 21:11:39 by kjikuhar #+# #+# # -# Updated: 2025/11/27 01:57:08 by kjikuhar ### ########.fr # +# Updated: 2025/11/27 14:58:00 by urassh ### ########.fr # # # # **************************************************************************** # @@ -60,7 +60,7 @@ SRCS_MAND := src/main.c \ src/callback/on_input.c \ src/checker/tokenize_checker.c \ src/checker/heredoc_checker.c \ - src/checker/env_table_checker.c \ + src/checker/shell_table_checker.c \ src/checker/parser_checker.c \ src/tokenize/tokenize.c \ src/tokenize/is_specific.c \ @@ -85,12 +85,15 @@ SRCS_MAND := src/main.c \ src/component/heredoc/heredoc.c \ src/component/heredoc/heredoc_prompt.c \ src/component/heredoc/tmpfile.c \ - src/component/env_table/build_env_table.c \ - src/component/env_table/export_envp.c \ + src/component/shell_table/shell_hash.c \ + src/component/shell_table/shell_insert.c \ + src/component/shell_table/shell_search.c \ + src/component/shell_table/shell_delete.c \ + src/component/shell_table/shell_destroy.c \ + src/component/shell_table/build_shell_table.c \ + src/component/shell_table/export_envp.c \ src/component/pattern/filter_pattern.c \ -#bonus sources - SRCS_BONUS := #object files diff --git a/includes/env_table.h b/includes/env_table.h deleted file mode 100644 index 0b83091..0000000 --- a/includes/env_table.h +++ /dev/null @@ -1,24 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* env_table.h :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/26 16:13:33 by urassh #+# #+# */ -/* Updated: 2025/11/26 16:31:31 by urassh ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#ifndef ENV_TABLE_H -# define ENV_TABLE_H - -# include -# include - -# define ENV_TABLE_INIT_SIZE 256 - -t_hash_table *build_env_table(char *const envp[]); -char **export_envp(t_hash_table *env_table); - -#endif diff --git a/includes/minishell.h b/includes/minishell.h index cf1b6a4..ef85288 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* minishell.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ +/* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:14:22 by kjikuhar #+# #+# */ -/* Updated: 2025/11/27 01:55:10 by kjikuhar ### ########.fr */ +/* Updated: 2025/11/27 14:54:45 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,7 +14,7 @@ # define MINISHELL_H # include "constants.h" -# include "env_table.h" +# include "shell_table.h" # include "heredoc.h" # include "libft.h" # include "prompt.h" @@ -22,11 +22,11 @@ # include "parser.h" // callbacks -void on_input(char *input, t_hash_table *env_table); +void on_input(char *input, t_shell_table *shell_table); // checkers -void tokenize_checker(char *input, t_hash_table *env_table); -void heredoc_checker(char *input, t_hash_table *env_table); -void env_table_checker(t_hash_table *env_table); -void parser_checker(char *input, t_hash_table *env_table); +void tokenize_checker(char *input, t_shell_table *shell_table); +void heredoc_checker(char *input, t_shell_table *shell_table); +void shell_table_checker(t_shell_table *shell_table); +void parser_checker(char *input, t_shell_table *shell_table); #endif diff --git a/includes/prompt.h b/includes/prompt.h index 94132e6..c8e99bc 100644 --- a/includes/prompt.h +++ b/includes/prompt.h @@ -6,7 +6,7 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/01 15:35:18 by urassh #+# #+# */ -/* Updated: 2025/11/26 16:48:53 by urassh ### ########.fr */ +/* Updated: 2025/11/27 14:54:45 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,14 +14,15 @@ # define PROMPT_H # include "constants.h" +# include "shell_table.h" # include "libft.h" # include # include # include # include -void prompt(void (*handler)(char *input, t_hash_table *env_table), - t_hash_table *env_table); +void prompt(void (*handler)(char *input, t_shell_table *shell_table), + t_shell_table *shell_table); # define PROMPT "minishell$ " diff --git a/includes/shell_table.h b/includes/shell_table.h new file mode 100644 index 0000000..b77b654 --- /dev/null +++ b/includes/shell_table.h @@ -0,0 +1,49 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* shell_table.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/27 00:00:00 by urassh #+# #+# */ +/* Updated: 2025/11/27 14:54:45 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef SHELL_TABLE_H +# define SHELL_TABLE_H + +# include +# include +# include + +# define SHELL_TABLE_INIT_SIZE 256 + +typedef struct s_shell_node +{ + char *key; + char *value; + bool exported; + struct s_shell_node *next; +} t_shell_node; + +typedef struct s_shell_table +{ + t_shell_node **buckets; + size_t size; + size_t n_nodes; +} t_shell_table; + +// shell_table operations +size_t st_hash(const char *key, size_t table_size); +int st_insert(t_shell_table *table, const char *key, + const char *value, bool exported); +char *st_search(t_shell_table *table, const char *key); +int st_delete(t_shell_table *table, const char *key); +void st_destroy(t_shell_table *table); + +// shell_table specific operations +t_shell_table *build_shell_table(char *const envp[]); +char **export_envp(t_shell_table *shell_table); + +#endif diff --git a/libft/Makefile b/libft/Makefile index 7f17871..a416e66 100644 --- a/libft/Makefile +++ b/libft/Makefile @@ -19,12 +19,6 @@ SRCS = conversion/ft_atoi.c \ conversion/ft_itoa.c \ conversion/ft_tolower.c \ conversion/ft_toupper.c \ - hash_table/hash_table.c \ - hash_table/hash_function.c \ - hash_table/hash_insert.c \ - hash_table/hash_search.c \ - hash_table/hash_delete.c \ - hash_table/hash_destroy.c \ judge/ft_isalnum.c \ judge/ft_isalpha.c \ judge/ft_isascii.c \ diff --git a/libft/hash_table/hash_table.c b/libft/hash_table/hash_table.c deleted file mode 100644 index afc1cc0..0000000 --- a/libft/hash_table/hash_table.c +++ /dev/null @@ -1,33 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* hash_table.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/05 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/11/05 00:00:00 by urassh ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "../libft.h" - -t_hash_table *ht_create(size_t size) -{ - t_hash_table *table; - - if (size == 0) - return (NULL); - table = (t_hash_table *)ft_calloc(1, sizeof(t_hash_table)); - if (!table) - return (NULL); - table->buckets = (t_hash_node **)ft_calloc(size, sizeof(t_hash_node *)); - if (!table->buckets) - { - free(table); - return (NULL); - } - table->size = size; - table->n_nodes = 0; - return (table); -} diff --git a/libft/libft.h b/libft/libft.h index 9652c3b..f9eff62 100644 --- a/libft/libft.h +++ b/libft/libft.h @@ -24,20 +24,6 @@ typedef struct s_list struct s_list *next; } t_list; -typedef struct s_hash_node -{ - char *key; - char *value; - struct s_hash_node *next; -} t_hash_node; - -typedef struct s_hash_table -{ - t_hash_node **buckets; - size_t size; - size_t n_nodes; -} t_hash_table; - // conversion int ft_atoi(const char *str); char *ft_itoa(int n); @@ -63,15 +49,6 @@ void ft_lstiter(t_list *lst, void (*f)(void *)); t_list *ft_lstmap(t_list *lst, void *(*f)(void *), void (*del)(void *)); -// hash_table -t_hash_table *ht_create(size_t size); -size_t ht_hash(const char *key, size_t table_size); -int ht_insert(t_hash_table *table, const char *key, - const char *value); -char *ht_search(t_hash_table *table, const char *key); -int ht_delete(t_hash_table *table, const char *key); -void ht_destroy(t_hash_table *table); - // memory void ft_bzero(void *s, size_t n); void *ft_calloc(size_t count, size_t size); diff --git a/src/callback/on_input.c b/src/callback/on_input.c index 2e1559a..c4baf1d 100644 --- a/src/callback/on_input.c +++ b/src/callback/on_input.c @@ -3,17 +3,17 @@ /* ::: :::::::: */ /* on_input.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ +/* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/10 17:04:25 by urassh #+# #+# */ -/* Updated: 2025/11/27 01:46:34 by kjikuhar ### ########.fr */ +/* Updated: 2025/11/27 14:54:45 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -void on_input(char *input, t_hash_table *env_table) +void on_input(char *input, t_shell_table *shell_table) { - (void)env_table; + (void)shell_table; free(input); } diff --git a/src/checker/heredoc_checker.c b/src/checker/heredoc_checker.c index a14621b..d105167 100644 --- a/src/checker/heredoc_checker.c +++ b/src/checker/heredoc_checker.c @@ -6,7 +6,7 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/20 15:55:55 by urassh #+# #+# */ -/* Updated: 2025/11/26 16:49:25 by urassh ### ########.fr */ +/* Updated: 2025/11/27 14:54:45 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,12 +18,12 @@ static void on_exit_token(t_list *token_list); static void print_tokens(t_list *token_list); static void unlink_tmpfiles(t_list *token_list); -void heredoc_checker(char *input, t_hash_table *env_table) +void heredoc_checker(char *input, t_shell_table *shell_table) { t_list *token_list; t_list *heredoced_list; - (void)env_table; + (void)shell_table; token_list = tokenize(input); if (!token_list) { diff --git a/src/checker/parser_checker.c b/src/checker/parser_checker.c index eb95b9c..76f1d56 100644 --- a/src/checker/parser_checker.c +++ b/src/checker/parser_checker.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* parser_checker.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ +/* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 01:46:42 by kjikuhar #+# #+# */ -/* Updated: 2025/11/27 01:52:44 by kjikuhar ### ########.fr */ +/* Updated: 2025/11/27 14:54:45 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,12 +19,12 @@ static void on_exit_token(t_list *token_list) exit(0); } -void parser_checker(char *input, t_hash_table *env_table) +void parser_checker(char *input, t_shell_table *shell_table) { t_list *token_list; t_ast *ast_root; - (void)env_table; + (void)shell_table; token_list = tokenize(input); if (!token_list) { diff --git a/src/checker/env_table_checker.c b/src/checker/shell_table_checker.c similarity index 63% rename from src/checker/env_table_checker.c rename to src/checker/shell_table_checker.c index 587177f..0dd6f3f 100644 --- a/src/checker/env_table_checker.c +++ b/src/checker/shell_table_checker.c @@ -1,12 +1,12 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* env_table_checker.c :+: :+: :+: */ +/* shell_table_checker.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/26 16:53:40 by urassh #+# #+# */ -/* Updated: 2025/11/26 17:29:16 by urassh ### ########.fr */ +/* Updated: 2025/11/27 14:55:00 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,37 +15,37 @@ #include #include -static void print_env_table_entries(t_hash_table *env_table); -static void print_exported_envp(t_hash_table *env_table); -static void test_execve_with_envp(t_hash_table *env_table); +static void print_shell_table_entries(t_shell_table *shell_table); +static void print_exported_envp(t_shell_table *shell_table); +static void test_execve_with_envp(t_shell_table *shell_table); -void env_table_checker(t_hash_table *env_table) +void shell_table_checker(t_shell_table *shell_table) { printf("\n========== ENV TABLE ENTRIES ==========\n"); - print_env_table_entries(env_table); + print_shell_table_entries(shell_table); printf("\n========== EXPORTED ENVP ==========\n"); - print_exported_envp(env_table); + print_exported_envp(shell_table); printf("\n========== EXECVE TEST ==========\n"); - test_execve_with_envp(env_table); + test_execve_with_envp(shell_table); printf("=======================================\n\n"); } -static void print_env_table_entries(t_hash_table *env_table) +static void print_shell_table_entries(t_shell_table *shell_table) { - size_t i; - t_hash_node *node; + size_t i; + t_shell_node *node; - if (!env_table) + if (!shell_table) { - printf("env_table is NULL\n"); + printf("shell_table is NULL\n"); return ; } - printf("Total entries: %zu\n", env_table->n_nodes); - printf("Table size: %zu\n\n", env_table->size); + printf("Total entries: %zu\n", shell_table->n_nodes); + printf("Table size: %zu\n\n", shell_table->size); i = 0; - while (i < env_table->size) + while (i < shell_table->size) { - node = env_table->buckets[i]; + node = shell_table->buckets[i]; while (node) { printf("[%zu] %s = %s\n", i, node->key, node->value); @@ -55,17 +55,17 @@ static void print_env_table_entries(t_hash_table *env_table) } } -static void print_exported_envp(t_hash_table *env_table) +static void print_exported_envp(t_shell_table *shell_table) { char **envp; size_t i; - if (!env_table) + if (!shell_table) { - printf("env_table is NULL\n"); + printf("shell_table is NULL\n"); return ; } - envp = export_envp(env_table); + envp = export_envp(shell_table); if (!envp) { printf("Failed to export envp\n"); @@ -91,17 +91,17 @@ static void free_envp(char **envp) free(envp); } -static void test_execve_with_envp(t_hash_table *env_table) +static void test_execve_with_envp(t_shell_table *shell_table) { char **envp; pid_t pid; int status; char *argv[2]; - envp = export_envp(env_table); - if (!env_table || !envp) + envp = export_envp(shell_table); + if (!shell_table || !envp) { - printf("env_table is NULL or failed to export envp\n"); + printf("shell_table is NULL or failed to export envp\n"); return ; } pid = fork(); diff --git a/src/checker/tokenize_checker.c b/src/checker/tokenize_checker.c index 28c823d..e44933f 100644 --- a/src/checker/tokenize_checker.c +++ b/src/checker/tokenize_checker.c @@ -6,7 +6,7 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/05 13:47:35 by urassh #+# #+# */ -/* Updated: 2025/11/26 16:49:18 by urassh ### ########.fr */ +/* Updated: 2025/11/27 14:54:45 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,11 +15,11 @@ static void on_exit_token(t_list *token_list); static void print_tokens(t_list *token_list); -void tokenize_checker(char *input, t_hash_table *env_table) +void tokenize_checker(char *input, t_shell_table *shell_table) { t_list *token_list; - (void)env_table; + (void)shell_table; token_list = tokenize(input); if (!token_list) { diff --git a/src/component/env_table/build_env_table.c b/src/component/shell_table/build_shell_table.c similarity index 61% rename from src/component/env_table/build_env_table.c rename to src/component/shell_table/build_shell_table.c index eef795a..4b0629e 100644 --- a/src/component/env_table/build_env_table.c +++ b/src/component/shell_table/build_shell_table.c @@ -1,27 +1,29 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* build_env_table.c :+: :+: :+: */ +/* build_shell_table.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/26 16:15:23 by urassh #+# #+# */ -/* Updated: 2025/11/26 17:01:50 by urassh ### ########.fr */ +/* Updated: 2025/11/27 14:53:48 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ -#include +#include -static int insert_env_entries(char *const envp[], t_hash_table *table); -static int parse_env_entry(char *env, char **key, char **value); +static t_shell_table *st_create(size_t size); +static int insert_env_entries(char *const envp[], + t_shell_table *table); +static int parse_env_entry(char *env, char **key, char **value); -t_hash_table *build_env_table(char *const envp[]) +t_shell_table *build_shell_table(char *const envp[]) { - t_hash_table *table; + t_shell_table *table; if (!envp) return (NULL); - table = ht_create(ENV_TABLE_INIT_SIZE); + table = st_create(SHELL_TABLE_INIT_SIZE); if (!table) return (NULL); if (insert_env_entries(envp, table) == ERROR) @@ -29,7 +31,7 @@ t_hash_table *build_env_table(char *const envp[]) return (table); } -static int insert_env_entries(char *const envp[], t_hash_table *table) +static int insert_env_entries(char *const envp[], t_shell_table *table) { size_t i; char *key_tmp; @@ -40,11 +42,11 @@ static int insert_env_entries(char *const envp[], t_hash_table *table) { if (parse_env_entry(envp[i], &key_tmp, &value_tmp) == ERROR) return (ERROR); - if (!ht_insert(table, key_tmp, value_tmp)) + if (!st_insert(table, key_tmp, value_tmp, true)) { free(key_tmp); free(value_tmp); - ht_destroy(table); + st_destroy(table); return (ERROR); } free(key_tmp); @@ -75,3 +77,23 @@ static int parse_env_entry(char *env, char **key, char **value) } return (SUCCESS); } + +static t_shell_table *st_create(size_t size) +{ + t_shell_table *table; + + if (size == 0) + return (NULL); + table = (t_shell_table *)ft_calloc(1, sizeof(t_shell_table)); + if (!table) + return (NULL); + table->buckets = (t_shell_node **)ft_calloc(size, sizeof(t_shell_node *)); + if (!table->buckets) + { + free(table); + return (NULL); + } + table->size = size; + table->n_nodes = 0; + return (table); +} diff --git a/src/component/env_table/export_envp.c b/src/component/shell_table/export_envp.c similarity index 52% rename from src/component/env_table/export_envp.c rename to src/component/shell_table/export_envp.c index 9fca268..3751d7e 100644 --- a/src/component/env_table/export_envp.c +++ b/src/component/shell_table/export_envp.c @@ -6,50 +6,75 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/26 16:15:41 by urassh #+# #+# */ -/* Updated: 2025/11/26 16:45:48 by urassh ### ########.fr */ +/* Updated: 2025/11/27 14:54:45 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ -#include +#include -static int export_envp_entries(char **envp, t_hash_table *env_table); -static char *export_envp_str(t_hash_node *node); -static void free_envp_array(char **envp, size_t count); +static int count_exported_nodes(t_shell_table *shell_table); +static int export_envp_entries(char **envp, t_shell_table *shell_table); +static char *export_envp_str(t_shell_node *node); +static int throw_export_envp(char **envp, size_t count); -char **export_envp(t_hash_table *env_table) +char **export_envp(t_shell_table *shell_table) { char **envp; + int count; - if (!env_table) + if (!shell_table) return (NULL); - envp = (char **)ft_calloc(env_table->n_nodes + 1, sizeof(char *)); + count = count_exported_nodes(shell_table); + envp = (char **)ft_calloc(count + 1, sizeof(char *)); if (!envp) return (NULL); - if (export_envp_entries(envp, env_table) == ERROR) + if (export_envp_entries(envp, shell_table) == ERROR) return (NULL); return (envp); } -static int export_envp_entries(char **envp, t_hash_table *env_table) +static int count_exported_nodes(t_shell_table *shell_table) { - size_t index; - size_t env_index; - t_hash_node *node; + size_t index; + t_shell_node *node; + int count; + + count = 0; + index = 0; + while (index < shell_table->size) + { + node = shell_table->buckets[index]; + while (node) + { + if (node->exported) + count++; + node = node->next; + } + index++; + } + return (count); +} + +static int export_envp_entries(char **envp, t_shell_table *shell_table) +{ + size_t index; + size_t env_index; + t_shell_node *node; env_index = 0; index = 0; - while (index < env_table->size) + while (index < shell_table->size) { - node = env_table->buckets[index]; + node = shell_table->buckets[index]; while (node) { - envp[env_index] = export_envp_str(node); - if (!envp[env_index]) + if (node->exported) { - free_envp_array(envp, env_index); - return (ERROR); + envp[env_index] = export_envp_str(node); + if (!envp[env_index]) + return (throw_export_envp(envp, env_index)); + env_index++; } - env_index++; node = node->next; } index++; @@ -57,7 +82,7 @@ static int export_envp_entries(char **envp, t_hash_table *env_table) return (SUCCESS); } -static char *export_envp_str(t_hash_node *node) +static char *export_envp_str(t_shell_node *node) { char *result; size_t key_len; @@ -74,7 +99,7 @@ static char *export_envp_str(t_hash_node *node) return (result); } -static void free_envp_array(char **envp, size_t count) +static int throw_export_envp(char **envp, size_t count) { size_t i; @@ -86,4 +111,5 @@ static void free_envp_array(char **envp, size_t count) i++; } free(envp); + return (ERROR); } diff --git a/libft/hash_table/hash_delete.c b/src/component/shell_table/shell_delete.c similarity index 73% rename from libft/hash_table/hash_delete.c rename to src/component/shell_table/shell_delete.c index 9df5e23..6959856 100644 --- a/libft/hash_table/hash_delete.c +++ b/src/component/shell_table/shell_delete.c @@ -1,18 +1,18 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* hash_delete.c :+: :+: :+: */ +/* shell_delete.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/05 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/11/05 00:00:00 by urassh ### ########.fr */ +/* Created: 2025/11/27 00:00:00 by urassh #+# #+# */ +/* Updated: 2025/11/27 00:00:00 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ -#include "libft.h" +#include -static void free_node(t_hash_node *node) +static void free_node(t_shell_node *node) { if (!node) return ; @@ -21,15 +21,15 @@ static void free_node(t_hash_node *node) free(node); } -int ht_delete(t_hash_table *table, const char *key) +int st_delete(t_shell_table *table, const char *key) { - size_t index; - t_hash_node *node; - t_hash_node *prev; + size_t index; + t_shell_node *node; + t_shell_node *prev; if (!table || !key) return (0); - index = ht_hash(key, table->size); + index = st_hash(key, table->size); node = table->buckets[index]; prev = NULL; while (node) diff --git a/libft/hash_table/hash_destroy.c b/src/component/shell_table/shell_destroy.c similarity index 75% rename from libft/hash_table/hash_destroy.c rename to src/component/shell_table/shell_destroy.c index ec9c502..7544aa5 100644 --- a/libft/hash_table/hash_destroy.c +++ b/src/component/shell_table/shell_destroy.c @@ -1,20 +1,20 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* hash_destroy.c :+: :+: :+: */ +/* shell_destroy.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/05 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/11/05 00:00:00 by urassh ### ########.fr */ +/* Created: 2025/11/27 00:00:00 by urassh #+# #+# */ +/* Updated: 2025/11/27 00:00:00 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ -#include "libft.h" +#include -static void free_chain(t_hash_node *node) +static void free_chain(t_shell_node *node) { - t_hash_node *next; + t_shell_node *next; while (node) { @@ -26,7 +26,7 @@ static void free_chain(t_hash_node *node) } } -void ht_destroy(t_hash_table *table) +void st_destroy(t_shell_table *table) { size_t i; diff --git a/libft/hash_table/hash_function.c b/src/component/shell_table/shell_hash.c similarity index 78% rename from libft/hash_table/hash_function.c rename to src/component/shell_table/shell_hash.c index f841a00..cbd4ef9 100644 --- a/libft/hash_table/hash_function.c +++ b/src/component/shell_table/shell_hash.c @@ -1,18 +1,18 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* hash_function.c :+: :+: :+: */ +/* shell_hash.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/05 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/11/23 15:09:38 by urassh ### ########.fr */ +/* Created: 2025/11/27 00:00:00 by urassh #+# #+# */ +/* Updated: 2025/11/27 00:00:00 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ -#include "libft.h" +#include -size_t ht_hash(const char *key, size_t table_size) +size_t st_hash(const char *key, size_t table_size) { const size_t inital_hash = 5381; size_t hash_num; diff --git a/libft/hash_table/hash_insert.c b/src/component/shell_table/shell_insert.c similarity index 67% rename from libft/hash_table/hash_insert.c rename to src/component/shell_table/shell_insert.c index 597057f..cffe651 100644 --- a/libft/hash_table/hash_insert.c +++ b/src/component/shell_table/shell_insert.c @@ -1,22 +1,23 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* hash_insert.c :+: :+: :+: */ +/* shell_insert.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/05 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/11/05 00:00:00 by urassh ### ########.fr */ +/* Created: 2025/11/27 00:00:00 by urassh #+# #+# */ +/* Updated: 2025/11/27 00:00:00 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ -#include "libft.h" +#include -static t_hash_node *create_node(const char *key, const char *value) +static t_shell_node *create_node(const char *key, const char *value, + bool exported) { - t_hash_node *node; + t_shell_node *node; - node = (t_hash_node *)ft_calloc(1, sizeof(t_hash_node)); + node = (t_shell_node *)ft_calloc(1, sizeof(t_shell_node)); if (!node) return (NULL); node->key = ft_strdup(key); @@ -32,10 +33,11 @@ static t_hash_node *create_node(const char *key, const char *value) free(node); return (NULL); } + node->exported = exported; return (node); } -static int update_existing_node(t_hash_node *node, const char *value) +static int update_existing_node(t_shell_node *node, const char *value) { char *new_value; @@ -47,15 +49,16 @@ static int update_existing_node(t_hash_node *node, const char *value) return (1); } -int ht_insert(t_hash_table *table, const char *key, const char *value) +int st_insert(t_shell_table *table, const char *key, const char *value, + bool exported) { - size_t index; - t_hash_node *node; - t_hash_node *new_node; + size_t index; + t_shell_node *node; + t_shell_node *new_node; if (!table || !key || !value) return (0); - index = ht_hash(key, table->size); + index = st_hash(key, table->size); node = table->buckets[index]; while (node) { @@ -63,7 +66,7 @@ int ht_insert(t_hash_table *table, const char *key, const char *value) return (update_existing_node(node, value)); node = node->next; } - new_node = create_node(key, value); + new_node = create_node(key, value, exported); if (!new_node) return (0); new_node->next = table->buckets[index]; diff --git a/libft/hash_table/hash_search.c b/src/component/shell_table/shell_search.c similarity index 72% rename from libft/hash_table/hash_search.c rename to src/component/shell_table/shell_search.c index cb0818d..39551ad 100644 --- a/libft/hash_table/hash_search.c +++ b/src/component/shell_table/shell_search.c @@ -1,25 +1,25 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* hash_search.c :+: :+: :+: */ +/* shell_search.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/05 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/11/05 00:00:00 by urassh ### ########.fr */ +/* Created: 2025/11/27 00:00:00 by urassh #+# #+# */ +/* Updated: 2025/11/27 00:00:00 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ -#include "libft.h" +#include -char *ht_search(t_hash_table *table, const char *key) +char *st_search(t_shell_table *table, const char *key) { - size_t index; - t_hash_node *node; + size_t index; + t_shell_node *node; if (!table || !key) return (NULL); - index = ht_hash(key, table->size); + index = st_hash(key, table->size); node = table->buckets[index]; while (node) { diff --git a/src/main.c b/src/main.c index 2bd8f61..1a8c821 100644 --- a/src/main.c +++ b/src/main.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* main.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ +/* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:13:47 by kjikuhar #+# #+# */ -/* Updated: 2025/11/27 01:53:40 by kjikuhar ### ########.fr */ +/* Updated: 2025/11/27 14:54:45 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,30 +14,30 @@ int main_prod(int argc, char const **argv, char *const envp[]) { - t_hash_table *env_table; + t_shell_table *shell_table; (void)argc; (void)argv; - env_table = build_env_table(envp); - if (!env_table) + shell_table = build_shell_table(envp); + if (!shell_table) return (1); - prompt(on_input, env_table); - ht_destroy(env_table); + prompt(on_input, shell_table); + st_destroy(shell_table); return (0); } int main_dev(int argc, char const **argv, char *const envp[]) { - t_hash_table *env_table; + t_shell_table *shell_table; (void)argc; (void)argv; - env_table = build_env_table(envp); - if (!env_table) + shell_table = build_shell_table(envp); + if (!shell_table) return (1); - env_table_checker(env_table); - prompt(parser_checker, env_table); - ht_destroy(env_table); + shell_table_checker(shell_table); + prompt(parser_checker, shell_table); + st_destroy(shell_table); return (0); } diff --git a/src/prompt/prompt.c b/src/prompt/prompt.c index 8c43c07..93cb2d8 100644 --- a/src/prompt/prompt.c +++ b/src/prompt/prompt.c @@ -6,14 +6,14 @@ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/01 15:35:00 by urassh #+# #+# */ -/* Updated: 2025/11/26 16:50:17 by urassh ### ########.fr */ +/* Updated: 2025/11/27 14:54:45 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ #include "prompt.h" -void prompt(void (*handler)(char *input, t_hash_table *env_table), - t_hash_table *env_table) +void prompt(void (*handler)(char *input, t_shell_table *shell_table), + t_shell_table *shell_table) { char *input; @@ -30,7 +30,7 @@ void prompt(void (*handler)(char *input, t_hash_table *env_table), if (*input) add_history(input); if (handler) - handler(input, env_table); + handler(input, shell_table); } rl_clear_history(); } From b3b28077e1746e3f39c5d527406bc1659a7ecec0 Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 27 Nov 2025 15:44:42 +0900 Subject: [PATCH 097/173] feat: get_directory_entries --- Makefile | 1 + includes/constants.h | 7 ++- includes/directory.h | 22 ++++++++ .../directory/get_directory_entries.c | 54 +++++++++++++++++++ 4 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 includes/directory.h create mode 100644 src/component/directory/get_directory_entries.c diff --git a/Makefile b/Makefile index 972a83a..ecd3127 100644 --- a/Makefile +++ b/Makefile @@ -93,6 +93,7 @@ SRCS_MAND := src/main.c \ src/component/shell_table/build_shell_table.c \ src/component/shell_table/export_envp.c \ src/component/pattern/filter_pattern.c \ + src/component/directory/get_directory_entries.c \ SRCS_BONUS := diff --git a/includes/constants.h b/includes/constants.h index 0997ef3..b68ae65 100644 --- a/includes/constants.h +++ b/includes/constants.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* constants.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/16 23:14:49 by urassh #+# #+# */ -/* Updated: 2025/10/16 23:15:06 by urassh ### ########.fr */ +/* Updated: 2025/11/27 15:26:31 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,5 +16,8 @@ // macros # define SUCCESS 0 # define ERROR -1 +# define NOT_FOUND -2 +# define NO_PERMISSION -3 +# define NOT_A_DIRECTORY -4 #endif diff --git a/includes/directory.h b/includes/directory.h new file mode 100644 index 0000000..327f9ba --- /dev/null +++ b/includes/directory.h @@ -0,0 +1,22 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* directory.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/27 15:25:07 by surayama #+# #+# */ +/* Updated: 2025/11/27 15:30:16 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef DIRECTORY_H +# define DIRECTORY_H + +# include +# include + +int get_directory_entries(const char *path, bool include_hidden, + t_list **entries); + +#endif diff --git a/src/component/directory/get_directory_entries.c b/src/component/directory/get_directory_entries.c new file mode 100644 index 0000000..b9de6aa --- /dev/null +++ b/src/component/directory/get_directory_entries.c @@ -0,0 +1,54 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* get_directory_entries.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/27 15:30:40 by surayama #+# #+# */ +/* Updated: 2025/11/27 15:40:07 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#include +#include +#include + +static int throw_error(void); + +int get_directory_entries(const char *path, bool include_hidden, + t_list **entries) +{ + DIR *dir; + struct dirent *entry; + + if (!entries) + return (ERROR); + *entries = NULL; + dir = opendir(path); + if (!dir) + return (throw_error()); + while (true) + { + entry = readdir(dir); + if (!entry) + break ; + if (!include_hidden && entry->d_name[0] == '.') + continue ; + ft_lstadd_back(entries, ft_lstnew(ft_strdup(entry->d_name))); + } + closedir(dir); + return (SUCCESS); +} + +static int throw_error(void) +{ + if (errno == ENOENT) + return (NOT_FOUND); + else if (errno == EACCES) + return (NO_PERMISSION); + else if (errno == ENOTDIR) + return (NOT_A_DIRECTORY); + return (ERROR); +} From 3b6cf4fa57737d1291bc219f3759f2fd1a1238bc Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 27 Nov 2025 16:06:23 +0900 Subject: [PATCH 098/173] =?UTF-8?q?feaet:=20get=5Fdirectory=5Fentries?= =?UTF-8?q?=E3=82=92=E5=86=8D=E5=B8=B0=E3=81=A7=E8=AA=AD=E3=81=BF=E5=8F=96?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- includes/directory.h | 11 ++- .../directory/get_directory_entries.c | 72 ++++++++++++++++--- 2 files changed, 72 insertions(+), 11 deletions(-) diff --git a/includes/directory.h b/includes/directory.h index 327f9ba..90a3c68 100644 --- a/includes/directory.h +++ b/includes/directory.h @@ -6,17 +6,22 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 15:25:07 by surayama #+# #+# */ -/* Updated: 2025/11/27 15:30:16 by surayama ### ########.fr */ +/* Updated: 2025/11/27 16:04:51 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef DIRECTORY_H # define DIRECTORY_H +# include +# include +# include # include # include +# include +# include -int get_directory_entries(const char *path, bool include_hidden, - t_list **entries); +int get_directory_entries(const char *path, bool include_hidden, + t_list **entries); #endif diff --git a/src/component/directory/get_directory_entries.c b/src/component/directory/get_directory_entries.c index b9de6aa..675aa83 100644 --- a/src/component/directory/get_directory_entries.c +++ b/src/component/directory/get_directory_entries.c @@ -6,22 +6,24 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 15:30:40 by surayama #+# #+# */ -/* Updated: 2025/11/27 15:40:07 by surayama ### ########.fr */ +/* Updated: 2025/11/27 16:04:54 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ -#include #include -#include -#include static int throw_error(void); +static int process_entry(const char *path, const char *name, + bool include_hidden, t_list **entries); +static char *join_path(const char *dir, const char *name); +static int read_directory_entries(DIR *dir, const char *path, + bool include_hidden, t_list **entries); int get_directory_entries(const char *path, bool include_hidden, t_list **entries) { - DIR *dir; - struct dirent *entry; + DIR *dir; + int result; if (!entries) return (ERROR); @@ -29,6 +31,17 @@ int get_directory_entries(const char *path, bool include_hidden, dir = opendir(path); if (!dir) return (throw_error()); + result = read_directory_entries(dir, path, include_hidden, entries); + closedir(dir); + return (result); +} + +static int read_directory_entries(DIR *dir, const char *path, + bool include_hidden, t_list **entries) +{ + struct dirent *entry; + int result; + while (true) { entry = readdir(dir); @@ -36,12 +49,55 @@ int get_directory_entries(const char *path, bool include_hidden, break ; if (!include_hidden && entry->d_name[0] == '.') continue ; - ft_lstadd_back(entries, ft_lstnew(ft_strdup(entry->d_name))); + result = process_entry(path, entry->d_name, include_hidden, entries); + if (result != SUCCESS) + return (result); } - closedir(dir); return (SUCCESS); } +static int process_entry(const char *path, const char *name, + bool include_hidden, t_list **entries) +{ + char *full_path; + struct stat st; + t_list *sub_entries; + int result; + + full_path = join_path(path, name); + if (!full_path) + return (ERROR); + ft_lstadd_back(entries, ft_lstnew(ft_strdup(name))); + if (stat(full_path, &st) != 0 || !S_ISDIR(st.st_mode)) + { + free(full_path); + return (SUCCESS); + } + if (ft_strncmp(name, ".", 2) == 0 || ft_strncmp(name, "..", 3) == 0) + { + free(full_path); + return (SUCCESS); + } + result = get_directory_entries(full_path, include_hidden, &sub_entries); + if (result == SUCCESS && sub_entries) + ft_lstadd_back(entries, sub_entries); + free(full_path); + return (SUCCESS); +} + +static char *join_path(const char *dir, const char *name) +{ + char *temp; + char *result; + + temp = ft_strjoin(dir, "/"); + if (!temp) + return (NULL); + result = ft_strjoin(temp, name); + free(temp); + return (result); +} + static int throw_error(void) { if (errno == ENOENT) From e36c8cb6443d7325a6e40cbdb4b140ea82bc4c8e Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 27 Nov 2025 16:09:24 +0900 Subject: [PATCH 099/173] feat: get_directory_all_entries --- includes/directory.h | 4 +- .../directory/get_directory_all_entries.c | 110 ++++++++++++++++++ .../directory/get_directory_entries.c | 69 +---------- 3 files changed, 118 insertions(+), 65 deletions(-) create mode 100644 src/component/directory/get_directory_all_entries.c diff --git a/includes/directory.h b/includes/directory.h index 90a3c68..9a9a5de 100644 --- a/includes/directory.h +++ b/includes/directory.h @@ -6,7 +6,7 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 15:25:07 by surayama #+# #+# */ -/* Updated: 2025/11/27 16:04:51 by surayama ### ########.fr */ +/* Updated: 2025/11/27 16:08:52 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -23,5 +23,7 @@ int get_directory_entries(const char *path, bool include_hidden, t_list **entries); +int get_directory_all_entries(const char *path, bool include_hidden, + t_list **entries); #endif diff --git a/src/component/directory/get_directory_all_entries.c b/src/component/directory/get_directory_all_entries.c new file mode 100644 index 0000000..3b63847 --- /dev/null +++ b/src/component/directory/get_directory_all_entries.c @@ -0,0 +1,110 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* get_directory_all_entries.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/27 15:30:40 by surayama #+# #+# */ +/* Updated: 2025/11/27 16:08:41 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include + +static int throw_error(void); +static int process_entry(const char *path, const char *name, + bool include_hidden, t_list **entries); +static char *join_path(const char *dir, const char *name); +static int read_directory_entries(DIR *dir, const char *path, + bool include_hidden, t_list **entries); + +int get_directory_all_entries(const char *path, bool include_hidden, + t_list **entries) +{ + DIR *dir; + int result; + + if (!entries) + return (ERROR); + *entries = NULL; + dir = opendir(path); + if (!dir) + return (throw_error()); + result = read_directory_entries(dir, path, include_hidden, entries); + closedir(dir); + return (result); +} + +static int read_directory_entries(DIR *dir, const char *path, + bool include_hidden, t_list **entries) +{ + struct dirent *entry; + int result; + + while (true) + { + entry = readdir(dir); + if (!entry) + break ; + if (!include_hidden && entry->d_name[0] == '.') + continue ; + result = process_entry(path, entry->d_name, include_hidden, entries); + if (result != SUCCESS) + return (result); + } + return (SUCCESS); +} + +static int process_entry(const char *path, const char *name, + bool include_hidden, t_list **entries) +{ + char *full_path; + struct stat st; + t_list *sub_entries; + int result; + + full_path = join_path(path, name); + if (!full_path) + return (ERROR); + ft_lstadd_back(entries, ft_lstnew(ft_strdup(name))); + if (stat(full_path, &st) != 0 || !S_ISDIR(st.st_mode)) + { + free(full_path); + return (SUCCESS); + } + if (ft_strncmp(name, ".", 2) == 0 || ft_strncmp(name, "..", 3) == 0) + { + free(full_path); + return (SUCCESS); + } + result = get_directory_entries(full_path, include_hidden, &sub_entries); + if (result == SUCCESS && sub_entries) + ft_lstadd_back(entries, sub_entries); + free(full_path); + return (SUCCESS); +} + +static char *join_path(const char *dir, const char *name) +{ + char *temp; + char *result; + + temp = ft_strjoin(dir, "/"); + if (!temp) + return (NULL); + result = ft_strjoin(temp, name); + free(temp); + return (result); +} + +static int throw_error(void) +{ + if (errno == ENOENT) + return (NOT_FOUND); + else if (errno == EACCES) + return (NO_PERMISSION); + else if (errno == ENOTDIR) + return (NOT_A_DIRECTORY); + return (ERROR); +} diff --git a/src/component/directory/get_directory_entries.c b/src/component/directory/get_directory_entries.c index 675aa83..f91df0b 100644 --- a/src/component/directory/get_directory_entries.c +++ b/src/component/directory/get_directory_entries.c @@ -6,24 +6,19 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 15:30:40 by surayama #+# #+# */ -/* Updated: 2025/11/27 16:04:54 by surayama ### ########.fr */ +/* Updated: 2025/11/27 16:08:26 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ #include static int throw_error(void); -static int process_entry(const char *path, const char *name, - bool include_hidden, t_list **entries); -static char *join_path(const char *dir, const char *name); -static int read_directory_entries(DIR *dir, const char *path, - bool include_hidden, t_list **entries); int get_directory_entries(const char *path, bool include_hidden, t_list **entries) { - DIR *dir; - int result; + DIR *dir; + struct dirent *entry; if (!entries) return (ERROR); @@ -31,17 +26,6 @@ int get_directory_entries(const char *path, bool include_hidden, dir = opendir(path); if (!dir) return (throw_error()); - result = read_directory_entries(dir, path, include_hidden, entries); - closedir(dir); - return (result); -} - -static int read_directory_entries(DIR *dir, const char *path, - bool include_hidden, t_list **entries) -{ - struct dirent *entry; - int result; - while (true) { entry = readdir(dir); @@ -49,55 +33,12 @@ static int read_directory_entries(DIR *dir, const char *path, break ; if (!include_hidden && entry->d_name[0] == '.') continue ; - result = process_entry(path, entry->d_name, include_hidden, entries); - if (result != SUCCESS) - return (result); - } - return (SUCCESS); -} - -static int process_entry(const char *path, const char *name, - bool include_hidden, t_list **entries) -{ - char *full_path; - struct stat st; - t_list *sub_entries; - int result; - - full_path = join_path(path, name); - if (!full_path) - return (ERROR); - ft_lstadd_back(entries, ft_lstnew(ft_strdup(name))); - if (stat(full_path, &st) != 0 || !S_ISDIR(st.st_mode)) - { - free(full_path); - return (SUCCESS); - } - if (ft_strncmp(name, ".", 2) == 0 || ft_strncmp(name, "..", 3) == 0) - { - free(full_path); - return (SUCCESS); + ft_lstadd_back(entries, ft_lstnew(ft_strdup(entry->d_name))); } - result = get_directory_entries(full_path, include_hidden, &sub_entries); - if (result == SUCCESS && sub_entries) - ft_lstadd_back(entries, sub_entries); - free(full_path); + closedir(dir); return (SUCCESS); } -static char *join_path(const char *dir, const char *name) -{ - char *temp; - char *result; - - temp = ft_strjoin(dir, "/"); - if (!temp) - return (NULL); - result = ft_strjoin(temp, name); - free(temp); - return (result); -} - static int throw_error(void) { if (errno == ENOENT) From 1c45cdb504d5e006c52c324fb2f50dae776831b5 Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 27 Nov 2025 16:21:20 +0900 Subject: [PATCH 100/173] =?UTF-8?q?=E3=81=A8=E3=82=8A=E3=81=BEchecker?= =?UTF-8?q?=E3=81=AF=E3=81=A7=E3=81=8D=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 6 +- includes/minishell.h | 10 ++-- libft/libft.h | 4 +- libft/output/ft_putendl_fd.c | 2 +- libft/output/ft_putstr_fd.c | 2 +- src/checker/directory_checker.c | 99 +++++++++++++++++++++++++++++++++ src/main.c | 6 +- 7 files changed, 116 insertions(+), 13 deletions(-) create mode 100644 src/checker/directory_checker.c diff --git a/Makefile b/Makefile index ecd3127..18cfd69 100644 --- a/Makefile +++ b/Makefile @@ -3,10 +3,10 @@ # ::: :::::::: # # Makefile :+: :+: :+: # # +:+ +:+ +:+ # -# By: urassh +#+ +:+ +#+ # +# By: surayama +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/05/18 21:11:39 by kjikuhar #+# #+# # -# Updated: 2025/11/27 14:58:00 by urassh ### ########.fr # +# Updated: 2025/11/27 16:17:13 by surayama ### ########.fr # # # # **************************************************************************** # @@ -62,6 +62,7 @@ SRCS_MAND := src/main.c \ src/checker/heredoc_checker.c \ src/checker/shell_table_checker.c \ src/checker/parser_checker.c \ + src/checker/directory_checker.c \ src/tokenize/tokenize.c \ src/tokenize/is_specific.c \ src/tokenize/state/in_normal.c \ @@ -94,6 +95,7 @@ SRCS_MAND := src/main.c \ src/component/shell_table/export_envp.c \ src/component/pattern/filter_pattern.c \ src/component/directory/get_directory_entries.c \ + src/component/directory/get_directory_all_entries.c \ SRCS_BONUS := diff --git a/includes/minishell.h b/includes/minishell.h index ef85288..ea3962f 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* minishell.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:14:22 by kjikuhar #+# #+# */ -/* Updated: 2025/11/27 14:54:45 by urassh ### ########.fr */ +/* Updated: 2025/11/27 16:11:07 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,12 +14,12 @@ # define MINISHELL_H # include "constants.h" -# include "shell_table.h" # include "heredoc.h" # include "libft.h" +# include "parser.h" # include "prompt.h" +# include "shell_table.h" # include "tokenize.h" -# include "parser.h" // callbacks void on_input(char *input, t_shell_table *shell_table); @@ -29,4 +29,6 @@ void tokenize_checker(char *input, t_shell_table *shell_table); void heredoc_checker(char *input, t_shell_table *shell_table); void shell_table_checker(t_shell_table *shell_table); void parser_checker(char *input, t_shell_table *shell_table); +void directory_checker(char *input, t_shell_table *shell_table); + #endif diff --git a/libft/libft.h b/libft/libft.h index f9eff62..fa2fe88 100644 --- a/libft/libft.h +++ b/libft/libft.h @@ -74,9 +74,9 @@ size_t ft_min_size_t(size_t a, size_t b); // output void ft_putchar_fd(char c, int fd); -void ft_putendl_fd(char *s, int fd); +void ft_putendl_fd(const char *s, int fd); void ft_putnbr_fd(int n, int fd); -void ft_putstr_fd(char *s, int fd); +void ft_putstr_fd(const char *s, int fd); // string char **ft_split(char const *s, char c); diff --git a/libft/output/ft_putendl_fd.c b/libft/output/ft_putendl_fd.c index b28858b..1328998 100644 --- a/libft/output/ft_putendl_fd.c +++ b/libft/output/ft_putendl_fd.c @@ -12,7 +12,7 @@ #include "libft.h" -void ft_putendl_fd(char *s, int fd) +void ft_putendl_fd(const char *s, int fd) { if (!s) return ; diff --git a/libft/output/ft_putstr_fd.c b/libft/output/ft_putstr_fd.c index 70aa6cb..ec62686 100644 --- a/libft/output/ft_putstr_fd.c +++ b/libft/output/ft_putstr_fd.c @@ -12,7 +12,7 @@ #include "libft.h" -void ft_putstr_fd(char *s, int fd) +void ft_putstr_fd(const char *s, int fd) { if (!s) return ; diff --git a/src/checker/directory_checker.c b/src/checker/directory_checker.c new file mode 100644 index 0000000..507601a --- /dev/null +++ b/src/checker/directory_checker.c @@ -0,0 +1,99 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* directory_checker.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/27 16:10:35 by surayama #+# #+# */ +/* Updated: 2025/11/27 16:16:25 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#include + +static void print_entries(t_list *entries, const char *title); +static void test_function(const char *input, bool include_hidden, + int (*func)(const char *, bool, t_list **), const char *title); +static void test_entries(const char *input); +static void test_all_entries(const char *input); + +void directory_checker(char *input, t_shell_table *shell_table) +{ + (void)shell_table; + test_entries(input); + test_all_entries(input); +} + +static void test_entries(const char *input) +{ + ft_putstr_fd("\n=== Testing get_directory_entries ===\n", 1); + ft_putstr_fd("Path: ", 1); + ft_putendl_fd(input, 1); + test_function(input, false, get_directory_entries, + "\n--- Without hidden files ---\nEntries"); + test_function(input, true, get_directory_entries, + "\n--- With hidden files ---\nEntries"); +} + +static void test_all_entries(const char *input) +{ + ft_putstr_fd("\n=== Testing get_directory_all_entries ===\n", 1); + ft_putstr_fd("Path: ", 1); + ft_putendl_fd(input, 1); + test_function(input, false, get_directory_all_entries, + "\n--- Without hidden files ---\nAll Entries (recursive)"); + test_function(input, true, get_directory_all_entries, + "\n--- With hidden files ---\nAll Entries (recursive)"); +} + +static void test_function(const char *input, bool include_hidden, + int (*func)(const char *, bool, t_list **), const char *title) +{ + t_list *entries; + t_list *tmp; + int result; + + result = func(input, include_hidden, &entries); + if (result != SUCCESS) + { + ft_putstr_fd("Error: ", 1); + if (result == NOT_FOUND) + ft_putendl_fd("Directory not found", 1); + else if (result == NO_PERMISSION) + ft_putendl_fd("Permission denied", 1); + else + ft_putendl_fd("Unknown error", 1); + return ; + } + print_entries(entries, title); + while (entries) + { + tmp = entries->next; + free(entries->content); + free(entries); + entries = tmp; + } +} + +static void print_entries(t_list *entries, const char *title) +{ + t_list *current; + int count; + + ft_putstr_fd(title, 1); + ft_putstr_fd(":\n", 1); + count = 0; + current = entries; + while (current) + { + ft_putstr_fd(" - ", 1); + ft_putendl_fd((char *)current->content, 1); + current = current->next; + count++; + } + ft_putstr_fd("Total: ", 1); + ft_putnbr_fd(count, 1); + ft_putendl_fd(" entries", 1); +} diff --git a/src/main.c b/src/main.c index 1a8c821..c81a206 100644 --- a/src/main.c +++ b/src/main.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* main.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:13:47 by kjikuhar #+# #+# */ -/* Updated: 2025/11/27 14:54:45 by urassh ### ########.fr */ +/* Updated: 2025/11/27 16:16:45 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -36,7 +36,7 @@ int main_dev(int argc, char const **argv, char *const envp[]) if (!shell_table) return (1); shell_table_checker(shell_table); - prompt(parser_checker, shell_table); + prompt(directory_checker, shell_table); st_destroy(shell_table); return (0); } From d96bb39d6940d6c28ce589018b1aec3bdf14e323 Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 27 Nov 2025 16:30:57 +0900 Subject: [PATCH 101/173] =?UTF-8?q?fix:=20=E5=86=8D=E5=B8=B0=E9=96=A2?= =?UTF-8?q?=E6=95=B0=E3=81=8C=E9=96=93=E9=81=95=E3=81=A3=E3=81=A6=E3=81=84?= =?UTF-8?q?=E3=81=9F=E3=81=AE=E3=81=A7=E3=81=9D=E3=81=AE=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?/full=5Fpath=E3=81=A7=E3=82=A8=E3=83=B3=E3=83=88=E3=83=AA?= =?UTF-8?q?=E3=81=AB=E8=BF=BD=E5=8A=A0=E3=81=95=E3=82=8C=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/component/directory/get_directory_all_entries.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/component/directory/get_directory_all_entries.c b/src/component/directory/get_directory_all_entries.c index 3b63847..f51f512 100644 --- a/src/component/directory/get_directory_all_entries.c +++ b/src/component/directory/get_directory_all_entries.c @@ -67,7 +67,7 @@ static int process_entry(const char *path, const char *name, full_path = join_path(path, name); if (!full_path) return (ERROR); - ft_lstadd_back(entries, ft_lstnew(ft_strdup(name))); + ft_lstadd_back(entries, ft_lstnew(ft_strdup(full_path))); if (stat(full_path, &st) != 0 || !S_ISDIR(st.st_mode)) { free(full_path); @@ -78,7 +78,7 @@ static int process_entry(const char *path, const char *name, free(full_path); return (SUCCESS); } - result = get_directory_entries(full_path, include_hidden, &sub_entries); + result = get_directory_all_entries(full_path, include_hidden, &sub_entries); if (result == SUCCESS && sub_entries) ft_lstadd_back(entries, sub_entries); free(full_path); From 0a858415460ea4f04533729def09ec819246d075 Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 27 Nov 2025 16:37:39 +0900 Subject: [PATCH 102/173] =?UTF-8?q?fix:=20join=5Fpath=E3=81=AEjoin?= =?UTF-8?q?=E5=BE=8C=E3=81=AE=E3=83=AA=E3=83=BC=E3=82=AF=E3=83=81=E3=82=A7?= =?UTF-8?q?=E3=83=83=E3=82=AF=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/component/directory/get_directory_all_entries.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/component/directory/get_directory_all_entries.c b/src/component/directory/get_directory_all_entries.c index f51f512..4af0d52 100644 --- a/src/component/directory/get_directory_all_entries.c +++ b/src/component/directory/get_directory_all_entries.c @@ -94,6 +94,11 @@ static char *join_path(const char *dir, const char *name) if (!temp) return (NULL); result = ft_strjoin(temp, name); + if (!result) + { + free(temp); + return (NULL); + } free(temp); return (result); } From 2418de606cae9c26a0218843e592cb33b885354d Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 27 Nov 2025 16:39:28 +0900 Subject: [PATCH 103/173] =?UTF-8?q?fix:=20directory=5Fchecker=E3=81=A7exit?= =?UTF-8?q?=E3=81=A7=E6=8A=9C=E3=81=91=E3=82=89=E3=82=8C=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/checker/directory_checker.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/checker/directory_checker.c b/src/checker/directory_checker.c index 507601a..fa60e0f 100644 --- a/src/checker/directory_checker.c +++ b/src/checker/directory_checker.c @@ -22,6 +22,12 @@ static void test_all_entries(const char *input); void directory_checker(char *input, t_shell_table *shell_table) { (void)shell_table; + + if (ft_strncmp(input, "exit", 5) == 0) + { + write(STDOUT_FILENO, "exit\n", 5); + exit(0); + } test_entries(input); test_all_entries(input); } From add0facd87d5cf1c8efe72e33bbb7c4d1d405306 Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 27 Nov 2025 16:40:49 +0900 Subject: [PATCH 104/173] fix: norminette --- src/checker/directory_checker.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/checker/directory_checker.c b/src/checker/directory_checker.c index fa60e0f..5c21951 100644 --- a/src/checker/directory_checker.c +++ b/src/checker/directory_checker.c @@ -6,7 +6,7 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 16:10:35 by surayama #+# #+# */ -/* Updated: 2025/11/27 16:16:25 by surayama ### ########.fr */ +/* Updated: 2025/11/27 16:40:38 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,7 +22,6 @@ static void test_all_entries(const char *input); void directory_checker(char *input, t_shell_table *shell_table) { (void)shell_table; - if (ft_strncmp(input, "exit", 5) == 0) { write(STDOUT_FILENO, "exit\n", 5); From 043414dc660344aa15643589c8ed02801833f89a Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 27 Nov 2025 16:42:22 +0900 Subject: [PATCH 105/173] fix: directory_checker leaks --- src/checker/directory_checker.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/checker/directory_checker.c b/src/checker/directory_checker.c index 5c21951..8f2eb08 100644 --- a/src/checker/directory_checker.c +++ b/src/checker/directory_checker.c @@ -6,7 +6,7 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 16:10:35 by surayama #+# #+# */ -/* Updated: 2025/11/27 16:40:38 by surayama ### ########.fr */ +/* Updated: 2025/11/27 16:42:07 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -25,6 +25,7 @@ void directory_checker(char *input, t_shell_table *shell_table) if (ft_strncmp(input, "exit", 5) == 0) { write(STDOUT_FILENO, "exit\n", 5); + st_destroy(shell_table); exit(0); } test_entries(input); From cccd66372480dec7a681217b91b3f488e0602840 Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 27 Nov 2025 16:45:33 +0900 Subject: [PATCH 106/173] =?UTF-8?q?directory=5Fchecker=E3=81=A7exit?= =?UTF-8?q?=E3=81=99=E3=82=8B=E6=99=82=E3=81=ABinput=E3=82=82free=E3=81=99?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/checker/directory_checker.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/checker/directory_checker.c b/src/checker/directory_checker.c index 8f2eb08..ba4d86b 100644 --- a/src/checker/directory_checker.c +++ b/src/checker/directory_checker.c @@ -6,7 +6,7 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 16:10:35 by surayama #+# #+# */ -/* Updated: 2025/11/27 16:42:07 by surayama ### ########.fr */ +/* Updated: 2025/11/27 16:45:10 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -25,6 +25,7 @@ void directory_checker(char *input, t_shell_table *shell_table) if (ft_strncmp(input, "exit", 5) == 0) { write(STDOUT_FILENO, "exit\n", 5); + free(input); st_destroy(shell_table); exit(0); } From 5ecbe24078e181def9b55212f5ccb0dab986e3ff Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 27 Nov 2025 16:50:05 +0900 Subject: [PATCH 107/173] =?UTF-8?q?=E3=81=93=E3=82=8C=E3=81=A7=E3=81=A9?= =?UTF-8?q?=E3=81=86=E3=81=A0=EF=BC=81=EF=BC=81=EF=BC=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/checker/directory_checker.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/checker/directory_checker.c b/src/checker/directory_checker.c index ba4d86b..97ec90a 100644 --- a/src/checker/directory_checker.c +++ b/src/checker/directory_checker.c @@ -25,12 +25,13 @@ void directory_checker(char *input, t_shell_table *shell_table) if (ft_strncmp(input, "exit", 5) == 0) { write(STDOUT_FILENO, "exit\n", 5); + rl_clear_history(); free(input); - st_destroy(shell_table); exit(0); } test_entries(input); test_all_entries(input); + free(input); } static void test_entries(const char *input) From 98a00d4980a952269f7158e3755a6bcf1aeb5bd2 Mon Sep 17 00:00:00 2001 From: urassh Date: Sat, 29 Nov 2025 20:05:54 +0900 Subject: [PATCH 108/173] =?UTF-8?q?fix:=20get=5Fdirectory=5Fentries?= =?UTF-8?q?=E3=81=AENULL=E3=82=AC=E3=83=BC=E3=83=89=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../directory/get_directory_entries.c | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/component/directory/get_directory_entries.c b/src/component/directory/get_directory_entries.c index f91df0b..9771568 100644 --- a/src/component/directory/get_directory_entries.c +++ b/src/component/directory/get_directory_entries.c @@ -6,13 +6,14 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 15:30:40 by surayama #+# #+# */ -/* Updated: 2025/11/27 16:08:26 by surayama ### ########.fr */ +/* Updated: 2025/11/29 20:05:20 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ #include static int throw_error(void); +static int append_entry(t_list **entries, const char *entry_name); int get_directory_entries(const char *path, bool include_hidden, t_list **entries) @@ -33,7 +34,11 @@ int get_directory_entries(const char *path, bool include_hidden, break ; if (!include_hidden && entry->d_name[0] == '.') continue ; - ft_lstadd_back(entries, ft_lstnew(ft_strdup(entry->d_name))); + if (append_entry(entries, entry->d_name) == ERROR) + { + closedir(dir); + return (ERROR); + } } closedir(dir); return (SUCCESS); @@ -49,3 +54,14 @@ static int throw_error(void) return (NOT_A_DIRECTORY); return (ERROR); } + +static int append_entry(t_list **entries, const char *entry_name) +{ + t_list *entry_node; + + entry_node = ft_lstnew(ft_strdup(entry_name)); + if (!entry_node) + return (ERROR); + ft_lstadd_back(entries, entry_node); + return (SUCCESS); +} From 7322b996b5a2328213d8a43222ff52b9b162928c Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Mon, 1 Dec 2025 00:19:08 +0900 Subject: [PATCH 109/173] =?UTF-8?q?=E2=91=A0=20echo=E3=82=B3=E3=83=9E?= =?UTF-8?q?=E3=83=B3=E3=83=89=E3=82=92=E5=AE=9F=E8=A3=85=E3=81=97=E3=81=9F?= =?UTF-8?q?=20(#36)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: echoコマンドを実装した * fix: norminette * fix: make出来ない不具合を修正 * fix: consumeは名前として変だと思ったのでskip_head_nodeに変更 * 僕天才 --- Makefile | 1 + includes/builtin.h | 21 ++++++++++++ src/builtin/echo.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 includes/builtin.h create mode 100644 src/builtin/echo.c diff --git a/Makefile b/Makefile index 18cfd69..7c64232 100644 --- a/Makefile +++ b/Makefile @@ -56,6 +56,7 @@ LIBFT_A := $(LIBFT_DIR)/libft.a #mandatory sources SRCS_MAND := src/main.c \ + src/builtin/echo.c \ src/prompt/prompt.c \ src/callback/on_input.c \ src/checker/tokenize_checker.c \ diff --git a/includes/builtin.h b/includes/builtin.h new file mode 100644 index 0000000..e19842c --- /dev/null +++ b/includes/builtin.h @@ -0,0 +1,21 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* builtin.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/29 17:16:51 by surayama #+# #+# */ +/* Updated: 2025/11/29 18:09:29 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef BUILTIN_H +# define BUILTIN_H + +# include +# include + +int echo(t_list *argv, t_shell_table *shell_table); + +#endif diff --git a/src/builtin/echo.c b/src/builtin/echo.c new file mode 100644 index 0000000..4fcef0c --- /dev/null +++ b/src/builtin/echo.c @@ -0,0 +1,82 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* echo.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/29 17:16:37 by surayama #+# #+# */ +/* Updated: 2025/12/01 00:10:08 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include + +static void skip_head_node(t_list **argv); +static bool is_n_option(t_list *argv); +static void print_argv(t_list *to_print_argv, bool with_newline); + +int echo(t_list *argv, t_shell_table *shell_table) +{ + t_list *echo_argv; + bool with_newline; + + (void)shell_table; + echo_argv = argv; + with_newline = true; + skip_head_node(&echo_argv); + while (is_n_option(echo_argv)) + { + with_newline = false; + skip_head_node(&echo_argv); + } + print_argv(echo_argv, with_newline); + return (0); +} + +static void skip_head_node(t_list **argv) +{ + if (argv && *argv) + *argv = (*argv)->next; +} + +static bool is_n_option(t_list *argv) +{ + t_list *option_node; + char *str; + int i; + + option_node = argv; + if (!option_node || !option_node->content) + return (false); + str = (char *)option_node->content; + if (str[0] != '-' || str[1] == '\0') + return (false); + i = 1; + while (str[i]) + { + if (str[i] != 'n') + return (false); + i++; + } + return (true); +} + +static void print_argv(t_list *to_print_argv, bool with_newline) +{ + t_list *current; + + current = to_print_argv; + while (current) + { + if (current->content) + { + printf("%s", (char *)current->content); + if (current->next) + printf(" "); + } + current = current->next; + } + if (with_newline) + printf("\n"); +} From 3909a4267f7e88ad100f15ac10f27513833cbf76 Mon Sep 17 00:00:00 2001 From: jiku <134150757+jiku0730@users.noreply.github.com> Date: Mon, 1 Dec 2025 03:08:48 +0900 Subject: [PATCH 110/173] =?UTF-8?q?prompt=E3=82=92jikussh=E3=81=AB?= =?UTF-8?q?=E5=A4=89=E6=9B=B4=E3=81=97=E3=81=BE=E3=81=97=E3=81=9F=E3=80=82?= =?UTF-8?q?=20(#40)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * change: prompt * add: compile command * fix: norminette * Delete src/checker/prompt_checker.c --- includes/constants.h | 6 ++++-- includes/prompt.h | 6 ++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/includes/constants.h b/includes/constants.h index b68ae65..c61aed3 100644 --- a/includes/constants.h +++ b/includes/constants.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* constants.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/16 23:14:49 by urassh #+# #+# */ -/* Updated: 2025/11/27 15:26:31 by surayama ### ########.fr */ +/* Updated: 2025/12/01 01:54:44 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,5 +19,7 @@ # define NOT_FOUND -2 # define NO_PERMISSION -3 # define NOT_A_DIRECTORY -4 +# define SHELL_NAME "jikussh" +# define PROMPT "jikussh$ " #endif diff --git a/includes/prompt.h b/includes/prompt.h index c8e99bc..47bcc5b 100644 --- a/includes/prompt.h +++ b/includes/prompt.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* prompt.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/01 15:35:18 by urassh #+# #+# */ -/* Updated: 2025/11/27 14:54:45 by urassh ### ########.fr */ +/* Updated: 2025/12/01 01:49:05 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -24,6 +24,4 @@ void prompt(void (*handler)(char *input, t_shell_table *shell_table), t_shell_table *shell_table); -# define PROMPT "minishell$ " - #endif From ffa80d5b87f9c566d77f669935cecaf74ceb66df Mon Sep 17 00:00:00 2001 From: jiku <134150757+jiku0730@users.noreply.github.com> Date: Mon, 1 Dec 2025 11:43:20 +0900 Subject: [PATCH 111/173] =?UTF-8?q?=E3=83=98=E3=83=83=E3=83=80=E3=83=BC?= =?UTF-8?q?=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB=E3=81=AE=E4=B8=A1=E7=AB=AF?= =?UTF-8?q?=E3=82=92<>=20=E3=81=8B=E3=82=89double=5Fqoutation=E3=81=AB?= =?UTF-8?q?=E5=A4=89=E6=9B=B4=E3=81=97=E3=81=BE=E3=81=97=E3=81=9F=E3=80=82?= =?UTF-8?q?=20(#42)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * change: <> to double_qoutation * change: libft header quotation --- includes/builtin.h | 6 +++--- includes/directory.h | 8 ++++---- includes/pattern.h | 6 +++--- includes/shell_table.h | 8 ++++---- src/builtin/echo.c | 6 +++--- src/checker/directory_checker.c | 8 ++++---- src/checker/heredoc_checker.c | 6 +++--- src/checker/shell_table_checker.c | 6 +++--- src/component/directory/get_directory_all_entries.c | 6 +++--- src/component/directory/get_directory_entries.c | 6 +++--- src/component/heredoc/heredoc.c | 6 +++--- src/component/heredoc/heredoc_prompt.c | 6 +++--- src/component/heredoc/tmpfile.c | 6 +++--- src/component/pattern/filter_pattern.c | 8 ++++---- src/component/shell_table/build_shell_table.c | 6 +++--- src/component/shell_table/export_envp.c | 6 +++--- src/component/shell_table/shell_delete.c | 6 +++--- src/component/shell_table/shell_destroy.c | 6 +++--- src/component/shell_table/shell_hash.c | 6 +++--- src/component/shell_table/shell_insert.c | 6 +++--- src/component/shell_table/shell_search.c | 6 +++--- 21 files changed, 67 insertions(+), 67 deletions(-) diff --git a/includes/builtin.h b/includes/builtin.h index e19842c..d1f1ffd 100644 --- a/includes/builtin.h +++ b/includes/builtin.h @@ -3,17 +3,17 @@ /* ::: :::::::: */ /* builtin.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/29 17:16:51 by surayama #+# #+# */ -/* Updated: 2025/11/29 18:09:29 by surayama ### ########.fr */ +/* Updated: 2025/12/01 03:23:00 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef BUILTIN_H # define BUILTIN_H -# include +# include "shell_table.h" # include int echo(t_list *argv, t_shell_table *shell_table); diff --git a/includes/directory.h b/includes/directory.h index 9a9a5de..b02e7f3 100644 --- a/includes/directory.h +++ b/includes/directory.h @@ -3,20 +3,20 @@ /* ::: :::::::: */ /* directory.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 15:25:07 by surayama #+# #+# */ -/* Updated: 2025/11/27 16:08:52 by surayama ### ########.fr */ +/* Updated: 2025/12/01 03:28:22 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef DIRECTORY_H # define DIRECTORY_H -# include +# include "constants.h" # include # include -# include +# include "libft.h" # include # include # include diff --git a/includes/pattern.h b/includes/pattern.h index 0310b6e..d9cc311 100644 --- a/includes/pattern.h +++ b/includes/pattern.h @@ -3,17 +3,17 @@ /* ::: :::::::: */ /* pattern.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 11:36:50 by urassh #+# #+# */ -/* Updated: 2025/11/27 12:02:52 by urassh ### ########.fr */ +/* Updated: 2025/12/01 03:28:22 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef PATTERN_H # define PATTERN_H -# include +# include "libft.h" # include # define WILDCARD '*' diff --git a/includes/shell_table.h b/includes/shell_table.h index b77b654..6bc15a0 100644 --- a/includes/shell_table.h +++ b/includes/shell_table.h @@ -3,18 +3,18 @@ /* ::: :::::::: */ /* shell_table.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/11/27 14:54:45 by urassh ### ########.fr */ +/* Updated: 2025/12/01 03:28:22 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef SHELL_TABLE_H # define SHELL_TABLE_H -# include -# include +# include "constants.h" +# include "libft.h" # include # define SHELL_TABLE_INIT_SIZE 256 diff --git a/src/builtin/echo.c b/src/builtin/echo.c index 4fcef0c..b99f194 100644 --- a/src/builtin/echo.c +++ b/src/builtin/echo.c @@ -3,14 +3,14 @@ /* ::: :::::::: */ /* echo.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/29 17:16:37 by surayama #+# #+# */ -/* Updated: 2025/12/01 00:10:08 by surayama ### ########.fr */ +/* Updated: 2025/12/01 03:17:35 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include +#include "builtin.h" static void skip_head_node(t_list **argv); static bool is_n_option(t_list *argv); diff --git a/src/checker/directory_checker.c b/src/checker/directory_checker.c index 97ec90a..e6eca0d 100644 --- a/src/checker/directory_checker.c +++ b/src/checker/directory_checker.c @@ -3,15 +3,15 @@ /* ::: :::::::: */ /* directory_checker.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 16:10:35 by surayama #+# #+# */ -/* Updated: 2025/11/27 16:45:10 by surayama ### ########.fr */ +/* Updated: 2025/12/01 03:20:46 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include -#include +#include "directory.h" +#include "minishell.h" static void print_entries(t_list *entries, const char *title); static void test_function(const char *input, bool include_hidden, diff --git a/src/checker/heredoc_checker.c b/src/checker/heredoc_checker.c index d105167..1fa6790 100644 --- a/src/checker/heredoc_checker.c +++ b/src/checker/heredoc_checker.c @@ -3,14 +3,14 @@ /* ::: :::::::: */ /* heredoc_checker.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/20 15:55:55 by urassh #+# #+# */ -/* Updated: 2025/11/27 14:54:45 by urassh ### ########.fr */ +/* Updated: 2025/12/01 03:20:46 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include +#include "minishell.h" #include #include diff --git a/src/checker/shell_table_checker.c b/src/checker/shell_table_checker.c index 0dd6f3f..1cb417e 100644 --- a/src/checker/shell_table_checker.c +++ b/src/checker/shell_table_checker.c @@ -3,14 +3,14 @@ /* ::: :::::::: */ /* shell_table_checker.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/26 16:53:40 by urassh #+# #+# */ -/* Updated: 2025/11/27 14:55:00 by urassh ### ########.fr */ +/* Updated: 2025/12/01 03:20:46 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include +#include "minishell.h" #include #include #include diff --git a/src/component/directory/get_directory_all_entries.c b/src/component/directory/get_directory_all_entries.c index 4af0d52..9c21831 100644 --- a/src/component/directory/get_directory_all_entries.c +++ b/src/component/directory/get_directory_all_entries.c @@ -3,14 +3,14 @@ /* ::: :::::::: */ /* get_directory_all_entries.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 15:30:40 by surayama #+# #+# */ -/* Updated: 2025/11/27 16:08:41 by surayama ### ########.fr */ +/* Updated: 2025/12/01 03:20:12 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include +#include "directory.h" static int throw_error(void); static int process_entry(const char *path, const char *name, diff --git a/src/component/directory/get_directory_entries.c b/src/component/directory/get_directory_entries.c index 9771568..97bcea1 100644 --- a/src/component/directory/get_directory_entries.c +++ b/src/component/directory/get_directory_entries.c @@ -3,14 +3,14 @@ /* ::: :::::::: */ /* get_directory_entries.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 15:30:40 by surayama #+# #+# */ -/* Updated: 2025/11/29 20:05:20 by surayama ### ########.fr */ +/* Updated: 2025/12/01 03:20:12 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include +#include "directory.h" static int throw_error(void); static int append_entry(t_list **entries, const char *entry_name); diff --git a/src/component/heredoc/heredoc.c b/src/component/heredoc/heredoc.c index e62529f..1244be3 100644 --- a/src/component/heredoc/heredoc.c +++ b/src/component/heredoc/heredoc.c @@ -3,14 +3,14 @@ /* ::: :::::::: */ /* heredoc.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/20 14:13:36 by urassh #+# #+# */ -/* Updated: 2025/11/21 16:16:47 by urassh ### ########.fr */ +/* Updated: 2025/12/01 03:20:28 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include +#include "heredoc.h" static bool is_heredoc_operator(const char *token); static int rebuild_tokens(t_list *current, t_list *eof_node, diff --git a/src/component/heredoc/heredoc_prompt.c b/src/component/heredoc/heredoc_prompt.c index d3e3ddc..574c27f 100644 --- a/src/component/heredoc/heredoc_prompt.c +++ b/src/component/heredoc/heredoc_prompt.c @@ -3,14 +3,14 @@ /* ::: :::::::: */ /* heredoc_prompt.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/20 15:05:31 by urassh #+# #+# */ -/* Updated: 2025/11/20 17:23:51 by urassh ### ########.fr */ +/* Updated: 2025/12/01 03:20:28 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include +#include "heredoc.h" #include static int write_line_to_file(int fd, char *line); diff --git a/src/component/heredoc/tmpfile.c b/src/component/heredoc/tmpfile.c index 66b16f0..587652e 100644 --- a/src/component/heredoc/tmpfile.c +++ b/src/component/heredoc/tmpfile.c @@ -3,14 +3,14 @@ /* ::: :::::::: */ /* tmpfile.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/20 14:28:49 by urassh #+# #+# */ -/* Updated: 2025/11/22 01:08:26 by urassh ### ########.fr */ +/* Updated: 2025/12/01 03:20:28 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include +#include "heredoc.h" static char *get_tmpfile_id(const char *tmp_prefix); diff --git a/src/component/pattern/filter_pattern.c b/src/component/pattern/filter_pattern.c index dc14406..abbf257 100644 --- a/src/component/pattern/filter_pattern.c +++ b/src/component/pattern/filter_pattern.c @@ -1,16 +1,16 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* filter_by_pattern.c :+: :+: :+: */ +/* filter_pattern.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 11:40:49 by urassh #+# #+# */ -/* Updated: 2025/11/27 12:10:33 by urassh ### ########.fr */ +/* Updated: 2025/12/01 03:22:08 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include +#include "pattern.h" #include static bool match_pattern(const char *str, const char *pattern); diff --git a/src/component/shell_table/build_shell_table.c b/src/component/shell_table/build_shell_table.c index 4b0629e..f770a1e 100644 --- a/src/component/shell_table/build_shell_table.c +++ b/src/component/shell_table/build_shell_table.c @@ -3,14 +3,14 @@ /* ::: :::::::: */ /* build_shell_table.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/26 16:15:23 by urassh #+# #+# */ -/* Updated: 2025/11/27 14:53:48 by urassh ### ########.fr */ +/* Updated: 2025/12/01 03:23:00 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include +#include "shell_table.h" static t_shell_table *st_create(size_t size); static int insert_env_entries(char *const envp[], diff --git a/src/component/shell_table/export_envp.c b/src/component/shell_table/export_envp.c index 3751d7e..7ab671e 100644 --- a/src/component/shell_table/export_envp.c +++ b/src/component/shell_table/export_envp.c @@ -3,14 +3,14 @@ /* ::: :::::::: */ /* export_envp.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/26 16:15:41 by urassh #+# #+# */ -/* Updated: 2025/11/27 14:54:45 by urassh ### ########.fr */ +/* Updated: 2025/12/01 03:23:00 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include +#include "shell_table.h" static int count_exported_nodes(t_shell_table *shell_table); static int export_envp_entries(char **envp, t_shell_table *shell_table); diff --git a/src/component/shell_table/shell_delete.c b/src/component/shell_table/shell_delete.c index 6959856..ded6107 100644 --- a/src/component/shell_table/shell_delete.c +++ b/src/component/shell_table/shell_delete.c @@ -3,14 +3,14 @@ /* ::: :::::::: */ /* shell_delete.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/11/27 00:00:00 by urassh ### ########.fr */ +/* Updated: 2025/12/01 03:23:00 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include +#include "shell_table.h" static void free_node(t_shell_node *node) { diff --git a/src/component/shell_table/shell_destroy.c b/src/component/shell_table/shell_destroy.c index 7544aa5..d4dc6bf 100644 --- a/src/component/shell_table/shell_destroy.c +++ b/src/component/shell_table/shell_destroy.c @@ -3,14 +3,14 @@ /* ::: :::::::: */ /* shell_destroy.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/11/27 00:00:00 by urassh ### ########.fr */ +/* Updated: 2025/12/01 03:23:00 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include +#include "shell_table.h" static void free_chain(t_shell_node *node) { diff --git a/src/component/shell_table/shell_hash.c b/src/component/shell_table/shell_hash.c index cbd4ef9..f06b472 100644 --- a/src/component/shell_table/shell_hash.c +++ b/src/component/shell_table/shell_hash.c @@ -3,14 +3,14 @@ /* ::: :::::::: */ /* shell_hash.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/11/27 00:00:00 by urassh ### ########.fr */ +/* Updated: 2025/12/01 03:23:00 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include +#include "shell_table.h" size_t st_hash(const char *key, size_t table_size) { diff --git a/src/component/shell_table/shell_insert.c b/src/component/shell_table/shell_insert.c index cffe651..36b664d 100644 --- a/src/component/shell_table/shell_insert.c +++ b/src/component/shell_table/shell_insert.c @@ -3,14 +3,14 @@ /* ::: :::::::: */ /* shell_insert.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/11/27 00:00:00 by urassh ### ########.fr */ +/* Updated: 2025/12/01 03:23:00 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include +#include "shell_table.h" static t_shell_node *create_node(const char *key, const char *value, bool exported) diff --git a/src/component/shell_table/shell_search.c b/src/component/shell_table/shell_search.c index 39551ad..aacaa82 100644 --- a/src/component/shell_table/shell_search.c +++ b/src/component/shell_table/shell_search.c @@ -3,14 +3,14 @@ /* ::: :::::::: */ /* shell_search.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/11/27 00:00:00 by urassh ### ########.fr */ +/* Updated: 2025/12/01 03:23:00 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include +#include "shell_table.h" char *st_search(t_shell_table *table, const char *key) { From d587c6613bdebd00e06d8401b3618c9f8e1c4e50 Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Mon, 1 Dec 2025 15:00:03 +0900 Subject: [PATCH 112/173] =?UTF-8?q?=E7=9B=B8=E5=AF=BE=E3=83=91=E3=82=B9?= =?UTF-8?q?=E3=82=92=E7=B5=B6=E5=AF=BE=E3=83=91=E3=82=B9=E3=81=AB=E5=A4=89?= =?UTF-8?q?=E6=8F=9B=E3=81=99=E3=82=8B=E3=82=B3=E3=83=B3=E3=83=9D=E3=83=BC?= =?UTF-8?q?=E3=83=8D=E3=83=B3=E3=83=88=E3=81=AE=E5=AE=9F=E8=A3=85=20(#43)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * とりあえずパス解決実装はできた * fix ガード * add: checkerを追加 * fix; norminette * ../が偶数時の不具合を修正 * NULLガードを追加 * fix: ft_lstdeloneを使うように * fix: append_path * refactor: ft_lstlastを使うように * fix: checker * elseを使うように --- Makefile | 2 + includes/minishell.h | 3 +- includes/path.h | 18 ++++ libft/Makefile | 1 + libft/libft.h | 1 + libft/list/ft_lstdel_back.c | 34 ++++++++ src/checker/path_checker.c | 44 ++++++++++ src/component/path/to_absolute.c | 143 +++++++++++++++++++++++++++++++ src/main.c | 2 +- 9 files changed, 246 insertions(+), 2 deletions(-) create mode 100644 includes/path.h create mode 100644 libft/list/ft_lstdel_back.c create mode 100644 src/checker/path_checker.c create mode 100644 src/component/path/to_absolute.c diff --git a/Makefile b/Makefile index 7c64232..902c1c7 100644 --- a/Makefile +++ b/Makefile @@ -63,6 +63,7 @@ SRCS_MAND := src/main.c \ src/checker/heredoc_checker.c \ src/checker/shell_table_checker.c \ src/checker/parser_checker.c \ + src/checker/path_checker.c \ src/checker/directory_checker.c \ src/tokenize/tokenize.c \ src/tokenize/is_specific.c \ @@ -97,6 +98,7 @@ SRCS_MAND := src/main.c \ src/component/pattern/filter_pattern.c \ src/component/directory/get_directory_entries.c \ src/component/directory/get_directory_all_entries.c \ + src/component/path/to_absolute.c \ SRCS_BONUS := diff --git a/includes/minishell.h b/includes/minishell.h index ea3962f..c945c9d 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -6,7 +6,7 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:14:22 by kjikuhar #+# #+# */ -/* Updated: 2025/11/27 16:11:07 by surayama ### ########.fr */ +/* Updated: 2025/12/01 13:57:20 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -30,5 +30,6 @@ void heredoc_checker(char *input, t_shell_table *shell_table); void shell_table_checker(t_shell_table *shell_table); void parser_checker(char *input, t_shell_table *shell_table); void directory_checker(char *input, t_shell_table *shell_table); +void path_checker(char *input, t_shell_table *shell_table); #endif diff --git a/includes/path.h b/includes/path.h new file mode 100644 index 0000000..2691da3 --- /dev/null +++ b/includes/path.h @@ -0,0 +1,18 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* path.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/12/01 00:00:00 by urassh #+# #+# */ +/* Updated: 2025/12/01 12:00:34 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef PATH_H +# define PATH_H + +char *to_absolute(const char *path); + +#endif diff --git a/libft/Makefile b/libft/Makefile index a416e66..31dfa4f 100644 --- a/libft/Makefile +++ b/libft/Makefile @@ -27,6 +27,7 @@ SRCS = conversion/ft_atoi.c \ list/ft_lstadd_back.c \ list/ft_lstadd_front.c \ list/ft_lstclear.c \ + list/ft_lstdel_back.c \ list/ft_lstdelone.c \ list/ft_lstiter.c \ list/ft_lstlast.c \ diff --git a/libft/libft.h b/libft/libft.h index fa2fe88..4332c97 100644 --- a/libft/libft.h +++ b/libft/libft.h @@ -44,6 +44,7 @@ t_list *ft_lstlast(t_list *lst); int ft_lstsize(t_list *lst); void ft_lstadd_back(t_list **lst, t_list *new); void ft_lstdelone(t_list *lst, void (*del)(void *)); +void ft_lstdel_back(t_list **lst, void (*del)(void *)); void ft_lstclear(t_list **lst, void (*del)(void *)); void ft_lstiter(t_list *lst, void (*f)(void *)); t_list *ft_lstmap(t_list *lst, void *(*f)(void *), diff --git a/libft/list/ft_lstdel_back.c b/libft/list/ft_lstdel_back.c new file mode 100644 index 0000000..ffab458 --- /dev/null +++ b/libft/list/ft_lstdel_back.c @@ -0,0 +1,34 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstdel_back.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/12/01 00:00:00 by urassh #+# #+# */ +/* Updated: 2025/12/01 00:00:00 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_lstdel_back(t_list **lst, void (*del)(void *)) +{ + t_list *current; + t_list *last; + + if (!lst || !*lst || !del) + return ; + if (!(*lst)->next) + { + ft_lstdelone(*lst, del); + *lst = NULL; + return ; + } + last = ft_lstlast(*lst); + current = *lst; + while (current->next != last) + current = current->next; + current->next = NULL; + ft_lstdelone(last, del); +} diff --git a/src/checker/path_checker.c b/src/checker/path_checker.c new file mode 100644 index 0000000..7dbaf7a --- /dev/null +++ b/src/checker/path_checker.c @@ -0,0 +1,44 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* path_checker.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/12/01 00:00:00 by surayama #+# #+# */ +/* Updated: 2025/12/01 13:57:16 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" +#include "path.h" +#include +#include +#include + +void path_checker(char *input, t_shell_table *shell_table) +{ + char *absolute_path; + + (void)shell_table; + if (ft_strncmp(input, "exit", 5) == 0) + { + printf("exit\n"); + rl_clear_history(); + free(input); + exit(0); + } + printf("\n=== Path Checker ===\n"); + printf("Input: %s\n", input); + absolute_path = to_absolute(input); + if (absolute_path) + { + printf("Absolute Path: %s\n", absolute_path); + free(absolute_path); + } + else + { + ft_putendl_fd("Error: Failed to convert to absolute path", 2); + } + free(input); +} diff --git a/src/component/path/to_absolute.c b/src/component/path/to_absolute.c new file mode 100644 index 0000000..e6ef167 --- /dev/null +++ b/src/component/path/to_absolute.c @@ -0,0 +1,143 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* to_absolute.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/12/01 00:00:00 by urassh #+# #+# */ +/* Updated: 2025/12/01 14:33:49 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" +#include +#include +#include +#include + +static t_list *init_resolved_path(bool is_head_absolute, t_list **path_list); +static t_list *split_path_to_list(const char *path); +static t_list *append_path(char *segment, t_list *resolved_path); +static char *list_to_path(t_list *resolved_path); + +char *to_absolute(const char *path) +{ + t_list *path_list; + t_list *resolved_path; + t_list *current; + char *result; + + if (!path || !*path) + return (NULL); + if (ft_strncmp(path, "/", 2) == 0) + return (ft_strdup("/")); + path_list = split_path_to_list(path); + if (!path_list && path[0] == '/') + return (ft_strdup("/")); + resolved_path = init_resolved_path(path[0] == '/', &path_list); + current = path_list; + while (current) + { + resolved_path = append_path((char *)current->content, resolved_path); + current = current->next; + } + ft_lstclear(&path_list, free); + result = list_to_path(resolved_path); + ft_lstclear(&resolved_path, free); + return (result); +} + +static t_list *init_resolved_path(bool is_head_absolute, t_list **path_list) +{ + char *cwd; + t_list *resolved_path; + t_list *temp; + + resolved_path = NULL; + if (is_head_absolute) + { + while (*path_list) + { + if (ft_strncmp((char *)(*path_list)->content, ".", 2) == 0 + || ft_strncmp((char *)(*path_list)->content, "..", 3) == 0) + break ; + ft_lstadd_back(&resolved_path, ft_lstnew((*path_list)->content)); + temp = *path_list; + *path_list = (*path_list)->next; + ft_lstdelone(temp, free); + } + return (resolved_path); + } + cwd = getcwd(NULL, 0); + if (!cwd) + return (NULL); + resolved_path = split_path_to_list(cwd); + free(cwd); + return (resolved_path); +} + +static t_list *split_path_to_list(const char *path) +{ + char **segments; + t_list *list; + int i; + + if (!path) + return (NULL); + segments = ft_split(path, '/'); + if (!segments) + return (NULL); + list = NULL; + i = 0; + while (segments[i]) + { + ft_lstadd_back(&list, ft_lstnew(segments[i])); + i++; + } + free(segments); + return (list); +} + +static t_list *append_path(char *segment, t_list *resolved_path) +{ + if (ft_strncmp(segment, "..", 3) == 0) + { + if (resolved_path) + ft_lstdel_back(&resolved_path, free); + } + else if (ft_strncmp(segment, ".", 2) == 0) + return (resolved_path); + else + ft_lstadd_back(&resolved_path, ft_lstnew(ft_strdup(segment))); + return (resolved_path); +} + +static char *list_to_path(t_list *resolved_path) +{ + t_list *current; + char *result; + char *temp; + + if (!resolved_path) + return (ft_strdup("/")); + result = ft_strdup("/"); + current = resolved_path; + while (current) + { + temp = ft_strjoin(result, (char *)current->content); + if (result) + free(result); + if (!temp) + return (NULL); + result = temp; + if (current->next) + { + temp = ft_strjoin(result, "/"); + free(result); + result = temp; + } + current = current->next; + } + return (result); +} diff --git a/src/main.c b/src/main.c index c81a206..d4fa321 100644 --- a/src/main.c +++ b/src/main.c @@ -36,7 +36,7 @@ int main_dev(int argc, char const **argv, char *const envp[]) if (!shell_table) return (1); shell_table_checker(shell_table); - prompt(directory_checker, shell_table); + prompt(path_checker, shell_table); st_destroy(shell_table); return (0); } From cbef1a21fffdda25af244ba08d81bd9774f62d40 Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Mon, 1 Dec 2025 15:16:02 +0900 Subject: [PATCH 113/173] =?UTF-8?q?=E2=91=A1=20pwd=E3=82=B3=E3=83=9E?= =?UTF-8?q?=E3=83=B3=E3=83=89=E3=82=92=E5=AE=9F=E8=A3=85=E3=81=97=E3=81=9F?= =?UTF-8?q?=20(#37)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: echoコマンドを実装した * fix: norminette * fix: make出来ない不具合を修正 * feat: pwd * refactor: includeはheaderにまとめた * echoの余計な変更を無くした * fix: pwdでshellテーブル検索を削除 * fix: src/builtin/pwd.c --- Makefile | 3 ++- includes/builtin.h | 7 +++++-- src/builtin/pwd.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 src/builtin/pwd.c diff --git a/Makefile b/Makefile index 902c1c7..6f33af8 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # By: surayama +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/05/18 21:11:39 by kjikuhar #+# #+# # -# Updated: 2025/11/27 16:17:13 by surayama ### ########.fr # +# Updated: 2025/12/01 00:22:27 by surayama ### ########.fr # # # # **************************************************************************** # @@ -57,6 +57,7 @@ LIBFT_A := $(LIBFT_DIR)/libft.a #mandatory sources SRCS_MAND := src/main.c \ src/builtin/echo.c \ + src/builtin/pwd.c \ src/prompt/prompt.c \ src/callback/on_input.c \ src/checker/tokenize_checker.c \ diff --git a/includes/builtin.h b/includes/builtin.h index d1f1ffd..6ace22b 100644 --- a/includes/builtin.h +++ b/includes/builtin.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* builtin.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ +/* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/29 17:16:51 by surayama #+# #+# */ -/* Updated: 2025/12/01 03:23:00 by kjikuhar ### ########.fr */ +/* Updated: 2025/12/01 15:09:49 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,8 +14,11 @@ # define BUILTIN_H # include "shell_table.h" +# include # include +# include int echo(t_list *argv, t_shell_table *shell_table); +int pwd(t_list *argv, t_shell_table *shell_table); #endif diff --git a/src/builtin/pwd.c b/src/builtin/pwd.c new file mode 100644 index 0000000..cedc3e2 --- /dev/null +++ b/src/builtin/pwd.c @@ -0,0 +1,30 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* pwd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/29 20:16:00 by surayama #+# #+# */ +/* Updated: 2025/12/01 15:13:22 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include + +int pwd(t_list *argv, t_shell_table *shell_table) +{ + char *pwd_path; + + (void)argv; + (void)shell_table; + pwd_path = getcwd(NULL, 0); + if (!pwd_path) + { + perror("pwd"); + return (EXIT_FAILURE); + } + printf("%s\n", pwd_path); + free(pwd_path); + return (EXIT_SUCCESS); +} From ce624d1786765dd3dbbc173dff4625b4337c73b9 Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Wed, 7 Jan 2026 21:02:18 +0900 Subject: [PATCH 114/173] =?UTF-8?q?=E2=91=A2=20export=E3=82=B3=E3=83=9E?= =?UTF-8?q?=E3=83=B3=E3=83=89=E3=82=92=E5=AE=9F=E8=A3=85=E3=81=97=E3=81=9F?= =?UTF-8?q?=20(#38)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: echoコマンドを実装した * fix: norminette * fix: make出来ない不具合を修正 * feat: pwd * refactor: includeはheaderにまとめた * feat: export * add: Makefileにexportを追加 * 複数nodeの場合もそれぞれexportできるように * fix: exportをキーなしで実行時にvalueが消えてしまう不具合を修正 * fix: include double quote * add: buildin checker * 一旦exportの検証用にshell_table_checkerを追加 * export時だけ、直後にshell_table_checkerも実行するように * fix: norminette * add: shell tableにkeyのvalidation制約をつけた * feat: shell_print * fix: export自体にprint機能が実装されるのでcheckerの分岐を削除 * exportで引数が空の時はst_print_envを実行するように * iの初期化修正 --- Makefile | 5 +- includes/builtin.h | 3 +- includes/minishell.h | 3 +- includes/shell_table.h | 7 +- src/builtin/export.c | 103 +++++++++++++++++++++++ src/checker/builtin_checker.c | 28 ++++++ src/component/shell_table/shell_insert.c | 52 +++++++++++- src/component/shell_table/shell_print.c | 37 ++++++++ src/main.c | 2 +- 9 files changed, 231 insertions(+), 9 deletions(-) create mode 100644 src/builtin/export.c create mode 100644 src/checker/builtin_checker.c create mode 100644 src/component/shell_table/shell_print.c diff --git a/Makefile b/Makefile index 6f33af8..ef3d564 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # By: surayama +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/05/18 21:11:39 by kjikuhar #+# #+# # -# Updated: 2025/12/01 00:22:27 by surayama ### ########.fr # +# Updated: 2025/12/06 16:21:35 by surayama ### ########.fr # # # # **************************************************************************** # @@ -57,9 +57,11 @@ LIBFT_A := $(LIBFT_DIR)/libft.a #mandatory sources SRCS_MAND := src/main.c \ src/builtin/echo.c \ + src/builtin/export.c \ src/builtin/pwd.c \ src/prompt/prompt.c \ src/callback/on_input.c \ + src/checker/builtin_checker.c \ src/checker/tokenize_checker.c \ src/checker/heredoc_checker.c \ src/checker/shell_table_checker.c \ @@ -94,6 +96,7 @@ SRCS_MAND := src/main.c \ src/component/shell_table/shell_search.c \ src/component/shell_table/shell_delete.c \ src/component/shell_table/shell_destroy.c \ + src/component/shell_table/shell_print.c \ src/component/shell_table/build_shell_table.c \ src/component/shell_table/export_envp.c \ src/component/pattern/filter_pattern.c \ diff --git a/includes/builtin.h b/includes/builtin.h index 6ace22b..d67cbc4 100644 --- a/includes/builtin.h +++ b/includes/builtin.h @@ -6,7 +6,7 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/29 17:16:51 by surayama #+# #+# */ -/* Updated: 2025/12/01 15:09:49 by surayama ### ########.fr */ +/* Updated: 2025/11/29 20:31:07 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -20,5 +20,6 @@ int echo(t_list *argv, t_shell_table *shell_table); int pwd(t_list *argv, t_shell_table *shell_table); +int export(t_list *argv, t_shell_table *shell_table); #endif diff --git a/includes/minishell.h b/includes/minishell.h index c945c9d..eeb7bcf 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -6,7 +6,7 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:14:22 by kjikuhar #+# #+# */ -/* Updated: 2025/12/01 13:57:20 by surayama ### ########.fr */ +/* Updated: 2025/12/06 15:51:28 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -31,5 +31,6 @@ void shell_table_checker(t_shell_table *shell_table); void parser_checker(char *input, t_shell_table *shell_table); void directory_checker(char *input, t_shell_table *shell_table); void path_checker(char *input, t_shell_table *shell_table); +void builtin_checker(char *input, t_shell_table *shell_table); #endif diff --git a/includes/shell_table.h b/includes/shell_table.h index 6bc15a0..7aef1ca 100644 --- a/includes/shell_table.h +++ b/includes/shell_table.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* shell_table.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ +/* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/12/01 03:28:22 by kjikuhar ### ########.fr */ +/* Updated: 2025/12/06 16:22:11 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,6 +16,7 @@ # include "constants.h" # include "libft.h" # include +# include # define SHELL_TABLE_INIT_SIZE 256 @@ -38,9 +39,11 @@ typedef struct s_shell_table size_t st_hash(const char *key, size_t table_size); int st_insert(t_shell_table *table, const char *key, const char *value, bool exported); +int st_set_exported(t_shell_table *table, const char *key); char *st_search(t_shell_table *table, const char *key); int st_delete(t_shell_table *table, const char *key); void st_destroy(t_shell_table *table); +void st_print_env(t_shell_table *table); // shell_table specific operations t_shell_table *build_shell_table(char *const envp[]); diff --git a/src/builtin/export.c b/src/builtin/export.c new file mode 100644 index 0000000..49dd388 --- /dev/null +++ b/src/builtin/export.c @@ -0,0 +1,103 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* export.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/29 20:29:03 by surayama #+# #+# */ +/* Updated: 2025/12/06 16:20:07 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "builtin.h" + +static void skip_head_node(t_list **argv); +static int insert_assignment(t_shell_table *shell_table, + const char *assignment); +static char *get_key_from_assignment(const char *assignment); +static char *get_value_from_assignment(const char *assignment); + +int export(t_list *argv, t_shell_table *shell_table) +{ + if (!argv || !argv->content) + return (ERROR); + skip_head_node(&argv); + if (!argv) + { + st_print_env(shell_table); + return (SUCCESS); + } + while (argv) + { + if (insert_assignment(shell_table, + (const char *)argv->content) == ERROR) + return (ERROR); + skip_head_node(&argv); + } + return (SUCCESS); +} + +static void skip_head_node(t_list **argv) +{ + if (argv && *argv) + *argv = (*argv)->next; +} + +static int insert_assignment(t_shell_table *shell_table, + const char *assignment) +{ + char *key; + char *value; + int result; + + if (!shell_table || !assignment) + return (ERROR); + key = get_key_from_assignment(assignment); + if (!key) + return (ERROR); + value = get_value_from_assignment(assignment); + if (!value) + { + free(key); + return (ERROR); + } + if (value[0] == '\0') + result = st_set_exported(shell_table, key); + else + result = st_insert(shell_table, key, value, true); + free(key); + free(value); + if (!result) + return (ERROR); + return (SUCCESS); +} + +static char *get_key_from_assignment(const char *assignment) +{ + char *equal_sign_pos; + size_t key_len; + + equal_sign_pos = ft_strchr(assignment, '='); + if (!equal_sign_pos) + return (ft_strdup(assignment)); + key_len = equal_sign_pos - assignment; + return (ft_substr(assignment, 0, key_len)); +} + +static char *get_value_from_assignment(const char *assignment) +{ + char *equal_sign_pos; + char *value; + + equal_sign_pos = ft_strchr(assignment, '='); + if (!equal_sign_pos) + { + value = (char *)ft_calloc(1, sizeof(char)); + if (!value) + return (NULL); + return (value); + } + value = ft_strdup(equal_sign_pos + 1); + return (value); +} diff --git a/src/checker/builtin_checker.c b/src/checker/builtin_checker.c new file mode 100644 index 0000000..5a7d75a --- /dev/null +++ b/src/checker/builtin_checker.c @@ -0,0 +1,28 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* builtin_checker.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/12/06 15:32:40 by surayama #+# #+# */ +/* Updated: 2025/12/06 16:19:06 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "builtin.h" +#include "minishell.h" + +void builtin_checker(char *input, t_shell_table *shell_table) +{ + t_list *tokens; + int (*builtin_func)(t_list *, t_shell_table *); + + builtin_func = export; + tokens = tokenize(input); + if (!tokens) + return ; + if (builtin_func) + builtin_func(tokens, shell_table); + ft_lstclear(&tokens, free); +} diff --git a/src/component/shell_table/shell_insert.c b/src/component/shell_table/shell_insert.c index 36b664d..d29eae0 100644 --- a/src/component/shell_table/shell_insert.c +++ b/src/component/shell_table/shell_insert.c @@ -3,15 +3,33 @@ /* ::: :::::::: */ /* shell_insert.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ +/* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/12/01 03:23:00 by kjikuhar ### ########.fr */ +/* Updated: 2025/12/06 16:05:07 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ #include "shell_table.h" +static bool is_valid_key(const char *key) +{ + size_t i; + + if (!key || !*key) + return (false); + if (!ft_isalpha(key[0]) && key[0] != '_') + return (false); + i = 1; + while (key[i]) + { + if (!ft_isalnum(key[i]) && key[i] != '_') + return (false); + i++; + } + return (true); +} + static t_shell_node *create_node(const char *key, const char *value, bool exported) { @@ -56,7 +74,7 @@ int st_insert(t_shell_table *table, const char *key, const char *value, t_shell_node *node; t_shell_node *new_node; - if (!table || !key || !value) + if (!table || !key || !value || !is_valid_key(key)) return (0); index = st_hash(key, table->size); node = table->buckets[index]; @@ -74,3 +92,31 @@ int st_insert(t_shell_table *table, const char *key, const char *value, table->n_nodes++; return (1); } + +int st_set_exported(t_shell_table *table, const char *key) +{ + size_t index; + t_shell_node *node; + t_shell_node *new_node; + + if (!table || !key || !is_valid_key(key)) + return (0); + index = st_hash(key, table->size); + node = table->buckets[index]; + while (node) + { + if (ft_strncmp(node->key, key, ft_strlen(key) + 1) == 0) + { + node->exported = true; + return (1); + } + node = node->next; + } + new_node = create_node(key, "", true); + if (!new_node) + return (0); + new_node->next = table->buckets[index]; + table->buckets[index] = new_node; + table->n_nodes++; + return (1); +} diff --git a/src/component/shell_table/shell_print.c b/src/component/shell_table/shell_print.c new file mode 100644 index 0000000..abef1ea --- /dev/null +++ b/src/component/shell_table/shell_print.c @@ -0,0 +1,37 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* print_shell_table.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/12/06 16:11:42 by surayama #+# #+# */ +/* Updated: 2025/12/06 16:17:45 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "shell_table.h" + +void st_print_env(t_shell_table *table) +{ + size_t i; + t_shell_node *node; + + i = 0; + while (i < table->size) + { + node = table->buckets[i]; + while (node) + { + if (node->exported) + { + if (node->value && node->value[0] != '\0') + printf("%s=%s\n", node->key, node->value); + else + printf("%s=''\n", node->key); + } + node = node->next; + } + i++; + } +} diff --git a/src/main.c b/src/main.c index d4fa321..9abd3da 100644 --- a/src/main.c +++ b/src/main.c @@ -36,7 +36,7 @@ int main_dev(int argc, char const **argv, char *const envp[]) if (!shell_table) return (1); shell_table_checker(shell_table); - prompt(path_checker, shell_table); + prompt(builtin_checker, shell_table); st_destroy(shell_table); return (0); } From 92e3b1ba72a7d4c3e4b88cccabb5600ea4a4744f Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Wed, 7 Jan 2026 21:25:03 +0900 Subject: [PATCH 115/173] =?UTF-8?q?=E2=91=A3=20unset=E3=82=B3=E3=83=9E?= =?UTF-8?q?=E3=83=B3=E3=83=89=E3=82=92=E5=AE=9F=E8=A3=85=E3=81=97=E3=81=9F?= =?UTF-8?q?=20(#39)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: echoコマンドを実装した * fix: norminette * fix: make出来ない不具合を修正 * feat: pwd * refactor: includeはheaderにまとめた * feat: export * add: Makefileにexportを追加 * 複数nodeの場合もそれぞれexportできるように * feat: unset * chore: header fileの括弧をダブルコーテーションに変更した。 --------- Co-authored-by: jiku <134150757+jiku0730@users.noreply.github.com> Co-authored-by: jiku0730 --- Makefile | 1 + includes/builtin.h | 1 + src/builtin/pwd.c | 6 +++--- src/builtin/unset.c | 46 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 src/builtin/unset.c diff --git a/Makefile b/Makefile index ef3d564..0f0403b 100644 --- a/Makefile +++ b/Makefile @@ -59,6 +59,7 @@ SRCS_MAND := src/main.c \ src/builtin/echo.c \ src/builtin/export.c \ src/builtin/pwd.c \ + src/builtin/unset.c \ src/prompt/prompt.c \ src/callback/on_input.c \ src/checker/builtin_checker.c \ diff --git a/includes/builtin.h b/includes/builtin.h index d67cbc4..522da83 100644 --- a/includes/builtin.h +++ b/includes/builtin.h @@ -21,5 +21,6 @@ int echo(t_list *argv, t_shell_table *shell_table); int pwd(t_list *argv, t_shell_table *shell_table); int export(t_list *argv, t_shell_table *shell_table); +int unset(t_list *argv, t_shell_table *shell_table); #endif diff --git a/src/builtin/pwd.c b/src/builtin/pwd.c index cedc3e2..8215c29 100644 --- a/src/builtin/pwd.c +++ b/src/builtin/pwd.c @@ -3,14 +3,14 @@ /* ::: :::::::: */ /* pwd.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/29 20:16:00 by surayama #+# #+# */ -/* Updated: 2025/12/01 15:13:22 by surayama ### ########.fr */ +/* Updated: 2026/01/07 21:11:50 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include +#include "builtin.h" int pwd(t_list *argv, t_shell_table *shell_table) { diff --git a/src/builtin/unset.c b/src/builtin/unset.c new file mode 100644 index 0000000..d0e506d --- /dev/null +++ b/src/builtin/unset.c @@ -0,0 +1,46 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* unset.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/29 20:59:00 by surayama #+# #+# */ +/* Updated: 2026/01/07 21:12:00 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "builtin.h" + +static void skip_head_node(t_list **argv); + +int unset(t_list *argv, t_shell_table *shell_table) +{ + char *key; + int result; + + if (!argv || !argv->content) + return (ERROR); + result = SUCCESS; + skip_head_node(&argv); + while (argv) + { + key = (char *)argv->content; + if (!key) + { + result = ERROR; + skip_head_node(&argv); + continue ; + } + if (!st_delete(shell_table, key)) + result = ERROR; + skip_head_node(&argv); + } + return (result); +} + +static void skip_head_node(t_list **argv) +{ + if (argv && *argv) + *argv = (*argv)->next; +} From 757b1fe799747ed6382113a4b4abb952c8b28111 Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Thu, 8 Jan 2026 09:41:20 +0900 Subject: [PATCH 116/173] =?UTF-8?q?fix:=20tokenize=E3=81=A7=E3=83=80?= =?UTF-8?q?=E3=83=96=E3=83=AB=E3=81=A8=E3=82=B7=E3=83=B3=E3=82=B0=E3=83=AB?= =?UTF-8?q?=E3=81=AE=E3=82=AF=E3=82=A9=E3=83=BC=E3=83=88=E3=81=AE=E5=8C=BA?= =?UTF-8?q?=E5=88=A5=E3=81=8C=E5=BF=85=E8=A6=81=E3=81=AA=E3=81=93=E3=81=A8?= =?UTF-8?q?=E3=81=AB=E6=B0=97=E3=81=8C=E3=81=A4=E3=81=84=E3=81=9F=E3=81=AE?= =?UTF-8?q?=E3=81=A7=E3=81=9D=E3=81=AE=E4=BF=AE=E6=AD=A3=20(#44)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 3 ++- includes/tokenize.h | 7 ++++-- src/main.c | 2 +- .../state/{in_quote.c => in_double_quote.c} | 11 +++++---- src/tokenize/state/in_normal.c | 7 +++--- src/tokenize/state/in_single_quote.c | 24 +++++++++++++++++++ src/tokenize/tokenize.c | 6 +++-- 7 files changed, 46 insertions(+), 14 deletions(-) rename src/tokenize/state/{in_quote.c => in_double_quote.c} (73%) create mode 100644 src/tokenize/state/in_single_quote.c diff --git a/Makefile b/Makefile index 0f0403b..770b395 100644 --- a/Makefile +++ b/Makefile @@ -72,7 +72,8 @@ SRCS_MAND := src/main.c \ src/tokenize/tokenize.c \ src/tokenize/is_specific.c \ src/tokenize/state/in_normal.c \ - src/tokenize/state/in_quote.c \ + src/tokenize/state/in_double_quote.c \ + src/tokenize/state/in_single_quote.c \ src/tokenize/state/in_operator.c \ src/tokenize/state/on_success.c \ src/tokenize/state/on_error.c \ diff --git a/includes/tokenize.h b/includes/tokenize.h index 8009461..7d3ca55 100644 --- a/includes/tokenize.h +++ b/includes/tokenize.h @@ -20,7 +20,8 @@ typedef enum e_token_state { IN_NORMAL, - IN_QUOTE, + IN_DOUBLE_QUOTE, + IN_SINGLE_QUOTE, IN_OPERATOR, ON_SUCCESS, ON_ERROR, @@ -46,7 +47,9 @@ void free_store(t_token_store *store); // state handler void in_normal(t_token_store *store, t_token_state *state, const char current); -void in_quote(t_token_store *store, t_token_state *state, +void in_double_quote(t_token_store *store, t_token_state *state, + const char current); +void in_single_quote(t_token_store *store, t_token_state *state, const char current); void in_operator(t_token_store *store, t_token_state *state, const char current); diff --git a/src/main.c b/src/main.c index 9abd3da..cc08a7f 100644 --- a/src/main.c +++ b/src/main.c @@ -36,7 +36,7 @@ int main_dev(int argc, char const **argv, char *const envp[]) if (!shell_table) return (1); shell_table_checker(shell_table); - prompt(builtin_checker, shell_table); + prompt(tokenize_checker, shell_table); st_destroy(shell_table); return (0); } diff --git a/src/tokenize/state/in_quote.c b/src/tokenize/state/in_double_quote.c similarity index 73% rename from src/tokenize/state/in_quote.c rename to src/tokenize/state/in_double_quote.c index dd925c1..0fe4f01 100644 --- a/src/tokenize/state/in_quote.c +++ b/src/tokenize/state/in_double_quote.c @@ -1,23 +1,24 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* in_quote.c :+: :+: :+: */ +/* in_double_quote.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/05 13:54:52 by urassh #+# #+# */ -/* Updated: 2025/11/05 14:21:31 by urassh ### ########.fr */ +/* Created: 2025/12/06 00:00:00 by urassh #+# #+# */ +/* Updated: 2025/12/06 00:00:00 by urassh ### ########.fr */ /* */ /* ************************************************************************** */ #include "tokenize.h" -void in_quote(t_token_store *store, t_token_state *state, const char current) +void in_double_quote(t_token_store *store, t_token_state *state, + const char current) { if (current == '\0') *state = ON_ERROR; else if (add_buffer(store, current) == ERROR) *state = ON_ERROR; - else if (is_quote(current)) + else if (current == '"') *state = IN_NORMAL; } diff --git a/src/tokenize/state/in_normal.c b/src/tokenize/state/in_normal.c index ea67e98..b77a8fc 100644 --- a/src/tokenize/state/in_normal.c +++ b/src/tokenize/state/in_normal.c @@ -68,9 +68,10 @@ static void by_operator(t_token_store *store, t_token_state *state, static void by_quote(t_token_store *store, t_token_state *state, const char current) { - (void)store; if (add_buffer(store, current) == ERROR) *state = ON_ERROR; - else - *state = IN_QUOTE; + else if (current == '"') + *state = IN_DOUBLE_QUOTE; + else if (current == '\'') + *state = IN_SINGLE_QUOTE; } diff --git a/src/tokenize/state/in_single_quote.c b/src/tokenize/state/in_single_quote.c new file mode 100644 index 0000000..ed7eb06 --- /dev/null +++ b/src/tokenize/state/in_single_quote.c @@ -0,0 +1,24 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* in_single_quote.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: urassh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/12/06 00:00:00 by urassh #+# #+# */ +/* Updated: 2025/12/06 00:00:00 by urassh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "tokenize.h" + +void in_single_quote(t_token_store *store, t_token_state *state, + const char current) +{ + if (current == '\0') + *state = ON_ERROR; + else if (add_buffer(store, current) == ERROR) + *state = ON_ERROR; + else if (current == '\'') + *state = IN_NORMAL; +} diff --git a/src/tokenize/tokenize.c b/src/tokenize/tokenize.c index 76b08db..f7a150a 100644 --- a/src/tokenize/tokenize.c +++ b/src/tokenize/tokenize.c @@ -28,8 +28,10 @@ t_list *tokenize(char *input) { if (state == IN_NORMAL) in_normal(&store, &state, *current); - else if (state == IN_QUOTE) - in_quote(&store, &state, *current); + else if (state == IN_DOUBLE_QUOTE) + in_double_quote(&store, &state, *current); + else if (state == IN_SINGLE_QUOTE) + in_single_quote(&store, &state, *current); else if (state == IN_OPERATOR) in_operator(&store, &state, *current); else if (state == ON_SUCCESS) From 70c1a8a2ac92e06f373c9cdd174943de69101e0e Mon Sep 17 00:00:00 2001 From: jiku <134150757+jiku0730@users.noreply.github.com> Date: Fri, 16 Jan 2026 15:12:30 +0900 Subject: [PATCH 117/173] fix: 42header about urassh->surayama (#46) Co-authored-by: jiku0730 --- includes/constants.h | 4 ++-- includes/heredoc.h | 6 +++--- includes/path.h | 6 +++--- includes/pattern.h | 4 ++-- includes/prompt.h | 4 ++-- includes/shell_table.h | 6 +++--- includes/tokenize.h | 6 +++--- libft/Makefile | 4 ++-- libft/libft.h | 4 ++-- libft/list/ft_lstdel_back.c | 6 +++--- libft/original/is_blank_line.c | 4 ++-- src/callback/on_input.c | 6 +++--- src/checker/heredoc_checker.c | 4 ++-- src/checker/parser_checker.c | 4 ++-- src/checker/shell_table_checker.c | 4 ++-- src/checker/tokenize_checker.c | 6 +++--- src/component/heredoc/heredoc.c | 4 ++-- src/component/heredoc/heredoc_prompt.c | 4 ++-- src/component/heredoc/tmpfile.c | 4 ++-- src/component/path/to_absolute.c | 6 +++--- src/component/pattern/filter_pattern.c | 4 ++-- src/component/shell_table/build_shell_table.c | 4 ++-- src/component/shell_table/export_envp.c | 4 ++-- src/component/shell_table/shell_delete.c | 4 ++-- src/component/shell_table/shell_destroy.c | 4 ++-- src/component/shell_table/shell_hash.c | 4 ++-- src/component/shell_table/shell_insert.c | 6 +++--- src/component/shell_table/shell_search.c | 4 ++-- src/prompt/prompt.c | 6 +++--- src/tokenize/is_specific.c | 6 +++--- src/tokenize/state/in_double_quote.c | 6 +++--- src/tokenize/state/in_normal.c | 6 +++--- src/tokenize/state/in_operator.c | 6 +++--- src/tokenize/state/in_single_quote.c | 6 +++--- src/tokenize/state/on_error.c | 6 +++--- src/tokenize/state/on_success.c | 6 +++--- src/tokenize/store/add_buffer.c | 6 +++--- src/tokenize/store/free_store.c | 6 +++--- src/tokenize/store/push_token.c | 6 +++--- src/tokenize/tokenize.c | 6 +++--- 40 files changed, 101 insertions(+), 101 deletions(-) diff --git a/includes/constants.h b/includes/constants.h index c61aed3..91486fd 100644 --- a/includes/constants.h +++ b/includes/constants.h @@ -5,8 +5,8 @@ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/10/16 23:14:49 by urassh #+# #+# */ -/* Updated: 2025/12/01 01:54:44 by kjikuhar ### ########.fr */ +/* Created: 2025/10/16 23:14:49 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/includes/heredoc.h b/includes/heredoc.h index d1b9c64..a8ea1e1 100644 --- a/includes/heredoc.h +++ b/includes/heredoc.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* heredoc.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/20 14:12:42 by urassh #+# #+# */ -/* Updated: 2025/11/20 17:36:09 by urassh ### ########.fr */ +/* Created: 2025/11/20 14:12:42 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:51 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/includes/path.h b/includes/path.h index 2691da3..ea64a50 100644 --- a/includes/path.h +++ b/includes/path.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* path.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/12/01 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/12/01 12:00:34 by surayama ### ########.fr */ +/* Created: 2025/12/01 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:51 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/includes/pattern.h b/includes/pattern.h index d9cc311..a205a01 100644 --- a/includes/pattern.h +++ b/includes/pattern.h @@ -5,8 +5,8 @@ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/27 11:36:50 by urassh #+# #+# */ -/* Updated: 2025/12/01 03:28:22 by kjikuhar ### ########.fr */ +/* Created: 2025/11/27 11:36:50 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:51 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/includes/prompt.h b/includes/prompt.h index 47bcc5b..09fb593 100644 --- a/includes/prompt.h +++ b/includes/prompt.h @@ -5,8 +5,8 @@ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/10/01 15:35:18 by urassh #+# #+# */ -/* Updated: 2025/12/01 01:49:05 by kjikuhar ### ########.fr */ +/* Created: 2025/10/01 15:35:18 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:51 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/includes/shell_table.h b/includes/shell_table.h index 7aef1ca..6d127b4 100644 --- a/includes/shell_table.h +++ b/includes/shell_table.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* shell_table.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/27 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/12/06 16:22:11 by surayama ### ########.fr */ +/* Created: 2025/11/27 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:51 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/includes/tokenize.h b/includes/tokenize.h index 7d3ca55..4d80316 100644 --- a/includes/tokenize.h +++ b/includes/tokenize.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* tokenize.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/10/10 17:09:25 by urassh #+# #+# */ -/* Updated: 2025/11/05 14:21:43 by urassh ### ########.fr */ +/* Created: 2025/10/10 17:09:25 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:51 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/libft/Makefile b/libft/Makefile index 31dfa4f..1f4ea7c 100644 --- a/libft/Makefile +++ b/libft/Makefile @@ -3,10 +3,10 @@ # ::: :::::::: # # Makefile :+: :+: :+: # # +:+ +:+ +:+ # -# By: urassh +#+ +:+ +#+ # +# By: kjikuhar +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/04/04 16:00:02 by kjikuhar #+# #+# # -# Updated: 2025/10/15 01:37:33 by urassh ### ########.fr # +# Updated: 2026/01/16 13:59:51 by kjikuhar ### ########.fr # # # # **************************************************************************** # diff --git a/libft/libft.h b/libft/libft.h index 4332c97..9038dd6 100644 --- a/libft/libft.h +++ b/libft/libft.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* libft.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/25 14:55:13 by kjikuhar #+# #+# */ -/* Updated: 2025/11/05 14:49:40 by urassh ### ########.fr */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/libft/list/ft_lstdel_back.c b/libft/list/ft_lstdel_back.c index ffab458..671ba78 100644 --- a/libft/list/ft_lstdel_back.c +++ b/libft/list/ft_lstdel_back.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* ft_lstdel_back.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/12/01 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/12/01 00:00:00 by urassh ### ########.fr */ +/* Created: 2025/12/01 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/libft/original/is_blank_line.c b/libft/original/is_blank_line.c index cb60dee..e385beb 100644 --- a/libft/original/is_blank_line.c +++ b/libft/original/is_blank_line.c @@ -5,8 +5,8 @@ /* +:+ +:+ +:+ */ /* By: urassh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/10/13 16:15:16 by urassh #+# #+# */ -/* Updated: 2025/10/13 16:16:46 by urassh ### ########.fr */ +/* Created: 2025/10/13 16:15:16 by surayama #+# #+# */ +/* Updated: 2025/10/13 16:16:46 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/callback/on_input.c b/src/callback/on_input.c index c4baf1d..40224b7 100644 --- a/src/callback/on_input.c +++ b/src/callback/on_input.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* on_input.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/10/10 17:04:25 by urassh #+# #+# */ -/* Updated: 2025/11/27 14:54:45 by urassh ### ########.fr */ +/* Created: 2025/10/10 17:04:25 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/checker/heredoc_checker.c b/src/checker/heredoc_checker.c index 1fa6790..1760ac4 100644 --- a/src/checker/heredoc_checker.c +++ b/src/checker/heredoc_checker.c @@ -5,8 +5,8 @@ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/20 15:55:55 by urassh #+# #+# */ -/* Updated: 2025/12/01 03:20:46 by kjikuhar ### ########.fr */ +/* Created: 2025/11/20 15:55:55 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/checker/parser_checker.c b/src/checker/parser_checker.c index 76f1d56..3278385 100644 --- a/src/checker/parser_checker.c +++ b/src/checker/parser_checker.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* parser_checker.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 01:46:42 by kjikuhar #+# #+# */ -/* Updated: 2025/11/27 14:54:45 by urassh ### ########.fr */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/checker/shell_table_checker.c b/src/checker/shell_table_checker.c index 1cb417e..e9753de 100644 --- a/src/checker/shell_table_checker.c +++ b/src/checker/shell_table_checker.c @@ -5,8 +5,8 @@ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/26 16:53:40 by urassh #+# #+# */ -/* Updated: 2025/12/01 03:20:46 by kjikuhar ### ########.fr */ +/* Created: 2025/11/26 16:53:40 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/checker/tokenize_checker.c b/src/checker/tokenize_checker.c index e44933f..a620832 100644 --- a/src/checker/tokenize_checker.c +++ b/src/checker/tokenize_checker.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* tokenize_checker.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/05 13:47:35 by urassh #+# #+# */ -/* Updated: 2025/11/27 14:54:45 by urassh ### ########.fr */ +/* Created: 2025/11/05 13:47:35 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/component/heredoc/heredoc.c b/src/component/heredoc/heredoc.c index 1244be3..baef0d5 100644 --- a/src/component/heredoc/heredoc.c +++ b/src/component/heredoc/heredoc.c @@ -5,8 +5,8 @@ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/20 14:13:36 by urassh #+# #+# */ -/* Updated: 2025/12/01 03:20:28 by kjikuhar ### ########.fr */ +/* Created: 2025/11/20 14:13:36 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/component/heredoc/heredoc_prompt.c b/src/component/heredoc/heredoc_prompt.c index 574c27f..97ac604 100644 --- a/src/component/heredoc/heredoc_prompt.c +++ b/src/component/heredoc/heredoc_prompt.c @@ -5,8 +5,8 @@ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/20 15:05:31 by urassh #+# #+# */ -/* Updated: 2025/12/01 03:20:28 by kjikuhar ### ########.fr */ +/* Created: 2025/11/20 15:05:31 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/component/heredoc/tmpfile.c b/src/component/heredoc/tmpfile.c index 587652e..732a51a 100644 --- a/src/component/heredoc/tmpfile.c +++ b/src/component/heredoc/tmpfile.c @@ -5,8 +5,8 @@ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/20 14:28:49 by urassh #+# #+# */ -/* Updated: 2025/12/01 03:20:28 by kjikuhar ### ########.fr */ +/* Created: 2025/11/20 14:28:49 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/component/path/to_absolute.c b/src/component/path/to_absolute.c index e6ef167..89ccf5c 100644 --- a/src/component/path/to_absolute.c +++ b/src/component/path/to_absolute.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* to_absolute.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/12/01 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/12/01 14:33:49 by surayama ### ########.fr */ +/* Created: 2025/12/01 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/component/pattern/filter_pattern.c b/src/component/pattern/filter_pattern.c index abbf257..0534b4b 100644 --- a/src/component/pattern/filter_pattern.c +++ b/src/component/pattern/filter_pattern.c @@ -5,8 +5,8 @@ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/27 11:40:49 by urassh #+# #+# */ -/* Updated: 2025/12/01 03:22:08 by kjikuhar ### ########.fr */ +/* Created: 2025/11/27 11:40:49 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/component/shell_table/build_shell_table.c b/src/component/shell_table/build_shell_table.c index f770a1e..2f4e1c8 100644 --- a/src/component/shell_table/build_shell_table.c +++ b/src/component/shell_table/build_shell_table.c @@ -5,8 +5,8 @@ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/26 16:15:23 by urassh #+# #+# */ -/* Updated: 2025/12/01 03:23:00 by kjikuhar ### ########.fr */ +/* Created: 2025/11/26 16:15:23 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/component/shell_table/export_envp.c b/src/component/shell_table/export_envp.c index 7ab671e..383ac27 100644 --- a/src/component/shell_table/export_envp.c +++ b/src/component/shell_table/export_envp.c @@ -5,8 +5,8 @@ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/26 16:15:41 by urassh #+# #+# */ -/* Updated: 2025/12/01 03:23:00 by kjikuhar ### ########.fr */ +/* Created: 2025/11/26 16:15:41 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/component/shell_table/shell_delete.c b/src/component/shell_table/shell_delete.c index ded6107..cf135bb 100644 --- a/src/component/shell_table/shell_delete.c +++ b/src/component/shell_table/shell_delete.c @@ -5,8 +5,8 @@ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/27 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/12/01 03:23:00 by kjikuhar ### ########.fr */ +/* Created: 2025/11/27 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/component/shell_table/shell_destroy.c b/src/component/shell_table/shell_destroy.c index d4dc6bf..4472c38 100644 --- a/src/component/shell_table/shell_destroy.c +++ b/src/component/shell_table/shell_destroy.c @@ -5,8 +5,8 @@ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/27 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/12/01 03:23:00 by kjikuhar ### ########.fr */ +/* Created: 2025/11/27 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/component/shell_table/shell_hash.c b/src/component/shell_table/shell_hash.c index f06b472..201ba1a 100644 --- a/src/component/shell_table/shell_hash.c +++ b/src/component/shell_table/shell_hash.c @@ -5,8 +5,8 @@ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/27 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/12/01 03:23:00 by kjikuhar ### ########.fr */ +/* Created: 2025/11/27 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/component/shell_table/shell_insert.c b/src/component/shell_table/shell_insert.c index d29eae0..f24873e 100644 --- a/src/component/shell_table/shell_insert.c +++ b/src/component/shell_table/shell_insert.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* shell_insert.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/27 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/12/06 16:05:07 by surayama ### ########.fr */ +/* Created: 2025/11/27 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/01/16 14:00:43 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/component/shell_table/shell_search.c b/src/component/shell_table/shell_search.c index aacaa82..0db5883 100644 --- a/src/component/shell_table/shell_search.c +++ b/src/component/shell_table/shell_search.c @@ -5,8 +5,8 @@ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/27 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/12/01 03:23:00 by kjikuhar ### ########.fr */ +/* Created: 2025/11/27 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/prompt/prompt.c b/src/prompt/prompt.c index 93cb2d8..9d91286 100644 --- a/src/prompt/prompt.c +++ b/src/prompt/prompt.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* prompt.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/10/01 15:35:00 by urassh #+# #+# */ -/* Updated: 2025/11/27 14:54:45 by urassh ### ########.fr */ +/* Created: 2025/10/01 15:35:00 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/tokenize/is_specific.c b/src/tokenize/is_specific.c index 380bfcf..37543a8 100644 --- a/src/tokenize/is_specific.c +++ b/src/tokenize/is_specific.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* is_specific.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/10/13 01:15:00 by urassh #+# #+# */ -/* Updated: 2025/11/05 14:21:43 by urassh ### ########.fr */ +/* Created: 2025/10/13 01:15:00 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/tokenize/state/in_double_quote.c b/src/tokenize/state/in_double_quote.c index 0fe4f01..0a1eee1 100644 --- a/src/tokenize/state/in_double_quote.c +++ b/src/tokenize/state/in_double_quote.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* in_double_quote.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/12/06 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/12/06 00:00:00 by urassh ### ########.fr */ +/* Created: 2025/12/06 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/tokenize/state/in_normal.c b/src/tokenize/state/in_normal.c index b77a8fc..60933b3 100644 --- a/src/tokenize/state/in_normal.c +++ b/src/tokenize/state/in_normal.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* in_normal.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/10/13 00:30:00 by urassh #+# #+# */ -/* Updated: 2025/11/05 14:21:43 by urassh ### ########.fr */ +/* Created: 2025/10/13 00:30:00 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/tokenize/state/in_operator.c b/src/tokenize/state/in_operator.c index 5dd519a..531e116 100644 --- a/src/tokenize/state/in_operator.c +++ b/src/tokenize/state/in_operator.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* in_operator.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/10/13 00:30:00 by urassh #+# #+# */ -/* Updated: 2025/11/05 14:21:43 by urassh ### ########.fr */ +/* Created: 2025/10/13 00:30:00 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/tokenize/state/in_single_quote.c b/src/tokenize/state/in_single_quote.c index ed7eb06..bf1780b 100644 --- a/src/tokenize/state/in_single_quote.c +++ b/src/tokenize/state/in_single_quote.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* in_single_quote.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/12/06 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/12/06 00:00:00 by urassh ### ########.fr */ +/* Created: 2025/12/06 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/tokenize/state/on_error.c b/src/tokenize/state/on_error.c index 8223edd..09814eb 100644 --- a/src/tokenize/state/on_error.c +++ b/src/tokenize/state/on_error.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* on_error.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/10/13 00:35:00 by urassh #+# #+# */ -/* Updated: 2025/10/17 22:54:59 by urassh ### ########.fr */ +/* Created: 2025/10/13 00:35:00 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/tokenize/state/on_success.c b/src/tokenize/state/on_success.c index 5f811e2..1fd3728 100644 --- a/src/tokenize/state/on_success.c +++ b/src/tokenize/state/on_success.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* on_success.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/10/13 00:35:00 by urassh #+# #+# */ -/* Updated: 2025/10/22 12:44:01 by urassh ### ########.fr */ +/* Created: 2025/10/13 00:35:00 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/tokenize/store/add_buffer.c b/src/tokenize/store/add_buffer.c index 348fa8e..8b304e4 100644 --- a/src/tokenize/store/add_buffer.c +++ b/src/tokenize/store/add_buffer.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* add_buffer.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/10/17 00:00:00 by urassh #+# #+# */ -/* Updated: 2025/10/17 00:46:16 by urassh ### ########.fr */ +/* Created: 2025/10/17 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/tokenize/store/free_store.c b/src/tokenize/store/free_store.c index cb52faf..c135f57 100644 --- a/src/tokenize/store/free_store.c +++ b/src/tokenize/store/free_store.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* free_store.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/10/16 23:57:51 by urassh #+# #+# */ -/* Updated: 2025/10/16 23:58:16 by urassh ### ########.fr */ +/* Created: 2025/10/16 23:57:51 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/tokenize/store/push_token.c b/src/tokenize/store/push_token.c index 7328377..5b9707c 100644 --- a/src/tokenize/store/push_token.c +++ b/src/tokenize/store/push_token.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* push_token.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/10/12 22:13:34 by urassh #+# #+# */ -/* Updated: 2025/10/22 12:31:20 by urassh ### ########.fr */ +/* Created: 2025/10/12 22:13:34 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/tokenize/tokenize.c b/src/tokenize/tokenize.c index f7a150a..31f5a40 100644 --- a/src/tokenize/tokenize.c +++ b/src/tokenize/tokenize.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* tokenize.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: urassh +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/10/10 17:14:04 by urassh #+# #+# */ -/* Updated: 2025/11/05 14:06:48 by urassh ### ########.fr */ +/* Created: 2025/10/10 17:14:04 by surayama #+# #+# */ +/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ From 232b6e39dc392b9d73f97479d6a3c73fb1e215d3 Mon Sep 17 00:00:00 2001 From: jiku <134150757+jiku0730@users.noreply.github.com> Date: Fri, 16 Jan 2026 15:21:47 +0900 Subject: [PATCH 118/173] refactor: tokenize (#47) * fix: const char c -> char c * fix: ft_list_clear don't need NULL guard --------- Co-authored-by: jiku0730 --- includes/tokenize.h | 15 +++++++-------- src/tokenize/is_specific.c | 4 ++-- src/tokenize/state/in_double_quote.c | 2 +- src/tokenize/state/in_normal.c | 25 +++++++++---------------- src/tokenize/state/in_operator.c | 13 +++++-------- src/tokenize/state/in_single_quote.c | 2 +- src/tokenize/state/on_success.c | 3 +-- src/tokenize/store/add_buffer.c | 2 +- src/tokenize/store/free_store.c | 6 ++---- 9 files changed, 29 insertions(+), 43 deletions(-) diff --git a/includes/tokenize.h b/includes/tokenize.h index 4d80316..cc46fb0 100644 --- a/includes/tokenize.h +++ b/includes/tokenize.h @@ -36,23 +36,22 @@ typedef struct s_token_store t_list *tokenize(char *input); // is specific -bool is_quote(const char c); -bool is_operator(const char c); +bool is_quote(char c); +bool is_operator(char c); // store int push_token(t_token_store *store); -int add_buffer(t_token_store *store, const char c); +int add_buffer(t_token_store *store, char c); void free_store(t_token_store *store); // state handler -void in_normal(t_token_store *store, t_token_state *state, - const char current); +void in_normal(t_token_store *store, t_token_state *state, char current); void in_double_quote(t_token_store *store, t_token_state *state, - const char current); + char current); void in_single_quote(t_token_store *store, t_token_state *state, - const char current); + char current); void in_operator(t_token_store *store, t_token_state *state, - const char current); + char current); t_list *on_success(t_token_store *store, char *input); t_list *on_error(t_token_store *store, char *input); diff --git a/src/tokenize/is_specific.c b/src/tokenize/is_specific.c index 37543a8..f7c1f8a 100644 --- a/src/tokenize/is_specific.c +++ b/src/tokenize/is_specific.c @@ -12,7 +12,7 @@ #include "tokenize.h" -bool is_quote(const char c) +bool is_quote(char c) { if (c == '"') return (true); @@ -21,7 +21,7 @@ bool is_quote(const char c) return (false); } -bool is_operator(const char c) +bool is_operator(char c) { if (c == '&') return (true); diff --git a/src/tokenize/state/in_double_quote.c b/src/tokenize/state/in_double_quote.c index 0a1eee1..84ddc52 100644 --- a/src/tokenize/state/in_double_quote.c +++ b/src/tokenize/state/in_double_quote.c @@ -13,7 +13,7 @@ #include "tokenize.h" void in_double_quote(t_token_store *store, t_token_state *state, - const char current) + char current) { if (current == '\0') *state = ON_ERROR; diff --git a/src/tokenize/state/in_normal.c b/src/tokenize/state/in_normal.c index 60933b3..24b80e0 100644 --- a/src/tokenize/state/in_normal.c +++ b/src/tokenize/state/in_normal.c @@ -12,17 +12,13 @@ #include "tokenize.h" -static void by_last(t_token_store *store, t_token_state *state, - const char current); -static void by_space(t_token_store *store, t_token_state *state, - const char current); -static void by_quote(t_token_store *store, t_token_state *state, - const char current); +static void by_last(t_token_store *store, t_token_state *state, char current); +static void by_space(t_token_store *store, t_token_state *state, char current); +static void by_quote(t_token_store *store, t_token_state *state, char current); static void by_operator(t_token_store *store, t_token_state *state, - const char current); + char current); -void in_normal(t_token_store *store, t_token_state *state, - const char current) +void in_normal(t_token_store *store, t_token_state *state, char current) { if (current == '\0') by_last(store, state, current); @@ -36,8 +32,7 @@ void in_normal(t_token_store *store, t_token_state *state, *state = ON_ERROR; } -static void by_last(t_token_store *store, t_token_state *state, - const char current) +static void by_last(t_token_store *store, t_token_state *state, char current) { (void)current; if (push_token(store) == ERROR) @@ -46,8 +41,7 @@ static void by_last(t_token_store *store, t_token_state *state, *state = ON_SUCCESS; } -static void by_space(t_token_store *store, t_token_state *state, - const char current) +static void by_space(t_token_store *store, t_token_state *state, char current) { (void)current; if (push_token(store) == ERROR) @@ -57,7 +51,7 @@ static void by_space(t_token_store *store, t_token_state *state, } static void by_operator(t_token_store *store, t_token_state *state, - const char current) + char current) { if (push_token(store) == ERROR || add_buffer(store, current) == ERROR) *state = ON_ERROR; @@ -65,8 +59,7 @@ static void by_operator(t_token_store *store, t_token_state *state, *state = IN_OPERATOR; } -static void by_quote(t_token_store *store, t_token_state *state, - const char current) +static void by_quote(t_token_store *store, t_token_state *state, char current) { if (add_buffer(store, current) == ERROR) *state = ON_ERROR; diff --git a/src/tokenize/state/in_operator.c b/src/tokenize/state/in_operator.c index 531e116..f1b2371 100644 --- a/src/tokenize/state/in_operator.c +++ b/src/tokenize/state/in_operator.c @@ -13,12 +13,10 @@ #include "tokenize.h" static void by_operator(t_token_store *store, t_token_state *state, - const char current); -static void by_normal(t_token_store *store, t_token_state *state, - const char current); + char current); +static void by_normal(t_token_store *store, t_token_state *state, char current); -void in_operator(t_token_store *store, t_token_state *state, - const char current) +void in_operator(t_token_store *store, t_token_state *state, char current) { if (current == '\0' && push_token(store)) *state = ON_SUCCESS; @@ -29,7 +27,7 @@ void in_operator(t_token_store *store, t_token_state *state, } static void by_operator(t_token_store *store, t_token_state *state, - const char current) + char current) { if (add_buffer(store, current) == ERROR) *state = ON_ERROR; @@ -39,8 +37,7 @@ static void by_operator(t_token_store *store, t_token_state *state, *state = IN_NORMAL; } -static void by_normal(t_token_store *store, t_token_state *state, - const char current) +static void by_normal(t_token_store *store, t_token_state *state, char current) { if (push_token(store) == ERROR) *state = ON_ERROR; diff --git a/src/tokenize/state/in_single_quote.c b/src/tokenize/state/in_single_quote.c index bf1780b..b79c16c 100644 --- a/src/tokenize/state/in_single_quote.c +++ b/src/tokenize/state/in_single_quote.c @@ -13,7 +13,7 @@ #include "tokenize.h" void in_single_quote(t_token_store *store, t_token_state *state, - const char current) + char current) { if (current == '\0') *state = ON_ERROR; diff --git a/src/tokenize/state/on_success.c b/src/tokenize/state/on_success.c index 1fd3728..9428b17 100644 --- a/src/tokenize/state/on_success.c +++ b/src/tokenize/state/on_success.c @@ -22,7 +22,6 @@ t_list *on_success(t_token_store *store, char *input) free(input); rtv_tokens = store->tokens; store->tokens = NULL; - if (store->buffer) - ft_lstclear(&(store->buffer), free); + ft_lstclear(&(store->buffer), free); return (rtv_tokens); } diff --git a/src/tokenize/store/add_buffer.c b/src/tokenize/store/add_buffer.c index 8b304e4..80622cb 100644 --- a/src/tokenize/store/add_buffer.c +++ b/src/tokenize/store/add_buffer.c @@ -12,7 +12,7 @@ #include "tokenize.h" -int add_buffer(t_token_store *store, const char c) +int add_buffer(t_token_store *store, char c) { char *char_ptr; t_list *new_node; diff --git a/src/tokenize/store/free_store.c b/src/tokenize/store/free_store.c index c135f57..6b6a2b5 100644 --- a/src/tokenize/store/free_store.c +++ b/src/tokenize/store/free_store.c @@ -16,8 +16,6 @@ void free_store(t_token_store *store) { if (!store) return ; - if (store->buffer) - ft_lstclear(&(store->buffer), free); - if (store->tokens) - ft_lstclear(&(store->tokens), free); + ft_lstclear(&(store->buffer), free); + ft_lstclear(&(store->tokens), free); } From da6d579f441fb1d73f9d0b8d1f6d9afc40930b93 Mon Sep 17 00:00:00 2001 From: jiku <134150757+jiku0730@users.noreply.github.com> Date: Fri, 16 Jan 2026 23:00:01 +0900 Subject: [PATCH 119/173] =?UTF-8?q?Refactor:=20checker=20=E9=83=A8?= =?UTF-8?q?=E5=88=86=E3=81=A7=E5=A4=9A=E3=81=8F=E3=81=AE=E5=87=BA=E5=8A=9B?= =?UTF-8?q?=E9=83=A8=E5=88=86=E3=82=92Printf=E3=81=A7=E3=81=BE=E3=81=A8?= =?UTF-8?q?=E3=82=81=E3=81=BE=E3=81=97=E3=81=9F=E3=80=82=20(#45)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: tokenize print change from write function to printf * fix: parser checker print change from write function to printf * fix: directory checker print change from write function to printf * delete: unneeded header file --------- Co-authored-by: jiku0730 --- src/checker/directory_checker.c | 38 +++++++++++++-------------------- src/checker/parser_checker.c | 4 ++-- src/checker/tokenize_checker.c | 15 ++++++------- 3 files changed, 23 insertions(+), 34 deletions(-) diff --git a/src/checker/directory_checker.c b/src/checker/directory_checker.c index e6eca0d..cad6fd9 100644 --- a/src/checker/directory_checker.c +++ b/src/checker/directory_checker.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/27 16:10:35 by surayama #+# #+# */ -/* Updated: 2025/12/01 03:20:46 by kjikuhar ### ########.fr */ +/* Updated: 2026/01/16 13:47:35 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -24,7 +24,7 @@ void directory_checker(char *input, t_shell_table *shell_table) (void)shell_table; if (ft_strncmp(input, "exit", 5) == 0) { - write(STDOUT_FILENO, "exit\n", 5); + printf("exit\n"); rl_clear_history(); free(input); exit(0); @@ -36,9 +36,7 @@ void directory_checker(char *input, t_shell_table *shell_table) static void test_entries(const char *input) { - ft_putstr_fd("\n=== Testing get_directory_entries ===\n", 1); - ft_putstr_fd("Path: ", 1); - ft_putendl_fd(input, 1); + printf("\n=== Testing get_directory_entries ===\nPath: %s\n", input); test_function(input, false, get_directory_entries, "\n--- Without hidden files ---\nEntries"); test_function(input, true, get_directory_entries, @@ -47,9 +45,7 @@ static void test_entries(const char *input) static void test_all_entries(const char *input) { - ft_putstr_fd("\n=== Testing get_directory_all_entries ===\n", 1); - ft_putstr_fd("Path: ", 1); - ft_putendl_fd(input, 1); + printf("\n=== Testing get_directory_all_entries ===\nPath: %s\n", input); test_function(input, false, get_directory_all_entries, "\n--- Without hidden files ---\nAll Entries (recursive)"); test_function(input, true, get_directory_all_entries, @@ -59,20 +55,20 @@ static void test_all_entries(const char *input) static void test_function(const char *input, bool include_hidden, int (*func)(const char *, bool, t_list **), const char *title) { - t_list *entries; - t_list *tmp; - int result; + t_list *entries; + t_list *tmp; + int result; + const char *error_msg; result = func(input, include_hidden, &entries); if (result != SUCCESS) { - ft_putstr_fd("Error: ", 1); + error_msg = "Unknown error"; if (result == NOT_FOUND) - ft_putendl_fd("Directory not found", 1); + error_msg = "Directory not found"; else if (result == NO_PERMISSION) - ft_putendl_fd("Permission denied", 1); - else - ft_putendl_fd("Unknown error", 1); + error_msg = "Permission denied"; + printf("Error: %s\n", error_msg); return ; } print_entries(entries, title); @@ -90,18 +86,14 @@ static void print_entries(t_list *entries, const char *title) t_list *current; int count; - ft_putstr_fd(title, 1); - ft_putstr_fd(":\n", 1); + printf("%s:\n", title); count = 0; current = entries; while (current) { - ft_putstr_fd(" - ", 1); - ft_putendl_fd((char *)current->content, 1); + printf(" - %s\n", (char *)current->content); current = current->next; count++; } - ft_putstr_fd("Total: ", 1); - ft_putnbr_fd(count, 1); - ft_putendl_fd(" entries", 1); + printf("Total: %d entries\n", count); } diff --git a/src/checker/parser_checker.c b/src/checker/parser_checker.c index 3278385..894678f 100644 --- a/src/checker/parser_checker.c +++ b/src/checker/parser_checker.c @@ -14,7 +14,7 @@ static void on_exit_token(t_list *token_list) { - write(STDOUT_FILENO, "exit\n", 5); + printf("exit\n"); ft_lstclear(&token_list, free); exit(0); } @@ -28,7 +28,7 @@ void parser_checker(char *input, t_shell_table *shell_table) token_list = tokenize(input); if (!token_list) { - write(STDOUT_FILENO, "Error: tokenize failed\n", 23); + printf("Error: tokenize failed\n"); return ; } if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) diff --git a/src/checker/tokenize_checker.c b/src/checker/tokenize_checker.c index a620832..abc2c1e 100644 --- a/src/checker/tokenize_checker.c +++ b/src/checker/tokenize_checker.c @@ -23,7 +23,7 @@ void tokenize_checker(char *input, t_shell_table *shell_table) token_list = tokenize(input); if (!token_list) { - write(STDOUT_FILENO, "Error: tokenize failed\n", 23); + ft_putstr_fd("Error: tokenize failed\n", STDOUT_FILENO); return ; } if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) @@ -36,18 +36,15 @@ static void print_tokens(t_list *token_list) { t_list *current; int index; + char *content; index = 0; current = token_list; - write(STDOUT_FILENO, "Tokens:\n", 8); + printf("Tokens:\n"); while (current) { - write(STDOUT_FILENO, "[", 1); - ft_putnbr_fd(index, STDOUT_FILENO); - write(STDOUT_FILENO, "] \"", 3); - if (current->content) - write(STDOUT_FILENO, current->content, ft_strlen(current->content)); - write(STDOUT_FILENO, "\"\n", 2); + content = current->content; + printf("[%d] \"%s\"\n", index, content); current = current->next; index++; } @@ -55,7 +52,7 @@ static void print_tokens(t_list *token_list) static void on_exit_token(t_list *token_list) { - write(STDOUT_FILENO, "exit\n", 5); + printf("exit\n"); ft_lstclear(&token_list, free); exit(0); } From e0fc66507e3d190dff42e61218e8d36c810cd8a1 Mon Sep 17 00:00:00 2001 From: jiku <134150757+jiku0730@users.noreply.github.com> Date: Fri, 16 Jan 2026 23:00:15 +0900 Subject: [PATCH 120/173] feat: make docs directory (#48) Co-authored-by: jiku0730 --- README.md => docs/README.md | 0 docs/parser.md | 17 +++++++++++++++++ 2 files changed, 17 insertions(+) rename README.md => docs/README.md (100%) create mode 100644 docs/parser.md diff --git a/README.md b/docs/README.md similarity index 100% rename from README.md rename to docs/README.md diff --git a/docs/parser.md b/docs/parser.md new file mode 100644 index 0000000..d2fd612 --- /dev/null +++ b/docs/parser.md @@ -0,0 +1,17 @@ +# parserの概要 +## 使用しているロジック +再帰降下法を使用している。これは、文法規則ごとに関数を作成し、入力を解析する手法である。各関数は特定の文法規則に対応し、その規則に従って入力を処理する。再帰降下法を利用するために、文法はEBNFで定義した。 + +## EBNFで定義したBASHの文法 +``` +pipeline ::= command ( '|' pipeline ) +command ::= simple_command | compound_command +simple_command ::= WORD ( argument ) +``` + +## 処理の流れ +1. **トークンの取得**: 字句解析器(lexer)からトークンを取得する。 +2. **文法規則の適用**: 現在のトークンに基づいて、対応する文法規則の関数を呼び出す。 +3. **再帰的解析**: 文法規則の関数内で、必要に応じて他の文法規則の関数を再帰的に呼び出す。 +4. **構文木の構築**: 解析が進むにつれて、構文木(AST)を構築する。 +5. **エラーハンドリング**: 解析中にエラーが発生した場合、適切なエラーメッセージを生成し、処理を中断する。 From 2c201b17982c56f1b0a6f619dbc0d630a01a361b Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Thu, 22 Jan 2026 20:49:14 +0900 Subject: [PATCH 121/173] =?UTF-8?q?=E2=91=A4=20cd=20=E3=82=B3=E3=83=9E?= =?UTF-8?q?=E3=83=B3=E3=83=89=E3=82=92=E5=AE=9F=E8=A3=85=E3=81=97=E3=81=9F?= =?UTF-8?q?=20(#41)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: echoコマンドを実装した * fix: norminette * fix: make出来ない不具合を修正 * feat: pwd * refactor: includeはheaderにまとめた * feat: export * add: Makefileにexportを追加 * 複数nodeの場合もそれぞれexportできるように * feat: unset * feat: cd * fix: make * fix: Makefile * refactor: cd * fix: cdで絶対パスを呼び出すように * fix: /binのときにエラーが出てしまう不具合を修正 * cd --------- Co-authored-by: jiku <134150757+jiku0730@users.noreply.github.com> --- Makefile | 2 + includes/builtin.h | 2 + includes/path.h | 8 +++ src/builtin/cd.c | 99 ++++++++++++++++++++++++++++++++ src/component/path/append_path.c | 37 ++++++++++++ src/component/path/to_absolute.c | 41 +++++-------- src/main.c | 2 +- 7 files changed, 164 insertions(+), 27 deletions(-) create mode 100644 src/builtin/cd.c create mode 100644 src/component/path/append_path.c diff --git a/Makefile b/Makefile index 770b395..1d7a3b6 100644 --- a/Makefile +++ b/Makefile @@ -60,6 +60,7 @@ SRCS_MAND := src/main.c \ src/builtin/export.c \ src/builtin/pwd.c \ src/builtin/unset.c \ + src/builtin/cd.c \ src/prompt/prompt.c \ src/callback/on_input.c \ src/checker/builtin_checker.c \ @@ -105,6 +106,7 @@ SRCS_MAND := src/main.c \ src/component/directory/get_directory_entries.c \ src/component/directory/get_directory_all_entries.c \ src/component/path/to_absolute.c \ + src/component/path/append_path.c \ SRCS_BONUS := diff --git a/includes/builtin.h b/includes/builtin.h index 522da83..038c79f 100644 --- a/includes/builtin.h +++ b/includes/builtin.h @@ -13,6 +13,7 @@ #ifndef BUILTIN_H # define BUILTIN_H +# include "path.h" # include "shell_table.h" # include # include @@ -22,5 +23,6 @@ int echo(t_list *argv, t_shell_table *shell_table); int pwd(t_list *argv, t_shell_table *shell_table); int export(t_list *argv, t_shell_table *shell_table); int unset(t_list *argv, t_shell_table *shell_table); +int cd(t_list *argv, t_shell_table *shell_table); #endif diff --git a/includes/path.h b/includes/path.h index ea64a50..5daf333 100644 --- a/includes/path.h +++ b/includes/path.h @@ -13,6 +13,14 @@ #ifndef PATH_H # define PATH_H +# include "libft.h" +# include +# include +# include +# include + char *to_absolute(const char *path); +t_list *append_path(t_list **dest, const char *content); +t_list *append_path_list(t_list **dest, const char *content); #endif diff --git a/src/builtin/cd.c b/src/builtin/cd.c new file mode 100644 index 0000000..4bc5e12 --- /dev/null +++ b/src/builtin/cd.c @@ -0,0 +1,99 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* cd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/12/01 00:48:09 by surayama #+# #+# */ +/* Updated: 2026/01/22 19:50:36 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include + +static int by_too_many_arguments_error(void); +static int by_move_to_home(t_shell_table *shell_table); +static int by_move_to_oldpwd(t_shell_table *shell_table); +static int move_to_path(const char *absolute_path, t_shell_table *shell_table); + +int cd(t_list *argv, t_shell_table *shell_table) +{ + int argc; + + argc = ft_lstsize(argv); + if (argc > 2) + return (by_too_many_arguments_error()); + if (argc == 1) + return (by_move_to_home(shell_table)); + if (argc == 2 && argv->next->content) + { + if (ft_strncmp((char *)argv->next->content, "~", 2) == 0) + return (by_move_to_home(shell_table)); + if (ft_strncmp((char *)argv->next->content, "-", 2) == 0) + return (by_move_to_oldpwd(shell_table)); + return (move_to_path(to_absolute((char *)argv->next->content), + shell_table)); + } + return (SUCCESS); +} + +static int by_too_many_arguments_error(void) +{ + ft_putstr_fd("Error: cd too many arguments\n", STDERR_FILENO); + return (1); +} + +static int by_move_to_home(t_shell_table *shell_table) +{ + char *home; + + home = st_search(shell_table, "HOME"); + if (!home) + { + ft_putstr_fd("Error: cd HOME not set\n", STDERR_FILENO); + return (1); + } + return (move_to_path(home, shell_table)); +} + +static int by_move_to_oldpwd(t_shell_table *shell_table) +{ + char *oldpwd; + + oldpwd = st_search(shell_table, "OLDPWD"); + if (!oldpwd) + { + ft_putstr_fd("Error: cd OLDPWD not set\n", STDERR_FILENO); + return (1); + } + return (move_to_path(oldpwd, shell_table)); +} + +static int move_to_path(const char *absolute_path, t_shell_table *shell_table) +{ + char *old_pwd; + char *new_pwd; + int has_insert_error; + + old_pwd = getcwd(NULL, 0); + if (!old_pwd) + return (1); + if (chdir(absolute_path) == -1) + { + perror("cd"); + free(old_pwd); + return (1); + } + new_pwd = getcwd(NULL, 0); + if (!new_pwd) + { + free(old_pwd); + return (1); + } + has_insert_error = st_insert(shell_table, "OLDPWD", old_pwd, true) == 0 + || st_insert(shell_table, "PWD", new_pwd, true) == 0; + free(old_pwd); + free(new_pwd); + return (has_insert_error); +} diff --git a/src/component/path/append_path.c b/src/component/path/append_path.c new file mode 100644 index 0000000..e70e9df --- /dev/null +++ b/src/component/path/append_path.c @@ -0,0 +1,37 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* append_path_list.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/12/04 15:18:33 by surayama #+# #+# */ +/* Updated: 2025/12/04 16:57:19 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "path.h" + +t_list *append_path(t_list **dest, const char *content) +{ + char *content_copy; + + if (!dest || !content) + return (NULL); + if (ft_strncmp(content, "..", 3) == 0) + { + if (*dest) + ft_lstdel_back(dest, free); + return (*dest); + } + else if (ft_strncmp(content, ".", 2) == 0) + return (*dest); + content_copy = ft_strdup(content); + if (!content_copy) + { + ft_lstclear(dest, free); + return (NULL); + } + ft_lstadd_back(dest, ft_lstnew(content_copy)); + return (*dest); +} diff --git a/src/component/path/to_absolute.c b/src/component/path/to_absolute.c index 89ccf5c..03d171b 100644 --- a/src/component/path/to_absolute.c +++ b/src/component/path/to_absolute.c @@ -10,15 +10,11 @@ /* */ /* ************************************************************************** */ -#include "libft.h" -#include -#include -#include -#include +#include "path.h" static t_list *init_resolved_path(bool is_head_absolute, t_list **path_list); static t_list *split_path_to_list(const char *path); -static t_list *append_path(char *segment, t_list *resolved_path); +static void consume_head(t_list **path_list); static char *list_to_path(t_list *resolved_path); char *to_absolute(const char *path) @@ -39,7 +35,7 @@ char *to_absolute(const char *path) current = path_list; while (current) { - resolved_path = append_path((char *)current->content, resolved_path); + resolved_path = append_path(&resolved_path, (char *)current->content); current = current->next; } ft_lstclear(&path_list, free); @@ -52,7 +48,6 @@ static t_list *init_resolved_path(bool is_head_absolute, t_list **path_list) { char *cwd; t_list *resolved_path; - t_list *temp; resolved_path = NULL; if (is_head_absolute) @@ -62,10 +57,9 @@ static t_list *init_resolved_path(bool is_head_absolute, t_list **path_list) if (ft_strncmp((char *)(*path_list)->content, ".", 2) == 0 || ft_strncmp((char *)(*path_list)->content, "..", 3) == 0) break ; - ft_lstadd_back(&resolved_path, ft_lstnew((*path_list)->content)); - temp = *path_list; - *path_list = (*path_list)->next; - ft_lstdelone(temp, free); + if (!append_path(&resolved_path, (char *)(*path_list)->content)) + return (NULL); + consume_head(path_list); } return (resolved_path); } @@ -77,6 +71,15 @@ static t_list *init_resolved_path(bool is_head_absolute, t_list **path_list) return (resolved_path); } +static void consume_head(t_list **path_list) +{ + t_list *temp; + + temp = *path_list; + *path_list = (*path_list)->next; + ft_lstdelone(temp, free); +} + static t_list *split_path_to_list(const char *path) { char **segments; @@ -99,20 +102,6 @@ static t_list *split_path_to_list(const char *path) return (list); } -static t_list *append_path(char *segment, t_list *resolved_path) -{ - if (ft_strncmp(segment, "..", 3) == 0) - { - if (resolved_path) - ft_lstdel_back(&resolved_path, free); - } - else if (ft_strncmp(segment, ".", 2) == 0) - return (resolved_path); - else - ft_lstadd_back(&resolved_path, ft_lstnew(ft_strdup(segment))); - return (resolved_path); -} - static char *list_to_path(t_list *resolved_path) { t_list *current; diff --git a/src/main.c b/src/main.c index cc08a7f..2f5a7b1 100644 --- a/src/main.c +++ b/src/main.c @@ -6,7 +6,7 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:13:47 by kjikuhar #+# #+# */ -/* Updated: 2025/11/27 16:16:45 by surayama ### ########.fr */ +/* Updated: 2025/12/04 17:34:40 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ From f7a4651d0c3f790dc25f600f024fb1ae99b6b535 Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Sun, 1 Feb 2026 21:39:52 +0900 Subject: [PATCH 122/173] =?UTF-8?q?=E3=83=AA=E3=82=B9=E3=83=88=E3=81=AE?= =?UTF-8?q?=E8=A6=81=E7=B4=A0=E3=82=92=E6=96=B0=E3=83=AA=E3=82=B9=E3=83=88?= =?UTF-8?q?=E3=81=A7=E3=82=B9=E3=83=AF=E3=83=83=E3=83=97=E3=81=A7=E3=81=8D?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=20(#50)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libft/Makefile | 5 +++-- libft/libft.h | 5 +++-- libft/list/ft_lstreplace.c | 28 ++++++++++++++++++++++++++++ src/component/path/append_path.c | 6 +++--- 4 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 libft/list/ft_lstreplace.c diff --git a/libft/Makefile b/libft/Makefile index 1f4ea7c..c3c4463 100644 --- a/libft/Makefile +++ b/libft/Makefile @@ -3,10 +3,10 @@ # ::: :::::::: # # Makefile :+: :+: :+: # # +:+ +:+ +:+ # -# By: kjikuhar +#+ +:+ +#+ # +# By: surayama +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/04/04 16:00:02 by kjikuhar #+# #+# # -# Updated: 2026/01/16 13:59:51 by kjikuhar ### ########.fr # +# Updated: 2026/02/01 21:36:07 by surayama ### ########.fr # # # # **************************************************************************** # @@ -34,6 +34,7 @@ SRCS = conversion/ft_atoi.c \ list/ft_lstmap.c \ list/ft_lstnew.c \ list/ft_lstsize.c \ + list/ft_lstreplace.c \ memory/ft_bzero.c \ memory/ft_calloc.c \ memory/ft_memchr.c \ diff --git a/libft/libft.h b/libft/libft.h index 9038dd6..538555a 100644 --- a/libft/libft.h +++ b/libft/libft.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* libft.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ +/* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/25 14:55:13 by kjikuhar #+# #+# */ -/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ +/* Updated: 2026/02/01 21:36:07 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -49,6 +49,7 @@ void ft_lstclear(t_list **lst, void (*del)(void *)); void ft_lstiter(t_list *lst, void (*f)(void *)); t_list *ft_lstmap(t_list *lst, void *(*f)(void *), void (*del)(void *)); +void ft_lstreplace(t_list *prev, t_list *target, t_list *new); // memory void ft_bzero(void *s, size_t n); diff --git a/libft/list/ft_lstreplace.c b/libft/list/ft_lstreplace.c new file mode 100644 index 0000000..c4e446d --- /dev/null +++ b/libft/list/ft_lstreplace.c @@ -0,0 +1,28 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstreplace.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/02/01 21:36:30 by surayama #+# #+# */ +/* Updated: 2026/02/01 21:36:37 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_lstreplace(t_list *prev, t_list *target, t_list *new) +{ + t_list *next_node; + t_list *last_new; + + if (!prev || !target || !new) + return ; + next_node = target->next; + last_new = ft_lstlast(new); + last_new->next = next_node; + free(target->content); + free(target); + prev->next = new; +} diff --git a/src/component/path/append_path.c b/src/component/path/append_path.c index e70e9df..43f30d2 100644 --- a/src/component/path/append_path.c +++ b/src/component/path/append_path.c @@ -1,12 +1,12 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* append_path_list.c :+: :+: :+: */ +/* append_path.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/12/04 15:18:33 by surayama #+# #+# */ -/* Updated: 2025/12/04 16:57:19 by surayama ### ########.fr */ +/* Created: 2025/12/01 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/01/22 21:26:48 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ From e50e3ef497b3601a587751e1905cebc001f20525 Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Thu, 5 Feb 2026 19:27:42 +0900 Subject: [PATCH 123/173] =?UTF-8?q?tokenize=E3=82=92=E5=85=A8=E3=81=A6?= =?UTF-8?q?=E3=81=AE=E6=BC=94=E7=AE=97=E5=AD=90=E5=8D=98=E4=BD=8D=E3=81=A7?= =?UTF-8?q?=E5=88=86=E5=89=B2=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= =?UTF-8?q?=20(#49)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: ()の定義をoperatorから分割するように * fix: あらゆる演算子に対応するように * add: LESSGREAT * refactor: 残っている意図が伝わる条件に * refactor: operator * chore: resultを削除 * if文の定義をまとめた * fix: if * fix: private tokenize * delete: internal header --- Dockerfile | 2 +- Makefile | 7 +- includes/tokenize.h | 42 +--------- src/tokenize/is_specific.c | 53 ++++++++---- src/tokenize/state/in_double_quote.c | 4 +- src/tokenize/state/in_normal.c | 56 +++---------- src/tokenize/state/in_normal/by_last.c | 22 +++++ src/tokenize/state/in_normal/by_operator.c | 21 +++++ src/tokenize/state/in_normal/by_parenthesis.c | 23 +++++ src/tokenize/state/in_normal/by_quote.c | 23 +++++ src/tokenize/state/in_normal/by_space.c | 22 +++++ src/tokenize/state/in_operator.c | 12 +-- src/tokenize/state/in_single_quote.c | 4 +- src/tokenize/state/on_error.c | 4 +- src/tokenize/state/on_success.c | 4 +- src/tokenize/store/add_buffer.c | 4 +- src/tokenize/store/free_store.c | 4 +- src/tokenize/store/push_token.c | 84 +++++++++++++++---- src/tokenize/tokenize.c | 2 +- src/tokenize/tokenize_private.h | 58 +++++++++++++ 20 files changed, 314 insertions(+), 137 deletions(-) create mode 100644 src/tokenize/state/in_normal/by_last.c create mode 100644 src/tokenize/state/in_normal/by_operator.c create mode 100644 src/tokenize/state/in_normal/by_parenthesis.c create mode 100644 src/tokenize/state/in_normal/by_quote.c create mode 100644 src/tokenize/state/in_normal/by_space.c create mode 100644 src/tokenize/tokenize_private.h diff --git a/Dockerfile b/Dockerfile index bd0ad5e..688e704 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,4 +15,4 @@ RUN apt-get update && \ rm -rf /var/lib/apt/lists/* RUN python3 -m pip install --upgrade pip && \ - python3 -m pip install norminette + python3 -m pip install norminette==3.3.55 diff --git a/Makefile b/Makefile index 1d7a3b6..ca93ebb 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # By: surayama +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/05/18 21:11:39 by kjikuhar #+# #+# # -# Updated: 2025/12/06 16:21:35 by surayama ### ########.fr # +# Updated: 2026/01/17 02:33:17 by surayama ### ########.fr # # # # **************************************************************************** # @@ -73,6 +73,11 @@ SRCS_MAND := src/main.c \ src/tokenize/tokenize.c \ src/tokenize/is_specific.c \ src/tokenize/state/in_normal.c \ + src/tokenize/state/in_normal/by_last.c \ + src/tokenize/state/in_normal/by_space.c \ + src/tokenize/state/in_normal/by_operator.c \ + src/tokenize/state/in_normal/by_quote.c \ + src/tokenize/state/in_normal/by_parenthesis.c \ src/tokenize/state/in_double_quote.c \ src/tokenize/state/in_single_quote.c \ src/tokenize/state/in_operator.c \ diff --git a/includes/tokenize.h b/includes/tokenize.h index cc46fb0..ade322e 100644 --- a/includes/tokenize.h +++ b/includes/tokenize.h @@ -3,56 +3,18 @@ /* ::: :::::::: */ /* tokenize.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ +/* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/10 17:09:25 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:51 by kjikuhar ### ########.fr */ +/* Updated: 2026/02/05 00:00:00 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef TOKENIZE_H # define TOKENIZE_H -# include "constants.h" # include "libft.h" -# include - -typedef enum e_token_state -{ - IN_NORMAL, - IN_DOUBLE_QUOTE, - IN_SINGLE_QUOTE, - IN_OPERATOR, - ON_SUCCESS, - ON_ERROR, -} t_token_state; - -typedef struct s_token_store -{ - t_list *tokens; - t_list *buffer; -} t_token_store; t_list *tokenize(char *input); -// is specific -bool is_quote(char c); -bool is_operator(char c); - -// store -int push_token(t_token_store *store); -int add_buffer(t_token_store *store, char c); -void free_store(t_token_store *store); - -// state handler -void in_normal(t_token_store *store, t_token_state *state, char current); -void in_double_quote(t_token_store *store, t_token_state *state, - char current); -void in_single_quote(t_token_store *store, t_token_state *state, - char current); -void in_operator(t_token_store *store, t_token_state *state, - char current); -t_list *on_success(t_token_store *store, char *input); -t_list *on_error(t_token_store *store, char *input); - #endif diff --git a/src/tokenize/is_specific.c b/src/tokenize/is_specific.c index f7c1f8a..004b63b 100644 --- a/src/tokenize/is_specific.c +++ b/src/tokenize/is_specific.c @@ -3,37 +3,58 @@ /* ::: :::::::: */ /* is_specific.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ +/* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/13 01:15:00 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ +/* Updated: 2026/02/05 00:00:00 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ -#include "tokenize.h" +#include "tokenize_private.h" bool is_quote(char c) { - if (c == '"') - return (true); - if (c == '\'') + if (c == '"' || c == '\'') return (true); return (false); } -bool is_operator(char c) +bool is_operator_char(char c) { - if (c == '&') - return (true); - if (c == '|') - return (true); - if (c == '<') - return (true); - if (c == '>') + if (c == '&' || c == '|' || c == '<' || c == '>') return (true); - if (c == '(') + return (false); +} + +size_t operator_length(const char *str) +{ + if (ft_strncmp(str, "<<<", 3) == 0 || \ + ft_strncmp(str, "<<-", 3) == 0) + return (3); + if (ft_strncmp(str, "&&", 2) == 0 || \ + ft_strncmp(str, "||", 2) == 0 || \ + ft_strncmp(str, "<<", 2) == 0 || \ + ft_strncmp(str, ">>", 2) == 0 || \ + ft_strncmp(str, ">&", 2) == 0 || \ + ft_strncmp(str, "<&", 2) == 0 || \ + ft_strncmp(str, ">|", 2) == 0 || \ + ft_strncmp(str, "<>", 2) == 0) + return (2); + if (is_operator_char(str[0])) + return (1); + return (0); +} + +bool is_operator(const char *str) +{ + if (operator_length(str) > 0) return (true); - if (c == ')') + return (false); +} + +bool is_parenthesis(char c) +{ + if (c == '(' || c == ')') return (true); return (false); } diff --git a/src/tokenize/state/in_double_quote.c b/src/tokenize/state/in_double_quote.c index 84ddc52..20494f5 100644 --- a/src/tokenize/state/in_double_quote.c +++ b/src/tokenize/state/in_double_quote.c @@ -6,11 +6,11 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/12/06 00:00:00 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ +/* Updated: 2026/02/05 00:00:00 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include "tokenize.h" +#include "../tokenize_private.h" void in_double_quote(t_token_store *store, t_token_state *state, char current) diff --git a/src/tokenize/state/in_normal.c b/src/tokenize/state/in_normal.c index 24b80e0..31503fd 100644 --- a/src/tokenize/state/in_normal.c +++ b/src/tokenize/state/in_normal.c @@ -6,17 +6,18 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/13 00:30:00 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ +/* Updated: 2026/02/05 00:00:00 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ -#include "tokenize.h" +#include "../tokenize_private.h" -static void by_last(t_token_store *store, t_token_state *state, char current); -static void by_space(t_token_store *store, t_token_state *state, char current); -static void by_quote(t_token_store *store, t_token_state *state, char current); -static void by_operator(t_token_store *store, t_token_state *state, - char current); +void by_last(t_token_store *store, t_token_state *state, char current); +void by_space(t_token_store *store, t_token_state *state, char current); +void by_quote(t_token_store *store, t_token_state *state, char current); +void by_operator(t_token_store *store, t_token_state *state, char current); +void by_parenthesis(t_token_store *store, t_token_state *state, + char current); void in_normal(t_token_store *store, t_token_state *state, char current) { @@ -24,47 +25,12 @@ void in_normal(t_token_store *store, t_token_state *state, char current) by_last(store, state, current); else if (ft_isspace(current)) by_space(store, state, current); - else if (is_operator(current)) + else if (is_parenthesis(current)) + by_parenthesis(store, state, current); + else if (is_operator_char(current)) by_operator(store, state, current); else if (is_quote(current)) by_quote(store, state, current); else if (add_buffer(store, current) == ERROR) *state = ON_ERROR; } - -static void by_last(t_token_store *store, t_token_state *state, char current) -{ - (void)current; - if (push_token(store) == ERROR) - *state = ON_ERROR; - else - *state = ON_SUCCESS; -} - -static void by_space(t_token_store *store, t_token_state *state, char current) -{ - (void)current; - if (push_token(store) == ERROR) - *state = ON_ERROR; - else - *state = IN_NORMAL; -} - -static void by_operator(t_token_store *store, t_token_state *state, - char current) -{ - if (push_token(store) == ERROR || add_buffer(store, current) == ERROR) - *state = ON_ERROR; - else - *state = IN_OPERATOR; -} - -static void by_quote(t_token_store *store, t_token_state *state, char current) -{ - if (add_buffer(store, current) == ERROR) - *state = ON_ERROR; - else if (current == '"') - *state = IN_DOUBLE_QUOTE; - else if (current == '\'') - *state = IN_SINGLE_QUOTE; -} diff --git a/src/tokenize/state/in_normal/by_last.c b/src/tokenize/state/in_normal/by_last.c new file mode 100644 index 0000000..d9f9e8b --- /dev/null +++ b/src/tokenize/state/in_normal/by_last.c @@ -0,0 +1,22 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* by_last.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/01/17 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/02/05 00:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../../tokenize_private.h" + +void by_last(t_token_store *store, t_token_state *state, char current) +{ + (void)current; + if (push_token(store) == ERROR) + *state = ON_ERROR; + else + *state = ON_SUCCESS; +} diff --git a/src/tokenize/state/in_normal/by_operator.c b/src/tokenize/state/in_normal/by_operator.c new file mode 100644 index 0000000..f6a3c5a --- /dev/null +++ b/src/tokenize/state/in_normal/by_operator.c @@ -0,0 +1,21 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* by_operator.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/01/17 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/02/05 00:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../../tokenize_private.h" + +void by_operator(t_token_store *store, t_token_state *state, char current) +{ + if (push_token(store) == ERROR || add_buffer(store, current) == ERROR) + *state = ON_ERROR; + else + *state = IN_OPERATOR; +} diff --git a/src/tokenize/state/in_normal/by_parenthesis.c b/src/tokenize/state/in_normal/by_parenthesis.c new file mode 100644 index 0000000..d5591e1 --- /dev/null +++ b/src/tokenize/state/in_normal/by_parenthesis.c @@ -0,0 +1,23 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* by_parenthesis.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/01/17 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/02/05 00:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../../tokenize_private.h" + +void by_parenthesis(t_token_store *store, t_token_state *state, + char current) +{ + if (push_token(store) == ERROR || add_buffer(store, current) == ERROR + || push_token(store) == ERROR) + *state = ON_ERROR; + else + *state = IN_NORMAL; +} diff --git a/src/tokenize/state/in_normal/by_quote.c b/src/tokenize/state/in_normal/by_quote.c new file mode 100644 index 0000000..83f36d7 --- /dev/null +++ b/src/tokenize/state/in_normal/by_quote.c @@ -0,0 +1,23 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* by_quote.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/01/17 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/02/05 00:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../../tokenize_private.h" + +void by_quote(t_token_store *store, t_token_state *state, char current) +{ + if (add_buffer(store, current) == ERROR) + *state = ON_ERROR; + else if (current == '"') + *state = IN_DOUBLE_QUOTE; + else if (current == '\'') + *state = IN_SINGLE_QUOTE; +} diff --git a/src/tokenize/state/in_normal/by_space.c b/src/tokenize/state/in_normal/by_space.c new file mode 100644 index 0000000..82e6b86 --- /dev/null +++ b/src/tokenize/state/in_normal/by_space.c @@ -0,0 +1,22 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* by_space.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/01/17 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/02/05 00:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../../tokenize_private.h" + +void by_space(t_token_store *store, t_token_state *state, char current) +{ + (void)current; + if (push_token(store) == ERROR) + *state = ON_ERROR; + else + *state = IN_NORMAL; +} diff --git a/src/tokenize/state/in_operator.c b/src/tokenize/state/in_operator.c index f1b2371..f862d90 100644 --- a/src/tokenize/state/in_operator.c +++ b/src/tokenize/state/in_operator.c @@ -6,11 +6,11 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/13 00:30:00 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ +/* Updated: 2026/02/05 00:00:00 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include "tokenize.h" +#include "../tokenize_private.h" static void by_operator(t_token_store *store, t_token_state *state, char current); @@ -20,7 +20,9 @@ void in_operator(t_token_store *store, t_token_state *state, char current) { if (current == '\0' && push_token(store)) *state = ON_SUCCESS; - else if (is_operator(current)) + else if (is_parenthesis(current)) + by_normal(store, state, current); + else if (is_operator_char(current)) by_operator(store, state, current); else by_normal(store, state, current); @@ -31,10 +33,8 @@ static void by_operator(t_token_store *store, t_token_state *state, { if (add_buffer(store, current) == ERROR) *state = ON_ERROR; - else if (push_token(store) == ERROR) - *state = ON_ERROR; else - *state = IN_NORMAL; + *state = IN_OPERATOR; } static void by_normal(t_token_store *store, t_token_state *state, char current) diff --git a/src/tokenize/state/in_single_quote.c b/src/tokenize/state/in_single_quote.c index b79c16c..ad02a2e 100644 --- a/src/tokenize/state/in_single_quote.c +++ b/src/tokenize/state/in_single_quote.c @@ -6,11 +6,11 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/12/06 00:00:00 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ +/* Updated: 2026/02/05 00:00:00 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include "tokenize.h" +#include "../tokenize_private.h" void in_single_quote(t_token_store *store, t_token_state *state, char current) diff --git a/src/tokenize/state/on_error.c b/src/tokenize/state/on_error.c index 09814eb..d481a83 100644 --- a/src/tokenize/state/on_error.c +++ b/src/tokenize/state/on_error.c @@ -6,11 +6,11 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/13 00:35:00 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ +/* Updated: 2026/02/05 00:00:00 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include "tokenize.h" +#include "../tokenize_private.h" t_list *on_error(t_token_store *store, char *input) { diff --git a/src/tokenize/state/on_success.c b/src/tokenize/state/on_success.c index 9428b17..151da46 100644 --- a/src/tokenize/state/on_success.c +++ b/src/tokenize/state/on_success.c @@ -6,11 +6,11 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/13 00:35:00 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ +/* Updated: 2026/02/05 00:00:00 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include "tokenize.h" +#include "../tokenize_private.h" t_list *on_success(t_token_store *store, char *input) { diff --git a/src/tokenize/store/add_buffer.c b/src/tokenize/store/add_buffer.c index 80622cb..60eea50 100644 --- a/src/tokenize/store/add_buffer.c +++ b/src/tokenize/store/add_buffer.c @@ -6,11 +6,11 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/17 00:00:00 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ +/* Updated: 2026/02/05 00:00:00 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include "tokenize.h" +#include "../tokenize_private.h" int add_buffer(t_token_store *store, char c) { diff --git a/src/tokenize/store/free_store.c b/src/tokenize/store/free_store.c index 6b6a2b5..5ddf393 100644 --- a/src/tokenize/store/free_store.c +++ b/src/tokenize/store/free_store.c @@ -6,11 +6,11 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/16 23:57:51 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ +/* Updated: 2026/02/05 00:00:00 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ -#include "tokenize.h" +#include "../tokenize_private.h" void free_store(t_token_store *store) { diff --git a/src/tokenize/store/push_token.c b/src/tokenize/store/push_token.c index 5b9707c..61736d1 100644 --- a/src/tokenize/store/push_token.c +++ b/src/tokenize/store/push_token.c @@ -3,14 +3,14 @@ /* ::: :::::::: */ /* push_token.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ +/* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/12 22:13:34 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ +/* Updated: 2026/02/05 00:00:00 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ -#include "tokenize.h" +#include "../tokenize_private.h" static char *build_token_from_buffer(t_list *buffer) { @@ -37,23 +37,37 @@ static char *build_token_from_buffer(t_list *buffer) return (token); } -static bool is_buffer_empty(const t_list *buffer) +static char *consume_operator_token(char **token_ptr) { - return (!buffer); + char *initial_token; + char *operator_token; + char *remained_token; + size_t operator_token_length; + + initial_token = *token_ptr; + operator_token_length = operator_length(initial_token); + operator_token = ft_substr(initial_token, 0, operator_token_length); + remained_token = NULL; + if (!operator_token) + return (NULL); + if (ft_strlen(initial_token) - operator_token_length > 0) + { + remained_token = ft_strdup(initial_token + operator_token_length); + if (!remained_token) + { + free(operator_token); + operator_token = NULL; + } + } + free(initial_token); + *token_ptr = remained_token; + return (operator_token); } -int push_token(t_token_store *store) +static int add_back_token(char *token, t_token_store *store) { - char *token; t_list *new_node; - if (!store) - return (ERROR); - if (is_buffer_empty(store->buffer)) - return (SUCCESS); - token = build_token_from_buffer(store->buffer); - if (!token) - return (ERROR); new_node = ft_lstnew(token); if (!new_node) { @@ -61,7 +75,47 @@ int push_token(t_token_store *store) return (ERROR); } ft_lstadd_back(&(store->tokens), new_node); + return (SUCCESS); +} + +static int push_operator_tokens(t_token_store *store, char *token) +{ + char *operator_token; + + while (token) + { + operator_token = consume_operator_token(&token); + if (!operator_token) + { + free(token); + return (ERROR); + } + if (add_back_token(operator_token, store) == ERROR) + { + free(token); + return (ERROR); + } + } + return (SUCCESS); +} + +int push_token(t_token_store *store) +{ + char *token; + int result; + + if (!store) + return (ERROR); + if (!store->buffer) + return (SUCCESS); + token = build_token_from_buffer(store->buffer); + if (!token) + return (ERROR); + if (is_operator(token)) + result = push_operator_tokens(store, token); + else + result = add_back_token(token, store); ft_lstclear(&(store->buffer), free); store->buffer = NULL; - return (SUCCESS); + return (result); } diff --git a/src/tokenize/tokenize.c b/src/tokenize/tokenize.c index 31f5a40..6972030 100644 --- a/src/tokenize/tokenize.c +++ b/src/tokenize/tokenize.c @@ -10,7 +10,7 @@ /* */ /* ************************************************************************** */ -#include "tokenize.h" +#include "tokenize_private.h" static void initialize(t_token_store *store, t_token_state *state, char **current, char *input); diff --git a/src/tokenize/tokenize_private.h b/src/tokenize/tokenize_private.h new file mode 100644 index 0000000..bf3a4aa --- /dev/null +++ b/src/tokenize/tokenize_private.h @@ -0,0 +1,58 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* tokenize_private.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/02/05 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/02/05 00:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef TOKENIZE_PRIVATE_H +# define TOKENIZE_PRIVATE_H + +# include "tokenize.h" +# include "constants.h" + +typedef enum e_token_state +{ + IN_NORMAL, + IN_DOUBLE_QUOTE, + IN_SINGLE_QUOTE, + IN_OPERATOR, + ON_SUCCESS, + ON_ERROR, +} t_token_state; + +typedef struct s_token_store +{ + t_list *tokens; + t_list *buffer; +} t_token_store; + +// is specific +bool is_quote(char c); +bool is_operator_char(char c); +bool is_operator(const char *str); +size_t operator_length(const char *str); +bool is_parenthesis(char c); + +// store +int push_token(t_token_store *store); +int add_buffer(t_token_store *store, char c); +void free_store(t_token_store *store); + +// state handler +void in_normal(t_token_store *store, t_token_state *state, char current); +void in_double_quote(t_token_store *store, t_token_state *state, + char current); +void in_single_quote(t_token_store *store, t_token_state *state, + char current); +void in_operator(t_token_store *store, t_token_state *state, + char current); +t_list *on_success(t_token_store *store, char *input); +t_list *on_error(t_token_store *store, char *input); + +#endif From 1fd9fd73ea09732a012723c8b40e537b46a9e240 Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Fri, 13 Feb 2026 23:34:54 +0900 Subject: [PATCH 124/173] =?UTF-8?q?=E3=82=AF=E3=82=A9=E3=83=BC=E3=83=88?= =?UTF-8?q?=E3=82=92=E5=89=8A=E9=99=A4=E3=81=99=E3=82=8B=E3=82=B3=E3=83=B3?= =?UTF-8?q?=E3=83=9D=E3=83=BC=E3=83=8D=E3=83=B3=E3=83=88=E3=81=AE=E5=AE=9F?= =?UTF-8?q?=E8=A3=85=20(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * tokenizeを全ての演算子単位で分割するように (#49) * fix: ()の定義をoperatorから分割するように * fix: あらゆる演算子に対応するように * add: LESSGREAT * refactor: 残っている意図が伝わる条件に * refactor: operator * chore: resultを削除 * if文の定義をまとめた * fix: if * fix: private tokenize * delete: internal header * fix: norminette * add: is_quote_char * rename: removed_str_length * fix: is_quote * fix: excluded_quote_length --- Makefile | 2 + includes/minishell.h | 2 + includes/remove_quotes.h | 20 +++++ src/checker/remove_quotes_checker.c | 68 ++++++++++++++++ src/component/remove_quotes/remove_quotes.c | 88 +++++++++++++++++++++ src/main.c | 2 +- 6 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 includes/remove_quotes.h create mode 100644 src/checker/remove_quotes_checker.c create mode 100644 src/component/remove_quotes/remove_quotes.c diff --git a/Makefile b/Makefile index ca93ebb..5b1228f 100644 --- a/Makefile +++ b/Makefile @@ -70,6 +70,7 @@ SRCS_MAND := src/main.c \ src/checker/parser_checker.c \ src/checker/path_checker.c \ src/checker/directory_checker.c \ + src/checker/remove_quotes_checker.c \ src/tokenize/tokenize.c \ src/tokenize/is_specific.c \ src/tokenize/state/in_normal.c \ @@ -112,6 +113,7 @@ SRCS_MAND := src/main.c \ src/component/directory/get_directory_all_entries.c \ src/component/path/to_absolute.c \ src/component/path/append_path.c \ + src/component/remove_quotes/remove_quotes.c \ SRCS_BONUS := diff --git a/includes/minishell.h b/includes/minishell.h index eeb7bcf..4cb35d4 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -18,6 +18,7 @@ # include "libft.h" # include "parser.h" # include "prompt.h" +# include "remove_quotes.h" # include "shell_table.h" # include "tokenize.h" @@ -32,5 +33,6 @@ void parser_checker(char *input, t_shell_table *shell_table); void directory_checker(char *input, t_shell_table *shell_table); void path_checker(char *input, t_shell_table *shell_table); void builtin_checker(char *input, t_shell_table *shell_table); +void remove_quotes_checker(char *input, t_shell_table *shell_table); #endif diff --git a/includes/remove_quotes.h b/includes/remove_quotes.h new file mode 100644 index 0000000..fa0b7cf --- /dev/null +++ b/includes/remove_quotes.h @@ -0,0 +1,20 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* remove_quote.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/02/07 00:50:48 by surayama #+# #+# */ +/* Updated: 2026/02/07 00:51:19 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef REMOVE_QUOTES_H +# define REMOVE_QUOTES_H + +# include "libft.h" + +t_list *remove_quotes(t_list *tokens); + +#endif diff --git a/src/checker/remove_quotes_checker.c b/src/checker/remove_quotes_checker.c new file mode 100644 index 0000000..91fb2ae --- /dev/null +++ b/src/checker/remove_quotes_checker.c @@ -0,0 +1,68 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* remove_quote_checker.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/02/07 00:52:00 by surayama #+# #+# */ +/* Updated: 2026/02/07 00:52:01 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +static void on_exit_token(t_list *token_list); +static void print_tokens(t_list *token_list, const char *title); + +void remove_quotes_checker(char *input, t_shell_table *shell_table) +{ + t_list *token_list; + t_list *result; + + (void)shell_table; + token_list = tokenize(input); + if (!token_list) + { + ft_putstr_fd("Error: tokenize failed\n", STDOUT_FILENO); + return ; + } + if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) + on_exit_token(token_list); + print_tokens(token_list, "Before remove_quote"); + result = remove_quotes(token_list); + if (!result) + { + ft_putstr_fd("Error: remove_quote failed\n", STDOUT_FILENO); + ft_lstclear(&token_list, free); + return ; + } + print_tokens(result, "After remove_quote"); + ft_lstclear(&result, free); +} + +static void print_tokens(t_list *token_list, const char *title) +{ + t_list *current; + int index; + char *content; + + index = 0; + current = token_list; + printf("\n%s:\n", title); + while (current) + { + content = current->content; + printf("[%d] \"%s\"\n", index, content); + current = current->next; + index++; + } + printf("\n"); +} + +static void on_exit_token(t_list *token_list) +{ + printf("exit\n"); + ft_lstclear(&token_list, free); + exit(0); +} diff --git a/src/component/remove_quotes/remove_quotes.c b/src/component/remove_quotes/remove_quotes.c new file mode 100644 index 0000000..67a3963 --- /dev/null +++ b/src/component/remove_quotes/remove_quotes.c @@ -0,0 +1,88 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* remove_quotes.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/02/07 00:51:36 by surayama #+# #+# */ +/* Updated: 2026/02/13 23:29:35 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "remove_quotes.h" +#include + +static bool is_quote(char c); +static char *remove_quotes_from_string(const char *str); +static int excluded_quote_length(const char *str); + +t_list *remove_quotes(t_list *tokens) +{ + t_list *current; + char *new_content; + char *old_content; + + if (!tokens) + return (NULL); + current = tokens; + while (current) + { + if (current->content) + { + new_content = remove_quotes_from_string((char *)current->content); + if (!new_content) + return (NULL); + old_content = current->content; + current->content = new_content; + free(old_content); + } + current = current->next; + } + return (tokens); +} + +static int excluded_quote_length(const char *str) +{ + size_t len; + size_t quote_count; + + len = ft_strlen(str); + quote_count = 0; + while (*str) + { + if (is_quote(*str)) + quote_count++; + str++; + } + return (len - quote_count); +} + +static char *remove_quotes_from_string(const char *str) +{ + char *removed_str; + int i; + int j; + + i = 0; + j = 0; + removed_str = malloc(sizeof(char) * (excluded_quote_length(str) + 1)); + if (!removed_str) + return (NULL); + while (str[i]) + { + if (!is_quote(str[i])) + { + removed_str[j] = str[i]; + j++; + } + i++; + } + removed_str[j] = '\0'; + return (removed_str); +} + +static bool is_quote(char c) +{ + return (c == '\'' || c == '"' || c == '`'); +} diff --git a/src/main.c b/src/main.c index 2f5a7b1..5b212d9 100644 --- a/src/main.c +++ b/src/main.c @@ -36,7 +36,7 @@ int main_dev(int argc, char const **argv, char *const envp[]) if (!shell_table) return (1); shell_table_checker(shell_table); - prompt(tokenize_checker, shell_table); + prompt(remove_quotes_checker, shell_table); st_destroy(shell_table); return (0); } From 11a1b2db4b94779489aee70d4bc38bc897f41820 Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Sat, 14 Feb 2026 00:22:53 +0900 Subject: [PATCH 125/173] =?UTF-8?q?expand=E3=81=AE=E5=AE=9F=E8=A3=85=20(#5?= =?UTF-8?q?3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: expand * fix: single quote * rename * rename all --- Makefile | 13 ++- includes/minishell.h | 3 +- includes/variable_expand.h | 22 ++++ libft/list/ft_lstreplace.c | 7 +- src/checker/expand_checker.c | 69 ++++++++++++ .../state/in_double_quote_expand.c | 91 +++++++++++++++ .../variable_expand/state/in_normal_expand.c | 105 +++++++++++++++++ .../state/in_single_quote_expand.c | 38 +++++++ .../variable_expand/state/on_error_expand.c | 22 ++++ .../variable_expand/state/on_success_expand.c | 27 +++++ .../variable_expand/store/add_buffer_expand.c | 35 ++++++ .../variable_expand/store/free_store_expand.c | 22 ++++ .../store/get_key_length_expand.c | 42 +++++++ .../variable_expand/store/push_token_expand.c | 68 +++++++++++ .../variable_expand/variable_expand.c | 106 ++++++++++++++++++ .../variable_expand_internal.h | 52 +++++++++ src/main.c | 4 +- 17 files changed, 719 insertions(+), 7 deletions(-) create mode 100644 includes/variable_expand.h create mode 100644 src/checker/expand_checker.c create mode 100644 src/component/variable_expand/state/in_double_quote_expand.c create mode 100644 src/component/variable_expand/state/in_normal_expand.c create mode 100644 src/component/variable_expand/state/in_single_quote_expand.c create mode 100644 src/component/variable_expand/state/on_error_expand.c create mode 100644 src/component/variable_expand/state/on_success_expand.c create mode 100644 src/component/variable_expand/store/add_buffer_expand.c create mode 100644 src/component/variable_expand/store/free_store_expand.c create mode 100644 src/component/variable_expand/store/get_key_length_expand.c create mode 100644 src/component/variable_expand/store/push_token_expand.c create mode 100644 src/component/variable_expand/variable_expand.c create mode 100644 src/component/variable_expand/variable_expand_internal.h diff --git a/Makefile b/Makefile index 5b1228f..06cb68c 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # By: surayama +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/05/18 21:11:39 by kjikuhar #+# #+# # -# Updated: 2026/01/17 02:33:17 by surayama ### ########.fr # +# Updated: 2026/02/13 23:37:21 by surayama ### ########.fr # # # # **************************************************************************** # @@ -70,6 +70,7 @@ SRCS_MAND := src/main.c \ src/checker/parser_checker.c \ src/checker/path_checker.c \ src/checker/directory_checker.c \ + src/checker/expand_checker.c \ src/checker/remove_quotes_checker.c \ src/tokenize/tokenize.c \ src/tokenize/is_specific.c \ @@ -113,6 +114,16 @@ SRCS_MAND := src/main.c \ src/component/directory/get_directory_all_entries.c \ src/component/path/to_absolute.c \ src/component/path/append_path.c \ + src/component/variable_expand/variable_expand.c \ + src/component/variable_expand/state/in_normal_expand.c \ + src/component/variable_expand/state/in_double_quote_expand.c \ + src/component/variable_expand/state/in_single_quote_expand.c \ + src/component/variable_expand/state/on_success_expand.c \ + src/component/variable_expand/state/on_error_expand.c \ + src/component/variable_expand/store/push_token_expand.c \ + src/component/variable_expand/store/add_buffer_expand.c \ + src/component/variable_expand/store/get_key_length_expand.c \ + src/component/variable_expand/store/free_store_expand.c \ src/component/remove_quotes/remove_quotes.c \ SRCS_BONUS := diff --git a/includes/minishell.h b/includes/minishell.h index 4cb35d4..a8fc1f9 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -6,7 +6,7 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:14:22 by kjikuhar #+# #+# */ -/* Updated: 2025/12/06 15:51:28 by surayama ### ########.fr */ +/* Updated: 2026/02/13 23:37:35 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -33,6 +33,7 @@ void parser_checker(char *input, t_shell_table *shell_table); void directory_checker(char *input, t_shell_table *shell_table); void path_checker(char *input, t_shell_table *shell_table); void builtin_checker(char *input, t_shell_table *shell_table); +void expand_checker(char *input, t_shell_table *shell_table); void remove_quotes_checker(char *input, t_shell_table *shell_table); #endif diff --git a/includes/variable_expand.h b/includes/variable_expand.h new file mode 100644 index 0000000..3f37991 --- /dev/null +++ b/includes/variable_expand.h @@ -0,0 +1,22 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* variable_expand.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/01/22 21:37:05 by surayama #+# #+# */ +/* Updated: 2026/02/05 16:29:26 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef VARIABLE_EXPAND_H +# define VARIABLE_EXPAND_H + +# include "constants.h" +# include "libft.h" +# include "shell_table.h" + +t_list *variable_expand(t_list *tokens, t_shell_table *shell_table); + +#endif diff --git a/libft/list/ft_lstreplace.c b/libft/list/ft_lstreplace.c index c4e446d..1854d35 100644 --- a/libft/list/ft_lstreplace.c +++ b/libft/list/ft_lstreplace.c @@ -6,7 +6,7 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/02/01 21:36:30 by surayama #+# #+# */ -/* Updated: 2026/02/01 21:36:37 by surayama ### ########.fr */ +/* Updated: 2026/02/07 00:15:40 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,12 +17,13 @@ void ft_lstreplace(t_list *prev, t_list *target, t_list *new) t_list *next_node; t_list *last_new; - if (!prev || !target || !new) + if (!target || !new) return ; next_node = target->next; last_new = ft_lstlast(new); last_new->next = next_node; free(target->content); free(target); - prev->next = new; + if (prev) + prev->next = new; } diff --git a/src/checker/expand_checker.c b/src/checker/expand_checker.c new file mode 100644 index 0000000..e3eb0bb --- /dev/null +++ b/src/checker/expand_checker.c @@ -0,0 +1,69 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* expand_checker.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/02/01 22:30:00 by surayama #+# #+# */ +/* Updated: 2026/02/01 22:30:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" +#include "variable_expand.h" + +static void on_exit_token(t_list *token_list); +static void print_expanded_tokens(t_list *token_list); + +void expand_checker(char *input, t_shell_table *shell_table) +{ + t_list *token_list; + t_list *expanded_tokens; + + token_list = tokenize(input); + if (!token_list) + { + ft_putstr_fd("Error: tokenize failed\n", STDOUT_FILENO); + return ; + } + if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) + on_exit_token(token_list); + expanded_tokens = variable_expand(token_list, shell_table); + if (!expanded_tokens) + { + ft_putstr_fd("Error: variable_expand failed\n", STDOUT_FILENO); + ft_lstclear(&token_list, free); + return ; + } + print_expanded_tokens(expanded_tokens); + ft_lstclear(&expanded_tokens, free); +} + +static void print_expanded_tokens(t_list *token_list) +{ + t_list *current; + int index; + char *content; + + index = 0; + current = token_list; + printf("expanded_tokens:\n"); + while (current) + { + content = current->content; + if (content) + printf("[%d] \"%s\"\n", index, content); + else + printf("[%d] (null)\n", index); + current = current->next; + index++; + } +} + +static void on_exit_token(t_list *token_list) +{ + printf("exit\n"); + ft_lstclear(&token_list, free); + exit(0); +} diff --git a/src/component/variable_expand/state/in_double_quote_expand.c b/src/component/variable_expand/state/in_double_quote_expand.c new file mode 100644 index 0000000..95d4c08 --- /dev/null +++ b/src/component/variable_expand/state/in_double_quote_expand.c @@ -0,0 +1,91 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* in_double_quote.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/02/01 22:14:06 by surayama #+# #+# */ +/* Updated: 2026/02/07 00:15:01 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../variable_expand_internal.h" +#include "variable_expand.h" + +static void by_dollar(t_shell_table *shell_table, t_expand_store *store, + t_expand_state *state, char **current); +static void by_double_quote_end(t_shell_table *shell_table, + t_expand_store *store, t_expand_state *state, char **current); +static void add_buffer_with_expanded(t_expand_store *store, + t_expand_state *state, char *expanded); + +void in_double_quote_expand(t_shell_table *shell_table, + t_expand_store *store, t_expand_state *state, char **current) +{ + if (**current == '\0') + *state = EXPAND_ON_ERROR; + else if (**current == '$') + by_dollar(shell_table, store, state, current); + else if (**current == '"') + by_double_quote_end(shell_table, store, state, current); + else if (add_buffer_expand(store, **current) == ERROR) + *state = EXPAND_ON_ERROR; +} + +static void by_dollar(t_shell_table *shell_table, t_expand_store *store, + t_expand_state *state, char **current) +{ + size_t key_length; + char *key; + char *expanded; + + key_length = get_key_length(*current + 1); + if (key_length == 0) + { + if (add_buffer_expand(store, **current) == ERROR) + *state = EXPAND_ON_ERROR; + return ; + } + key = ft_substr(*current, 1, key_length); + if (!key) + { + *state = EXPAND_ON_ERROR; + return ; + } + expanded = st_search(shell_table, key); + free(key); + add_buffer_with_expanded(store, state, expanded); + if (*state == EXPAND_ON_ERROR) + return ; + store->skip_count = key_length; +} + +static void by_double_quote_end(t_shell_table *shell_table, + t_expand_store *store, t_expand_state *state, char **current) +{ + if (add_buffer_expand(store, **current) == ERROR || push_token_expand(store, + shell_table) == ERROR) + *state = EXPAND_ON_ERROR; + else + *state = EXPAND_IN_NORMAL; +} + +static void add_buffer_with_expanded(t_expand_store *store, + t_expand_state *state, char *expanded) +{ + size_t i; + + if (!expanded) + return ; + i = 0; + while (expanded[i] != '\0') + { + if (add_buffer_expand(store, expanded[i]) == ERROR) + { + *state = EXPAND_ON_ERROR; + return ; + } + i++; + } +} diff --git a/src/component/variable_expand/state/in_normal_expand.c b/src/component/variable_expand/state/in_normal_expand.c new file mode 100644 index 0000000..6bd079a --- /dev/null +++ b/src/component/variable_expand/state/in_normal_expand.c @@ -0,0 +1,105 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* in_normal.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/02/01 21:49:36 by surayama #+# #+# */ +/* Updated: 2026/02/07 00:15:04 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../variable_expand_internal.h" +#include "variable_expand.h" + +static void by_last(t_shell_table *shell_table, t_expand_store *store, + t_expand_state *state, char **current); +static void by_quote(t_shell_table *shell_table, t_expand_store *store, + t_expand_state *state, char **current); +static void by_dollar(t_shell_table *shell_table, t_expand_store *store, + t_expand_state *state, char **current); +static void add_buffer_with_expanded(t_expand_store *store, + t_expand_state *state, char *expanded); + +void in_normal_expand(t_shell_table *shell_table, t_expand_store *store, + t_expand_state *state, char **current) +{ + if (**current == '\0') + by_last(shell_table, store, state, current); + else if (**current == '"' || **current == '\'') + by_quote(shell_table, store, state, current); + else if (**current == '$') + by_dollar(shell_table, store, state, current); + else if (add_buffer_expand(store, **current) == ERROR) + *state = EXPAND_ON_ERROR; +} + +static void by_last(t_shell_table *shell_table, t_expand_store *store, + t_expand_state *state, char **current) +{ + (void)current; + if (push_token_expand(store, shell_table) == ERROR) + *state = EXPAND_ON_ERROR; + else + *state = EXPAND_ON_SUCCESS; +} + +static void by_quote(t_shell_table *shell_table, t_expand_store *store, + t_expand_state *state, char **current) +{ + if (push_token_expand(store, shell_table) == ERROR + || add_buffer_expand(store, **current) == ERROR) + *state = EXPAND_ON_ERROR; + else if (**current == '"') + *state = EXPAND_IN_DOUBLE_QUOTE; + else + *state = EXPAND_IN_SINGLE_QUOTE; +} + +static void by_dollar(t_shell_table *shell_table, t_expand_store *store, + t_expand_state *state, char **current) +{ + size_t key_length; + char *key; + char *expanded; + + key_length = get_key_length(*current + 1); + if (key_length == 0) + { + if (add_buffer_expand(store, **current) == ERROR) + *state = EXPAND_ON_ERROR; + return ; + } + key = ft_substr(*current, 1, key_length); + if (!key) + { + *state = EXPAND_ON_ERROR; + return ; + } + expanded = st_search(shell_table, key); + free(key); + add_buffer_with_expanded(store, state, expanded); + if (*state == EXPAND_ON_ERROR) + return ; + store->skip_count = key_length; +} + +static void add_buffer_with_expanded(t_expand_store *store, + t_expand_state *state, char *expanded) +{ + size_t i; + + if (!expanded) + return ; + i = 0; + while (expanded[i] != '\0') + { + if (add_buffer_expand(store, expanded[i]) == ERROR) + { + *state = EXPAND_ON_ERROR; + return ; + } + i++; + } +} diff --git a/src/component/variable_expand/state/in_single_quote_expand.c b/src/component/variable_expand/state/in_single_quote_expand.c new file mode 100644 index 0000000..c998a86 --- /dev/null +++ b/src/component/variable_expand/state/in_single_quote_expand.c @@ -0,0 +1,38 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* in_single_quote.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/02/01 22:22:34 by surayama #+# #+# */ +/* Updated: 2026/02/07 00:46:06 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../variable_expand_internal.h" +#include "variable_expand.h" + +static void by_single_quote_end(t_shell_table *shell_table, + t_expand_store *store, t_expand_state *state, char **current); + +void in_single_quote_expand(t_shell_table *shell_table, + t_expand_store *store, t_expand_state *state, char **current) +{ + if (**current == '\0') + *state = EXPAND_ON_ERROR; + else if (**current == '\'') + by_single_quote_end(shell_table, store, state, current); + else if (add_buffer_expand(store, **current) == ERROR) + *state = EXPAND_ON_ERROR; +} + +static void by_single_quote_end(t_shell_table *shell_table, + t_expand_store *store, t_expand_state *state, char **current) +{ + if (add_buffer_expand(store, **current) == ERROR || push_token_expand(store, + shell_table) == ERROR) + *state = EXPAND_ON_ERROR; + else + *state = EXPAND_IN_NORMAL; +} diff --git a/src/component/variable_expand/state/on_error_expand.c b/src/component/variable_expand/state/on_error_expand.c new file mode 100644 index 0000000..c3db8cf --- /dev/null +++ b/src/component/variable_expand/state/on_error_expand.c @@ -0,0 +1,22 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* on_error.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/02/01 22:42:03 by surayama #+# #+# */ +/* Updated: 2026/02/07 00:15:10 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../variable_expand_internal.h" +#include "variable_expand.h" + +t_list *on_error_expand(t_expand_store *store, char *token) +{ + (void)token; + if (store) + free_store_expand(store); + return (NULL); +} diff --git a/src/component/variable_expand/state/on_success_expand.c b/src/component/variable_expand/state/on_success_expand.c new file mode 100644 index 0000000..daa3ffa --- /dev/null +++ b/src/component/variable_expand/state/on_success_expand.c @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* on_success.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/02/01 22:38:01 by surayama #+# #+# */ +/* Updated: 2026/02/07 00:15:14 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../variable_expand_internal.h" +#include "variable_expand.h" + +t_list *on_success_expand(t_expand_store *store, char *token) +{ + t_list *expanded_tokens; + + (void)token; + if (!store) + return (NULL); + expanded_tokens = store->tokens; + store->tokens = NULL; + ft_lstclear(&(store->buffer), free); + return (expanded_tokens); +} diff --git a/src/component/variable_expand/store/add_buffer_expand.c b/src/component/variable_expand/store/add_buffer_expand.c new file mode 100644 index 0000000..7c964cf --- /dev/null +++ b/src/component/variable_expand/store/add_buffer_expand.c @@ -0,0 +1,35 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* add_buffer.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/02/01 21:10:42 by surayama #+# #+# */ +/* Updated: 2026/02/07 00:14:41 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../variable_expand_internal.h" +#include "variable_expand.h" + +int add_buffer_expand(t_expand_store *store, char c) +{ + char *char_ptr; + t_list *new_node; + + if (!store) + return (ERROR); + char_ptr = (char *)malloc(sizeof(char)); + if (!char_ptr) + return (ERROR); + *char_ptr = c; + new_node = ft_lstnew(char_ptr); + if (!new_node) + { + free(char_ptr); + return (ERROR); + } + ft_lstadd_back(&(store->buffer), new_node); + return (SUCCESS); +} diff --git a/src/component/variable_expand/store/free_store_expand.c b/src/component/variable_expand/store/free_store_expand.c new file mode 100644 index 0000000..8326e2b --- /dev/null +++ b/src/component/variable_expand/store/free_store_expand.c @@ -0,0 +1,22 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* free_store.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/02/01 22:44:15 by surayama #+# #+# */ +/* Updated: 2026/02/07 00:14:47 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../variable_expand_internal.h" +#include "variable_expand.h" + +void free_store_expand(t_expand_store *store) +{ + if (!store) + return ; + ft_lstclear(&(store->buffer), free); + ft_lstclear(&(store->tokens), free); +} diff --git a/src/component/variable_expand/store/get_key_length_expand.c b/src/component/variable_expand/store/get_key_length_expand.c new file mode 100644 index 0000000..a9c1e3e --- /dev/null +++ b/src/component/variable_expand/store/get_key_length_expand.c @@ -0,0 +1,42 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* get_key_length.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/02/01 22:44:15 by surayama #+# #+# */ +/* Updated: 2026/02/14 00:08:47 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "variable_expand.h" + +static bool is_special_char(const char c); + +size_t get_key_length(const char *from) +{ + size_t i; + + if (!from || from[0] == '\0') + return (0); + if (is_special_char(from[0]) || ft_isdigit(from[0])) + return (1); + i = 0; + while (from[i] != '\0') + { + if (ft_isalnum((unsigned char)from[i]) || from[i] == '_') + i++; + else + break ; + } + return (i); +} + +static bool is_special_char(const char c) +{ + if (c == '?' || c == '$' || c == '#' || c == '*' || c == '@' || c == '-' + || c == '!') + return (true); + return (false); +} diff --git a/src/component/variable_expand/store/push_token_expand.c b/src/component/variable_expand/store/push_token_expand.c new file mode 100644 index 0000000..2119c88 --- /dev/null +++ b/src/component/variable_expand/store/push_token_expand.c @@ -0,0 +1,68 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* push_token.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/02/01 21:12:08 by surayama #+# #+# */ +/* Updated: 2026/02/07 00:14:55 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../variable_expand_internal.h" +#include "variable_expand.h" + +static char *build_token_from_buffer(t_list *buffer) +{ + int size; + char *token; + int i; + t_list *current; + + size = ft_lstsize(buffer); + if (size == 0) + return (NULL); + token = (char *)malloc(sizeof(char) * (size + 1)); + if (!token) + return (NULL); + i = 0; + current = buffer; + while (current) + { + token[i] = *(char *)(current->content); + i++; + current = current->next; + } + token[i] = '\0'; + return (token); +} + +int push_token_expand(t_expand_store *store, t_shell_table *shell_table) +{ + char *token; + t_list *new_node; + + (void)shell_table; + if (!store) + return (ERROR); + if (!store->buffer) + return (SUCCESS); + token = build_token_from_buffer(store->buffer); + if (!token) + { + ft_lstclear(&(store->buffer), free); + store->buffer = NULL; + return (SUCCESS); + } + new_node = ft_lstnew((void *)token); + if (!new_node) + { + free(token); + return (ERROR); + } + ft_lstadd_back(&(store->tokens), new_node); + ft_lstclear(&(store->buffer), free); + store->buffer = NULL; + return (SUCCESS); +} diff --git a/src/component/variable_expand/variable_expand.c b/src/component/variable_expand/variable_expand.c new file mode 100644 index 0000000..204ebac --- /dev/null +++ b/src/component/variable_expand/variable_expand.c @@ -0,0 +1,106 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* variable_expand.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/01/22 21:55:17 by surayama #+# #+# */ +/* Updated: 2026/02/05 17:58:51 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "variable_expand.h" +#include "variable_expand_internal.h" + +static t_list *expand_token(char *token, t_shell_table *shell_table); +static t_list *remove_current_token(t_list *tokens, t_list *prev_token, + t_list *current_token, t_list *next_token); +static t_list *insert_expanded_token(t_list **tokens, t_list *prev_token, + t_list *current_token, t_list *expanded_token); + +t_list *variable_expand(t_list *tokens, t_shell_table *shell_table) +{ + t_list *prev_token; + t_list *current_token; + t_list *next_token; + t_list *expanded_token; + + current_token = tokens; + prev_token = NULL; + while (current_token && current_token->content) + { + next_token = current_token->next; + expanded_token = expand_token(current_token->content, shell_table); + if (expanded_token) + prev_token = insert_expanded_token(&tokens, prev_token, + current_token, expanded_token); + else + tokens = remove_current_token(tokens, prev_token, current_token, + next_token); + current_token = next_token; + } + return (tokens); +} + +static void initialize(t_expand_store *store, t_expand_state *state, + char **current, char *token) +{ + store->tokens = NULL; + store->buffer = NULL; + store->skip_count = 0; + *current = token; + *state = EXPAND_IN_NORMAL; +} + +static t_list *expand_token(char *token, t_shell_table *shell_table) +{ + t_expand_store store; + t_expand_state state; + char *current; + + initialize(&store, &state, ¤t, token); + while (true) + { + if (state == EXPAND_IN_NORMAL) + in_normal_expand(shell_table, &store, &state, ¤t); + else if (state == EXPAND_IN_DOUBLE_QUOTE) + in_double_quote_expand(shell_table, &store, &state, ¤t); + else if (state == EXPAND_IN_SINGLE_QUOTE) + in_single_quote_expand(shell_table, &store, &state, ¤t); + else if (state == EXPAND_ON_SUCCESS) + return (on_success_expand(&store, token)); + else if (state == EXPAND_ON_ERROR) + return (on_error_expand(&store, token)); + current++; + if (store.skip_count > 0) + { + current += store.skip_count; + store.skip_count = 0; + } + } +} + +static t_list *insert_expanded_token(t_list **tokens, t_list *prev_token, + t_list *current_token, t_list *expanded_token) +{ + t_list *replaced_prev; + + replaced_prev = ft_lstlast(expanded_token); + ft_lstreplace(prev_token, current_token, expanded_token); + if (!prev_token) + *tokens = expanded_token; + return (replaced_prev); +} + +static t_list *remove_current_token(t_list *tokens, t_list *prev_token, + t_list *current_token, t_list *next_token) +{ + if (prev_token) + prev_token->next = next_token; + else + tokens = next_token; + free(current_token->content); + free(current_token); + return (tokens); +} diff --git a/src/component/variable_expand/variable_expand_internal.h b/src/component/variable_expand/variable_expand_internal.h new file mode 100644 index 0000000..1f69ec7 --- /dev/null +++ b/src/component/variable_expand/variable_expand_internal.h @@ -0,0 +1,52 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* variable_expand_internal.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/02/01 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/02/05 16:28:45 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef VARIABLE_EXPAND_INTERNAL_H +# define VARIABLE_EXPAND_INTERNAL_H + +# include "libft.h" +# include "shell_table.h" + +typedef enum e_expand_state +{ + EXPAND_IN_NORMAL, + EXPAND_IN_DOUBLE_QUOTE, + EXPAND_IN_SINGLE_QUOTE, + EXPAND_ON_ERROR, + EXPAND_ON_SUCCESS, +} t_expand_state; + +typedef struct s_expand_store +{ + t_list *tokens; + t_list *buffer; + size_t skip_count; +} t_expand_store; + +// store +int push_token_expand(t_expand_store *store, + t_shell_table *shell_table); +void free_store_expand(t_expand_store *store); +int add_buffer_expand(t_expand_store *store, char c); +size_t get_key_length(const char *from); + +// state handler +void in_normal_expand(t_shell_table *shell_table, t_expand_store *store, + t_expand_state *state, char **current); +void in_double_quote_expand(t_shell_table *shell_table, + t_expand_store *store, t_expand_state *state, char **current); +void in_single_quote_expand(t_shell_table *shell_table, + t_expand_store *store, t_expand_state *state, char **current); +t_list *on_success_expand(t_expand_store *store, char *token); +t_list *on_error_expand(t_expand_store *store, char *token); + +#endif diff --git a/src/main.c b/src/main.c index 5b212d9..331bb14 100644 --- a/src/main.c +++ b/src/main.c @@ -6,7 +6,7 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:13:47 by kjikuhar #+# #+# */ -/* Updated: 2025/12/04 17:34:40 by surayama ### ########.fr */ +/* Updated: 2026/02/13 23:37:48 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -36,7 +36,7 @@ int main_dev(int argc, char const **argv, char *const envp[]) if (!shell_table) return (1); shell_table_checker(shell_table); - prompt(remove_quotes_checker, shell_table); + prompt(expand_checker, shell_table); st_destroy(shell_table); return (0); } From acb5be19da7b0fcfd8c35c344bfae521a088c7db Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Sat, 14 Feb 2026 00:23:00 +0900 Subject: [PATCH 126/173] =?UTF-8?q?expand=E3=81=AE=E5=AE=9F=E8=A3=85=20(#5?= =?UTF-8?q?3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: expand * fix: single quote * rename * rename all From c51a43fb431438fe571b58757f2ea4dfbaeb2ec2 Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Tue, 3 Mar 2026 14:45:55 +0900 Subject: [PATCH 127/173] =?UTF-8?q?Claude=20Code=20=E3=81=AE=E3=82=BB?= =?UTF-8?q?=E3=83=83=E3=83=88=E3=82=A2=E3=83=83=E3=83=97=20(#58)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * claude codeのセットアップ * fix: パス修正 * delete: いらない --- .claude/CLAUDE.md | 86 +++++++++++++++++++++ .claude/commands/code-review.md | 30 +++++++ .claude/commands/pr-creation.md | 11 +++ .claude/hooks/post-edit-norminette.sh | 23 ++++++ .claude/hooks/pre-bash-safety-check.sh | 25 ++++++ .claude/hooks/session-start-branch-check.sh | 15 ++++ .claude/settings.json | 36 +++++++++ 7 files changed, 226 insertions(+) create mode 100644 .claude/CLAUDE.md create mode 100644 .claude/commands/code-review.md create mode 100644 .claude/commands/pr-creation.md create mode 100644 .claude/hooks/post-edit-norminette.sh create mode 100644 .claude/hooks/pre-bash-safety-check.sh create mode 100644 .claude/hooks/session-start-branch-check.sh create mode 100644 .claude/settings.json diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md new file mode 100644 index 0000000..22aa007 --- /dev/null +++ b/.claude/CLAUDE.md @@ -0,0 +1,86 @@ +# CLAUDE.md + +このファイルは Claude Code (claude.ai/code) がこのリポジトリで作業する際のガイダンスを提供する。 + +## プロジェクト概要 + +42 Tokyo の minishell プロジェクト。C言語による最小限の POSIX シェル実装。開発者: surayama, kjikuhar。 + +## ビルドコマンド + +```bash +make # ビルド (libft → ソースを -Wall -Wextra -Werror でコンパイル) +make re # クリーンビルド +make clean # オブジェクトファイル削除 +make fclean # オブジェクトファイルとバイナリ削除 +make norm # norminette スタイルチェック +make valgrind # リビルド後 valgrind でメモリリーク検出 (readline.supp 使用) +make test # norminette + valgrind 両方実行 +make docker # Docker コンテナをビルドして入る +``` + +## 実行方法 + +ビルド・実行は必ずDocker環境内で行うこと。 + +```bash +make docker # Docker コンテナをビルドして入る +make # コンテナ内でビルド +./minishell # 通常モード (対話シェル) +./minishell --dev # 開発モード (expand_checker でパイプラインデバッグ) +``` + +## Architecture + +シェルは以下のインタープリタパイプラインに従う: + +``` +Input → tokenize() → heredoc() → variable_expand() → remove_quotes() → parser() → AST → execute +``` + +### パイプラインの各段階 + +1. **tokenize** (`src/tokenize/`) — 状態機械による字句解析。状態: `IN_NORMAL`, `IN_SINGLE_QUOTE`, `IN_DOUBLE_QUOTE`, `IN_OPERATOR`, `ON_SUCCESS`, `ON_ERROR`。演算子・スペース・クォート境界で `t_list` のトークン文字列に分割する。 + +2. **変数展開** (`src/component/variable_expand/`) — `$VAR` 構文を展開。クォート文脈を尊重し、シングルクォート内では展開しない。トークナイザと同様の状態機械パターンを使用。 + +3. **クォート削除** (`src/component/remove_quotes/`) — 展開後のトークンからクォート文字を除去。 + +4. **parser** (`src/parser/`) — 再帰下降パーサ。二分木ASTを生成。ノード型: `PIPE`(内部ノード)、`CMD`(葉ノード、`t_cmd` に argv リストとリダイレクションリストを持つ)。 + +5. **実行** — 未実装。エントリポイントは `src/callback/on_input.c`。 + +### 主要コンポーネント + +- **Shell Table** (`src/component/shell_table/`) — 環境変数のハッシュテーブル。export 状態を追跡。関数プレフィックス: `st_*`。 +- **ビルトイン** (`src/builtin/`) — echo, pwd, export, unset, cd。全て `(t_list *argv, t_shell_table *shell_table)` を引数に取る。 +- **ヒアドキュメント** (`src/component/heredoc/`) — `<<` リダイレクションを処理。一時ファイルを `/tmp/minishell_heredoc_*` に作成。 +- **チェッカー** (`src/checker/`) — 各パイプライン段階のデバッグ・テスト用ハーネス。個別に呼び出し可能。 + +### 主要データ構造 (`includes/`) + +- `t_shell_table` / `t_shell_node` — 環境変数ハッシュテーブル (`shell_table.h`) +- `t_ast` — AST木。`t_ast_type` (PIPE/CMD) と left/right 子ノード (`parser.h`) +- `t_cmd` — コマンド。`t_list *argv` と `t_list *redirs` を持つ (`parser.h`) +- `t_redir` — リダイレクション。`t_redir_kind` (R_IN, R_OUT_TRUNC, R_OUT_APPEND) と filename (`parser.h`) +- `t_list` — libft のリンクリスト。トークンリストや引数リストとして全体で使用 + +## Critical Rules + +### コーディング規約 (42 Norminette) + +- 1行最大80文字、関数本体最大25行、関数の引数最大4つ +- 変数宣言は関数の先頭、全て snake_case +- typedef: `typedef struct s_name { ... } t_name;` +- 公開ヘッダは `includes/`、非公開ヘッダ (例: `tokenize_private.h`) はソースファイルと同階層 +- 全ファイルに 42 ヘッダコメントブロックが必要 +- 新規ソースファイルは Makefile の `SRCS_MAND` に追加すること + +### メモリリークチェック + +- メモリリークの検出は必ず valgrind で行うこと (`make valgrind`) + +## 依存関係 + +- **libft** (`libft/`) — カスタムCライブラリ。Makefile で自動コンパイル +- **readline** — GNU readline。対話入力用 (`-lreadline`) diff --git a/.claude/commands/code-review.md b/.claude/commands/code-review.md new file mode 100644 index 0000000..bcef153 --- /dev/null +++ b/.claude/commands/code-review.md @@ -0,0 +1,30 @@ +--- +description: 変更コードの自動レビュー +--- + + +# 変更コードの自動レビュー + +## 実行手順 + +### Step 1: 並列レビューエージェントの起動 +以下の 3 つのエージェントを並列で起動してください: + + +#### エージェント 1: コーディング規約チェック + +- 1行最大80文字、関数本体最大25行、関数の引数最大4つ +- 変数宣言は関数の先頭、全て snake_case +- typedef: `typedef struct s_name { ... } t_name;` +- 公開ヘッダは `includes/`、非公開ヘッダ (例: `tokenize_private.h`) はソースファイルと同階層 +- 全ファイルに 42 ヘッダコメントブロックが必要 + +#### エージェント 2: 命名・可読性チェック + +- 変数名・メソッド名の適切さ +- マジックナンバー + +#### エージェント 3: メモリリークチェック + +- `malloc`などのメモリ確保が行われた場合に、全てのパターンにおいて`free`解放が行われているか検証する。 +- 入力パターンで再現性があれば、それもユーザに報告する。 diff --git a/.claude/commands/pr-creation.md b/.claude/commands/pr-creation.md new file mode 100644 index 0000000..56d38cc --- /dev/null +++ b/.claude/commands/pr-creation.md @@ -0,0 +1,11 @@ +--- +description: PR 作成 +--- + +## 実行手順 + +### 1. コミット状態の確認 +### 2. 変更内容の分析 +### 3. norminette 最終確認(変更ファイルのみ) +### 4. PR 説明文の生成(テンプレートに従う) +### 5. PR 作成(gh pr create) diff --git a/.claude/hooks/post-edit-norminette.sh b/.claude/hooks/post-edit-norminette.sh new file mode 100644 index 0000000..6a26635 --- /dev/null +++ b/.claude/hooks/post-edit-norminette.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# post-edit-norminette.sh + +INPUT=$(cat) +FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty') + +# C/H ファイルでない場合はスキップ +if [[ ! "$FILE_PATH" =~ \.(c|h)$ ]]; then + exit 0 +fi + +# norminette 実行 +NORM_OUTPUT=$(norminette "$FILE_PATH" 2>&1 || true) + +if echo "$NORM_OUTPUT" | grep -q "Error"; then + ERRORS=$(echo "$NORM_OUTPUT" | grep "Error" | head -20) + cat << EOF +{ + "decision": "block", + "reason": "norminette エラー:\n$ERRORS" +} +EOF +fi diff --git a/.claude/hooks/pre-bash-safety-check.sh b/.claude/hooks/pre-bash-safety-check.sh new file mode 100644 index 0000000..a79252e --- /dev/null +++ b/.claude/hooks/pre-bash-safety-check.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# pre-bash-safety-check.sh + +INPUT=$(cat) +COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty') + +DANGEROUS_PATTERNS=( + "rm -rf /" + "git push --force.*main" + "git push --force.*develop" +) + +for pattern in "${DANGEROUS_PATTERNS[@]}"; do + if echo "$COMMAND" | grep -qE "$pattern"; then + cat << EOF +{ + "decision": "Reject", + "feedback": "🚨 危険なコマンドがブロックされました + +コマンド: \`$COMMAND\`" +} +EOF + exit 0 + fi +done diff --git a/.claude/hooks/session-start-branch-check.sh b/.claude/hooks/session-start-branch-check.sh new file mode 100644 index 0000000..8b10313 --- /dev/null +++ b/.claude/hooks/session-start-branch-check.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# session-start-branch-check.sh + +CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) + +if [ "$CURRENT_BRANCH" = "develop" ] || [ "$CURRENT_BRANCH" = "main" ]; then + cat << EOF +{ + "decision": "Proceed", + "feedback": "⚠️ 現在のブランチ: **$CURRENT_BRANCH** + +開発作業は feature ブランチでおこなってください。" +} +EOF +fi diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..39d0fa9 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,36 @@ +{ + "hooks": { + "SessionStart": [ + { + "hooks": [ + { + "type": "command", + "command": ".claude/hooks/session-start-branch-check.sh" + } + ] + } + ], + "PostToolUse": [ + { + "matcher": "Write|Edit", + "hooks": [ + { + "type": "command", + "command": ".claude/hooks/post-edit-norminette.sh" + } + ] + } + ], + "PreToolUse": [ + { + "matcher": "Bash", + "hooks": [ + { + "type": "command", + "command": ".claude/hooks/pre-bash-safety-check.sh" + } + ] + } + ] + } +} From fd419ec7aa5d73e4938bbe41f441fc57b6ac9c3e Mon Sep 17 00:00:00 2001 From: jiku <134150757+jiku0730@users.noreply.github.com> Date: Tue, 3 Mar 2026 17:02:17 +0900 Subject: [PATCH 128/173] =?UTF-8?q?add:=20join=5Fpath.c=E3=82=92src/compon?= =?UTF-8?q?ents/path=E3=81=AB=E8=BF=BD=E5=8A=A0=E3=81=97=E3=81=BE=E3=81=97?= =?UTF-8?q?=E3=81=9F=E3=80=82=20(#59)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add: join_path.c * fix: join_path関数の返り値の型からstaticを削除。 * update: makefileにsrc/components/path/join_path.cを追加。 * update: path.hにjoin_path関数のプロトタイプ宣言を追加。 * fix: join_pathの引数名を変更。path -> path_before, cmd -> path_after. --------- Co-authored-by: jiku0730 --- Makefile | 5 +++-- includes/path.h | 3 ++- src/component/path/join_path.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 src/component/path/join_path.c diff --git a/Makefile b/Makefile index 06cb68c..f069b33 100644 --- a/Makefile +++ b/Makefile @@ -3,10 +3,10 @@ # ::: :::::::: # # Makefile :+: :+: :+: # # +:+ +:+ +:+ # -# By: surayama +#+ +:+ +#+ # +# By: kjikuhar +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/05/18 21:11:39 by kjikuhar #+# #+# # -# Updated: 2026/02/13 23:37:21 by surayama ### ########.fr # +# Updated: 2026/03/03 16:45:10 by kjikuhar ### ########.fr # # # # **************************************************************************** # @@ -113,6 +113,7 @@ SRCS_MAND := src/main.c \ src/component/directory/get_directory_entries.c \ src/component/directory/get_directory_all_entries.c \ src/component/path/to_absolute.c \ + src/component/path/join_path.c \ src/component/path/append_path.c \ src/component/variable_expand/variable_expand.c \ src/component/variable_expand/state/in_normal_expand.c \ diff --git a/includes/path.h b/includes/path.h index 5daf333..7f42858 100644 --- a/includes/path.h +++ b/includes/path.h @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/12/01 00:00:00 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:51 by kjikuhar ### ########.fr */ +/* Updated: 2026/03/03 16:57:47 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,5 +22,6 @@ char *to_absolute(const char *path); t_list *append_path(t_list **dest, const char *content); t_list *append_path_list(t_list **dest, const char *content); +char *join_path(const char *path_before, const char *path_after); #endif diff --git a/src/component/path/join_path.c b/src/component/path/join_path.c new file mode 100644 index 0000000..af93257 --- /dev/null +++ b/src/component/path/join_path.c @@ -0,0 +1,30 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* join_path.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/03/03 16:34:11 by kjikuhar #+# #+# */ +/* Updated: 2026/03/03 16:57:28 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "path.h" + +char *join_path(const char *path_before, const char *path_after) +{ + size_t path_len; + size_t cmd_len; + char *joined; + + path_len = ft_strlen(path_before); + cmd_len = ft_strlen(path_after); + joined = malloc(sizeof(char) * (path_len + 1 + cmd_len + 1)); + if (!joined) + return (NULL); + ft_strlcpy(joined, path_before, path_len + 1); + joined[path_len] = '/'; + ft_strlcpy(joined + path_len + 1, path_after, cmd_len + 1); + return (joined); +} From aa8d2305373dbadf30c9e4ae9e98cb79b6034d76 Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Tue, 3 Mar 2026 17:07:58 +0900 Subject: [PATCH 129/173] =?UTF-8?q?=E3=83=91=E3=82=B9=E8=A7=A3=E6=B1=BA?= =?UTF-8?q?=E3=82=B3=E3=83=B3=E3=83=9D=E3=83=BC=E3=83=8D=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=81=AE=E5=AE=9F=E8=A3=85=20(#56)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * rename: to_absolute_path * パス解決コンポーネントの実装 ワイルドカード展開(*パターンマッチング)と相対パスの絶対パス変換を行う resolve_pathコンポーネントを追加した。 to_absolute.cのファイル名をto_absolute_path.cにリネーム。 Co-Authored-By: Claude Opus 4.6 * fix: norminette * ワイルドカード展開と相対パス解決を分離 resolve_pathをresolve_wildcard_pathとresolve_relative_pathに分割し、 checkerもwildcard_checkerとrelative_path_checkerに分割した。 Co-Authored-By: Claude Opus 4.6 * fix: code review --------- Co-authored-by: Claude Opus 4.6 --- Makefile | 12 ++- docs/path_resolve.md | 100 ++++++++++++++++++ includes/minishell.h | 3 + includes/path.h | 10 +- src/builtin/cd.c | 4 +- src/checker/path_checker.c | 4 +- src/checker/relative_path_checker.c | 62 +++++++++++ src/checker/wildcard_checker.c | 68 ++++++++++++ src/component/path/resolve_relative_path.c | 43 ++++++++ src/component/path/resolve_wildcard.c | 86 +++++++++++++++ src/component/path/resolve_wildcard_path.c | 54 ++++++++++ .../{to_absolute.c => to_absolute_path.c} | 8 +- src/main.c | 4 +- 13 files changed, 441 insertions(+), 17 deletions(-) create mode 100644 docs/path_resolve.md create mode 100644 src/checker/relative_path_checker.c create mode 100644 src/checker/wildcard_checker.c create mode 100644 src/component/path/resolve_relative_path.c create mode 100644 src/component/path/resolve_wildcard.c create mode 100644 src/component/path/resolve_wildcard_path.c rename src/component/path/{to_absolute.c => to_absolute_path.c} (93%) diff --git a/Makefile b/Makefile index f069b33..cb0213e 100644 --- a/Makefile +++ b/Makefile @@ -3,13 +3,14 @@ # ::: :::::::: # # Makefile :+: :+: :+: # # +:+ +:+ +:+ # -# By: kjikuhar +#+ +:+ +#+ # +# By: surayama +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/05/18 21:11:39 by kjikuhar #+# #+# # -# Updated: 2026/03/03 16:45:10 by kjikuhar ### ########.fr # +# Updated: 2026/03/03 17:04:01 by surayama ### ########.fr # # # # **************************************************************************** # + #----------------------------------------------------------------------------- #> options #----------------------------------------------------------------------------- @@ -72,6 +73,8 @@ SRCS_MAND := src/main.c \ src/checker/directory_checker.c \ src/checker/expand_checker.c \ src/checker/remove_quotes_checker.c \ + src/checker/wildcard_checker.c \ + src/checker/relative_path_checker.c \ src/tokenize/tokenize.c \ src/tokenize/is_specific.c \ src/tokenize/state/in_normal.c \ @@ -112,9 +115,12 @@ SRCS_MAND := src/main.c \ src/component/pattern/filter_pattern.c \ src/component/directory/get_directory_entries.c \ src/component/directory/get_directory_all_entries.c \ - src/component/path/to_absolute.c \ + src/component/path/to_absolute_path.c \ src/component/path/join_path.c \ src/component/path/append_path.c \ + src/component/path/resolve_wildcard_path.c \ + src/component/path/resolve_relative_path.c \ + src/component/path/resolve_wildcard.c \ src/component/variable_expand/variable_expand.c \ src/component/variable_expand/state/in_normal_expand.c \ src/component/variable_expand/state/in_double_quote_expand.c \ diff --git a/docs/path_resolve.md b/docs/path_resolve.md new file mode 100644 index 0000000..85d125b --- /dev/null +++ b/docs/path_resolve.md @@ -0,0 +1,100 @@ +# path_resolveの実装計画 + +## 概要 +トークン内のパスを解決するコンポーネント。2つの機能を持つ: +1. **ワイルドカード展開**: `*` を含むトークンをファイルシステムに対してパターンマッチングし、マッチしたファイルパスの一覧に展開する +2. **相対パス解決**: `/` を含むトークン(パスとみなせるもの)を絶対パスに変換する + +## 入出力例 +``` +# ワイルドカード展開 +入力トークン: ["ls", "/Users/urassh/*.png"] +出力トークン: ["ls", "/Users/urassh/pic1.png", "/Users/urassh/pic2.png", "/Users/urassh/pic3.png"] + +# 相対パス解決 +入力トークン: ["ls", "../dir3/tmp.c"] +出力トークン: ["ls", "/Users/urassh/dir3/tmp.c"] +``` + +## シグネチャ +```c +t_list *resolve_path(t_list *tokens); +void resolve_path_checker(char *input, t_shell_table *shell_table); +``` + +## アルゴリズム +1. トークンリストを順に走査する +2. 各トークンに対して以下の判定を行う: + +### A. ワイルドカードを含む場合(`*` あり) + a. `ft_strrchr(token, '/')` で最後の `/` を見つけ、ディレクトリ部とパターン部に分割 + - `/Users/urassh/*.png` → dir: `/Users/urassh/`, pattern: `*.png` + - `*.c`(`/`なし)→ dir: `.`, pattern: `*.c` + b. `to_absolute_path(dir)` でディレクトリを絶対パスに変換 + c. `get_directory_entries(abs_dir, hidden, &entries)` でディレクトリ内のエントリ一覧を取得 + - パターンが `.` 始まりなら隠しファイルも含める + d. `filter_pattern(entries, pattern)` でパターンにマッチするエントリを絞り込む + e. マッチした各エントリに `abs_dir + "/" + entry` のフルパスを構築する + f. `ft_lstreplace(prev, current, resolved)` で元のトークンをマッチ結果リストに置換する + g. マッチ結果が0件の場合、元のトークンをそのまま残す + +### B. パスを含む場合(`/` あり、`*` なし) + a. `to_absolute_path(token)` で絶対パスに変換 + b. トークンの内容を変換後の絶対パスに置き換える(contentをfree→新しいcontentに差し替え) + +### C. それ以外 + - そのまま次へ進む + +## 利用する既存コンポーネント +| 関数 | ファイル | 役割 | +|------|---------|------| +| `to_absolute_path()` | `src/component/path/to_absolute_path.c` | 相対パス→絶対パス変換 | +| `filter_pattern()` | `src/component/pattern/filter_pattern.c` | ワイルドカードパターンマッチング | +| `get_directory_entries()` | `src/component/directory/get_directory_entries.c` | ディレクトリ内エントリ取得 | +| `ft_lstreplace()` | `libft/list/ft_lstreplace.c` | リスト要素の置換 | +| `ft_strrchr()` | `libft/` | 最後の文字検索(dir/pattern分割) | + +## ファイル構成 +``` +includes/path_resolve.h # ヘッダ(resolveの宣言) +src/component/path_resolve/path_resolve.c # メインロジック(resolve, has_wildcard, resolve_token, build_full_paths) +src/checker/resolve_checker.c # 開発用チェッカー +``` + +## 関数設計(path_resolve.c) + +### `t_list *resolve_path(t_list *tokens)` +- トークンリストを走査し、ワイルドカード展開・相対パス解決を行う +- prev/currentでリストを辿り、ワイルドカード時は`ft_lstreplace`で置換 +- パス時はcontent差し替え +- 先頭トークンが置換された場合は新しいheadを返す + +### `static bool has_wildcard(const char *str)` +- 文字列に `WILDCARD('*')` が含まれるか判定 + +### `static bool has_path(const char *str)` +- 文字列に `/` が含まれるか判定(パスとみなせるか) + +### `static t_list *resolve_wildcard(const char *token)` +- 単一トークンのワイルドカード解決 +- dir部とpattern部に分割 → to_absolute_path → get_directory_entries → filter_pattern → フルパス構築 + +### `static t_list *build_full_paths(t_list *matches, const char *abs_dir)` +- マッチしたファイル名リストに `abs_dir + "/"` を付与してフルパスリストを構築 + +## Makefileへの変更 +`SRCS_MAND` に以下を追加: +``` +src/component/path_resolve/path_resolve.c +src/checker/resolve_checker.c +``` + +## minishell.hへの変更 +- `#include "path_resolve.h"` を追加 +- `void resolve_checker(char *input, t_shell_table *shell_table);` を宣言に追加 + +## 実装後の検証 +実装完了後、必ず以下を実行してnorminetteに準拠していることを確認する: +```bash +docker compose exec minishell norminette src/component/path_resolve/ src/checker/resolve_checker.c includes/path_resolve.h +``` diff --git a/includes/minishell.h b/includes/minishell.h index a8fc1f9..2735969 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -18,6 +18,7 @@ # include "libft.h" # include "parser.h" # include "prompt.h" +# include "path.h" # include "remove_quotes.h" # include "shell_table.h" # include "tokenize.h" @@ -35,5 +36,7 @@ void path_checker(char *input, t_shell_table *shell_table); void builtin_checker(char *input, t_shell_table *shell_table); void expand_checker(char *input, t_shell_table *shell_table); void remove_quotes_checker(char *input, t_shell_table *shell_table); +void wildcard_checker(char *input, t_shell_table *shell_table); +void relative_path_checker(char *input, t_shell_table *shell_table); #endif diff --git a/includes/path.h b/includes/path.h index 7f42858..0bf8b15 100644 --- a/includes/path.h +++ b/includes/path.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* path.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ +/* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/12/01 00:00:00 by surayama #+# #+# */ -/* Updated: 2026/03/03 16:57:47 by kjikuhar ### ########.fr */ +/* Updated: 2026/03/03 17:03:25 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,9 +19,11 @@ # include # include -char *to_absolute(const char *path); +char *to_absolute_path(const char *path); t_list *append_path(t_list **dest, const char *content); -t_list *append_path_list(t_list **dest, const char *content); +t_list *resolve_wildcard_path(t_list *tokens); +t_list *resolve_relative_path(t_list *tokens); +t_list *resolve_wildcard(const char *token); char *join_path(const char *path_before, const char *path_after); #endif diff --git a/src/builtin/cd.c b/src/builtin/cd.c index 4bc5e12..2377171 100644 --- a/src/builtin/cd.c +++ b/src/builtin/cd.c @@ -6,7 +6,7 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/12/01 00:48:09 by surayama #+# #+# */ -/* Updated: 2026/01/22 19:50:36 by surayama ### ########.fr */ +/* Updated: 2026/03/03 12:41:23 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -32,7 +32,7 @@ int cd(t_list *argv, t_shell_table *shell_table) return (by_move_to_home(shell_table)); if (ft_strncmp((char *)argv->next->content, "-", 2) == 0) return (by_move_to_oldpwd(shell_table)); - return (move_to_path(to_absolute((char *)argv->next->content), + return (move_to_path(to_absolute_path((char *)argv->next->content), shell_table)); } return (SUCCESS); diff --git a/src/checker/path_checker.c b/src/checker/path_checker.c index 7dbaf7a..4436e21 100644 --- a/src/checker/path_checker.c +++ b/src/checker/path_checker.c @@ -6,7 +6,7 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/12/01 00:00:00 by surayama #+# #+# */ -/* Updated: 2025/12/01 13:57:16 by surayama ### ########.fr */ +/* Updated: 2026/03/03 12:41:23 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -30,7 +30,7 @@ void path_checker(char *input, t_shell_table *shell_table) } printf("\n=== Path Checker ===\n"); printf("Input: %s\n", input); - absolute_path = to_absolute(input); + absolute_path = to_absolute_path(input); if (absolute_path) { printf("Absolute Path: %s\n", absolute_path); diff --git a/src/checker/relative_path_checker.c b/src/checker/relative_path_checker.c new file mode 100644 index 0000000..55d3216 --- /dev/null +++ b/src/checker/relative_path_checker.c @@ -0,0 +1,62 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* relative_path_checker.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/03/03 13:00:00 by surayama #+# #+# */ +/* Updated: 2026/03/03 13:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +static void on_exit_token(t_list *token_list); +static void print_tokens(t_list *token_list, const char *title); + +void relative_path_checker(char *input, t_shell_table *shell_table) +{ + t_list *token_list; + t_list *result; + + (void)shell_table; + token_list = tokenize(input); + if (!token_list) + { + ft_putstr_fd("Error: tokenize failed\n", STDOUT_FILENO); + return ; + } + if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) + on_exit_token(token_list); + print_tokens(token_list, "Before resolve_relative_path"); + result = resolve_relative_path(token_list); + print_tokens(result, "After resolve_relative_path"); + ft_lstclear(&result, free); +} + +static void print_tokens(t_list *token_list, const char *title) +{ + t_list *current; + int index; + char *content; + + index = 0; + current = token_list; + printf("\n%s:\n", title); + while (current) + { + content = current->content; + printf("[%d] \"%s\"\n", index, content); + current = current->next; + index++; + } + printf("\n"); +} + +static void on_exit_token(t_list *token_list) +{ + printf("exit\n"); + ft_lstclear(&token_list, free); + exit(0); +} diff --git a/src/checker/wildcard_checker.c b/src/checker/wildcard_checker.c new file mode 100644 index 0000000..40eea38 --- /dev/null +++ b/src/checker/wildcard_checker.c @@ -0,0 +1,68 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* wildcard_checker.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/03/03 13:00:00 by surayama #+# #+# */ +/* Updated: 2026/03/03 13:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +static void on_exit_token(t_list *token_list); +static void print_tokens(t_list *token_list, const char *title); + +void wildcard_checker(char *input, t_shell_table *shell_table) +{ + t_list *token_list; + t_list *result; + + (void)shell_table; + token_list = tokenize(input); + if (!token_list) + { + ft_putstr_fd("Error: tokenize failed\n", STDOUT_FILENO); + return ; + } + if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) + on_exit_token(token_list); + print_tokens(token_list, "Before resolve_wildcard_path"); + result = resolve_wildcard_path(token_list); + if (!result) + { + ft_putstr_fd("Error: resolve_wildcard_path failed\n", STDOUT_FILENO); + ft_lstclear(&token_list, free); + return ; + } + print_tokens(result, "After resolve_wildcard_path"); + ft_lstclear(&result, free); +} + +static void print_tokens(t_list *token_list, const char *title) +{ + t_list *current; + int index; + char *content; + + index = 0; + current = token_list; + printf("\n%s:\n", title); + while (current) + { + content = current->content; + printf("[%d] \"%s\"\n", index, content); + current = current->next; + index++; + } + printf("\n"); +} + +static void on_exit_token(t_list *token_list) +{ + printf("exit\n"); + ft_lstclear(&token_list, free); + exit(0); +} diff --git a/src/component/path/resolve_relative_path.c b/src/component/path/resolve_relative_path.c new file mode 100644 index 0000000..1a8a288 --- /dev/null +++ b/src/component/path/resolve_relative_path.c @@ -0,0 +1,43 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* resolve_relative_path.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/03/03 13:00:00 by surayama #+# #+# */ +/* Updated: 2026/03/03 13:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "path.h" +#include + +static bool has_path(const char *str); + +t_list *resolve_relative_path(t_list *tokens) +{ + t_list *current; + char *abs_path; + + current = tokens; + while (current) + { + if (has_path((char *)current->content)) + { + abs_path = to_absolute_path((char *)current->content); + if (abs_path) + { + free(current->content); + current->content = abs_path; + } + } + current = current->next; + } + return (tokens); +} + +static bool has_path(const char *str) +{ + return (ft_strchr(str, '/') != NULL); +} diff --git a/src/component/path/resolve_wildcard.c b/src/component/path/resolve_wildcard.c new file mode 100644 index 0000000..025af4c --- /dev/null +++ b/src/component/path/resolve_wildcard.c @@ -0,0 +1,86 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* resolve_wildcard.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/03/03 13:00:00 by surayama #+# #+# */ +/* Updated: 2026/03/03 13:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "path.h" +#include "pattern.h" +#include "directory.h" + +static t_list *get_matches(const char *abs_dir, const char *pattern); +static t_list *build_full_paths(t_list *matches, const char *abs_dir); + +t_list *resolve_wildcard(const char *token) +{ + char *slash; + char *dir; + char *abs_dir; + t_list *result; + + slash = ft_strrchr(token, '/'); + if (slash) + dir = ft_substr(token, 0, slash - token + 1); + else + dir = ft_strdup("."); + abs_dir = to_absolute_path(dir); + free(dir); + if (!abs_dir) + return (NULL); + if (slash) + result = get_matches(abs_dir, slash + 1); + else + result = get_matches(abs_dir, token); + free(abs_dir); + return (result); +} + +static t_list *get_matches(const char *abs_dir, const char *pattern) +{ + t_list *entries; + t_list *matches; + t_list *result; + + if (get_directory_entries(abs_dir, pattern[0] == '.', &entries) != SUCCESS) + return (NULL); + matches = filter_pattern(entries, pattern); + ft_lstclear(&entries, free); + result = build_full_paths(matches, abs_dir); + ft_lstclear(&matches, free); + return (result); +} + +static t_list *build_full_paths(t_list *matches, const char *abs_dir) +{ + t_list *result; + t_list *current; + t_list *node; + char *dir_slash; + char *full_path; + + result = NULL; + dir_slash = ft_strjoin(abs_dir, "/"); + if (!dir_slash) + return (NULL); + current = matches; + while (current) + { + full_path = ft_strjoin(dir_slash, (char *)current->content); + node = ft_lstnew(full_path); + if (!node) + { + free(full_path); + break ; + } + ft_lstadd_back(&result, node); + current = current->next; + } + free(dir_slash); + return (result); +} diff --git a/src/component/path/resolve_wildcard_path.c b/src/component/path/resolve_wildcard_path.c new file mode 100644 index 0000000..cadbf6f --- /dev/null +++ b/src/component/path/resolve_wildcard_path.c @@ -0,0 +1,54 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* resolve_wildcard_path.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/03/03 13:00:00 by surayama #+# #+# */ +/* Updated: 2026/03/03 13:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "path.h" +#include "pattern.h" +#include + +static bool has_wildcard(const char *str); +static t_list *handle_wildcard(t_list *prev, t_list *current, t_list **head); + +t_list *resolve_wildcard_path(t_list *tokens) +{ + t_list *prev; + t_list *current; + + prev = NULL; + current = tokens; + while (current) + { + if (has_wildcard((char *)current->content)) + prev = handle_wildcard(prev, current, &tokens); + else + prev = current; + current = prev->next; + } + return (tokens); +} + +static bool has_wildcard(const char *str) +{ + return (ft_strchr(str, WILDCARD) != NULL); +} + +static t_list *handle_wildcard(t_list *prev, t_list *current, t_list **head) +{ + t_list *resolved; + + resolved = resolve_wildcard((char *)current->content); + if (!resolved) + return (current); + ft_lstreplace(prev, current, resolved); + if (!prev) + *head = resolved; + return (ft_lstlast(resolved)); +} diff --git a/src/component/path/to_absolute.c b/src/component/path/to_absolute_path.c similarity index 93% rename from src/component/path/to_absolute.c rename to src/component/path/to_absolute_path.c index 03d171b..1a3ba03 100644 --- a/src/component/path/to_absolute.c +++ b/src/component/path/to_absolute_path.c @@ -1,12 +1,12 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* to_absolute.c :+: :+: :+: */ +/* to_absolute_path.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ +/* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/12/01 00:00:00 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ +/* Updated: 2026/03/03 13:10:31 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,7 +17,7 @@ static t_list *split_path_to_list(const char *path); static void consume_head(t_list **path_list); static char *list_to_path(t_list *resolved_path); -char *to_absolute(const char *path) +char *to_absolute_path(const char *path) { t_list *path_list; t_list *resolved_path; diff --git a/src/main.c b/src/main.c index 331bb14..620718f 100644 --- a/src/main.c +++ b/src/main.c @@ -6,7 +6,7 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:13:47 by kjikuhar #+# #+# */ -/* Updated: 2026/02/13 23:37:48 by surayama ### ########.fr */ +/* Updated: 2026/03/03 13:03:53 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -36,7 +36,7 @@ int main_dev(int argc, char const **argv, char *const envp[]) if (!shell_table) return (1); shell_table_checker(shell_table); - prompt(expand_checker, shell_table); + prompt(wildcard_checker, shell_table); st_destroy(shell_table); return (0); } From 5d209ad05c5ceb47d56cf390fe5b8017de57d152 Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Tue, 3 Mar 2026 19:42:30 +0900 Subject: [PATCH 130/173] =?UTF-8?q?fix:=20export=20=E3=81=AE=E8=BF=94?= =?UTF-8?q?=E3=82=8A=E5=80=A4=E3=82=92=E7=B5=82=E4=BA=86=E3=82=B9=E3=83=86?= =?UTF-8?q?=E3=83=BC=E3=82=BF=E3=82=B9=20(0/1)=20=E3=81=AB=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=20(#62)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ERROR (-1) を返すと終了ステータスが 255 になるため、 シェル規約に合わせて成功時 0、失敗時 1 を返すように変更。 Closes #60 Co-authored-by: Claude Opus 4.6 --- src/builtin/export.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/builtin/export.c b/src/builtin/export.c index 49dd388..8812355 100644 --- a/src/builtin/export.c +++ b/src/builtin/export.c @@ -6,7 +6,7 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/29 20:29:03 by surayama #+# #+# */ -/* Updated: 2025/12/06 16:20:07 by surayama ### ########.fr */ +/* Updated: 2026/03/03 19:31:33 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -21,21 +21,21 @@ static char *get_value_from_assignment(const char *assignment); int export(t_list *argv, t_shell_table *shell_table) { if (!argv || !argv->content) - return (ERROR); + return (1); skip_head_node(&argv); if (!argv) { st_print_env(shell_table); - return (SUCCESS); + return (0); } while (argv) { if (insert_assignment(shell_table, (const char *)argv->content) == ERROR) - return (ERROR); + return (1); skip_head_node(&argv); } - return (SUCCESS); + return (0); } static void skip_head_node(t_list **argv) From cfa843b7201affa9693a637b1ac2452cb39029fb Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Tue, 3 Mar 2026 19:43:25 +0900 Subject: [PATCH 131/173] =?UTF-8?q?parser=20=E2=86=92=20parse=20=E3=81=AB?= =?UTF-8?q?=E3=83=AA=E3=83=8D=E3=83=BC=E3=83=A0=EF=BC=88=E4=BB=96=E3=83=91?= =?UTF-8?q?=E3=82=A4=E3=83=97=E3=83=A9=E3=82=A4=E3=83=B3=E9=96=A2=E6=95=B0?= =?UTF-8?q?=E3=81=A8=E5=91=BD=E5=90=8D=E7=B5=B1=E4=B8=80=EF=BC=89=20(#63)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tokenize, expand と統一するため、parser ディレクトリ・ファイル・関数名を 動詞形 parse に変更。データ構造名 (t_ast, t_cmd 等) は変更なし。 Co-authored-by: Claude Opus 4.6 --- .claude/CLAUDE.md | 10 ++++----- Makefile | 22 +++++++++---------- includes/minishell.h | 4 ++-- includes/{parser.h => parse.h} | 8 +++---- .../{parser_checker.c => parse_checker.c} | 6 ++--- src/{parser/parser.c => parse/parse.c} | 6 ++--- src/{parser => parse}/utils/add_to_cmd.c | 2 +- src/{parser => parse}/utils/free_ast.c | 2 +- src/{parser => parse}/utils/new_ast_node.c | 2 +- src/{parser => parse}/utils/new_cmd.c | 2 +- src/{parser => parse}/utils/new_redir.c | 2 +- src/{parser => parse}/utils/print_ast.c | 2 +- src/{parser => parse}/utils/print_ast_utils.c | 2 +- .../utils/print_ast_utils2.c | 2 +- src/{parser => parse}/utils/token_check.c | 2 +- 15 files changed, 37 insertions(+), 37 deletions(-) rename includes/{parser.h => parse.h} (95%) rename src/checker/{parser_checker.c => parse_checker.c} (89%) rename src/{parser/parser.c => parse/parse.c} (95%) rename src/{parser => parse}/utils/add_to_cmd.c (98%) rename src/{parser => parse}/utils/free_ast.c (98%) rename src/{parser => parse}/utils/new_ast_node.c (98%) rename src/{parser => parse}/utils/new_cmd.c (98%) rename src/{parser => parse}/utils/new_redir.c (98%) rename src/{parser => parse}/utils/print_ast.c (99%) rename src/{parser => parse}/utils/print_ast_utils.c (98%) rename src/{parser => parse}/utils/print_ast_utils2.c (99%) rename src/{parser => parse}/utils/token_check.c (98%) diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 22aa007..3bd9f39 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -35,7 +35,7 @@ make # コンテナ内でビルド シェルは以下のインタープリタパイプラインに従う: ``` -Input → tokenize() → heredoc() → variable_expand() → remove_quotes() → parser() → AST → execute +Input → tokenize() → heredoc() → variable_expand() → remove_quotes() → parse() → AST → execute ``` ### パイプラインの各段階 @@ -46,7 +46,7 @@ Input → tokenize() → heredoc() → variable_expand() → remove_quotes() → 3. **クォート削除** (`src/component/remove_quotes/`) — 展開後のトークンからクォート文字を除去。 -4. **parser** (`src/parser/`) — 再帰下降パーサ。二分木ASTを生成。ノード型: `PIPE`(内部ノード)、`CMD`(葉ノード、`t_cmd` に argv リストとリダイレクションリストを持つ)。 +4. **parse** (`src/parse/`) — 再帰下降パーサ。二分木ASTを生成。ノード型: `PIPE`(内部ノード)、`CMD`(葉ノード、`t_cmd` に argv リストとリダイレクションリストを持つ)。 5. **実行** — 未実装。エントリポイントは `src/callback/on_input.c`。 @@ -60,9 +60,9 @@ Input → tokenize() → heredoc() → variable_expand() → remove_quotes() → ### 主要データ構造 (`includes/`) - `t_shell_table` / `t_shell_node` — 環境変数ハッシュテーブル (`shell_table.h`) -- `t_ast` — AST木。`t_ast_type` (PIPE/CMD) と left/right 子ノード (`parser.h`) -- `t_cmd` — コマンド。`t_list *argv` と `t_list *redirs` を持つ (`parser.h`) -- `t_redir` — リダイレクション。`t_redir_kind` (R_IN, R_OUT_TRUNC, R_OUT_APPEND) と filename (`parser.h`) +- `t_ast` — AST木。`t_ast_type` (PIPE/CMD) と left/right 子ノード (`parse.h`) +- `t_cmd` — コマンド。`t_list *argv` と `t_list *redirs` を持つ (`parse.h`) +- `t_redir` — リダイレクション。`t_redir_kind` (R_IN, R_OUT_TRUNC, R_OUT_APPEND) と filename (`parse.h`) - `t_list` — libft のリンクリスト。トークンリストや引数リストとして全体で使用 ## Critical Rules diff --git a/Makefile b/Makefile index cb0213e..9a591df 100644 --- a/Makefile +++ b/Makefile @@ -68,7 +68,7 @@ SRCS_MAND := src/main.c \ src/checker/tokenize_checker.c \ src/checker/heredoc_checker.c \ src/checker/shell_table_checker.c \ - src/checker/parser_checker.c \ + src/checker/parse_checker.c \ src/checker/path_checker.c \ src/checker/directory_checker.c \ src/checker/expand_checker.c \ @@ -91,16 +91,16 @@ SRCS_MAND := src/main.c \ src/tokenize/store/free_store.c \ src/tokenize/store/push_token.c \ src/tokenize/store/add_buffer.c \ - src/parser/parser.c \ - src/parser/utils/add_to_cmd.c \ - src/parser/utils/new_ast_node.c \ - src/parser/utils/new_cmd.c \ - src/parser/utils/new_redir.c \ - src/parser/utils/token_check.c \ - src/parser/utils/free_ast.c \ - src/parser/utils/print_ast.c \ - src/parser/utils/print_ast_utils.c \ - src/parser/utils/print_ast_utils2.c \ + src/parse/parse.c \ + src/parse/utils/add_to_cmd.c \ + src/parse/utils/new_ast_node.c \ + src/parse/utils/new_cmd.c \ + src/parse/utils/new_redir.c \ + src/parse/utils/token_check.c \ + src/parse/utils/free_ast.c \ + src/parse/utils/print_ast.c \ + src/parse/utils/print_ast_utils.c \ + src/parse/utils/print_ast_utils2.c \ src/component/heredoc/heredoc.c \ src/component/heredoc/heredoc_prompt.c \ src/component/heredoc/tmpfile.c \ diff --git a/includes/minishell.h b/includes/minishell.h index 2735969..3f45bdf 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -16,7 +16,7 @@ # include "constants.h" # include "heredoc.h" # include "libft.h" -# include "parser.h" +# include "parse.h" # include "prompt.h" # include "path.h" # include "remove_quotes.h" @@ -30,7 +30,7 @@ void on_input(char *input, t_shell_table *shell_table); void tokenize_checker(char *input, t_shell_table *shell_table); void heredoc_checker(char *input, t_shell_table *shell_table); void shell_table_checker(t_shell_table *shell_table); -void parser_checker(char *input, t_shell_table *shell_table); +void parse_checker(char *input, t_shell_table *shell_table); void directory_checker(char *input, t_shell_table *shell_table); void path_checker(char *input, t_shell_table *shell_table); void builtin_checker(char *input, t_shell_table *shell_table); diff --git a/includes/parser.h b/includes/parse.h similarity index 95% rename from includes/parser.h rename to includes/parse.h index 8d1529f..2a7fff7 100644 --- a/includes/parser.h +++ b/includes/parse.h @@ -1,7 +1,7 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* parser.h :+: :+: :+: */ +/* parse.h :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ @@ -10,8 +10,8 @@ /* */ /* ************************************************************************** */ -#ifndef PARSER_H -# define PARSER_H +#ifndef PARSE_H +# define PARSE_H # include "libft.h" # include "constants.h" @@ -59,7 +59,7 @@ typedef struct s_ast } t_ast; /* main function------------------------------------------------------------- */ -t_ast *parser(t_list *token_head); +t_ast *parse(t_list *token_head); /* AST's token utils--------------------------------------------------------- */ bool is_word(const t_list *node); diff --git a/src/checker/parser_checker.c b/src/checker/parse_checker.c similarity index 89% rename from src/checker/parser_checker.c rename to src/checker/parse_checker.c index 894678f..5fecc17 100644 --- a/src/checker/parser_checker.c +++ b/src/checker/parse_checker.c @@ -1,7 +1,7 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* parser_checker.c :+: :+: :+: */ +/* parse_checker.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ @@ -19,7 +19,7 @@ static void on_exit_token(t_list *token_list) exit(0); } -void parser_checker(char *input, t_shell_table *shell_table) +void parse_checker(char *input, t_shell_table *shell_table) { t_list *token_list; t_ast *ast_root; @@ -33,7 +33,7 @@ void parser_checker(char *input, t_shell_table *shell_table) } if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) on_exit_token(token_list); - ast_root = parser(token_list); + ast_root = parse(token_list); print_ast(ast_root); free_ast(ast_root); ft_lstclear(&token_list, free); diff --git a/src/parser/parser.c b/src/parse/parse.c similarity index 95% rename from src/parser/parser.c rename to src/parse/parse.c index 6b2f976..7553bc4 100644 --- a/src/parser/parser.c +++ b/src/parse/parse.c @@ -1,7 +1,7 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* parser.c :+: :+: :+: */ +/* parse.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ @@ -10,7 +10,7 @@ /* */ /* ************************************************************************** */ -#include "parser.h" +#include "parse.h" static t_redir_kind find_redir_kind(t_list *current) { @@ -91,7 +91,7 @@ static t_ast *parse_pipeline(t_list **current) return (left); } -t_ast *parser(t_list *token_head) +t_ast *parse(t_list *token_head) { t_list *current; t_ast *root; diff --git a/src/parser/utils/add_to_cmd.c b/src/parse/utils/add_to_cmd.c similarity index 98% rename from src/parser/utils/add_to_cmd.c rename to src/parse/utils/add_to_cmd.c index dbfa85a..15de621 100644 --- a/src/parser/utils/add_to_cmd.c +++ b/src/parse/utils/add_to_cmd.c @@ -10,7 +10,7 @@ /* */ /* ************************************************************************** */ -#include "parser.h" +#include "parse.h" bool add_redir_to_cmd(t_cmd *cmd, t_redir_kind kind, const char *file) { diff --git a/src/parser/utils/free_ast.c b/src/parse/utils/free_ast.c similarity index 98% rename from src/parser/utils/free_ast.c rename to src/parse/utils/free_ast.c index 58e7281..1a73608 100644 --- a/src/parser/utils/free_ast.c +++ b/src/parse/utils/free_ast.c @@ -10,7 +10,7 @@ /* */ /* ************************************************************************** */ -#include "parser.h" +#include "parse.h" static void free_redir(void *ptr) { diff --git a/src/parser/utils/new_ast_node.c b/src/parse/utils/new_ast_node.c similarity index 98% rename from src/parser/utils/new_ast_node.c rename to src/parse/utils/new_ast_node.c index 123bf37..0d99e94 100644 --- a/src/parser/utils/new_ast_node.c +++ b/src/parse/utils/new_ast_node.c @@ -10,7 +10,7 @@ /* */ /* ************************************************************************** */ -#include "parser.h" +#include "parse.h" t_ast *new_ast_node(t_ast_type type) { diff --git a/src/parser/utils/new_cmd.c b/src/parse/utils/new_cmd.c similarity index 98% rename from src/parser/utils/new_cmd.c rename to src/parse/utils/new_cmd.c index 65cad92..070e50d 100644 --- a/src/parser/utils/new_cmd.c +++ b/src/parse/utils/new_cmd.c @@ -10,7 +10,7 @@ /* */ /* ************************************************************************** */ -#include "parser.h" +#include "parse.h" t_cmd *new_cmd(void) { diff --git a/src/parser/utils/new_redir.c b/src/parse/utils/new_redir.c similarity index 98% rename from src/parser/utils/new_redir.c rename to src/parse/utils/new_redir.c index f3b608c..7f37194 100644 --- a/src/parser/utils/new_redir.c +++ b/src/parse/utils/new_redir.c @@ -10,7 +10,7 @@ /* */ /* ************************************************************************** */ -#include "parser.h" +#include "parse.h" t_redir *new_redir(t_redir_kind kind, const char *filename) { diff --git a/src/parser/utils/print_ast.c b/src/parse/utils/print_ast.c similarity index 99% rename from src/parser/utils/print_ast.c rename to src/parse/utils/print_ast.c index f4215d0..3351d58 100644 --- a/src/parser/utils/print_ast.c +++ b/src/parse/utils/print_ast.c @@ -10,7 +10,7 @@ /* */ /* ************************************************************************** */ -#include "parser.h" +#include "parse.h" void print_pipe_node(t_ast *node, const char *prefix, bool is_last) { diff --git a/src/parser/utils/print_ast_utils.c b/src/parse/utils/print_ast_utils.c similarity index 98% rename from src/parser/utils/print_ast_utils.c rename to src/parse/utils/print_ast_utils.c index fbe5e19..ef8486d 100644 --- a/src/parser/utils/print_ast_utils.c +++ b/src/parse/utils/print_ast_utils.c @@ -10,7 +10,7 @@ /* */ /* ************************************************************************** */ -#include "parser.h" +#include "parse.h" void print_branch_line(const char *prefix, bool is_last, const char *text) { diff --git a/src/parser/utils/print_ast_utils2.c b/src/parse/utils/print_ast_utils2.c similarity index 99% rename from src/parser/utils/print_ast_utils2.c rename to src/parse/utils/print_ast_utils2.c index b71327c..baf27bb 100644 --- a/src/parser/utils/print_ast_utils2.c +++ b/src/parse/utils/print_ast_utils2.c @@ -10,7 +10,7 @@ /* */ /* ************************************************************************** */ -#include "parser.h" +#include "parse.h" void print_redir_entry(t_redir *redir, int index) { diff --git a/src/parser/utils/token_check.c b/src/parse/utils/token_check.c similarity index 98% rename from src/parser/utils/token_check.c rename to src/parse/utils/token_check.c index 60b99d7..9ce37bd 100644 --- a/src/parser/utils/token_check.c +++ b/src/parse/utils/token_check.c @@ -10,7 +10,7 @@ /* */ /* ************************************************************************** */ -#include "parser.h" +#include "parse.h" bool is_word(const t_list *node) { From c087ef1aa30865e2b8d63d0199ed84f1ccd1b86d Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Tue, 3 Mar 2026 20:01:13 +0900 Subject: [PATCH 132/173] =?UTF-8?q?expand=20=E3=83=AC=E3=82=A4=E3=83=A4?= =?UTF-8?q?=E3=83=BC=E3=81=AE=E7=B5=B1=E5=90=88=E3=81=A8=E5=91=BD=E5=90=8D?= =?UTF-8?q?=E8=A6=8F=E7=B4=84=E3=81=AE=E7=B5=B1=E4=B8=80=20(#61)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: expand layer * refactor * finished --- Makefile | 33 +++++----- includes/directory.h | 4 +- includes/{variable_expand.h => expand.h} | 17 +++-- includes/minishell.h | 2 +- includes/path.h | 4 +- includes/pattern.h | 23 ------- src/checker/directory_checker.c | 12 ++-- src/checker/expand_checker.c | 7 +-- src/checker/remove_quotes_checker.c | 2 +- src/checker/wildcard_checker.c | 8 +-- ...t_directory_entries.c => list_directory.c} | 2 +- ...l_entries.c => list_directory_recursive.c} | 26 ++------ src/component/pattern/filter_pattern.c | 62 ------------------- src/expand/expand.c | 30 +++++++++ .../expand_parameter/expand_parameter.c} | 6 +- .../expand_parameter_internal.h} | 4 +- .../state/in_double_quote_expand.c | 4 +- .../state/in_normal_expand.c | 4 +- .../state/in_single_quote_expand.c | 4 +- .../expand_parameter}/state/on_error_expand.c | 4 +- .../state/on_success_expand.c | 4 +- .../store/add_buffer_expand.c | 4 +- .../store/free_store_expand.c | 4 +- .../store/get_key_length_expand.c | 2 +- .../store/push_token_expand.c | 4 +- .../expand_remove_quotes.c} | 4 +- src/expand/expand_tilde/expand_tilde.c | 59 ++++++++++++++++++ .../expand_wildcard/expand_wildcard.c} | 9 ++- .../expand_wildcard_internal.h | 15 +++-- .../expand_wildcard}/resolve_wildcard.c | 60 ++++++++++++++++-- src/main.c | 4 +- 31 files changed, 233 insertions(+), 194 deletions(-) rename includes/{variable_expand.h => expand.h} (59%) delete mode 100644 includes/pattern.h rename src/component/directory/{get_directory_entries.c => list_directory.c} (96%) rename src/component/directory/{get_directory_all_entries.c => list_directory_recursive.c} (82%) delete mode 100644 src/component/pattern/filter_pattern.c create mode 100644 src/expand/expand.c rename src/{component/variable_expand/variable_expand.c => expand/expand_parameter/expand_parameter.c} (96%) rename src/{component/variable_expand/variable_expand_internal.h => expand/expand_parameter/expand_parameter_internal.h} (96%) rename src/{component/variable_expand => expand/expand_parameter}/state/in_double_quote_expand.c (97%) rename src/{component/variable_expand => expand/expand_parameter}/state/in_normal_expand.c (97%) rename src/{component/variable_expand => expand/expand_parameter}/state/in_single_quote_expand.c (95%) rename src/{component/variable_expand => expand/expand_parameter}/state/on_error_expand.c (93%) rename src/{component/variable_expand => expand/expand_parameter}/state/on_success_expand.c (94%) rename src/{component/variable_expand => expand/expand_parameter}/store/add_buffer_expand.c (94%) rename src/{component/variable_expand => expand/expand_parameter}/store/free_store_expand.c (93%) rename src/{component/variable_expand => expand/expand_parameter}/store/get_key_length_expand.c (97%) rename src/{component/variable_expand => expand/expand_parameter}/store/push_token_expand.c (96%) rename src/{component/remove_quotes/remove_quotes.c => expand/expand_remove_quotes/expand_remove_quotes.c} (97%) create mode 100644 src/expand/expand_tilde/expand_tilde.c rename src/{component/path/resolve_wildcard_path.c => expand/expand_wildcard/expand_wildcard.c} (90%) rename includes/remove_quotes.h => src/expand/expand_wildcard/expand_wildcard_internal.h (67%) rename src/{component/path => expand/expand_wildcard}/resolve_wildcard.c (62%) diff --git a/Makefile b/Makefile index 9a591df..ddc3157 100644 --- a/Makefile +++ b/Makefile @@ -112,26 +112,27 @@ SRCS_MAND := src/main.c \ src/component/shell_table/shell_print.c \ src/component/shell_table/build_shell_table.c \ src/component/shell_table/export_envp.c \ - src/component/pattern/filter_pattern.c \ - src/component/directory/get_directory_entries.c \ - src/component/directory/get_directory_all_entries.c \ + src/component/directory/list_directory.c \ + src/component/directory/list_directory_recursive.c \ src/component/path/to_absolute_path.c \ src/component/path/join_path.c \ src/component/path/append_path.c \ - src/component/path/resolve_wildcard_path.c \ src/component/path/resolve_relative_path.c \ - src/component/path/resolve_wildcard.c \ - src/component/variable_expand/variable_expand.c \ - src/component/variable_expand/state/in_normal_expand.c \ - src/component/variable_expand/state/in_double_quote_expand.c \ - src/component/variable_expand/state/in_single_quote_expand.c \ - src/component/variable_expand/state/on_success_expand.c \ - src/component/variable_expand/state/on_error_expand.c \ - src/component/variable_expand/store/push_token_expand.c \ - src/component/variable_expand/store/add_buffer_expand.c \ - src/component/variable_expand/store/get_key_length_expand.c \ - src/component/variable_expand/store/free_store_expand.c \ - src/component/remove_quotes/remove_quotes.c \ + src/expand/expand.c \ + src/expand/expand_parameter/expand_parameter.c \ + src/expand/expand_parameter/state/in_normal_expand.c \ + src/expand/expand_parameter/state/in_double_quote_expand.c \ + src/expand/expand_parameter/state/in_single_quote_expand.c \ + src/expand/expand_parameter/state/on_success_expand.c \ + src/expand/expand_parameter/state/on_error_expand.c \ + src/expand/expand_parameter/store/push_token_expand.c \ + src/expand/expand_parameter/store/add_buffer_expand.c \ + src/expand/expand_parameter/store/get_key_length_expand.c \ + src/expand/expand_parameter/store/free_store_expand.c \ + src/expand/expand_tilde/expand_tilde.c \ + src/expand/expand_wildcard/resolve_wildcard.c \ + src/expand/expand_wildcard/expand_wildcard.c \ + src/expand/expand_remove_quotes/expand_remove_quotes.c \ SRCS_BONUS := diff --git a/includes/directory.h b/includes/directory.h index b02e7f3..59e22da 100644 --- a/includes/directory.h +++ b/includes/directory.h @@ -21,9 +21,9 @@ # include # include -int get_directory_entries(const char *path, bool include_hidden, +int list_directory(const char *path, bool include_hidden, t_list **entries); -int get_directory_all_entries(const char *path, bool include_hidden, +int list_directory_recursive(const char *path, bool include_hidden, t_list **entries); #endif diff --git a/includes/variable_expand.h b/includes/expand.h similarity index 59% rename from includes/variable_expand.h rename to includes/expand.h index 3f37991..c6b51b6 100644 --- a/includes/variable_expand.h +++ b/includes/expand.h @@ -1,22 +1,27 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* variable_expand.h :+: :+: :+: */ +/* expand.h :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2026/01/22 21:37:05 by surayama #+# #+# */ -/* Updated: 2026/02/05 16:29:26 by surayama ### ########.fr */ +/* Created: 2026/03/03 17:13:55 by surayama #+# #+# */ +/* Updated: 2026/03/03 18:00:00 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ -#ifndef VARIABLE_EXPAND_H -# define VARIABLE_EXPAND_H +#ifndef EXPAND_H +# define EXPAND_H # include "constants.h" # include "libft.h" # include "shell_table.h" +# include -t_list *variable_expand(t_list *tokens, t_shell_table *shell_table); +t_list *expand(t_list *tokens, t_shell_table *shell_table); +t_list *expand_parameter(t_list *tokens, t_shell_table *shell_table); +t_list *expand_tilde(t_list *tokens, t_shell_table *shell_table); +t_list *expand_wildcard(t_list *tokens); +t_list *expand_remove_quotes(t_list *tokens); #endif diff --git a/includes/minishell.h b/includes/minishell.h index 3f45bdf..f835fbc 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -14,12 +14,12 @@ # define MINISHELL_H # include "constants.h" +# include "expand.h" # include "heredoc.h" # include "libft.h" # include "parse.h" # include "prompt.h" # include "path.h" -# include "remove_quotes.h" # include "shell_table.h" # include "tokenize.h" diff --git a/includes/path.h b/includes/path.h index 0bf8b15..cea2a5f 100644 --- a/includes/path.h +++ b/includes/path.h @@ -6,7 +6,7 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/12/01 00:00:00 by surayama #+# #+# */ -/* Updated: 2026/03/03 17:03:25 by surayama ### ########.fr */ +/* Updated: 2026/03/03 17:15:58 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -21,9 +21,7 @@ char *to_absolute_path(const char *path); t_list *append_path(t_list **dest, const char *content); -t_list *resolve_wildcard_path(t_list *tokens); t_list *resolve_relative_path(t_list *tokens); -t_list *resolve_wildcard(const char *token); char *join_path(const char *path_before, const char *path_after); #endif diff --git a/includes/pattern.h b/includes/pattern.h deleted file mode 100644 index a205a01..0000000 --- a/includes/pattern.h +++ /dev/null @@ -1,23 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* pattern.h :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/27 11:36:50 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:51 by kjikuhar ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#ifndef PATTERN_H -# define PATTERN_H - -# include "libft.h" -# include - -# define WILDCARD '*' - -t_list *filter_pattern(t_list *source, const char *pattern); - -#endif diff --git a/src/checker/directory_checker.c b/src/checker/directory_checker.c index cad6fd9..77a7575 100644 --- a/src/checker/directory_checker.c +++ b/src/checker/directory_checker.c @@ -36,19 +36,19 @@ void directory_checker(char *input, t_shell_table *shell_table) static void test_entries(const char *input) { - printf("\n=== Testing get_directory_entries ===\nPath: %s\n", input); - test_function(input, false, get_directory_entries, + printf("\n=== Testing list_directory ===\nPath: %s\n", input); + test_function(input, false, list_directory, "\n--- Without hidden files ---\nEntries"); - test_function(input, true, get_directory_entries, + test_function(input, true, list_directory, "\n--- With hidden files ---\nEntries"); } static void test_all_entries(const char *input) { - printf("\n=== Testing get_directory_all_entries ===\nPath: %s\n", input); - test_function(input, false, get_directory_all_entries, + printf("\n=== Testing list_directory_recursive ===\nPath: %s\n", input); + test_function(input, false, list_directory_recursive, "\n--- Without hidden files ---\nAll Entries (recursive)"); - test_function(input, true, get_directory_all_entries, + test_function(input, true, list_directory_recursive, "\n--- With hidden files ---\nAll Entries (recursive)"); } diff --git a/src/checker/expand_checker.c b/src/checker/expand_checker.c index e3eb0bb..98cd067 100644 --- a/src/checker/expand_checker.c +++ b/src/checker/expand_checker.c @@ -11,7 +11,6 @@ /* ************************************************************************** */ #include "minishell.h" -#include "variable_expand.h" static void on_exit_token(t_list *token_list); static void print_expanded_tokens(t_list *token_list); @@ -29,10 +28,10 @@ void expand_checker(char *input, t_shell_table *shell_table) } if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) on_exit_token(token_list); - expanded_tokens = variable_expand(token_list, shell_table); + expanded_tokens = expand(token_list, shell_table); if (!expanded_tokens) { - ft_putstr_fd("Error: variable_expand failed\n", STDOUT_FILENO); + ft_putstr_fd("Error: expand failed\n", STDOUT_FILENO); ft_lstclear(&token_list, free); return ; } @@ -48,7 +47,7 @@ static void print_expanded_tokens(t_list *token_list) index = 0; current = token_list; - printf("expanded_tokens:\n"); + printf("expanded:\n"); while (current) { content = current->content; diff --git a/src/checker/remove_quotes_checker.c b/src/checker/remove_quotes_checker.c index 91fb2ae..7713825 100644 --- a/src/checker/remove_quotes_checker.c +++ b/src/checker/remove_quotes_checker.c @@ -30,7 +30,7 @@ void remove_quotes_checker(char *input, t_shell_table *shell_table) if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) on_exit_token(token_list); print_tokens(token_list, "Before remove_quote"); - result = remove_quotes(token_list); + result = expand_remove_quotes(token_list); if (!result) { ft_putstr_fd("Error: remove_quote failed\n", STDOUT_FILENO); diff --git a/src/checker/wildcard_checker.c b/src/checker/wildcard_checker.c index 40eea38..7c70210 100644 --- a/src/checker/wildcard_checker.c +++ b/src/checker/wildcard_checker.c @@ -29,15 +29,15 @@ void wildcard_checker(char *input, t_shell_table *shell_table) } if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) on_exit_token(token_list); - print_tokens(token_list, "Before resolve_wildcard_path"); - result = resolve_wildcard_path(token_list); + print_tokens(token_list, "Before expand_wildcard"); + result = expand_wildcard(token_list); if (!result) { - ft_putstr_fd("Error: resolve_wildcard_path failed\n", STDOUT_FILENO); + ft_putstr_fd("Error: expand_wildcard failed\n", STDOUT_FILENO); ft_lstclear(&token_list, free); return ; } - print_tokens(result, "After resolve_wildcard_path"); + print_tokens(result, "After expand_wildcard"); ft_lstclear(&result, free); } diff --git a/src/component/directory/get_directory_entries.c b/src/component/directory/list_directory.c similarity index 96% rename from src/component/directory/get_directory_entries.c rename to src/component/directory/list_directory.c index 97bcea1..1b27507 100644 --- a/src/component/directory/get_directory_entries.c +++ b/src/component/directory/list_directory.c @@ -15,7 +15,7 @@ static int throw_error(void); static int append_entry(t_list **entries, const char *entry_name); -int get_directory_entries(const char *path, bool include_hidden, +int list_directory(const char *path, bool include_hidden, t_list **entries) { DIR *dir; diff --git a/src/component/directory/get_directory_all_entries.c b/src/component/directory/list_directory_recursive.c similarity index 82% rename from src/component/directory/get_directory_all_entries.c rename to src/component/directory/list_directory_recursive.c index 9c21831..1efc24e 100644 --- a/src/component/directory/get_directory_all_entries.c +++ b/src/component/directory/list_directory_recursive.c @@ -1,7 +1,7 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* get_directory_all_entries.c :+: :+: :+: */ +/* list_directory_recursive.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ @@ -11,15 +11,15 @@ /* ************************************************************************** */ #include "directory.h" +#include "path.h" static int throw_error(void); static int process_entry(const char *path, const char *name, bool include_hidden, t_list **entries); -static char *join_path(const char *dir, const char *name); static int read_directory_entries(DIR *dir, const char *path, bool include_hidden, t_list **entries); -int get_directory_all_entries(const char *path, bool include_hidden, +int list_directory_recursive(const char *path, bool include_hidden, t_list **entries) { DIR *dir; @@ -78,31 +78,13 @@ static int process_entry(const char *path, const char *name, free(full_path); return (SUCCESS); } - result = get_directory_all_entries(full_path, include_hidden, &sub_entries); + result = list_directory_recursive(full_path, include_hidden, &sub_entries); if (result == SUCCESS && sub_entries) ft_lstadd_back(entries, sub_entries); free(full_path); return (SUCCESS); } -static char *join_path(const char *dir, const char *name) -{ - char *temp; - char *result; - - temp = ft_strjoin(dir, "/"); - if (!temp) - return (NULL); - result = ft_strjoin(temp, name); - if (!result) - { - free(temp); - return (NULL); - } - free(temp); - return (result); -} - static int throw_error(void) { if (errno == ENOENT) diff --git a/src/component/pattern/filter_pattern.c b/src/component/pattern/filter_pattern.c deleted file mode 100644 index 0534b4b..0000000 --- a/src/component/pattern/filter_pattern.c +++ /dev/null @@ -1,62 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* filter_pattern.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/27 11:40:49 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "pattern.h" -#include - -static bool match_pattern(const char *str, const char *pattern); - -t_list *filter_pattern(t_list *source, const char *pattern) -{ - t_list *result; - t_list *current; - t_list *new_node; - - if (!source || !pattern) - return (NULL); - result = NULL; - current = source; - while (current) - { - if (match_pattern((const char *)current->content, pattern)) - { - new_node = ft_lstnew(ft_strdup((const char *)current->content)); - if (!new_node) - { - ft_lstclear(&result, free); - return (NULL); - } - ft_lstadd_back(&result, new_node); - } - current = current->next; - } - return (result); -} - -static bool match_pattern(const char *str, const char *pattern) -{ - if (*pattern == '\0') - return (*str == '\0'); - if (*pattern == WILDCARD) - { - while (*str) - { - if (match_pattern(str, pattern + 1)) - return (true); - str++; - } - return (match_pattern(str, pattern + 1)); - } - if (*str == *pattern) - return (match_pattern(str + 1, pattern + 1)); - return (false); -} diff --git a/src/expand/expand.c b/src/expand/expand.c new file mode 100644 index 0000000..ee342e4 --- /dev/null +++ b/src/expand/expand.c @@ -0,0 +1,30 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* expand.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/03/03 17:16:33 by surayama #+# #+# */ +/* Updated: 2026/03/03 17:54:02 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "expand.h" + +t_list *expand(t_list *tokens, t_shell_table *shell_table) +{ + tokens = expand_tilde(tokens, shell_table); + if (!tokens) + return (NULL); + tokens = expand_parameter(tokens, shell_table); + if (!tokens) + return (NULL); + tokens = expand_wildcard(tokens); + if (!tokens) + return (NULL); + tokens = expand_remove_quotes(tokens); + if (!tokens) + return (NULL); + return (tokens); +} diff --git a/src/component/variable_expand/variable_expand.c b/src/expand/expand_parameter/expand_parameter.c similarity index 96% rename from src/component/variable_expand/variable_expand.c rename to src/expand/expand_parameter/expand_parameter.c index 204ebac..cab4cb5 100644 --- a/src/component/variable_expand/variable_expand.c +++ b/src/expand/expand_parameter/expand_parameter.c @@ -10,8 +10,8 @@ /* */ /* ************************************************************************** */ -#include "variable_expand.h" -#include "variable_expand_internal.h" +#include "expand.h" +#include "expand_parameter_internal.h" static t_list *expand_token(char *token, t_shell_table *shell_table); static t_list *remove_current_token(t_list *tokens, t_list *prev_token, @@ -19,7 +19,7 @@ static t_list *remove_current_token(t_list *tokens, t_list *prev_token, static t_list *insert_expanded_token(t_list **tokens, t_list *prev_token, t_list *current_token, t_list *expanded_token); -t_list *variable_expand(t_list *tokens, t_shell_table *shell_table) +t_list *expand_parameter(t_list *tokens, t_shell_table *shell_table) { t_list *prev_token; t_list *current_token; diff --git a/src/component/variable_expand/variable_expand_internal.h b/src/expand/expand_parameter/expand_parameter_internal.h similarity index 96% rename from src/component/variable_expand/variable_expand_internal.h rename to src/expand/expand_parameter/expand_parameter_internal.h index 1f69ec7..fb58925 100644 --- a/src/component/variable_expand/variable_expand_internal.h +++ b/src/expand/expand_parameter/expand_parameter_internal.h @@ -10,8 +10,8 @@ /* */ /* ************************************************************************** */ -#ifndef VARIABLE_EXPAND_INTERNAL_H -# define VARIABLE_EXPAND_INTERNAL_H +#ifndef EXPAND_PARAMETER_INTERNAL_H +# define EXPAND_PARAMETER_INTERNAL_H # include "libft.h" # include "shell_table.h" diff --git a/src/component/variable_expand/state/in_double_quote_expand.c b/src/expand/expand_parameter/state/in_double_quote_expand.c similarity index 97% rename from src/component/variable_expand/state/in_double_quote_expand.c rename to src/expand/expand_parameter/state/in_double_quote_expand.c index 95d4c08..f10df32 100644 --- a/src/component/variable_expand/state/in_double_quote_expand.c +++ b/src/expand/expand_parameter/state/in_double_quote_expand.c @@ -10,8 +10,8 @@ /* */ /* ************************************************************************** */ -#include "../variable_expand_internal.h" -#include "variable_expand.h" +#include "../expand_parameter_internal.h" +#include "expand.h" static void by_dollar(t_shell_table *shell_table, t_expand_store *store, t_expand_state *state, char **current); diff --git a/src/component/variable_expand/state/in_normal_expand.c b/src/expand/expand_parameter/state/in_normal_expand.c similarity index 97% rename from src/component/variable_expand/state/in_normal_expand.c rename to src/expand/expand_parameter/state/in_normal_expand.c index 6bd079a..630ada7 100644 --- a/src/component/variable_expand/state/in_normal_expand.c +++ b/src/expand/expand_parameter/state/in_normal_expand.c @@ -10,8 +10,8 @@ /* */ /* ************************************************************************** */ -#include "../variable_expand_internal.h" -#include "variable_expand.h" +#include "../expand_parameter_internal.h" +#include "expand.h" static void by_last(t_shell_table *shell_table, t_expand_store *store, t_expand_state *state, char **current); diff --git a/src/component/variable_expand/state/in_single_quote_expand.c b/src/expand/expand_parameter/state/in_single_quote_expand.c similarity index 95% rename from src/component/variable_expand/state/in_single_quote_expand.c rename to src/expand/expand_parameter/state/in_single_quote_expand.c index c998a86..1b4bbc2 100644 --- a/src/component/variable_expand/state/in_single_quote_expand.c +++ b/src/expand/expand_parameter/state/in_single_quote_expand.c @@ -10,8 +10,8 @@ /* */ /* ************************************************************************** */ -#include "../variable_expand_internal.h" -#include "variable_expand.h" +#include "../expand_parameter_internal.h" +#include "expand.h" static void by_single_quote_end(t_shell_table *shell_table, t_expand_store *store, t_expand_state *state, char **current); diff --git a/src/component/variable_expand/state/on_error_expand.c b/src/expand/expand_parameter/state/on_error_expand.c similarity index 93% rename from src/component/variable_expand/state/on_error_expand.c rename to src/expand/expand_parameter/state/on_error_expand.c index c3db8cf..46f893f 100644 --- a/src/component/variable_expand/state/on_error_expand.c +++ b/src/expand/expand_parameter/state/on_error_expand.c @@ -10,8 +10,8 @@ /* */ /* ************************************************************************** */ -#include "../variable_expand_internal.h" -#include "variable_expand.h" +#include "../expand_parameter_internal.h" +#include "expand.h" t_list *on_error_expand(t_expand_store *store, char *token) { diff --git a/src/component/variable_expand/state/on_success_expand.c b/src/expand/expand_parameter/state/on_success_expand.c similarity index 94% rename from src/component/variable_expand/state/on_success_expand.c rename to src/expand/expand_parameter/state/on_success_expand.c index daa3ffa..08a65ad 100644 --- a/src/component/variable_expand/state/on_success_expand.c +++ b/src/expand/expand_parameter/state/on_success_expand.c @@ -10,8 +10,8 @@ /* */ /* ************************************************************************** */ -#include "../variable_expand_internal.h" -#include "variable_expand.h" +#include "../expand_parameter_internal.h" +#include "expand.h" t_list *on_success_expand(t_expand_store *store, char *token) { diff --git a/src/component/variable_expand/store/add_buffer_expand.c b/src/expand/expand_parameter/store/add_buffer_expand.c similarity index 94% rename from src/component/variable_expand/store/add_buffer_expand.c rename to src/expand/expand_parameter/store/add_buffer_expand.c index 7c964cf..9e831dc 100644 --- a/src/component/variable_expand/store/add_buffer_expand.c +++ b/src/expand/expand_parameter/store/add_buffer_expand.c @@ -10,8 +10,8 @@ /* */ /* ************************************************************************** */ -#include "../variable_expand_internal.h" -#include "variable_expand.h" +#include "../expand_parameter_internal.h" +#include "expand.h" int add_buffer_expand(t_expand_store *store, char c) { diff --git a/src/component/variable_expand/store/free_store_expand.c b/src/expand/expand_parameter/store/free_store_expand.c similarity index 93% rename from src/component/variable_expand/store/free_store_expand.c rename to src/expand/expand_parameter/store/free_store_expand.c index 8326e2b..2f1820d 100644 --- a/src/component/variable_expand/store/free_store_expand.c +++ b/src/expand/expand_parameter/store/free_store_expand.c @@ -10,8 +10,8 @@ /* */ /* ************************************************************************** */ -#include "../variable_expand_internal.h" -#include "variable_expand.h" +#include "../expand_parameter_internal.h" +#include "expand.h" void free_store_expand(t_expand_store *store) { diff --git a/src/component/variable_expand/store/get_key_length_expand.c b/src/expand/expand_parameter/store/get_key_length_expand.c similarity index 97% rename from src/component/variable_expand/store/get_key_length_expand.c rename to src/expand/expand_parameter/store/get_key_length_expand.c index a9c1e3e..0283788 100644 --- a/src/component/variable_expand/store/get_key_length_expand.c +++ b/src/expand/expand_parameter/store/get_key_length_expand.c @@ -10,7 +10,7 @@ /* */ /* ************************************************************************** */ -#include "variable_expand.h" +#include "expand.h" static bool is_special_char(const char c); diff --git a/src/component/variable_expand/store/push_token_expand.c b/src/expand/expand_parameter/store/push_token_expand.c similarity index 96% rename from src/component/variable_expand/store/push_token_expand.c rename to src/expand/expand_parameter/store/push_token_expand.c index 2119c88..72f1ad0 100644 --- a/src/component/variable_expand/store/push_token_expand.c +++ b/src/expand/expand_parameter/store/push_token_expand.c @@ -10,8 +10,8 @@ /* */ /* ************************************************************************** */ -#include "../variable_expand_internal.h" -#include "variable_expand.h" +#include "../expand_parameter_internal.h" +#include "expand.h" static char *build_token_from_buffer(t_list *buffer) { diff --git a/src/component/remove_quotes/remove_quotes.c b/src/expand/expand_remove_quotes/expand_remove_quotes.c similarity index 97% rename from src/component/remove_quotes/remove_quotes.c rename to src/expand/expand_remove_quotes/expand_remove_quotes.c index 67a3963..cdc8502 100644 --- a/src/component/remove_quotes/remove_quotes.c +++ b/src/expand/expand_remove_quotes/expand_remove_quotes.c @@ -10,14 +10,14 @@ /* */ /* ************************************************************************** */ -#include "remove_quotes.h" +#include "expand.h" #include static bool is_quote(char c); static char *remove_quotes_from_string(const char *str); static int excluded_quote_length(const char *str); -t_list *remove_quotes(t_list *tokens) +t_list *expand_remove_quotes(t_list *tokens) { t_list *current; char *new_content; diff --git a/src/expand/expand_tilde/expand_tilde.c b/src/expand/expand_tilde/expand_tilde.c new file mode 100644 index 0000000..627beff --- /dev/null +++ b/src/expand/expand_tilde/expand_tilde.c @@ -0,0 +1,59 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* expand_tilde.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/03/03 18:00:00 by surayama #+# #+# */ +/* Updated: 2026/03/03 18:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "expand.h" + +static bool is_tilde_prefix(const char *token); +static char *expand_tilde_token(const char *token, t_shell_table *table); + +t_list *expand_tilde(t_list *tokens, t_shell_table *shell_table) +{ + t_list *current; + char *expanded; + char *old; + + current = tokens; + while (current) + { + if (current->content && is_tilde_prefix(current->content)) + { + expanded = expand_tilde_token(current->content, shell_table); + if (expanded) + { + old = current->content; + current->content = expanded; + free(old); + } + } + current = current->next; + } + return (tokens); +} + +static bool is_tilde_prefix(const char *token) +{ + if (token[0] != '~') + return (false); + return (token[1] == '\0' || token[1] == '/'); +} + +static char *expand_tilde_token(const char *token, t_shell_table *table) +{ + char *home; + + home = st_search(table, "HOME"); + if (!home) + return (NULL); + if (token[1] == '\0') + return (ft_strdup(home)); + return (ft_strjoin(home, token + 1)); +} diff --git a/src/component/path/resolve_wildcard_path.c b/src/expand/expand_wildcard/expand_wildcard.c similarity index 90% rename from src/component/path/resolve_wildcard_path.c rename to src/expand/expand_wildcard/expand_wildcard.c index cadbf6f..9fd523d 100644 --- a/src/component/path/resolve_wildcard_path.c +++ b/src/expand/expand_wildcard/expand_wildcard.c @@ -6,18 +6,17 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/03/03 13:00:00 by surayama #+# #+# */ -/* Updated: 2026/03/03 13:00:00 by surayama ### ########.fr */ +/* Updated: 2026/03/03 18:00:00 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ -#include "path.h" -#include "pattern.h" -#include +#include "expand.h" +#include "expand_wildcard_internal.h" static bool has_wildcard(const char *str); static t_list *handle_wildcard(t_list *prev, t_list *current, t_list **head); -t_list *resolve_wildcard_path(t_list *tokens) +t_list *expand_wildcard(t_list *tokens) { t_list *prev; t_list *current; diff --git a/includes/remove_quotes.h b/src/expand/expand_wildcard/expand_wildcard_internal.h similarity index 67% rename from includes/remove_quotes.h rename to src/expand/expand_wildcard/expand_wildcard_internal.h index fa0b7cf..59ff1fc 100644 --- a/includes/remove_quotes.h +++ b/src/expand/expand_wildcard/expand_wildcard_internal.h @@ -1,20 +1,23 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* remove_quote.h :+: :+: :+: */ +/* wildcard_expand_internal.h :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2026/02/07 00:50:48 by surayama #+# #+# */ -/* Updated: 2026/02/07 00:51:19 by surayama ### ########.fr */ +/* Created: 2026/03/03 17:21:58 by surayama #+# #+# */ +/* Updated: 2026/03/03 18:00:00 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ -#ifndef REMOVE_QUOTES_H -# define REMOVE_QUOTES_H +#ifndef EXPAND_WILDCARD_INTERNAL_H +# define EXPAND_WILDCARD_INTERNAL_H # include "libft.h" +# include -t_list *remove_quotes(t_list *tokens); +# define WILDCARD '*' + +t_list *resolve_wildcard(const char *token); #endif diff --git a/src/component/path/resolve_wildcard.c b/src/expand/expand_wildcard/resolve_wildcard.c similarity index 62% rename from src/component/path/resolve_wildcard.c rename to src/expand/expand_wildcard/resolve_wildcard.c index 025af4c..29adef5 100644 --- a/src/component/path/resolve_wildcard.c +++ b/src/expand/expand_wildcard/resolve_wildcard.c @@ -11,11 +11,13 @@ /* ************************************************************************** */ #include "path.h" -#include "pattern.h" #include "directory.h" +#include "expand_wildcard_internal.h" static t_list *get_matches(const char *abs_dir, const char *pattern); static t_list *build_full_paths(t_list *matches, const char *abs_dir); +static bool match_pattern(const char *str, const char *pattern); +static t_list *filter_pattern(t_list *source, const char *pattern); t_list *resolve_wildcard(const char *token) { @@ -44,15 +46,15 @@ t_list *resolve_wildcard(const char *token) static t_list *get_matches(const char *abs_dir, const char *pattern) { t_list *entries; - t_list *matches; + t_list *filtered_matches; t_list *result; - if (get_directory_entries(abs_dir, pattern[0] == '.', &entries) != SUCCESS) + if (list_directory(abs_dir, pattern[0] == '.', &entries) != SUCCESS) return (NULL); - matches = filter_pattern(entries, pattern); + filtered_matches = filter_pattern(entries, pattern); ft_lstclear(&entries, free); - result = build_full_paths(matches, abs_dir); - ft_lstclear(&matches, free); + result = build_full_paths(filtered_matches, abs_dir); + ft_lstclear(&filtered_matches, free); return (result); } @@ -84,3 +86,49 @@ static t_list *build_full_paths(t_list *matches, const char *abs_dir) free(dir_slash); return (result); } + +static t_list *filter_pattern(t_list *source, const char *pattern) +{ + t_list *result; + t_list *current; + t_list *new_node; + + if (!source || !pattern) + return (NULL); + result = NULL; + current = source; + while (current) + { + if (match_pattern((const char *)current->content, pattern)) + { + new_node = ft_lstnew(ft_strdup((const char *)current->content)); + if (!new_node) + { + ft_lstclear(&result, free); + return (NULL); + } + ft_lstadd_back(&result, new_node); + } + current = current->next; + } + return (result); +} + +static bool match_pattern(const char *str, const char *pattern) +{ + if (*pattern == '\0') + return (*str == '\0'); + if (*pattern == WILDCARD) + { + while (*str) + { + if (match_pattern(str, pattern + 1)) + return (true); + str++; + } + return (match_pattern(str, pattern + 1)); + } + if (*str == *pattern) + return (match_pattern(str + 1, pattern + 1)); + return (false); +} diff --git a/src/main.c b/src/main.c index 620718f..9ed338d 100644 --- a/src/main.c +++ b/src/main.c @@ -6,7 +6,7 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:13:47 by kjikuhar #+# #+# */ -/* Updated: 2026/03/03 13:03:53 by surayama ### ########.fr */ +/* Updated: 2026/03/03 19:17:28 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -36,7 +36,7 @@ int main_dev(int argc, char const **argv, char *const envp[]) if (!shell_table) return (1); shell_table_checker(shell_table); - prompt(wildcard_checker, shell_table); + prompt(expand_checker, shell_table); st_destroy(shell_table); return (0); } From 197e3020a975d9f98e47bf47d42bee41b8d8f001 Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Mon, 6 Apr 2026 07:27:27 +0900 Subject: [PATCH 133/173] =?UTF-8?q?=E5=85=A8=E3=83=81=E3=82=A7=E3=83=83?= =?UTF-8?q?=E3=82=AB=E3=83=BC=E3=82=92=20CLI=20=E3=83=95=E3=83=A9=E3=82=B0?= =?UTF-8?q?=E3=81=A7=E8=B5=B7=E5=8B=95=E5=8F=AF=E8=83=BD=E3=81=AB=E3=81=99?= =?UTF-8?q?=E3=82=8B=20(#65)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/leak-check-all-checker.yml | 260 +++++++++++++++++++ includes/minishell.h | 7 + src/main.c | 58 +++-- 3 files changed, 308 insertions(+), 17 deletions(-) create mode 100644 .github/workflows/leak-check-all-checker.yml diff --git a/.github/workflows/leak-check-all-checker.yml b/.github/workflows/leak-check-all-checker.yml new file mode 100644 index 0000000..c711179 --- /dev/null +++ b/.github/workflows/leak-check-all-checker.yml @@ -0,0 +1,260 @@ +name: Memory Leak Check (All Checkers) + +on: + pull_request: + branches: [ "master", "develop" ] + push: + branches: [ "master", "develop" ] + +jobs: + leak-check-all-checker: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + checker: + - tokenize + - heredoc + - expand + - remove-quotes + - parse + - builtin + - directory + - path + - relative-path + - wildcard + + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y build-essential libreadline-dev valgrind + + - name: Build project + run: | + echo "Building minishell..." + make + + - name: Verify binary exists + run: | + if [ ! -f "./minishell" ]; then + echo "ERROR: minishell binary not found" + exit 1 + fi + echo "minishell binary found" + ls -la ./minishell + + - name: Generate test input for ${{ matrix.checker }} + run: | + CHECKER="${{ matrix.checker }}" + case "$CHECKER" in + tokenize) + cat << 'TESTEOF' > test_input.txt + + echo hello + echo "'nested'" + cmd|cat>file>out + || && + "unclosed + echo "hello world" | cat -e > output.txt + TESTEOF + ;; + heredoc) + cat << 'TESTEOF' > test_input.txt + cat << EOF + hello world + EOF + echo hello + cat << 'DELIM' + no expand $VAR + DELIM + cat << EOF | grep hello + hello world + EOF + + cat << EOF > /tmp/test_heredoc_out + test + EOF + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + cat << EOF + $HOME + EOF + TESTEOF + ;; + expand) + cat << 'TESTEOF' > test_input.txt + echo $PATH + echo $UNDEFINED + echo '$NO_EXPAND' + echo "$HOME" + echo $? + echo $A$B$C + echo $ + echo $AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + echo "" + echo "$?" + TESTEOF + ;; + remove-quotes) + cat << 'TESTEOF' > test_input.txt + echo "" + echo '' + echo "'nested'" + echo 'hello world' + echo "he said \"hi\"" + echo "a"'b'"c" + echo "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + echo hello + echo "hello"'world'"!" + TESTEOF + ;; + parse) + cat << 'TESTEOF' > test_input.txt + echo hello + cat | grep | wc + echo > out.txt + < in cat | grep > out + echo a | echo b | echo c | echo d | echo e | echo f | echo g | echo h | echo i | echo j + echo "hello | world" + echo hello > out.txt < in.txt >> append.txt + echo hello world foo bar baz + cat | grep pattern | sort | uniq + TESTEOF + ;; + builtin) + cat << 'TESTEOF' > test_input.txt + export A=1 + export A=1 B=2 C=3 + export EMPTY= + export + unset A + export LONG_VAR=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + export SPECIAL="hello world" + export A=1 + export A=2 + unset NONEXISTENT + TESTEOF + ;; + directory) + cat << 'TESTEOF' > test_input.txt + . + .. + /tmp + /nonexistent + / + + /usr/local/bin + /a/b/c/d/e/f/g/h/i/j + /tmp/test dir + TESTEOF + ;; + path) + cat << 'TESTEOF' > test_input.txt + ../src + ./file.c + /usr/bin + ../../.. + //tmp///file + . + / + /tmp/ + ./a/b/c/d + TESTEOF + ;; + relative-path) + cat << 'TESTEOF' > test_input.txt + ./file + ../dir + ../../file + ./a/b/../c + . + .. + hello + ./aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + ../a/b/c + TESTEOF + ;; + wildcard) + cat << 'TESTEOF' > test_input.txt + *.c + src/*.h + ? + nonexistent*.xyz + "*.c" + src/*/*.c + [a-z]* + * + *.o + TESTEOF + ;; + esac + + echo "exit" >> test_input.txt + + echo "=== Test input for $CHECKER ===" + cat -n test_input.txt + + - name: Run valgrind leak check for ${{ matrix.checker }} + run: | + CHECKER="${{ matrix.checker }}" + echo "Running valgrind for --${CHECKER} checker..." + + cat test_input.txt | timeout 10 valgrind \ + --leak-check=full \ + --show-leak-kinds=all \ + --track-origins=yes \ + --suppressions=./readline.supp \ + --error-exitcode=42 \ + --log-file=valgrind_result.txt \ + ./minishell --${CHECKER} 2>&1 || true + + VALGRIND_EXIT=${PIPESTATUS[1]:-$?} + + echo "" + echo "==========================================" + echo "Valgrind Output (--${CHECKER}):" + echo "==========================================" + cat valgrind_result.txt + echo "==========================================" + + if [ "$VALGRIND_EXIT" -eq 42 ]; then + echo "" + echo "MEMORY LEAK DETECTED in --${CHECKER} checker!" + echo "" + echo "Summary of leaks:" + grep "definitely lost" valgrind_result.txt || echo "No definitely lost blocks" + grep "indirectly lost" valgrind_result.txt || echo "No indirectly lost blocks" + grep "possibly lost" valgrind_result.txt || echo "No possibly lost blocks" + exit 1 + else + echo "" + echo "NO MEMORY LEAKS DETECTED in --${CHECKER} checker" + echo "" + echo "Leak Summary:" + grep "LEAK SUMMARY" valgrind_result.txt -A 5 || true + + if grep -q "All heap blocks were freed -- no leaks are possible" valgrind_result.txt; then + echo "All heap blocks were freed" + elif grep -q "definitely lost: 0 bytes in 0 blocks" valgrind_result.txt && \ + grep -q "indirectly lost: 0 bytes in 0 blocks" valgrind_result.txt && \ + grep -q "possibly lost: 0 bytes in 0 blocks" valgrind_result.txt; then + echo "No definite, indirect, or possible leaks" + else + echo "Warning: Some reachable memory detected (this is usually OK for readline)" + fi + + exit 0 + fi + + - name: Upload valgrind report + if: always() + uses: actions/upload-artifact@v4 + with: + name: valgrind-report-${{ matrix.checker }} + path: valgrind_result.txt + retention-days: 30 diff --git a/includes/minishell.h b/includes/minishell.h index f835fbc..663ec52 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -23,6 +23,13 @@ # include "shell_table.h" # include "tokenize.h" +typedef void (*t_checker)(char *, t_shell_table *); +typedef struct s_checker_entry +{ + char *name; + t_checker checker; +} t_checker_entry; + // callbacks void on_input(char *input, t_shell_table *shell_table); diff --git a/src/main.c b/src/main.c index 9ed338d..11d897c 100644 --- a/src/main.c +++ b/src/main.c @@ -6,18 +6,26 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:13:47 by kjikuhar #+# #+# */ -/* Updated: 2026/03/03 19:17:28 by surayama ### ########.fr */ +/* Updated: 2026/03/03 20:42:40 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -int main_prod(int argc, char const **argv, char *const envp[]) +static t_checker find_checker(const char *arg); +static int run_checker(t_checker checker, char *const envp[]); + +int main(int argc, char const **argv, char *const envp[]) { t_shell_table *shell_table; + t_checker checker; - (void)argc; - (void)argv; + if (argc > 1) + { + checker = find_checker(argv[1]); + if (checker) + return (run_checker(checker, envp)); + } shell_table = build_shell_table(envp); if (!shell_table) return (1); @@ -26,25 +34,41 @@ int main_prod(int argc, char const **argv, char *const envp[]) return (0); } -int main_dev(int argc, char const **argv, char *const envp[]) +static t_checker find_checker(const char *arg) +{ + static const t_checker_entry g[] = { + {"--tokenize", tokenize_checker}, + {"--heredoc", heredoc_checker}, + {"--parse", parse_checker}, + {"--directory", directory_checker}, + {"--path", path_checker}, + {"--builtin", builtin_checker}, + {"--expand", expand_checker}, + {"--remove-quotes", remove_quotes_checker}, + {"--wildcard", wildcard_checker}, + {"--relative-path", relative_path_checker}, + {NULL, NULL} + }; + int i; + + i = 0; + while (g[i].name) + { + if (ft_strncmp(arg, g[i].name, ft_strlen(g[i].name) + 1) == 0) + return (g[i].checker); + i++; + } + return (NULL); +} + +static int run_checker(t_checker checker, char *const envp[]) { t_shell_table *shell_table; - (void)argc; - (void)argv; shell_table = build_shell_table(envp); if (!shell_table) return (1); - shell_table_checker(shell_table); - prompt(expand_checker, shell_table); + prompt(checker, shell_table); st_destroy(shell_table); return (0); } - -int main(int argc, char const **argv, char *const envp[]) -{ - if (argc > 1 && ft_strncmp(argv[1], "--dev", 6) == 0) - return (main_dev(argc, argv, envp)); - else - return (main_prod(argc, argv, envp)); -} From b8a24c91bba83e10be6fab3504e7a82cfd706b84 Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Mon, 6 Apr 2026 07:28:38 +0900 Subject: [PATCH 134/173] =?UTF-8?q?C=E8=A8=80=E8=AA=9E=E3=81=AE=E3=83=AB?= =?UTF-8?q?=E3=83=BC=E3=83=AB=E3=82=92=E8=BF=BD=E5=8A=A0=20(#66)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/rules/c.md | 98 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 .claude/rules/c.md diff --git a/.claude/rules/c.md b/.claude/rules/c.md new file mode 100644 index 0000000..7d47cd8 --- /dev/null +++ b/.claude/rules/c.md @@ -0,0 +1,98 @@ +--- +paths: + - "src/**/*.c" +--- + +# C Code Guidelines + +### Code Style + +- Use snake_case for variable and function names. +- Limit lines to a maximum of 80 characters. +- Your project must be written in accordance with the Norminette. +- All heap-allocated memory must be properly freed when necessary. Memory leaks will not be tolerated. + +### Allowable External Functions + +以下の関数のみ使用可能。それ以外の外部関数は使用禁止。 + +#### readline +- `char *readline(const char *prompt)` — プロンプトを表示し、ユーザ入力を返す +- `void rl_clear_history(void)` — 履歴リストを全削除 +- `void rl_on_new_line(void)` — カーソルが新しい行に移動したことを通知 +- `void rl_replace_line(const char *text, int clear_undo)` — 現在の入力行を置換 +- `void rl_redisplay(void)` — プロンプトと入力行を再描画 +- `void add_history(const char *string)` — 履歴リストに追加 + +#### stdio / stdlib +- `int printf(const char *format, ...)` — フォーマット出力 +- `void *malloc(size_t size)` — メモリ確保 +- `void free(void *ptr)` — メモリ解放 + +#### I/O +- `ssize_t write(int fd, const void *buf, size_t count)` — ファイルディスクリプタへ書き込み +- `int access(const char *pathname, int mode)` — ファイルのアクセス権確認 +- `int open(const char *pathname, int flags, ...)` — ファイルを開く +- `ssize_t read(int fd, void *buf, size_t count)` — ファイルディスクリプタから読み込み +- `int close(int fd)` — ファイルディスクリプタを閉じる + +#### プロセス制御 +- `pid_t fork(void)` — 子プロセスを生成 +- `pid_t wait(int *wstatus)` — 子プロセスの終了を待つ +- `pid_t waitpid(pid_t pid, int *wstatus, int options)` — 指定子プロセスの終了を待つ +- `pid_t wait3(int *wstatus, int options, struct rusage *rusage)` — リソース使用情報付きwait +- `pid_t wait4(pid_t pid, int *wstatus, int options, struct rusage *rusage)` — リソース使用情報付きwaitpid + +#### シグナル +- `sighandler_t signal(int signum, sighandler_t handler)` — シグナルハンドラを設定 +- `int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)` — シグナルアクションを設定 +- `int sigemptyset(sigset_t *set)` — シグナルセットを空にする +- `int sigaddset(sigset_t *set, int signum)` — シグナルセットにシグナルを追加 +- `int kill(pid_t pid, int sig)` — プロセスにシグナルを送信 + +#### プロセス終了・実行 +- `void exit(int status)` — プロセスを終了 +- `int execve(const char *pathname, char *const argv[], char *const envp[])` — プログラムを実行 + +#### ファイルシステム +- `char *getcwd(char *buf, size_t size)` — カレントディレクトリを取得 +- `int chdir(const char *path)` — カレントディレクトリを変更 +- `int stat(const char *pathname, struct stat *statbuf)` — ファイル情報を取得 +- `int lstat(const char *pathname, struct stat *statbuf)` — シンボリックリンク情報を取得 +- `int fstat(int fd, struct stat *statbuf)` — fdからファイル情報を取得 +- `int unlink(const char *pathname)` — ファイルを削除 + +#### パイプ・ファイルディスクリプタ +- `int dup(int oldfd)` — ファイルディスクリプタを複製 +- `int dup2(int oldfd, int newfd)` — ファイルディスクリプタを指定番号に複製 +- `int pipe(int pipefd[2])` — パイプを作成 + +#### ディレクトリ操作 +- `DIR *opendir(const char *name)` — ディレクトリを開く +- `struct dirent *readdir(DIR *dirp)` — ディレクトリエントリを読む +- `int closedir(DIR *dirp)` — ディレクトリを閉じる + +#### エラー処理 +- `char *strerror(int errnum)` — エラー番号に対応する文字列を返す +- `void perror(const char *s)` — エラーメッセージを出力 + +#### ターミナル +- `int isatty(int fd)` — fdが端末か判定 +- `char *ttyname(int fd)` — 端末名を返す +- `int ttyslot(void)` — 端末スロット番号を返す +- `int ioctl(int fd, unsigned long request, ...)` — デバイス制御 + +#### 環境変数 +- `char *getenv(const char *name)` — 環境変数の値を取得 + +#### termios +- `int tcsetattr(int fd, int optional_actions, const struct termios *termios_p)` — 端末属性を設定 +- `int tcgetattr(int fd, struct termios *termios_p)` — 端末属性を取得 + +#### termcap +- `int tgetent(char *bp, const char *name)` — termcapエントリを取得 +- `int tgetflag(const char *id)` — ブール型ケーパビリティを取得 +- `int tgetnum(const char *id)` — 数値型ケーパビリティを取得 +- `char *tgetstr(const char *id, char **area)` — 文字列型ケーパビリティを取得 +- `char *tgoto(const char *cap, int col, int row)` — カーソル移動文字列を生成 +- `int tputs(const char *str, int affcnt, int (*putc)(int))` — ケーパビリティ文字列を出力 From acb5696f71c7b45df3991343e3b7a8d5543b840c Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Sat, 11 Apr 2026 14:42:09 +0900 Subject: [PATCH 135/173] =?UTF-8?q?cd=20=E3=81=AB=20CDPATH=20=E5=AF=BE?= =?UTF-8?q?=E5=BF=9C=E3=82=92=E8=BF=BD=E5=8A=A0=20+=20builtin=20=E3=83=87?= =?UTF-8?q?=E3=82=A3=E3=83=AC=E3=82=AF=E3=83=88=E3=83=AA=E6=95=B4=E7=90=86?= =?UTF-8?q?=20(#64)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * cdで不要な~展開を削除 * cd に CDPATH 対応を追加 + builtin をコマンド別ディレクトリに整理 - CDPATH 環境変数による相対パスのディレクトリ探索を実装 - CDPATH マッチ時は移動先の絶対パスを stdout に出力 - 空エントリ(::, 先頭/末尾の :)はカレントディレクトリとして扱う - src/builtin/ 以下をコマンド別サブディレクトリに再構成 Co-Authored-By: Claude Opus 4.6 * fix: builtin.h の関数宣言アラインメントを修正 norminette MISALIGNED_FUNC_DECL を解消するため int の後のタブ幅を char と揃えた Co-Authored-By: Claude Opus 4.6 * ヘッダーファイルの修正 * fix: プロトタイプ宣言に移動した * fix: search_cdpath --------- Co-authored-by: Claude Opus 4.6 --- Makefile | 13 +++-- includes/builtin.h | 12 ++-- src/builtin/{ => cd}/cd.c | 31 ++++++---- src/builtin/cd/search_cdpath.c | 95 +++++++++++++++++++++++++++++++ src/builtin/{ => echo}/echo.c | 0 src/builtin/{ => export}/export.c | 0 src/builtin/{ => pwd}/pwd.c | 0 src/builtin/{ => unset}/unset.c | 0 8 files changed, 129 insertions(+), 22 deletions(-) rename src/builtin/{ => cd}/cd.c (77%) create mode 100644 src/builtin/cd/search_cdpath.c rename src/builtin/{ => echo}/echo.c (100%) rename src/builtin/{ => export}/export.c (100%) rename src/builtin/{ => pwd}/pwd.c (100%) rename src/builtin/{ => unset}/unset.c (100%) diff --git a/Makefile b/Makefile index ddc3157..121ea36 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # By: surayama +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/05/18 21:11:39 by kjikuhar #+# #+# # -# Updated: 2026/03/03 17:04:01 by surayama ### ########.fr # +# Updated: 2026/03/03 20:32:45 by surayama ### ########.fr # # # # **************************************************************************** # @@ -57,11 +57,12 @@ LIBFT_A := $(LIBFT_DIR)/libft.a #mandatory sources SRCS_MAND := src/main.c \ - src/builtin/echo.c \ - src/builtin/export.c \ - src/builtin/pwd.c \ - src/builtin/unset.c \ - src/builtin/cd.c \ + src/builtin/echo/echo.c \ + src/builtin/export/export.c \ + src/builtin/pwd/pwd.c \ + src/builtin/unset/unset.c \ + src/builtin/cd/cd.c \ + src/builtin/cd/search_cdpath.c \ src/prompt/prompt.c \ src/callback/on_input.c \ src/checker/builtin_checker.c \ diff --git a/includes/builtin.h b/includes/builtin.h index 038c79f..8dd0a85 100644 --- a/includes/builtin.h +++ b/includes/builtin.h @@ -6,7 +6,7 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/29 17:16:51 by surayama #+# #+# */ -/* Updated: 2025/11/29 20:31:07 by surayama ### ########.fr */ +/* Updated: 2026/04/06 07:41:22 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,10 +19,10 @@ # include # include -int echo(t_list *argv, t_shell_table *shell_table); -int pwd(t_list *argv, t_shell_table *shell_table); -int export(t_list *argv, t_shell_table *shell_table); -int unset(t_list *argv, t_shell_table *shell_table); -int cd(t_list *argv, t_shell_table *shell_table); +int echo(t_list *argv, t_shell_table *shell_table); +int pwd(t_list *argv, t_shell_table *shell_table); +int export(t_list *argv, t_shell_table *shell_table); +int unset(t_list *argv, t_shell_table *shell_table); +int cd(t_list *argv, t_shell_table *shell_table); #endif diff --git a/src/builtin/cd.c b/src/builtin/cd/cd.c similarity index 77% rename from src/builtin/cd.c rename to src/builtin/cd/cd.c index 2377171..aca89ad 100644 --- a/src/builtin/cd.c +++ b/src/builtin/cd/cd.c @@ -6,16 +6,17 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/12/01 00:48:09 by surayama #+# #+# */ -/* Updated: 2026/03/03 12:41:23 by surayama ### ########.fr */ +/* Updated: 2026/04/06 07:48:40 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ #include -static int by_too_many_arguments_error(void); static int by_move_to_home(t_shell_table *shell_table); static int by_move_to_oldpwd(t_shell_table *shell_table); +static int by_move_to_arg(const char *arg, t_shell_table *shell_table); static int move_to_path(const char *absolute_path, t_shell_table *shell_table); +char *search_cdpath(const char *arg, t_shell_table *st); int cd(t_list *argv, t_shell_table *shell_table) { @@ -23,25 +24,35 @@ int cd(t_list *argv, t_shell_table *shell_table) argc = ft_lstsize(argv); if (argc > 2) - return (by_too_many_arguments_error()); + { + ft_putstr_fd("Error: cd too many arguments\n", STDERR_FILENO); + return (1); + } if (argc == 1) return (by_move_to_home(shell_table)); if (argc == 2 && argv->next->content) { - if (ft_strncmp((char *)argv->next->content, "~", 2) == 0) - return (by_move_to_home(shell_table)); if (ft_strncmp((char *)argv->next->content, "-", 2) == 0) return (by_move_to_oldpwd(shell_table)); - return (move_to_path(to_absolute_path((char *)argv->next->content), - shell_table)); + return (by_move_to_arg((char *)argv->next->content, shell_table)); } return (SUCCESS); } -static int by_too_many_arguments_error(void) +static int by_move_to_arg(const char *arg, t_shell_table *shell_table) { - ft_putstr_fd("Error: cd too many arguments\n", STDERR_FILENO); - return (1); + char *cdpath_result; + + if (arg[0] != '/') + { + cdpath_result = search_cdpath(arg, shell_table); + if (cdpath_result) + { + ft_putendl_fd(cdpath_result, STDOUT_FILENO); + return (move_to_path(cdpath_result, shell_table)); + } + } + return (move_to_path(to_absolute_path(arg), shell_table)); } static int by_move_to_home(t_shell_table *shell_table) diff --git a/src/builtin/cd/search_cdpath.c b/src/builtin/cd/search_cdpath.c new file mode 100644 index 0000000..afb5a14 --- /dev/null +++ b/src/builtin/cd/search_cdpath.c @@ -0,0 +1,95 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* search_cdpath.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/03/03 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/04/06 07:44:23 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "builtin.h" + +static t_list *split_cdpath(const char *cdpath); +static char *try_cdpath_entry(const char *entry, const char *arg); + +char *search_cdpath(const char *arg, t_shell_table *st) +{ + char *cdpath; + t_list *entries; + t_list *cur; + char *result; + + cdpath = st_search(st, "CDPATH"); + if (!cdpath) + return (NULL); + entries = split_cdpath(cdpath); + cur = entries; + while (cur) + { + result = try_cdpath_entry((char *)cur->content, arg); + if (result) + { + ft_lstclear(&entries, free); + return (result); + } + cur = cur->next; + } + ft_lstclear(&entries, free); + return (NULL); +} + +static char *try_cdpath_entry(const char *entry, const char *arg) +{ + char *joined; + char *absolute; + + joined = join_path(entry, arg); + if (!joined) + return (NULL); + absolute = to_absolute_path(joined); + free(joined); + if (!absolute) + return (NULL); + if (access(absolute, F_OK) == 0) + return (absolute); + free(absolute); + return (NULL); +} + +static void add_entry(t_list **list, const char *cdpath, size_t start, + size_t end) +{ + char *entry; + + if (start == end) + entry = ft_strdup("."); + else + entry = ft_substr(cdpath, start, end - start); + if (entry) + ft_lstadd_back(list, ft_lstnew(entry)); +} + +static t_list *split_cdpath(const char *cdpath) +{ + t_list *list; + size_t i; + size_t start; + + list = NULL; + i = 0; + start = 0; + while (cdpath[i]) + { + if (cdpath[i] == ':') + { + add_entry(&list, cdpath, start, i); + start = i + 1; + } + i++; + } + add_entry(&list, cdpath, start, i); + return (list); +} diff --git a/src/builtin/echo.c b/src/builtin/echo/echo.c similarity index 100% rename from src/builtin/echo.c rename to src/builtin/echo/echo.c diff --git a/src/builtin/export.c b/src/builtin/export/export.c similarity index 100% rename from src/builtin/export.c rename to src/builtin/export/export.c diff --git a/src/builtin/pwd.c b/src/builtin/pwd/pwd.c similarity index 100% rename from src/builtin/pwd.c rename to src/builtin/pwd/pwd.c diff --git a/src/builtin/unset.c b/src/builtin/unset/unset.c similarity index 100% rename from src/builtin/unset.c rename to src/builtin/unset/unset.c From 0fae5c6d3e6144d7c3399f8f946859f38f8df8bf Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Sat, 11 Apr 2026 16:02:02 +0900 Subject: [PATCH 136/173] =?UTF-8?q?=E3=82=B7=E3=82=B0=E3=83=8A=E3=83=AB?= =?UTF-8?q?=E3=83=8F=E3=83=B3=E3=83=89=E3=83=AA=E3=83=B3=E3=82=B0=E3=81=AE?= =?UTF-8?q?=E5=AE=9F=E8=A3=85(sigint)=20(#67)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add: sigint * rename: signal_handler.h → signal.h、シグナル関数をファイル分割 Co-Authored-By: Claude Opus 4.6 (1M context) * fix: signal_handler.h に戻す(システムヘッダとの名前衝突回避)、EOF空行修正 Co-Authored-By: Claude Opus 4.6 (1M context) * add: stdlib * fix: 制御文字がシェルに出力されないように * fix: struct termios をゼロ初期化して valgrind の未初期化バイト警告を修正 Co-Authored-By: Claude Opus 4.6 (1M context) * add: Ctrl-D (EOF) で "exit" を表示してからシェルを終了する Co-Authored-By: Claude Opus 4.6 (1M context) * fix: Ctrl-C 後に Ctrl-D が無視されるバグを修正 シグナルハンドラが rl_replace_line + rl_redisplay で readline を継続させるため、 SIGINT で readline が NULL を返すことはない。g_signal による SIGINT/EOF 分岐を 削除し、readline() == NULL は常に EOF として処理する。 g_signal は将来 executor で $? = 130 に使うため維持。 Co-Authored-By: Claude Opus 4.6 (1M context) * add: heredoc 入力中のシグナルハンドリングを実装 heredoc 用シグナルモード set_signal_heredoc() を追加。 Ctrl-C で heredoc を中断し、tmpfile を削除してプロンプトに戻る。 Ctrl-\ は heredoc 中も無視する。 Co-Authored-By: Claude Opus 4.6 (1M context) --------- Co-authored-by: Claude Opus 4.6 (1M context) --- Makefile | 2 + includes/minishell.h | 1 + includes/signal_handler.h | 27 ++++++++++++ src/component/heredoc/heredoc.c | 5 +++ src/component/heredoc/heredoc_prompt.c | 12 ++++++ src/main.c | 1 + src/prompt/prompt.c | 4 ++ src/signal/set_signals.c | 60 ++++++++++++++++++++++++++ src/signal/setup_signal_handlers.c | 51 ++++++++++++++++++++++ 9 files changed, 163 insertions(+) create mode 100644 includes/signal_handler.h create mode 100644 src/signal/set_signals.c create mode 100644 src/signal/setup_signal_handlers.c diff --git a/Makefile b/Makefile index 121ea36..008c7f4 100644 --- a/Makefile +++ b/Makefile @@ -134,6 +134,8 @@ SRCS_MAND := src/main.c \ src/expand/expand_wildcard/resolve_wildcard.c \ src/expand/expand_wildcard/expand_wildcard.c \ src/expand/expand_remove_quotes/expand_remove_quotes.c \ + src/signal/setup_signal_handlers.c \ + src/signal/set_signals.c \ SRCS_BONUS := diff --git a/includes/minishell.h b/includes/minishell.h index 663ec52..21adf08 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -21,6 +21,7 @@ # include "prompt.h" # include "path.h" # include "shell_table.h" +# include "signal_handler.h" # include "tokenize.h" typedef void (*t_checker)(char *, t_shell_table *); diff --git a/includes/signal_handler.h b/includes/signal_handler.h new file mode 100644 index 0000000..dbe4c4c --- /dev/null +++ b/includes/signal_handler.h @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* signal_handler.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/06 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/04/06 00:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef SIGNAL_HANDLER_H +# define SIGNAL_HANDLER_H + +# include +# include + +extern volatile sig_atomic_t g_signal; + +void setup_signal_handlers(void); +void set_signal_ignore(void); +void set_signal_default(void); +void set_signal_interactive(void); +void set_signal_heredoc(void); + +#endif diff --git a/src/component/heredoc/heredoc.c b/src/component/heredoc/heredoc.c index baef0d5..d33cfe9 100644 --- a/src/component/heredoc/heredoc.c +++ b/src/component/heredoc/heredoc.c @@ -11,6 +11,7 @@ /* ************************************************************************** */ #include "heredoc.h" +#include "signal_handler.h" static bool is_heredoc_operator(const char *token); static int rebuild_tokens(t_list *current, t_list *eof_node, @@ -30,7 +31,11 @@ t_list *heredoc(t_list *tokens) eof_node = current->next; if (eof_node == NULL) return (NULL); + set_signal_heredoc(); tmpfile_path = heredoc_prompt((char *)eof_node->content); + set_signal_interactive(); + if (tmpfile_path == NULL) + return (NULL); if (rebuild_tokens(current, eof_node, tmpfile_path) == ERROR) return (NULL); } diff --git a/src/component/heredoc/heredoc_prompt.c b/src/component/heredoc/heredoc_prompt.c index 97ac604..db8372d 100644 --- a/src/component/heredoc/heredoc_prompt.c +++ b/src/component/heredoc/heredoc_prompt.c @@ -11,11 +11,13 @@ /* ************************************************************************** */ #include "heredoc.h" +#include "signal_handler.h" #include static int write_line_to_file(int fd, char *line); static char *by_found_delimiter(char *line, int fd, char *tmpfile_path); static void *by_fail_write_line_to_file(char *line, int fd, char *tmpfile_path); +static void *by_sigint(int fd, char *tmpfile_path); char *heredoc_prompt(const char *delimiter) { @@ -32,6 +34,8 @@ char *heredoc_prompt(const char *delimiter) while (1) { line = readline(HEREDOC_PROMPT); + if (line == NULL && g_signal == SIGINT) + return (by_sigint(fd, tmpfile_path)); if (line == NULL) break ; if (ft_strncmp(line, delimiter, ft_strlen(delimiter) + 1) == 0) @@ -70,3 +74,11 @@ static void *by_fail_write_line_to_file(char *line, int fd, char *tmpfile_path) free(tmpfile_path); return (NULL); } + +static void *by_sigint(int fd, char *tmpfile_path) +{ + close(fd); + unlink(tmpfile_path); + free(tmpfile_path); + return (NULL); +} diff --git a/src/main.c b/src/main.c index 11d897c..2815359 100644 --- a/src/main.c +++ b/src/main.c @@ -29,6 +29,7 @@ int main(int argc, char const **argv, char *const envp[]) shell_table = build_shell_table(envp); if (!shell_table) return (1); + setup_signal_handlers(); prompt(on_input, shell_table); st_destroy(shell_table); return (0); diff --git a/src/prompt/prompt.c b/src/prompt/prompt.c index 9d91286..ecd86b8 100644 --- a/src/prompt/prompt.c +++ b/src/prompt/prompt.c @@ -11,6 +11,7 @@ /* ************************************************************************** */ #include "prompt.h" +#include "signal_handler.h" void prompt(void (*handler)(char *input, t_shell_table *shell_table), t_shell_table *shell_table) @@ -21,7 +22,10 @@ void prompt(void (*handler)(char *input, t_shell_table *shell_table), { input = readline(PROMPT); if (!input) + { + write(STDOUT_FILENO, "exit\n", 5); break ; + } if (is_blank_line(input)) { free(input); diff --git a/src/signal/set_signals.c b/src/signal/set_signals.c new file mode 100644 index 0000000..224b466 --- /dev/null +++ b/src/signal/set_signals.c @@ -0,0 +1,60 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* set_signals.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/06 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/04/06 00:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "signal_handler.h" +#include +#include + +void set_signal_ignore(void) +{ + struct sigaction sa; + + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = SIG_IGN; + sigaction(SIGINT, &sa, NULL); +} + +void set_signal_default(void) +{ + struct sigaction sa; + + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = SIG_DFL; + sigaction(SIGINT, &sa, NULL); + sigaction(SIGQUIT, &sa, NULL); +} + +void set_signal_interactive(void) +{ + setup_signal_handlers(); +} + +static void sigint_heredoc_handler(int sig) +{ + g_signal = sig; + write(STDOUT_FILENO, "\n", 1); + rl_done = 1; +} + +void set_signal_heredoc(void) +{ + struct sigaction sa; + + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = sigint_heredoc_handler; + sigaction(SIGINT, &sa, NULL); + sa.sa_handler = SIG_IGN; + sigaction(SIGQUIT, &sa, NULL); +} diff --git a/src/signal/setup_signal_handlers.c b/src/signal/setup_signal_handlers.c new file mode 100644 index 0000000..39aaf52 --- /dev/null +++ b/src/signal/setup_signal_handlers.c @@ -0,0 +1,51 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* setup_signal_handlers.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/06 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/04/06 00:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "signal_handler.h" +#include "libft.h" +#include +#include +#include + +volatile sig_atomic_t g_signal; + +static void sigint_handler(int sig) +{ + g_signal = sig; + write(STDOUT_FILENO, "\n", 1); + rl_on_new_line(); + rl_replace_line("", 0); + rl_redisplay(); +} + +static void disable_echoctl(void) +{ + struct termios term; + + ft_memset(&term, 0, sizeof(term)); + tcgetattr(STDIN_FILENO, &term); + term.c_lflag &= ~(ECHOCTL); + tcsetattr(STDIN_FILENO, TCSANOW, &term); +} + +void setup_signal_handlers(void) +{ + struct sigaction sa; + + disable_echoctl(); + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = sigint_handler; + sigaction(SIGINT, &sa, NULL); + sa.sa_handler = SIG_IGN; + sigaction(SIGQUIT, &sa, NULL); +} From 286620af05cc70b7bb68b17acc14704569ffc599 Mon Sep 17 00:00:00 2001 From: jiku Date: Sat, 11 Apr 2026 18:43:35 +0900 Subject: [PATCH 137/173] =?UTF-8?q?execute=E9=83=A8=E5=88=86=E3=82=92?= =?UTF-8?q?=E4=BD=9C=E6=88=90=E3=81=97=E3=81=BE=E3=81=97=E3=81=9F=E3=80=82?= =?UTF-8?q?=20(#35)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * finish: execute * change: exec_ast function * change: exec_pipe function declearation * change: exec_pipe function and fix int -> static int * change: exec_right_child and exec_left_child function * change: exec_cmd and find_path function * change and delete: get_env_path -> st_serch * change: join_path correspond s2 -> / * change: exec_cmd_core * change: exec_cmd_core about creating envp * fix: type error, const modifier cannot free * change: ft_free_split ->ft_free_array に関数名を変更。 * change: ft_free_arrayの引数の型をchar ** -> void **に変更。 * change: Signiture変更に伴って、呼び出し側の型をキャストした。 * rename: 外部コマンド実行・パス検索の関数名を修正 * refactor: utils/ を command/, pipe/, redirects/ に分割 * rename: exec_cmd_core.c -> exec_external_cmd.c * fix: makefileを修正。 * fix: parser.h->parse.h * fix: norminette * add: executeのDocumentを追加。 * add: builtin_exit を実装 * add: ビルトインの振り分け処理を実装 * fix: exec_cmd にビルトインの振り分け処理を組み込み Makefile を更新 * fix: headerを修正。 * rename: exec_builtin → exec_builtin_cmd * refactor: fatal_child を削除して close/exit を直接記述 * fix: header を修正。 --------- Co-authored-by: jiku0730 --- Makefile | 13 ++- docs/execute.md | 88 ++++++++++++++ includes/builtin.h | 1 + includes/execute.h | 38 ++++++ libft/Makefile | 5 +- libft/libft.h | 5 +- libft/string/ft_free_array.c | 28 +++++ src/builtin/exit/exit.c | 64 ++++++++++ src/component/shell_table/export_envp.c | 4 +- src/execute/command/exec_builtin_cmd.c | 50 ++++++++ .../command/exec_builtin_cmd_private.h | 27 +++++ src/execute/command/exec_external_cmd.c | 40 +++++++ src/execute/command/list_to_argv.c | 39 +++++++ src/execute/exec_ast.c | 25 ++++ src/execute/exec_cmd.c | 101 ++++++++++++++++ src/execute/exec_pipe.c | 70 +++++++++++ src/execute/pipe/exec_pipe_child.c | 59 ++++++++++ src/execute/redirects/exec_redirs.c | 109 ++++++++++++++++++ src/execute/utils/ft_wexitstatus.c | 16 +++ src/execute/utils/ft_wifexited.c | 16 +++ 20 files changed, 791 insertions(+), 7 deletions(-) create mode 100644 docs/execute.md create mode 100644 includes/execute.h create mode 100644 libft/string/ft_free_array.c create mode 100644 src/builtin/exit/exit.c create mode 100644 src/execute/command/exec_builtin_cmd.c create mode 100644 src/execute/command/exec_builtin_cmd_private.h create mode 100644 src/execute/command/exec_external_cmd.c create mode 100644 src/execute/command/list_to_argv.c create mode 100644 src/execute/exec_ast.c create mode 100644 src/execute/exec_cmd.c create mode 100644 src/execute/exec_pipe.c create mode 100644 src/execute/pipe/exec_pipe_child.c create mode 100644 src/execute/redirects/exec_redirs.c create mode 100644 src/execute/utils/ft_wexitstatus.c create mode 100644 src/execute/utils/ft_wifexited.c diff --git a/Makefile b/Makefile index 008c7f4..fe8630e 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ # ::: :::::::: # # Makefile :+: :+: :+: # # +:+ +:+ +:+ # -# By: surayama +#+ +:+ +#+ # +# By: kjikuhar +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/05/18 21:11:39 by kjikuhar #+# #+# # # Updated: 2026/03/03 20:32:45 by surayama ### ########.fr # @@ -63,6 +63,7 @@ SRCS_MAND := src/main.c \ src/builtin/unset/unset.c \ src/builtin/cd/cd.c \ src/builtin/cd/search_cdpath.c \ + src/builtin/exit/exit.c \ src/prompt/prompt.c \ src/callback/on_input.c \ src/checker/builtin_checker.c \ @@ -113,6 +114,16 @@ SRCS_MAND := src/main.c \ src/component/shell_table/shell_print.c \ src/component/shell_table/build_shell_table.c \ src/component/shell_table/export_envp.c \ + src/execute/exec_ast.c \ + src/execute/exec_cmd.c \ + src/execute/exec_pipe.c \ + src/execute/utils/ft_wexitstatus.c \ + src/execute/utils/ft_wifexited.c \ + src/execute/command/exec_external_cmd.c \ + src/execute/command/exec_builtin_cmd.c \ + src/execute/command/list_to_argv.c \ + src/execute/pipe/exec_pipe_child.c \ + src/execute/redirects/exec_redirs.c \ src/component/directory/list_directory.c \ src/component/directory/list_directory_recursive.c \ src/component/path/to_absolute_path.c \ diff --git a/docs/execute.md b/docs/execute.md new file mode 100644 index 0000000..0d4e985 --- /dev/null +++ b/docs/execute.md @@ -0,0 +1,88 @@ +# Execute の設計 + +`jiku/feature/execute` ブランチに実装済み。 + +## ファイル構成 + +``` +src/execute/ +├── exec_ast.c # エントリーポイント。ASTノードを PIPE/CMD に振り分け +├── exec_cmd.c # CMDノードの実行。リダイレクション処理 → 外部コマンド実行 +├── exec_pipe.c # PIPEノードの実行。左右を fork して pipe でつなぐ +├── pipe/ +│ └── exec_pipe_child.c # 子プロセス内の fd 付け替え(dup2)と再帰実行 +├── command/ +│ ├── exec_external_cmd.c # execve() による外部コマンド実行 +│ └── list_to_argv.c # t_list のトークンリストを char** argv に変換 +├── redirects/ +│ └── exec_redirs.c # リダイレクションの適用(<, >, >>) +└── utils/ + ├── ft_wifexited.c # WIFEXITED マクロの代替実装 + └── ft_wexitstatus.c # WEXITSTATUS マクロの代替実装 +``` + +## 実行フロー + +### シングルコマンド(`ls -la`) + +``` +exec_ast(CMD) + └─ exec_cmd() + ├─ exec_redirs() # リダイレクションを dup2 で適用 + ├─ list_to_argv() # t_list → char** に変換 + └─ exec_external_cmd() + ├─ find_exec_path() # $PATH を走査してフルパスを取得 + ├─ export_envp() # shell_table → envp[] に変換 + └─ execve() # プロセスを置き換えて実行 +``` + +### パイプ(`ls | grep src`) + +``` +exec_ast(PIPE) + └─ exec_pipe() + ├─ pipe(fd) # パイプを作成 + ├─ fork() → exec_left_child() + │ ├─ dup2(fd[1], STDOUT) # 左側の stdout → パイプ書き込み端 + │ └─ exec_ast(node->left) # 左ノードを再帰実行 + ├─ fork() → exec_right_child() + │ ├─ dup2(fd[0], STDIN) # 右側の stdin → パイプ読み込み端 + │ └─ exec_ast(node->right) # 右ノードを再帰実行 + ├─ close(fd[0]), close(fd[1]) + ├─ waitpid(left) + └─ waitpid(right) → 右側の終了ステータスを返す +``` + +パイプは左右それぞれを別プロセスで並行実行し、親は両方の終了を待つ。 +終了ステータスは右側(最後のコマンド)のものを使う。 + +### リダイレクション(`exec_redirs.c`) + +リダイレクションは `exec_cmd()` がコマンドを実行する前に適用する。 +複数のリダイレクションがある場合はリストの順に処理する。 + +| 記法 | 処理 | +|-----------|------| +| `< file` | `open(O_RDONLY)` → `dup2(fd, STDIN_FILENO)` | +| `> file` | `open(O_WRONLY\|O_CREAT\|O_TRUNC, 0644)` → `dup2(fd, STDOUT_FILENO)` | +| `>> file` | `open(O_WRONLY\|O_CREAT\|O_APPEND, 0644)` → `dup2(fd, STDOUT_FILENO)` | +| `<< EOF` | `heredoc()` が事前に tmpfile に変換済みのため `< tmpfile` として処理 | + +## 注意点・既知の問題 + +### ビルトイン未対応 + +`exec_cmd()` は現在すべてのコマンドを `exec_external_cmd()` に渡している。 +`echo`, `pwd`, `cd`, `export`, `unset`, `exit` を判別してビルトイン関数に +振り分けるディスパッチ処理が必要。 + +### exit コードのバグ + +`exec_external_cmd()` で `find_exec_path()` が `NULL` を返したとき(= コマンドが +見つからない)に `126` を返しているが、正しくは `127`。`126` は「ファイルは +存在するが実行権限がない」場合に使う。 + +### パイプ内のビルトイン + +パイプの子プロセス内でビルトインが呼ばれた場合、その副作用(`cd` による +`PWD` 変更など)は親プロセスには反映されない。これは bash の仕様通りの挙動。 diff --git a/includes/builtin.h b/includes/builtin.h index 8dd0a85..4d0ce5a 100644 --- a/includes/builtin.h +++ b/includes/builtin.h @@ -24,5 +24,6 @@ int pwd(t_list *argv, t_shell_table *shell_table); int export(t_list *argv, t_shell_table *shell_table); int unset(t_list *argv, t_shell_table *shell_table); int cd(t_list *argv, t_shell_table *shell_table); +int builtin_exit(t_list *argv, t_shell_table *shell_table); #endif diff --git a/includes/execute.h b/includes/execute.h new file mode 100644 index 0000000..6a88ef7 --- /dev/null +++ b/includes/execute.h @@ -0,0 +1,38 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* execute.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/09/30 16:38:39 by kjikuhar #+# #+# */ +/* Updated: 2026/01/08 10:37:36 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +/* prevent re-include-------------------------------------------------------- */ +#ifndef EXECUTE_H +# define EXECUTE_H + +/* include header file------------------------------------------------------- */ +# include "parse.h" +# include "shell_table.h" + +/* main function------------------------------------------------------------- */ +int exec_ast(t_ast *node, t_shell_table *shell_table); +int exec_builtin_cmd(t_ast *node, t_shell_table *shell_table); +int exec_cmd(t_ast *node, t_shell_table *shell_table); +int exec_external_cmd(char **argv, t_shell_table *shell_table); +char *find_exec_path(const char *cmd, \ + t_shell_table *shell_table); +int exec_pipe(t_ast *node, t_shell_table *shell_table); +void exec_left_child(t_ast *node, \ + t_shell_table *shell_table, int fd[2]); +void exec_right_child(t_ast *node, \ + t_shell_table *shell_table, int fd[2]); +int exec_redirs(t_list *redirs); +char **list_to_argv(t_list *lst); +int ft_wifexited(int exit_status); +int ft_wexitstatus(int exit_status); + +#endif diff --git a/libft/Makefile b/libft/Makefile index c3c4463..45d9f31 100644 --- a/libft/Makefile +++ b/libft/Makefile @@ -3,10 +3,10 @@ # ::: :::::::: # # Makefile :+: :+: :+: # # +:+ +:+ +:+ # -# By: surayama +#+ +:+ +#+ # +# By: kjikuhar +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/04/04 16:00:02 by kjikuhar #+# #+# # -# Updated: 2026/02/01 21:36:07 by surayama ### ########.fr # +# Updated: 2026/03/03 13:49:37 by kjikuhar ### ########.fr # # # # **************************************************************************** # @@ -47,6 +47,7 @@ SRCS = conversion/ft_atoi.c \ output/ft_putendl_fd.c \ output/ft_putnbr_fd.c \ output/ft_putstr_fd.c \ + string/ft_free_array.c \ string/ft_split.c \ string/ft_strchr.c \ string/ft_strdup.c \ diff --git a/libft/libft.h b/libft/libft.h index 538555a..b9a7f69 100644 --- a/libft/libft.h +++ b/libft/libft.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* libft.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/25 14:55:13 by kjikuhar #+# #+# */ -/* Updated: 2026/02/01 21:36:07 by surayama ### ########.fr */ +/* Updated: 2026/03/03 13:53:04 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -81,6 +81,7 @@ void ft_putnbr_fd(int n, int fd); void ft_putstr_fd(const char *s, int fd); // string +void ft_free_array(void **arr); char **ft_split(char const *s, char c); char *ft_strchr(const char *s, int c); char *ft_strdup(const char *s); diff --git a/libft/string/ft_free_array.c b/libft/string/ft_free_array.c new file mode 100644 index 0000000..e77afe6 --- /dev/null +++ b/libft/string/ft_free_array.c @@ -0,0 +1,28 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_free_array.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/14 23:08:19 by kjikuhar #+# #+# */ +/* Updated: 2026/03/03 14:23:20 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_free_array(void **arr) +{ + void **temp; + + if (!arr) + return ; + temp = arr; + while (*temp) + { + free(*temp); + temp++; + } + free(arr); +} diff --git a/src/builtin/exit/exit.c b/src/builtin/exit/exit.c new file mode 100644 index 0000000..9c87d0a --- /dev/null +++ b/src/builtin/exit/exit.c @@ -0,0 +1,64 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exit.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/11 17:55:33 by kjikuhar #+# #+# */ +/* Updated: 2026/04/11 17:55:34 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "builtin.h" + +static bool is_numeric(const char *str) +{ + int i; + + i = 0; + if (str[i] == '-' || str[i] == '+') + i++; + if (!str[i]) + return (false); + while (str[i]) + { + if (!ft_isdigit((unsigned char)str[i])) + return (false); + i++; + } + return (true); +} + +static void exit_numeric_error(const char *str) +{ + ft_putstr_fd(SHELL_NAME ": exit: ", STDERR_FILENO); + ft_putstr_fd(str, STDERR_FILENO); + ft_putstr_fd(": numeric argument required\n", STDERR_FILENO); + exit(2); +} + +int builtin_exit(t_list *argv, t_shell_table *shell_table) +{ + t_list *args; + char *str; + + write(STDOUT_FILENO, "exit\n", 5); + args = argv->next; + if (!args) + { + str = st_search(shell_table, "?"); + if (!str) + exit(0); + exit(ft_atoi(str) & 0xFF); + } + if (args->next) + { + ft_putstr_fd(SHELL_NAME ": exit: too many arguments\n", STDERR_FILENO); + return (1); + } + str = (char *)args->content; + if (!is_numeric(str)) + exit_numeric_error(str); + exit(ft_atoi(str) & 0xFF); +} diff --git a/src/component/shell_table/export_envp.c b/src/component/shell_table/export_envp.c index 383ac27..b79fc48 100644 --- a/src/component/shell_table/export_envp.c +++ b/src/component/shell_table/export_envp.c @@ -5,8 +5,8 @@ /* +:+ +:+ +:+ */ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/26 16:15:41 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ +/* Created: 2026/04/11 18:31:48 by kjikuhar #+# #+# */ +/* Updated: 2026/04/11 18:31:49 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/execute/command/exec_builtin_cmd.c b/src/execute/command/exec_builtin_cmd.c new file mode 100644 index 0000000..74f4a31 --- /dev/null +++ b/src/execute/command/exec_builtin_cmd.c @@ -0,0 +1,50 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_builtin_cmd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/11 18:30:04 by kjikuhar #+# #+# */ +/* Updated: 2026/04/11 18:30:05 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "exec_builtin_cmd_private.h" + +static t_builtin_fn find_builtin(const char *name) +{ + static const t_builtin_entry g[] = { + {"echo", echo}, + {"pwd", pwd}, + {"cd", cd}, + {"export", export}, + {"unset", unset}, + {"exit", builtin_exit}, + {NULL, NULL} + }; + int i; + + i = 0; + while (g[i].name) + { + if (ft_strncmp(name, g[i].name, ft_strlen(g[i].name) + 1) == 0) + return (g[i].func); + i++; + } + return (NULL); +} + +int exec_builtin_cmd(t_ast *node, t_shell_table *shell_table) +{ + t_builtin_fn fn; + char *name; + + if (!node->cmd->argv || !node->cmd->argv->content) + return (-1); + name = (char *)node->cmd->argv->content; + fn = find_builtin(name); + if (!fn) + return (-1); + return (fn(node->cmd->argv, shell_table)); +} diff --git a/src/execute/command/exec_builtin_cmd_private.h b/src/execute/command/exec_builtin_cmd_private.h new file mode 100644 index 0000000..8ac80a1 --- /dev/null +++ b/src/execute/command/exec_builtin_cmd_private.h @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_builtin_cmd_private.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/11 18:30:58 by kjikuhar #+# #+# */ +/* Updated: 2026/04/11 18:30:59 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef EXEC_BUILTIN_CMD_PRIVATE_H +# define EXEC_BUILTIN_CMD_PRIVATE_H + +# include "builtin.h" +# include "execute.h" + +typedef int (*t_builtin_fn)(t_list *, t_shell_table *); + +typedef struct s_builtin_entry +{ + const char *name; + t_builtin_fn func; +} t_builtin_entry; + +#endif diff --git a/src/execute/command/exec_external_cmd.c b/src/execute/command/exec_external_cmd.c new file mode 100644 index 0000000..598bb90 --- /dev/null +++ b/src/execute/command/exec_external_cmd.c @@ -0,0 +1,40 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_external_cmd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/14 23:08:19 by kjikuhar #+# #+# */ +/* Updated: 2026/03/03 13:49:37 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "execute.h" + +int exec_external_cmd(char **argv, t_shell_table *shell_table) +{ + char *cmd_path; + char **new_envp; + + cmd_path = find_exec_path(argv[0], shell_table); + if (!cmd_path) + { + ft_free_array((void **)argv); + return (126); + } + new_envp = export_envp(shell_table); + if (!new_envp) + { + free(cmd_path); + ft_free_array((void **)argv); + return (1); + } + execve(cmd_path, argv, new_envp); + perror(cmd_path); + free(cmd_path); + st_destroy(shell_table); + ft_free_array((void **)new_envp); + ft_free_array((void **)argv); + return (127); +} diff --git a/src/execute/command/list_to_argv.c b/src/execute/command/list_to_argv.c new file mode 100644 index 0000000..c0e08dc --- /dev/null +++ b/src/execute/command/list_to_argv.c @@ -0,0 +1,39 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* list_to_argv.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/14 17:41:14 by kjikuhar #+# #+# */ +/* Updated: 2026/03/03 13:49:37 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char **list_to_argv(t_list *lst) +{ + size_t count; + size_t i; + char **out; + + count = ft_lstsize(lst); + out = malloc(sizeof(char *) * (count + 1)); + if (!out) + return (NULL); + i = 0; + while (lst) + { + out[i] = ft_strdup((const char *)lst->content); + if (!out[i]) + { + ft_free_array((void **)out); + return (NULL); + } + i++; + lst = lst->next; + } + out[i] = NULL; + return (out); +} diff --git a/src/execute/exec_ast.c b/src/execute/exec_ast.c new file mode 100644 index 0000000..f0e2947 --- /dev/null +++ b/src/execute/exec_ast.c @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_ast.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/10/31 21:10:34 by kjikuhar #+# #+# */ +/* Updated: 2026/01/08 10:07:05 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "execute.h" + +int exec_ast(t_ast *node, t_shell_table *shell_table) +{ + if (!node) + return (EXIT_FAILURE); + if (node->type == PIPE) + return (exec_pipe(node, shell_table)); + else if (node->type == CMD) + return (exec_cmd(node, shell_table)); + else + return (EXIT_FAILURE); +} diff --git a/src/execute/exec_cmd.c b/src/execute/exec_cmd.c new file mode 100644 index 0000000..2ac9603 --- /dev/null +++ b/src/execute/exec_cmd.c @@ -0,0 +1,101 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_cmd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/14 17:18:25 by kjikuhar #+# #+# */ +/* Updated: 2026/03/03 13:49:37 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "execute.h" + +static char *join_path(const char *path, const char *cmd) +{ + size_t path_len; + size_t cmd_len; + char *joined; + + path_len = ft_strlen(path); + cmd_len = ft_strlen(cmd); + joined = malloc(sizeof(char) * (path_len + 1 + cmd_len + 1)); + if (!joined) + return (NULL); + ft_strlcpy(joined, path, path_len + 1); + joined[path_len] = '/'; + ft_strlcpy(joined + path_len + 1, cmd, cmd_len + 1); + return (joined); +} + +static char *find_in_path(const char *cmd, t_shell_table *shell_table) +{ + char **paths; + char *path_env; + char *full_path; + int i; + + path_env = st_search(shell_table, "PATH"); + if (!path_env) + return (NULL); + paths = ft_split(path_env, ':'); + if (!paths) + return (NULL); + i = 0; + while (paths[i]) + { + full_path = join_path(paths[i], cmd); + if (!full_path) + return (ft_free_array((void **)paths), NULL); + if (access(full_path, X_OK) == 0) + return (ft_free_array((void **)paths), full_path); + free(full_path); + i++; + } + ft_free_array((void **)paths); + return (NULL); +} + +static char *resolve_exec_path(const char *cmd) +{ + if (access(cmd, X_OK) == 0) + return (ft_strdup(cmd)); + return (NULL); +} + +char *find_exec_path(const char *cmd, t_shell_table *shell_table) +{ + char *result; + + if (!cmd || !*cmd) + return (NULL); + if (ft_strchr(cmd, '/')) + result = resolve_exec_path(cmd); + else + result = find_in_path(cmd, shell_table); + return (result); +} + +int exec_cmd(t_ast *node, t_shell_table *shell_table) +{ + char **argv; + int status; + + if (node->cmd->redirs) + { + if (exec_redirs(node->cmd->redirs) != 0) + return (1); + } + status = exec_builtin_cmd(node, shell_table); + if (status != -1) + return (status); + argv = list_to_argv(node->cmd->argv); + if (!argv || !argv[0]) + { + if (argv) + ft_free_array((void **)argv); + return (127); + } + return (exec_external_cmd(argv, shell_table)); +} diff --git a/src/execute/exec_pipe.c b/src/execute/exec_pipe.c new file mode 100644 index 0000000..30ac237 --- /dev/null +++ b/src/execute/exec_pipe.c @@ -0,0 +1,70 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_pipe.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/01 05:46:56 by kjikuhar #+# #+# */ +/* Updated: 2026/01/08 10:19:25 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "execute.h" + +static int exec_pipe_left(t_ast *node, t_shell_table *shell_table, \ + pid_t *left, int fd[2]) +{ + *left = fork(); + if (*left == 0) + exec_left_child(node, shell_table, fd); + else if (*left < 0) + { + close(fd[0]); + close(fd[1]); + return (1); + } + return (0); +} + +static int exec_pipe_right(t_ast *node, t_shell_table *shell_table, \ + pid_t *right, int fd[2]) +{ + *right = fork(); + if (*right == 0) + exec_right_child(node, shell_table, fd); + else if (*right < 0) + { + close(fd[0]); + close(fd[1]); + return (1); + } + return (0); +} + +int exec_pipe(t_ast *node, t_shell_table *shell_table) +{ + int fd[2]; + pid_t left; + pid_t right; + int exit_status_left_child; + int exit_status_right_child; + + if (pipe(fd) == -1) + return (1); + if (exec_pipe_left(node, shell_table, &left, fd) != 0) + return (1); + if (exec_pipe_right(node, shell_table, &right, fd) != 0) + { + if (left > 0) + waitpid(left, NULL, 0); + return (1); + } + close(fd[0]); + close(fd[1]); + waitpid(left, &exit_status_left_child, 0); + waitpid(right, &exit_status_right_child, 0); + if (ft_wifexited(exit_status_right_child)) + return (ft_wexitstatus(exit_status_right_child)); + return (1); +} diff --git a/src/execute/pipe/exec_pipe_child.c b/src/execute/pipe/exec_pipe_child.c new file mode 100644 index 0000000..f3d9fc9 --- /dev/null +++ b/src/execute/pipe/exec_pipe_child.c @@ -0,0 +1,59 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_pipe_child.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/14 23:08:24 by kjikuhar #+# #+# */ +/* Updated: 2026/04/11 00:00:00 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "execute.h" + +void exec_left_child(t_ast *node, t_shell_table *shell_table, int fd[2]) +{ + int status; + t_ast *left_node; + t_ast *right_node; + + if (dup2(fd[1], STDOUT_FILENO) == -1) + { + close(fd[0]); + close(fd[1]); + exit(1); + } + close(fd[0]); + close(fd[1]); + left_node = node->left; + right_node = node->right; + free(node); + status = exec_ast(left_node, shell_table); + free_ast(left_node); + free_ast(right_node); + exit(status); +} + +void exec_right_child(t_ast *node, t_shell_table *shell_table, int fd[2]) +{ + int status; + t_ast *left_node; + t_ast *right_node; + + if (dup2(fd[0], STDIN_FILENO) == -1) + { + close(fd[0]); + close(fd[1]); + exit(1); + } + close(fd[1]); + close(fd[0]); + left_node = node->left; + right_node = node->right; + free(node); + status = exec_ast(right_node, shell_table); + free_ast(left_node); + free_ast(right_node); + exit(status); +} diff --git a/src/execute/redirects/exec_redirs.c b/src/execute/redirects/exec_redirs.c new file mode 100644 index 0000000..d71261a --- /dev/null +++ b/src/execute/redirects/exec_redirs.c @@ -0,0 +1,109 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_redirs.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/14 17:41:09 by kjikuhar #+# #+# */ +/* Updated: 2025/11/27 16:45:26 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "execute.h" + +static int exec_redir_in(const char *filename) +{ + int fd; + + fd = open(filename, O_RDONLY); + if (fd == -1) + { + perror(filename); + return (1); + } + if (dup2(fd, STDIN_FILENO) == -1) + { + perror(filename); + close(fd); + return (1); + } + close(fd); + return (0); +} + +static int exec_redir_out_trunc(const char *filename) +{ + int fd; + + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) + { + perror(filename); + return (1); + } + if (dup2(fd, STDOUT_FILENO) == -1) + { + perror(filename); + close(fd); + return (1); + } + close(fd); + return (0); +} + +static int exec_redir_out_append(const char *filename) +{ + int fd; + + fd = open(filename, O_WRONLY | O_CREAT | O_APPEND, 0644); + if (fd == -1) + { + perror(filename); + return (1); + } + if (dup2(fd, STDOUT_FILENO) == -1) + { + perror(filename); + close(fd); + return (1); + } + close(fd); + return (0); +} + +static int exec_one_redir(t_redir *redir) +{ + if (redir->kind == R_IN) + { + if (exec_redir_in(redir->filename) != 0) + return (ERROR); + } + else if (redir->kind == R_OUT_TRUNC) + { + if (exec_redir_out_trunc(redir->filename) != 0) + return (ERROR); + } + else if (redir->kind == R_OUT_APPEND) + { + if (exec_redir_out_append(redir->filename) != 0) + return (ERROR); + } + return (SUCCESS); +} + +int exec_redirs(t_list *redirs) +{ + t_list *current; + t_redir *redir; + + current = redirs; + while (current) + { + redir = (t_redir *)current->content; + if (exec_one_redir(redir) != 0) + return (1); + current = current->next; + } + return (0); +} diff --git a/src/execute/utils/ft_wexitstatus.c b/src/execute/utils/ft_wexitstatus.c new file mode 100644 index 0000000..74bc078 --- /dev/null +++ b/src/execute/utils/ft_wexitstatus.c @@ -0,0 +1,16 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_wexitstatus.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/14 21:45:08 by kjikuhar #+# #+# */ +/* Updated: 2025/11/14 21:45:33 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +int ft_wexitstatus(int exit_status) +{ + return ((exit_status & 0xff00) >> 8); +} diff --git a/src/execute/utils/ft_wifexited.c b/src/execute/utils/ft_wifexited.c new file mode 100644 index 0000000..d81d994 --- /dev/null +++ b/src/execute/utils/ft_wifexited.c @@ -0,0 +1,16 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_wifexited.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/11/14 21:45:42 by kjikuhar #+# #+# */ +/* Updated: 2025/11/14 21:45:55 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +int ft_wifexited(int exit_status) +{ + return ((exit_status & 0x7f) == 0); +} From af5d6917d5a348242419189fb3c8efed4293bca6 Mon Sep 17 00:00:00 2001 From: urassh <84073765+urassh@users.noreply.github.com> Date: Sat, 11 Apr 2026 18:50:26 +0900 Subject: [PATCH 138/173] =?UTF-8?q?README.md=20=E3=82=92=E8=BF=BD=E5=8A=A0?= =?UTF-8?q?=20(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Claude Opus 4.6 (1M context) --- README.md | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..6504ba4 --- /dev/null +++ b/README.md @@ -0,0 +1,100 @@ +*This project has been created as part of the 42 curriculum by surayama, kjikuhar.* + +# minishell + +## Description + +Minishell is a simplified shell implementation written in C, inspired by bash. The goal of this project is to understand how a real shell works by building one from scratch: parsing user input, managing environment variables, handling redirections and pipes, and executing commands. + +Key features include: + +- Interactive prompt with command history (GNU readline) +- Tokenization and parsing of shell commands into an AST (Abstract Syntax Tree) +- Pipes (`|`) and redirections (`<`, `>`, `>>`, `<<`) +- Environment variable expansion (`$VAR`, `$?`) +- Quote handling (single and double quotes) +- Here-documents (`<<`) +- Built-in commands: `echo`, `cd`, `pwd`, `export`, `unset`, `env`, `exit` +- Signal handling (`Ctrl+C`, `Ctrl+D`, `Ctrl+\`) + +## Instructions + +### Prerequisites + +- Docker (recommended for building and running) +- Or: GCC, Make, GNU readline library + +### Build and Run + +The recommended way to build and run is inside the Docker environment: + +```bash +# Enter the Docker container +make docker + +# Build inside the container +make + +# Run the shell +./minishell +``` + +### Other Make Targets + +| Command | Description | +|-----------------|--------------------------------------------------| +| `make` | Build the project | +| `make re` | Clean rebuild | +| `make clean` | Remove object files | +| `make fclean` | Remove object files and binary | +| `make norm` | Run norminette style checker | +| `make valgrind` | Rebuild and run with valgrind for leak detection | +| `make test` | Run norminette + valgrind | + +### Usage Examples + +``` +$ ./minishell +minishell$ echo hello world +hello world +minishell$ ls -la | grep Makefile +-rw-r--r-- 1 user staff 2048 Apr 10 12:00 Makefile +minishell$ export FOO=bar +minishell$ echo $FOO +bar +minishell$ cat << EOF +> hello +> world +> EOF +hello +world +minishell$ exit +``` + +## Architecture + +The shell follows an interpreter pipeline: + +``` +Input -> tokenize() -> heredoc() -> variable_expand() -> remove_quotes() -> parse() -> AST -> execute +``` + +1. **Tokenizer** -- State-machine-based lexer that splits input into tokens at operator, space, and quote boundaries. +2. **Variable Expansion** -- Expands `$VAR` syntax while respecting quote context. +3. **Quote Removal** -- Strips quote characters from expanded tokens. +4. **Parser** -- Recursive descent parser that produces a binary AST with `PIPE` (internal) and `CMD` (leaf) nodes. +5. **Executor** -- Walks the AST, sets up pipes and redirections, and executes commands via `fork`/`execve`. + +## Resources + +- [The Open Group Base Specifications -- Shell Command Language](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html) +- [Bash Reference Manual](https://www.gnu.org/software/bash/manual/bash.html) +- [Writing Your Own Shell (42 tutorial)](https://harm-smits.github.io/42docs/projects/minishell) +- [GNU Readline Library Documentation](https://tiswww.case.edu/php/chet/readline/rltop.html) + +### Use of AI + +AI (Claude Code by Anthropic) was used as a development assistant for the following tasks: + +- Code review and debugging assistance +- Generating boilerplate code and Makefile configurations From 78f65c5d4d4902e17c2f3ad9506945ee65f0d84a Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 16 Apr 2026 17:06:13 +0900 Subject: [PATCH 139/173] =?UTF-8?q?=E6=8F=90=E5=87=BA=E7=94=A8=E3=81=AB?= =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E3=83=BB=E3=83=87=E3=83=90=E3=83=83?= =?UTF-8?q?=E3=82=B0=E3=82=B3=E3=83=BC=E3=83=89=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit checker ディレクトリ、print_ast デバッグ出力、Makefile のテストルールを削除し、 main.c を本番用のシンプルなエントリポイントに整理。 Co-Authored-By: Claude Opus 4.6 (1M context) --- Makefile | 24 +----- includes/minishell.h | 22 +---- includes/parse.h | 16 ---- src/checker/builtin_checker.c | 28 ------- src/checker/directory_checker.c | 99 ----------------------- src/checker/expand_checker.c | 68 ---------------- src/checker/heredoc_checker.c | 85 ------------------- src/checker/parse_checker.c | 40 --------- src/checker/path_checker.c | 44 ---------- src/checker/relative_path_checker.c | 62 -------------- src/checker/remove_quotes_checker.c | 68 ---------------- src/checker/shell_table_checker.c | 121 ---------------------------- src/checker/tokenize_checker.c | 58 ------------- src/checker/wildcard_checker.c | 68 ---------------- src/main.c | 53 +----------- src/parse/utils/print_ast.c | 67 --------------- src/parse/utils/print_ast_utils.c | 57 ------------- src/parse/utils/print_ast_utils2.c | 99 ----------------------- 18 files changed, 5 insertions(+), 1074 deletions(-) delete mode 100644 src/checker/builtin_checker.c delete mode 100644 src/checker/directory_checker.c delete mode 100644 src/checker/expand_checker.c delete mode 100644 src/checker/heredoc_checker.c delete mode 100644 src/checker/parse_checker.c delete mode 100644 src/checker/path_checker.c delete mode 100644 src/checker/relative_path_checker.c delete mode 100644 src/checker/remove_quotes_checker.c delete mode 100644 src/checker/shell_table_checker.c delete mode 100644 src/checker/tokenize_checker.c delete mode 100644 src/checker/wildcard_checker.c delete mode 100644 src/parse/utils/print_ast.c delete mode 100644 src/parse/utils/print_ast_utils.c delete mode 100644 src/parse/utils/print_ast_utils2.c diff --git a/Makefile b/Makefile index fe8630e..c6b0c6a 100644 --- a/Makefile +++ b/Makefile @@ -66,17 +66,6 @@ SRCS_MAND := src/main.c \ src/builtin/exit/exit.c \ src/prompt/prompt.c \ src/callback/on_input.c \ - src/checker/builtin_checker.c \ - src/checker/tokenize_checker.c \ - src/checker/heredoc_checker.c \ - src/checker/shell_table_checker.c \ - src/checker/parse_checker.c \ - src/checker/path_checker.c \ - src/checker/directory_checker.c \ - src/checker/expand_checker.c \ - src/checker/remove_quotes_checker.c \ - src/checker/wildcard_checker.c \ - src/checker/relative_path_checker.c \ src/tokenize/tokenize.c \ src/tokenize/is_specific.c \ src/tokenize/state/in_normal.c \ @@ -100,9 +89,6 @@ SRCS_MAND := src/main.c \ src/parse/utils/new_redir.c \ src/parse/utils/token_check.c \ src/parse/utils/free_ast.c \ - src/parse/utils/print_ast.c \ - src/parse/utils/print_ast_utils.c \ - src/parse/utils/print_ast_utils2.c \ src/component/heredoc/heredoc.c \ src/component/heredoc/heredoc_prompt.c \ src/component/heredoc/tmpfile.c \ @@ -209,15 +195,7 @@ re: fclean all #----------------------------------------------------------------------------- -norm: - norminette src/* includes/* libft/ - -valgrind: re - valgrind --leak-check=full --suppressions=readline.supp ./$(NAME) --dev - -test: norm valgrind - docker: docker compose up -d && docker compose exec minishell bash -.PHONY: norm valgrind test docker +.PHONY: docker diff --git a/includes/minishell.h b/includes/minishell.h index 21adf08..f4e0006 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -6,7 +6,7 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:14:22 by kjikuhar #+# #+# */ -/* Updated: 2026/02/13 23:37:35 by surayama ### ########.fr */ +/* Updated: 2026/04/16 00:00:00 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -24,27 +24,7 @@ # include "signal_handler.h" # include "tokenize.h" -typedef void (*t_checker)(char *, t_shell_table *); -typedef struct s_checker_entry -{ - char *name; - t_checker checker; -} t_checker_entry; - // callbacks void on_input(char *input, t_shell_table *shell_table); -// checkers -void tokenize_checker(char *input, t_shell_table *shell_table); -void heredoc_checker(char *input, t_shell_table *shell_table); -void shell_table_checker(t_shell_table *shell_table); -void parse_checker(char *input, t_shell_table *shell_table); -void directory_checker(char *input, t_shell_table *shell_table); -void path_checker(char *input, t_shell_table *shell_table); -void builtin_checker(char *input, t_shell_table *shell_table); -void expand_checker(char *input, t_shell_table *shell_table); -void remove_quotes_checker(char *input, t_shell_table *shell_table); -void wildcard_checker(char *input, t_shell_table *shell_table); -void relative_path_checker(char *input, t_shell_table *shell_table); - #endif diff --git a/includes/parse.h b/includes/parse.h index 2a7fff7..163e417 100644 --- a/includes/parse.h +++ b/includes/parse.h @@ -78,20 +78,4 @@ bool add_argv_to_cmd(t_cmd *cmd, const char *arg); void free_cmd(t_cmd *cmd); void free_ast(t_ast *node); -/* test print function------------------------------------------------------- */ -void print_branch_line(const char *prefix, bool is_last, - const char *text); -void build_child_prefix(const char *prefix, bool is_last, - char *buffer, size_t size); -void print_argv_item(t_list *node, int index); -const char *get_redir_symbol(t_redir *redir); -void print_redir_entry(t_redir *redir, int index); -void print_argv_line(const char *prefix, bool is_last, - t_list *argv); -void print_redir_line(const char *prefix, bool is_last, - t_list *redirs); -void print_pipe_children(t_ast *node, const char *prefix); -void print_pipe_node(t_ast *node, const char *prefix, bool is_last); -void print_ast_node(t_ast *node, const char *prefix, bool is_last); -void print_ast(t_ast *ast_root); #endif diff --git a/src/checker/builtin_checker.c b/src/checker/builtin_checker.c deleted file mode 100644 index 5a7d75a..0000000 --- a/src/checker/builtin_checker.c +++ /dev/null @@ -1,28 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* builtin_checker.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/12/06 15:32:40 by surayama #+# #+# */ -/* Updated: 2025/12/06 16:19:06 by surayama ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "builtin.h" -#include "minishell.h" - -void builtin_checker(char *input, t_shell_table *shell_table) -{ - t_list *tokens; - int (*builtin_func)(t_list *, t_shell_table *); - - builtin_func = export; - tokens = tokenize(input); - if (!tokens) - return ; - if (builtin_func) - builtin_func(tokens, shell_table); - ft_lstclear(&tokens, free); -} diff --git a/src/checker/directory_checker.c b/src/checker/directory_checker.c deleted file mode 100644 index 77a7575..0000000 --- a/src/checker/directory_checker.c +++ /dev/null @@ -1,99 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* directory_checker.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/27 16:10:35 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:47:35 by kjikuhar ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "directory.h" -#include "minishell.h" - -static void print_entries(t_list *entries, const char *title); -static void test_function(const char *input, bool include_hidden, - int (*func)(const char *, bool, t_list **), const char *title); -static void test_entries(const char *input); -static void test_all_entries(const char *input); - -void directory_checker(char *input, t_shell_table *shell_table) -{ - (void)shell_table; - if (ft_strncmp(input, "exit", 5) == 0) - { - printf("exit\n"); - rl_clear_history(); - free(input); - exit(0); - } - test_entries(input); - test_all_entries(input); - free(input); -} - -static void test_entries(const char *input) -{ - printf("\n=== Testing list_directory ===\nPath: %s\n", input); - test_function(input, false, list_directory, - "\n--- Without hidden files ---\nEntries"); - test_function(input, true, list_directory, - "\n--- With hidden files ---\nEntries"); -} - -static void test_all_entries(const char *input) -{ - printf("\n=== Testing list_directory_recursive ===\nPath: %s\n", input); - test_function(input, false, list_directory_recursive, - "\n--- Without hidden files ---\nAll Entries (recursive)"); - test_function(input, true, list_directory_recursive, - "\n--- With hidden files ---\nAll Entries (recursive)"); -} - -static void test_function(const char *input, bool include_hidden, - int (*func)(const char *, bool, t_list **), const char *title) -{ - t_list *entries; - t_list *tmp; - int result; - const char *error_msg; - - result = func(input, include_hidden, &entries); - if (result != SUCCESS) - { - error_msg = "Unknown error"; - if (result == NOT_FOUND) - error_msg = "Directory not found"; - else if (result == NO_PERMISSION) - error_msg = "Permission denied"; - printf("Error: %s\n", error_msg); - return ; - } - print_entries(entries, title); - while (entries) - { - tmp = entries->next; - free(entries->content); - free(entries); - entries = tmp; - } -} - -static void print_entries(t_list *entries, const char *title) -{ - t_list *current; - int count; - - printf("%s:\n", title); - count = 0; - current = entries; - while (current) - { - printf(" - %s\n", (char *)current->content); - current = current->next; - count++; - } - printf("Total: %d entries\n", count); -} diff --git a/src/checker/expand_checker.c b/src/checker/expand_checker.c deleted file mode 100644 index 98cd067..0000000 --- a/src/checker/expand_checker.c +++ /dev/null @@ -1,68 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* expand_checker.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2026/02/01 22:30:00 by surayama #+# #+# */ -/* Updated: 2026/02/01 22:30:00 by surayama ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "minishell.h" - -static void on_exit_token(t_list *token_list); -static void print_expanded_tokens(t_list *token_list); - -void expand_checker(char *input, t_shell_table *shell_table) -{ - t_list *token_list; - t_list *expanded_tokens; - - token_list = tokenize(input); - if (!token_list) - { - ft_putstr_fd("Error: tokenize failed\n", STDOUT_FILENO); - return ; - } - if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) - on_exit_token(token_list); - expanded_tokens = expand(token_list, shell_table); - if (!expanded_tokens) - { - ft_putstr_fd("Error: expand failed\n", STDOUT_FILENO); - ft_lstclear(&token_list, free); - return ; - } - print_expanded_tokens(expanded_tokens); - ft_lstclear(&expanded_tokens, free); -} - -static void print_expanded_tokens(t_list *token_list) -{ - t_list *current; - int index; - char *content; - - index = 0; - current = token_list; - printf("expanded:\n"); - while (current) - { - content = current->content; - if (content) - printf("[%d] \"%s\"\n", index, content); - else - printf("[%d] (null)\n", index); - current = current->next; - index++; - } -} - -static void on_exit_token(t_list *token_list) -{ - printf("exit\n"); - ft_lstclear(&token_list, free); - exit(0); -} diff --git a/src/checker/heredoc_checker.c b/src/checker/heredoc_checker.c deleted file mode 100644 index 1760ac4..0000000 --- a/src/checker/heredoc_checker.c +++ /dev/null @@ -1,85 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* heredoc_checker.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/20 15:55:55 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "minishell.h" -#include -#include - -static void on_exit_token(t_list *token_list); -static void print_tokens(t_list *token_list); -static void unlink_tmpfiles(t_list *token_list); - -void heredoc_checker(char *input, t_shell_table *shell_table) -{ - t_list *token_list; - t_list *heredoced_list; - - (void)shell_table; - token_list = tokenize(input); - if (!token_list) - { - printf("Error: tokenize failed\n"); - return ; - } - if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) - on_exit_token(token_list); - heredoced_list = heredoc(token_list); - if (!heredoced_list) - { - printf("Error: heredoc failed\n"); - ft_lstclear(&token_list, free); - return ; - } - print_tokens(heredoced_list); - unlink_tmpfiles(heredoced_list); - ft_lstclear(&heredoced_list, free); -} - -static void print_tokens(t_list *token_list) -{ - t_list *current; - int index; - - index = 0; - current = token_list; - printf("here_doced_tokens:\n"); - while (current) - { - printf("[%d] \"", index); - if (current->content) - printf("%s", (char *)current->content); - printf("\"\n"); - current = current->next; - index++; - } -} - -static void on_exit_token(t_list *token_list) -{ - printf("exit\n"); - ft_lstclear(&token_list, free); - exit(0); -} - -static void unlink_tmpfiles(t_list *token_list) -{ - t_list *current; - - current = token_list; - while (current) - { - if (current->content && ft_strncmp(current->content, HEREDOC_TMP_PREFIX, - ft_strlen(HEREDOC_TMP_PREFIX)) == 0) - unlink((char *)current->content); - current = current->next; - } -} diff --git a/src/checker/parse_checker.c b/src/checker/parse_checker.c deleted file mode 100644 index 5fecc17..0000000 --- a/src/checker/parse_checker.c +++ /dev/null @@ -1,40 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* parse_checker.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/27 01:46:42 by kjikuhar #+# #+# */ -/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "minishell.h" - -static void on_exit_token(t_list *token_list) -{ - printf("exit\n"); - ft_lstclear(&token_list, free); - exit(0); -} - -void parse_checker(char *input, t_shell_table *shell_table) -{ - t_list *token_list; - t_ast *ast_root; - - (void)shell_table; - token_list = tokenize(input); - if (!token_list) - { - printf("Error: tokenize failed\n"); - return ; - } - if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) - on_exit_token(token_list); - ast_root = parse(token_list); - print_ast(ast_root); - free_ast(ast_root); - ft_lstclear(&token_list, free); -} diff --git a/src/checker/path_checker.c b/src/checker/path_checker.c deleted file mode 100644 index 4436e21..0000000 --- a/src/checker/path_checker.c +++ /dev/null @@ -1,44 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* path_checker.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/12/01 00:00:00 by surayama #+# #+# */ -/* Updated: 2026/03/03 12:41:23 by surayama ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "minishell.h" -#include "path.h" -#include -#include -#include - -void path_checker(char *input, t_shell_table *shell_table) -{ - char *absolute_path; - - (void)shell_table; - if (ft_strncmp(input, "exit", 5) == 0) - { - printf("exit\n"); - rl_clear_history(); - free(input); - exit(0); - } - printf("\n=== Path Checker ===\n"); - printf("Input: %s\n", input); - absolute_path = to_absolute_path(input); - if (absolute_path) - { - printf("Absolute Path: %s\n", absolute_path); - free(absolute_path); - } - else - { - ft_putendl_fd("Error: Failed to convert to absolute path", 2); - } - free(input); -} diff --git a/src/checker/relative_path_checker.c b/src/checker/relative_path_checker.c deleted file mode 100644 index 55d3216..0000000 --- a/src/checker/relative_path_checker.c +++ /dev/null @@ -1,62 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* relative_path_checker.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2026/03/03 13:00:00 by surayama #+# #+# */ -/* Updated: 2026/03/03 13:00:00 by surayama ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "minishell.h" - -static void on_exit_token(t_list *token_list); -static void print_tokens(t_list *token_list, const char *title); - -void relative_path_checker(char *input, t_shell_table *shell_table) -{ - t_list *token_list; - t_list *result; - - (void)shell_table; - token_list = tokenize(input); - if (!token_list) - { - ft_putstr_fd("Error: tokenize failed\n", STDOUT_FILENO); - return ; - } - if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) - on_exit_token(token_list); - print_tokens(token_list, "Before resolve_relative_path"); - result = resolve_relative_path(token_list); - print_tokens(result, "After resolve_relative_path"); - ft_lstclear(&result, free); -} - -static void print_tokens(t_list *token_list, const char *title) -{ - t_list *current; - int index; - char *content; - - index = 0; - current = token_list; - printf("\n%s:\n", title); - while (current) - { - content = current->content; - printf("[%d] \"%s\"\n", index, content); - current = current->next; - index++; - } - printf("\n"); -} - -static void on_exit_token(t_list *token_list) -{ - printf("exit\n"); - ft_lstclear(&token_list, free); - exit(0); -} diff --git a/src/checker/remove_quotes_checker.c b/src/checker/remove_quotes_checker.c deleted file mode 100644 index 7713825..0000000 --- a/src/checker/remove_quotes_checker.c +++ /dev/null @@ -1,68 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* remove_quote_checker.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2026/02/07 00:52:00 by surayama #+# #+# */ -/* Updated: 2026/02/07 00:52:01 by surayama ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "minishell.h" - -static void on_exit_token(t_list *token_list); -static void print_tokens(t_list *token_list, const char *title); - -void remove_quotes_checker(char *input, t_shell_table *shell_table) -{ - t_list *token_list; - t_list *result; - - (void)shell_table; - token_list = tokenize(input); - if (!token_list) - { - ft_putstr_fd("Error: tokenize failed\n", STDOUT_FILENO); - return ; - } - if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) - on_exit_token(token_list); - print_tokens(token_list, "Before remove_quote"); - result = expand_remove_quotes(token_list); - if (!result) - { - ft_putstr_fd("Error: remove_quote failed\n", STDOUT_FILENO); - ft_lstclear(&token_list, free); - return ; - } - print_tokens(result, "After remove_quote"); - ft_lstclear(&result, free); -} - -static void print_tokens(t_list *token_list, const char *title) -{ - t_list *current; - int index; - char *content; - - index = 0; - current = token_list; - printf("\n%s:\n", title); - while (current) - { - content = current->content; - printf("[%d] \"%s\"\n", index, content); - current = current->next; - index++; - } - printf("\n"); -} - -static void on_exit_token(t_list *token_list) -{ - printf("exit\n"); - ft_lstclear(&token_list, free); - exit(0); -} diff --git a/src/checker/shell_table_checker.c b/src/checker/shell_table_checker.c deleted file mode 100644 index e9753de..0000000 --- a/src/checker/shell_table_checker.c +++ /dev/null @@ -1,121 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* shell_table_checker.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/26 16:53:40 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "minishell.h" -#include -#include -#include - -static void print_shell_table_entries(t_shell_table *shell_table); -static void print_exported_envp(t_shell_table *shell_table); -static void test_execve_with_envp(t_shell_table *shell_table); - -void shell_table_checker(t_shell_table *shell_table) -{ - printf("\n========== ENV TABLE ENTRIES ==========\n"); - print_shell_table_entries(shell_table); - printf("\n========== EXPORTED ENVP ==========\n"); - print_exported_envp(shell_table); - printf("\n========== EXECVE TEST ==========\n"); - test_execve_with_envp(shell_table); - printf("=======================================\n\n"); -} - -static void print_shell_table_entries(t_shell_table *shell_table) -{ - size_t i; - t_shell_node *node; - - if (!shell_table) - { - printf("shell_table is NULL\n"); - return ; - } - printf("Total entries: %zu\n", shell_table->n_nodes); - printf("Table size: %zu\n\n", shell_table->size); - i = 0; - while (i < shell_table->size) - { - node = shell_table->buckets[i]; - while (node) - { - printf("[%zu] %s = %s\n", i, node->key, node->value); - node = node->next; - } - i++; - } -} - -static void print_exported_envp(t_shell_table *shell_table) -{ - char **envp; - size_t i; - - if (!shell_table) - { - printf("shell_table is NULL\n"); - return ; - } - envp = export_envp(shell_table); - if (!envp) - { - printf("Failed to export envp\n"); - return ; - } - i = 0; - while (envp[i]) - { - printf("%s\n", envp[i]); - free(envp[i]); - i++; - } - free(envp); -} - -static void free_envp(char **envp) -{ - char **tmp; - - tmp = envp; - while (*tmp) - free(*tmp++); - free(envp); -} - -static void test_execve_with_envp(t_shell_table *shell_table) -{ - char **envp; - pid_t pid; - int status; - char *argv[2]; - - envp = export_envp(shell_table); - if (!shell_table || !envp) - { - printf("shell_table is NULL or failed to export envp\n"); - return ; - } - pid = fork(); - if (pid == 0) - { - argv[0] = "/usr/bin/env"; - argv[1] = NULL; - execve("/usr/bin/env", argv, envp); - perror("execve failed"); - exit(1); - } - else if (pid > 0 && waitpid(pid, &status, 0) != -1 && WIFEXITED(status)) - printf("execve test completed!!\n"); - else - printf("\nFork failed or test terminated abnormally\n"); - free_envp(envp); -} diff --git a/src/checker/tokenize_checker.c b/src/checker/tokenize_checker.c deleted file mode 100644 index abc2c1e..0000000 --- a/src/checker/tokenize_checker.c +++ /dev/null @@ -1,58 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* tokenize_checker.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/05 13:47:35 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "minishell.h" - -static void on_exit_token(t_list *token_list); -static void print_tokens(t_list *token_list); - -void tokenize_checker(char *input, t_shell_table *shell_table) -{ - t_list *token_list; - - (void)shell_table; - token_list = tokenize(input); - if (!token_list) - { - ft_putstr_fd("Error: tokenize failed\n", STDOUT_FILENO); - return ; - } - if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) - on_exit_token(token_list); - print_tokens(token_list); - ft_lstclear(&token_list, free); -} - -static void print_tokens(t_list *token_list) -{ - t_list *current; - int index; - char *content; - - index = 0; - current = token_list; - printf("Tokens:\n"); - while (current) - { - content = current->content; - printf("[%d] \"%s\"\n", index, content); - current = current->next; - index++; - } -} - -static void on_exit_token(t_list *token_list) -{ - printf("exit\n"); - ft_lstclear(&token_list, free); - exit(0); -} diff --git a/src/checker/wildcard_checker.c b/src/checker/wildcard_checker.c deleted file mode 100644 index 7c70210..0000000 --- a/src/checker/wildcard_checker.c +++ /dev/null @@ -1,68 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* wildcard_checker.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2026/03/03 13:00:00 by surayama #+# #+# */ -/* Updated: 2026/03/03 13:00:00 by surayama ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "minishell.h" - -static void on_exit_token(t_list *token_list); -static void print_tokens(t_list *token_list, const char *title); - -void wildcard_checker(char *input, t_shell_table *shell_table) -{ - t_list *token_list; - t_list *result; - - (void)shell_table; - token_list = tokenize(input); - if (!token_list) - { - ft_putstr_fd("Error: tokenize failed\n", STDOUT_FILENO); - return ; - } - if (token_list->content && ft_strncmp(token_list->content, "exit", 5) == 0) - on_exit_token(token_list); - print_tokens(token_list, "Before expand_wildcard"); - result = expand_wildcard(token_list); - if (!result) - { - ft_putstr_fd("Error: expand_wildcard failed\n", STDOUT_FILENO); - ft_lstclear(&token_list, free); - return ; - } - print_tokens(result, "After expand_wildcard"); - ft_lstclear(&result, free); -} - -static void print_tokens(t_list *token_list, const char *title) -{ - t_list *current; - int index; - char *content; - - index = 0; - current = token_list; - printf("\n%s:\n", title); - while (current) - { - content = current->content; - printf("[%d] \"%s\"\n", index, content); - current = current->next; - index++; - } - printf("\n"); -} - -static void on_exit_token(t_list *token_list) -{ - printf("exit\n"); - ft_lstclear(&token_list, free); - exit(0); -} diff --git a/src/main.c b/src/main.c index 2815359..3a59797 100644 --- a/src/main.c +++ b/src/main.c @@ -6,26 +6,18 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:13:47 by kjikuhar #+# #+# */ -/* Updated: 2026/03/03 20:42:40 by surayama ### ########.fr */ +/* Updated: 2026/04/16 00:00:00 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -static t_checker find_checker(const char *arg); -static int run_checker(t_checker checker, char *const envp[]); - int main(int argc, char const **argv, char *const envp[]) { t_shell_table *shell_table; - t_checker checker; - if (argc > 1) - { - checker = find_checker(argv[1]); - if (checker) - return (run_checker(checker, envp)); - } + (void)argc; + (void)argv; shell_table = build_shell_table(envp); if (!shell_table) return (1); @@ -34,42 +26,3 @@ int main(int argc, char const **argv, char *const envp[]) st_destroy(shell_table); return (0); } - -static t_checker find_checker(const char *arg) -{ - static const t_checker_entry g[] = { - {"--tokenize", tokenize_checker}, - {"--heredoc", heredoc_checker}, - {"--parse", parse_checker}, - {"--directory", directory_checker}, - {"--path", path_checker}, - {"--builtin", builtin_checker}, - {"--expand", expand_checker}, - {"--remove-quotes", remove_quotes_checker}, - {"--wildcard", wildcard_checker}, - {"--relative-path", relative_path_checker}, - {NULL, NULL} - }; - int i; - - i = 0; - while (g[i].name) - { - if (ft_strncmp(arg, g[i].name, ft_strlen(g[i].name) + 1) == 0) - return (g[i].checker); - i++; - } - return (NULL); -} - -static int run_checker(t_checker checker, char *const envp[]) -{ - t_shell_table *shell_table; - - shell_table = build_shell_table(envp); - if (!shell_table) - return (1); - prompt(checker, shell_table); - st_destroy(shell_table); - return (0); -} diff --git a/src/parse/utils/print_ast.c b/src/parse/utils/print_ast.c deleted file mode 100644 index 3351d58..0000000 --- a/src/parse/utils/print_ast.c +++ /dev/null @@ -1,67 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* print_ast.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/19 23:57:42 by kjikuhar #+# #+# */ -/* Updated: 2025/11/20 11:49:39 by kjikuhar ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "parse.h" - -void print_pipe_node(t_ast *node, const char *prefix, bool is_last) -{ - char child_prefix[256]; - - print_branch_line(prefix, is_last, "PIPE"); - build_child_prefix(prefix, is_last, child_prefix, sizeof(child_prefix)); - print_pipe_children(node, child_prefix); -} - -void print_cmd_node(t_ast *node, const char *prefix, bool is_last) -{ - char child_prefix[256]; - t_list *argv_list; - t_list *redir_list; - - argv_list = NULL; - redir_list = NULL; - if (node->cmd) - { - argv_list = node->cmd->argv; - redir_list = node->cmd->redirs; - } - print_branch_line(prefix, is_last, "CMD"); - build_child_prefix(prefix, is_last, child_prefix, sizeof(child_prefix)); - print_argv_line(child_prefix, false, argv_list); - print_redir_line(child_prefix, true, redir_list); -} - -void print_ast_node(t_ast *node, const char *prefix, bool is_last) -{ - if (!node) - { - print_branch_line(prefix, is_last, "(null)"); - return ; - } - if (node->type == PIPE) - { - print_pipe_node(node, prefix, is_last); - return ; - } - if (node->type == CMD) - { - print_cmd_node(node, prefix, is_last); - return ; - } - return ; -} - -void print_ast(t_ast *ast_root) -{ - printf("AST\n"); - print_ast_node(ast_root, "", true); -} diff --git a/src/parse/utils/print_ast_utils.c b/src/parse/utils/print_ast_utils.c deleted file mode 100644 index ef8486d..0000000 --- a/src/parse/utils/print_ast_utils.c +++ /dev/null @@ -1,57 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* print_ast_utils.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/19 23:57:42 by kjikuhar #+# #+# */ -/* Updated: 2025/11/20 11:57:27 by kjikuhar ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "parse.h" - -void print_branch_line(const char *prefix, bool is_last, const char *text) -{ - printf("%s", prefix); - if (is_last) - printf("`-- %s\n", text); - else - printf("|-- %s\n", text); -} - -void build_child_prefix(const char *prefix, bool is_last, - char *buffer, size_t size) -{ - ft_strlcpy(buffer, prefix, size); - if (is_last) - ft_strlcat(buffer, " ", size); - else - ft_strlcat(buffer, "| ", size); -} - -static const char *get_argv_value(t_list *node) -{ - if (node && node->content) - return ((const char *)node->content); - return (""); -} - -const char *get_redir_symbol(t_redir *redir) -{ - static const char *kind_str[] = {"<", "<<", ">", ">>"}; - - if (!redir) - return ("?"); - if (R_IN <= redir->kind && redir->kind <= R_OUT_APPEND) - return (kind_str[redir->kind]); - return ("?"); -} - -void print_argv_item(t_list *node, int index) -{ - if (index > 0) - printf(" "); - printf("[%d].%s", index + 1, get_argv_value(node)); -} diff --git a/src/parse/utils/print_ast_utils2.c b/src/parse/utils/print_ast_utils2.c deleted file mode 100644 index baf27bb..0000000 --- a/src/parse/utils/print_ast_utils2.c +++ /dev/null @@ -1,99 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* print_ast_utils2.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/20 11:39:03 by kjikuhar #+# #+# */ -/* Updated: 2025/11/20 11:49:54 by kjikuhar ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "parse.h" - -void print_redir_entry(t_redir *redir, int index) -{ - const char *symbol; - const char *filename; - - symbol = get_redir_symbol(redir); - filename = ""; - if (redir && redir->filename) - filename = redir->filename; - printf("[%d].%s%s", index + 1, symbol, filename); -} - -void print_argv_line(const char *prefix, bool is_last, t_list *argv) -{ - t_list *current; - int index; - - printf("%s", prefix); - if (is_last) - printf("`-- argv: "); - else - printf("|-- argv: "); - if (!argv) - { - printf("(empty)\n"); - return ; - } - current = argv; - index = 0; - while (current) - { - print_argv_item(current, index); - current = current->next; - index++; - } - printf("\n"); -} - -void print_redir_line(const char *prefix, bool is_last, t_list *redirs) -{ - t_list *current; - int index; - - printf("%s", prefix); - if (is_last) - printf("`-- redirs: "); - else - printf("|-- redirs: "); - if (!redirs) - { - printf("(empty)\n"); - return ; - } - current = redirs; - index = 0; - while (current) - { - print_redir_entry((t_redir *)current->content, index); - current = current->next; - index++; - } - printf("\n"); -} - -void print_pipe_children(t_ast *node, const char *prefix) -{ - bool has_right; - - has_right = false; - if (node->right) - has_right = true; - if (node->left) - { - if (has_right) - print_ast_node(node->left, prefix, false); - else - print_ast_node(node->left, prefix, true); - } - else if (has_right) - print_ast_node(NULL, prefix, false); - if (has_right) - print_ast_node(node->right, prefix, true); - else if (!node->left) - print_ast_node(NULL, prefix, true); -} From 83391bcaf793ff032332a46103a3235a3d805e07 Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 16 Apr 2026 17:16:58 +0900 Subject: [PATCH 140/173] =?UTF-8?q?add:=20on=5Finput=E3=82=92=E6=9C=AC?= =?UTF-8?q?=E7=95=AA=E7=94=A8=E3=81=AB=E7=B5=84=E3=81=BF=E6=9B=BF=E3=81=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/callback/on_input.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/callback/on_input.c b/src/callback/on_input.c index 40224b7..c4b0cfe 100644 --- a/src/callback/on_input.c +++ b/src/callback/on_input.c @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/10 17:04:25 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ +/* Updated: 2026/04/16 00:00:00 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,6 +14,24 @@ void on_input(char *input, t_shell_table *shell_table) { - (void)shell_table; - free(input); + t_list *tokens; + t_ast *ast; + + tokens = tokenize(input); + if (!tokens) + return ; + if (!heredoc(tokens)) + { + ft_lstclear(&tokens, free); + return ; + } + tokens = expand(tokens, shell_table); + if (!tokens) + return ; + ast = parse(tokens); + ft_lstclear(&tokens, free); + if (!ast) + return ; + exec_ast(ast, shell_table); + free_ast(ast); } From d91bab9e692452df12ef43e43d7f7a8d3dcf19f4 Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 16 Apr 2026 17:20:32 +0900 Subject: [PATCH 141/173] =?UTF-8?q?delete:=20docs=E5=89=8A=E9=99=A4/execut?= =?UTF-8?q?or=E3=81=AE=E3=83=98=E3=83=83=E3=83=80=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 1 - docs/execute.md | 88 ------------------------------------- docs/parser.md | 17 -------- docs/path_resolve.md | 100 ------------------------------------------- includes/minishell.h | 1 + 5 files changed, 1 insertion(+), 206 deletions(-) delete mode 100644 docs/README.md delete mode 100644 docs/execute.md delete mode 100644 docs/parser.md delete mode 100644 docs/path_resolve.md diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 9daeafb..0000000 --- a/docs/README.md +++ /dev/null @@ -1 +0,0 @@ -test diff --git a/docs/execute.md b/docs/execute.md deleted file mode 100644 index 0d4e985..0000000 --- a/docs/execute.md +++ /dev/null @@ -1,88 +0,0 @@ -# Execute の設計 - -`jiku/feature/execute` ブランチに実装済み。 - -## ファイル構成 - -``` -src/execute/ -├── exec_ast.c # エントリーポイント。ASTノードを PIPE/CMD に振り分け -├── exec_cmd.c # CMDノードの実行。リダイレクション処理 → 外部コマンド実行 -├── exec_pipe.c # PIPEノードの実行。左右を fork して pipe でつなぐ -├── pipe/ -│ └── exec_pipe_child.c # 子プロセス内の fd 付け替え(dup2)と再帰実行 -├── command/ -│ ├── exec_external_cmd.c # execve() による外部コマンド実行 -│ └── list_to_argv.c # t_list のトークンリストを char** argv に変換 -├── redirects/ -│ └── exec_redirs.c # リダイレクションの適用(<, >, >>) -└── utils/ - ├── ft_wifexited.c # WIFEXITED マクロの代替実装 - └── ft_wexitstatus.c # WEXITSTATUS マクロの代替実装 -``` - -## 実行フロー - -### シングルコマンド(`ls -la`) - -``` -exec_ast(CMD) - └─ exec_cmd() - ├─ exec_redirs() # リダイレクションを dup2 で適用 - ├─ list_to_argv() # t_list → char** に変換 - └─ exec_external_cmd() - ├─ find_exec_path() # $PATH を走査してフルパスを取得 - ├─ export_envp() # shell_table → envp[] に変換 - └─ execve() # プロセスを置き換えて実行 -``` - -### パイプ(`ls | grep src`) - -``` -exec_ast(PIPE) - └─ exec_pipe() - ├─ pipe(fd) # パイプを作成 - ├─ fork() → exec_left_child() - │ ├─ dup2(fd[1], STDOUT) # 左側の stdout → パイプ書き込み端 - │ └─ exec_ast(node->left) # 左ノードを再帰実行 - ├─ fork() → exec_right_child() - │ ├─ dup2(fd[0], STDIN) # 右側の stdin → パイプ読み込み端 - │ └─ exec_ast(node->right) # 右ノードを再帰実行 - ├─ close(fd[0]), close(fd[1]) - ├─ waitpid(left) - └─ waitpid(right) → 右側の終了ステータスを返す -``` - -パイプは左右それぞれを別プロセスで並行実行し、親は両方の終了を待つ。 -終了ステータスは右側(最後のコマンド)のものを使う。 - -### リダイレクション(`exec_redirs.c`) - -リダイレクションは `exec_cmd()` がコマンドを実行する前に適用する。 -複数のリダイレクションがある場合はリストの順に処理する。 - -| 記法 | 処理 | -|-----------|------| -| `< file` | `open(O_RDONLY)` → `dup2(fd, STDIN_FILENO)` | -| `> file` | `open(O_WRONLY\|O_CREAT\|O_TRUNC, 0644)` → `dup2(fd, STDOUT_FILENO)` | -| `>> file` | `open(O_WRONLY\|O_CREAT\|O_APPEND, 0644)` → `dup2(fd, STDOUT_FILENO)` | -| `<< EOF` | `heredoc()` が事前に tmpfile に変換済みのため `< tmpfile` として処理 | - -## 注意点・既知の問題 - -### ビルトイン未対応 - -`exec_cmd()` は現在すべてのコマンドを `exec_external_cmd()` に渡している。 -`echo`, `pwd`, `cd`, `export`, `unset`, `exit` を判別してビルトイン関数に -振り分けるディスパッチ処理が必要。 - -### exit コードのバグ - -`exec_external_cmd()` で `find_exec_path()` が `NULL` を返したとき(= コマンドが -見つからない)に `126` を返しているが、正しくは `127`。`126` は「ファイルは -存在するが実行権限がない」場合に使う。 - -### パイプ内のビルトイン - -パイプの子プロセス内でビルトインが呼ばれた場合、その副作用(`cd` による -`PWD` 変更など)は親プロセスには反映されない。これは bash の仕様通りの挙動。 diff --git a/docs/parser.md b/docs/parser.md deleted file mode 100644 index d2fd612..0000000 --- a/docs/parser.md +++ /dev/null @@ -1,17 +0,0 @@ -# parserの概要 -## 使用しているロジック -再帰降下法を使用している。これは、文法規則ごとに関数を作成し、入力を解析する手法である。各関数は特定の文法規則に対応し、その規則に従って入力を処理する。再帰降下法を利用するために、文法はEBNFで定義した。 - -## EBNFで定義したBASHの文法 -``` -pipeline ::= command ( '|' pipeline ) -command ::= simple_command | compound_command -simple_command ::= WORD ( argument ) -``` - -## 処理の流れ -1. **トークンの取得**: 字句解析器(lexer)からトークンを取得する。 -2. **文法規則の適用**: 現在のトークンに基づいて、対応する文法規則の関数を呼び出す。 -3. **再帰的解析**: 文法規則の関数内で、必要に応じて他の文法規則の関数を再帰的に呼び出す。 -4. **構文木の構築**: 解析が進むにつれて、構文木(AST)を構築する。 -5. **エラーハンドリング**: 解析中にエラーが発生した場合、適切なエラーメッセージを生成し、処理を中断する。 diff --git a/docs/path_resolve.md b/docs/path_resolve.md deleted file mode 100644 index 85d125b..0000000 --- a/docs/path_resolve.md +++ /dev/null @@ -1,100 +0,0 @@ -# path_resolveの実装計画 - -## 概要 -トークン内のパスを解決するコンポーネント。2つの機能を持つ: -1. **ワイルドカード展開**: `*` を含むトークンをファイルシステムに対してパターンマッチングし、マッチしたファイルパスの一覧に展開する -2. **相対パス解決**: `/` を含むトークン(パスとみなせるもの)を絶対パスに変換する - -## 入出力例 -``` -# ワイルドカード展開 -入力トークン: ["ls", "/Users/urassh/*.png"] -出力トークン: ["ls", "/Users/urassh/pic1.png", "/Users/urassh/pic2.png", "/Users/urassh/pic3.png"] - -# 相対パス解決 -入力トークン: ["ls", "../dir3/tmp.c"] -出力トークン: ["ls", "/Users/urassh/dir3/tmp.c"] -``` - -## シグネチャ -```c -t_list *resolve_path(t_list *tokens); -void resolve_path_checker(char *input, t_shell_table *shell_table); -``` - -## アルゴリズム -1. トークンリストを順に走査する -2. 各トークンに対して以下の判定を行う: - -### A. ワイルドカードを含む場合(`*` あり) - a. `ft_strrchr(token, '/')` で最後の `/` を見つけ、ディレクトリ部とパターン部に分割 - - `/Users/urassh/*.png` → dir: `/Users/urassh/`, pattern: `*.png` - - `*.c`(`/`なし)→ dir: `.`, pattern: `*.c` - b. `to_absolute_path(dir)` でディレクトリを絶対パスに変換 - c. `get_directory_entries(abs_dir, hidden, &entries)` でディレクトリ内のエントリ一覧を取得 - - パターンが `.` 始まりなら隠しファイルも含める - d. `filter_pattern(entries, pattern)` でパターンにマッチするエントリを絞り込む - e. マッチした各エントリに `abs_dir + "/" + entry` のフルパスを構築する - f. `ft_lstreplace(prev, current, resolved)` で元のトークンをマッチ結果リストに置換する - g. マッチ結果が0件の場合、元のトークンをそのまま残す - -### B. パスを含む場合(`/` あり、`*` なし) - a. `to_absolute_path(token)` で絶対パスに変換 - b. トークンの内容を変換後の絶対パスに置き換える(contentをfree→新しいcontentに差し替え) - -### C. それ以外 - - そのまま次へ進む - -## 利用する既存コンポーネント -| 関数 | ファイル | 役割 | -|------|---------|------| -| `to_absolute_path()` | `src/component/path/to_absolute_path.c` | 相対パス→絶対パス変換 | -| `filter_pattern()` | `src/component/pattern/filter_pattern.c` | ワイルドカードパターンマッチング | -| `get_directory_entries()` | `src/component/directory/get_directory_entries.c` | ディレクトリ内エントリ取得 | -| `ft_lstreplace()` | `libft/list/ft_lstreplace.c` | リスト要素の置換 | -| `ft_strrchr()` | `libft/` | 最後の文字検索(dir/pattern分割) | - -## ファイル構成 -``` -includes/path_resolve.h # ヘッダ(resolveの宣言) -src/component/path_resolve/path_resolve.c # メインロジック(resolve, has_wildcard, resolve_token, build_full_paths) -src/checker/resolve_checker.c # 開発用チェッカー -``` - -## 関数設計(path_resolve.c) - -### `t_list *resolve_path(t_list *tokens)` -- トークンリストを走査し、ワイルドカード展開・相対パス解決を行う -- prev/currentでリストを辿り、ワイルドカード時は`ft_lstreplace`で置換 -- パス時はcontent差し替え -- 先頭トークンが置換された場合は新しいheadを返す - -### `static bool has_wildcard(const char *str)` -- 文字列に `WILDCARD('*')` が含まれるか判定 - -### `static bool has_path(const char *str)` -- 文字列に `/` が含まれるか判定(パスとみなせるか) - -### `static t_list *resolve_wildcard(const char *token)` -- 単一トークンのワイルドカード解決 -- dir部とpattern部に分割 → to_absolute_path → get_directory_entries → filter_pattern → フルパス構築 - -### `static t_list *build_full_paths(t_list *matches, const char *abs_dir)` -- マッチしたファイル名リストに `abs_dir + "/"` を付与してフルパスリストを構築 - -## Makefileへの変更 -`SRCS_MAND` に以下を追加: -``` -src/component/path_resolve/path_resolve.c -src/checker/resolve_checker.c -``` - -## minishell.hへの変更 -- `#include "path_resolve.h"` を追加 -- `void resolve_checker(char *input, t_shell_table *shell_table);` を宣言に追加 - -## 実装後の検証 -実装完了後、必ず以下を実行してnorminetteに準拠していることを確認する: -```bash -docker compose exec minishell norminette src/component/path_resolve/ src/checker/resolve_checker.c includes/path_resolve.h -``` diff --git a/includes/minishell.h b/includes/minishell.h index f4e0006..255880f 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -14,6 +14,7 @@ # define MINISHELL_H # include "constants.h" +# include "execute.h" # include "expand.h" # include "heredoc.h" # include "libft.h" From 3243355423baa5c82b868d63aae75405a90d444f Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 16 Apr 2026 17:23:04 +0900 Subject: [PATCH 142/173] =?UTF-8?q?fix:=20=E5=A4=96=E9=83=A8=E3=82=B3?= =?UTF-8?q?=E3=83=9E=E3=83=B3=E3=83=89=E5=AE=9F=E8=A1=8C=E6=99=82=E3=81=AB?= =?UTF-8?q?=20fork=20=E3=81=97=E3=81=A6=E8=A6=AA=E3=83=97=E3=83=AD?= =?UTF-8?q?=E3=82=BB=E3=82=B9=E3=81=8C=E7=B5=82=E4=BA=86=E3=81=97=E3=81=AA?= =?UTF-8?q?=E3=81=84=E3=82=88=E3=81=86=E3=81=AB=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit exec_cmd から外部コマンドを実行する際、fork + waitpid で子プロセスを 生成するようにした。これにより ls 等の実行後も minishell が継続する。 Co-Authored-By: Claude Opus 4.6 (1M context) --- src/execute/exec_cmd.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/execute/exec_cmd.c b/src/execute/exec_cmd.c index 2ac9603..24e49fa 100644 --- a/src/execute/exec_cmd.c +++ b/src/execute/exec_cmd.c @@ -77,9 +77,33 @@ char *find_exec_path(const char *cmd, t_shell_table *shell_table) return (result); } -int exec_cmd(t_ast *node, t_shell_table *shell_table) +static int fork_and_exec(t_ast *node, t_shell_table *shell_table) { + pid_t pid; + int wstatus; char **argv; + + pid = fork(); + if (pid < 0) + return (perror("fork"), 1); + if (pid == 0) + { + if (node->cmd->redirs) + if (exec_redirs(node->cmd->redirs) != 0) + exit(1); + argv = list_to_argv(node->cmd->argv); + if (!argv || !argv[0]) + exit(127); + exit(exec_external_cmd(argv, shell_table)); + } + waitpid(pid, &wstatus, 0); + if (ft_wifexited(wstatus)) + return (ft_wexitstatus(wstatus)); + return (1); +} + +int exec_cmd(t_ast *node, t_shell_table *shell_table) +{ int status; if (node->cmd->redirs) @@ -90,12 +114,5 @@ int exec_cmd(t_ast *node, t_shell_table *shell_table) status = exec_builtin_cmd(node, shell_table); if (status != -1) return (status); - argv = list_to_argv(node->cmd->argv); - if (!argv || !argv[0]) - { - if (argv) - ft_free_array((void **)argv); - return (127); - } - return (exec_external_cmd(argv, shell_table)); + return (fork_and_exec(node, shell_table)); } From 93ad2697afe3f80134541af40a1fe4b9d81a342f Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 16 Apr 2026 17:33:20 +0900 Subject: [PATCH 143/173] =?UTF-8?q?refactor:=20exec=5Fcmd.c=20=E3=81=AB?= =?UTF-8?q?=E5=A4=96=E9=83=A8=E3=82=B3=E3=83=9E=E3=83=B3=E3=83=89=E5=AE=9F?= =?UTF-8?q?=E8=A1=8C=E3=82=92=E7=B5=B1=E5=90=88=E3=81=97=E9=87=8D=E8=A4=87?= =?UTF-8?q?=20join=5Fpath=20=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit exec_external_cmd.c を exec_cmd.c に統合(norminette 5関数制限対応)。 重複していた join_path を削除し、path.h の既存関数を利用。 Co-Authored-By: Claude Opus 4.6 (1M context) --- Makefile | 1 - includes/execute.h | 1 - src/execute/command/exec_external_cmd.c | 40 --------------- src/execute/exec_cmd.c | 66 +++++++++++++------------ 4 files changed, 35 insertions(+), 73 deletions(-) delete mode 100644 src/execute/command/exec_external_cmd.c diff --git a/Makefile b/Makefile index c6b0c6a..1d756a3 100644 --- a/Makefile +++ b/Makefile @@ -105,7 +105,6 @@ SRCS_MAND := src/main.c \ src/execute/exec_pipe.c \ src/execute/utils/ft_wexitstatus.c \ src/execute/utils/ft_wifexited.c \ - src/execute/command/exec_external_cmd.c \ src/execute/command/exec_builtin_cmd.c \ src/execute/command/list_to_argv.c \ src/execute/pipe/exec_pipe_child.c \ diff --git a/includes/execute.h b/includes/execute.h index 6a88ef7..4e24a39 100644 --- a/includes/execute.h +++ b/includes/execute.h @@ -22,7 +22,6 @@ int exec_ast(t_ast *node, t_shell_table *shell_table); int exec_builtin_cmd(t_ast *node, t_shell_table *shell_table); int exec_cmd(t_ast *node, t_shell_table *shell_table); -int exec_external_cmd(char **argv, t_shell_table *shell_table); char *find_exec_path(const char *cmd, \ t_shell_table *shell_table); int exec_pipe(t_ast *node, t_shell_table *shell_table); diff --git a/src/execute/command/exec_external_cmd.c b/src/execute/command/exec_external_cmd.c deleted file mode 100644 index 598bb90..0000000 --- a/src/execute/command/exec_external_cmd.c +++ /dev/null @@ -1,40 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* exec_external_cmd.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: kjikuhar +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/11/14 23:08:19 by kjikuhar #+# #+# */ -/* Updated: 2026/03/03 13:49:37 by kjikuhar ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "execute.h" - -int exec_external_cmd(char **argv, t_shell_table *shell_table) -{ - char *cmd_path; - char **new_envp; - - cmd_path = find_exec_path(argv[0], shell_table); - if (!cmd_path) - { - ft_free_array((void **)argv); - return (126); - } - new_envp = export_envp(shell_table); - if (!new_envp) - { - free(cmd_path); - ft_free_array((void **)argv); - return (1); - } - execve(cmd_path, argv, new_envp); - perror(cmd_path); - free(cmd_path); - st_destroy(shell_table); - ft_free_array((void **)new_envp); - ft_free_array((void **)argv); - return (127); -} diff --git a/src/execute/exec_cmd.c b/src/execute/exec_cmd.c index 24e49fa..637c232 100644 --- a/src/execute/exec_cmd.c +++ b/src/execute/exec_cmd.c @@ -6,28 +6,12 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/14 17:18:25 by kjikuhar #+# #+# */ -/* Updated: 2026/03/03 13:49:37 by kjikuhar ### ########.fr */ +/* Updated: 2026/04/16 00:00:00 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ #include "execute.h" - -static char *join_path(const char *path, const char *cmd) -{ - size_t path_len; - size_t cmd_len; - char *joined; - - path_len = ft_strlen(path); - cmd_len = ft_strlen(cmd); - joined = malloc(sizeof(char) * (path_len + 1 + cmd_len + 1)); - if (!joined) - return (NULL); - ft_strlcpy(joined, path, path_len + 1); - joined[path_len] = '/'; - ft_strlcpy(joined + path_len + 1, cmd, cmd_len + 1); - return (joined); -} +#include "path.h" static char *find_in_path(const char *cmd, t_shell_table *shell_table) { @@ -57,24 +41,44 @@ static char *find_in_path(const char *cmd, t_shell_table *shell_table) return (NULL); } -static char *resolve_exec_path(const char *cmd) -{ - if (access(cmd, X_OK) == 0) - return (ft_strdup(cmd)); - return (NULL); -} - char *find_exec_path(const char *cmd, t_shell_table *shell_table) { - char *result; - if (!cmd || !*cmd) return (NULL); if (ft_strchr(cmd, '/')) - result = resolve_exec_path(cmd); - else - result = find_in_path(cmd, shell_table); - return (result); + { + if (access(cmd, X_OK) == 0) + return (ft_strdup(cmd)); + return (NULL); + } + return (find_in_path(cmd, shell_table)); +} + +static int exec_external_cmd(char **argv, t_shell_table *shell_table) +{ + char *cmd_path; + char **new_envp; + + cmd_path = find_exec_path(argv[0], shell_table); + if (!cmd_path) + { + ft_free_array((void **)argv); + return (126); + } + new_envp = export_envp(shell_table); + if (!new_envp) + { + free(cmd_path); + ft_free_array((void **)argv); + return (1); + } + execve(cmd_path, argv, new_envp); + perror(cmd_path); + free(cmd_path); + st_destroy(shell_table); + ft_free_array((void **)new_envp); + ft_free_array((void **)argv); + return (127); } static int fork_and_exec(t_ast *node, t_shell_table *shell_table) From d6cd77ef9a6eb957a05d3af33df6c60878d99d57 Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 16 Apr 2026 18:00:25 +0900 Subject: [PATCH 144/173] =?UTF-8?q?fix:=20=E5=AD=98=E5=9C=A8=E3=81=97?= =?UTF-8?q?=E3=81=AA=E3=81=84=E3=82=B3=E3=83=9E=E3=83=B3=E3=83=89=E3=81=8C?= =?UTF-8?q?=E5=85=A5=E5=8A=9B=E3=81=95=E3=82=8C=E3=81=9F=E6=99=82=E3=81=AE?= =?UTF-8?q?=E6=8C=99=E5=8B=95=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 1 + src/execute/command/find_exec_path.c | 55 +++++++++++++++++++++++++ src/execute/exec_cmd.c | 60 +++++++++------------------- 3 files changed, 75 insertions(+), 41 deletions(-) create mode 100644 src/execute/command/find_exec_path.c diff --git a/Makefile b/Makefile index 1d756a3..3205be6 100644 --- a/Makefile +++ b/Makefile @@ -105,6 +105,7 @@ SRCS_MAND := src/main.c \ src/execute/exec_pipe.c \ src/execute/utils/ft_wexitstatus.c \ src/execute/utils/ft_wifexited.c \ + src/execute/command/find_exec_path.c \ src/execute/command/exec_builtin_cmd.c \ src/execute/command/list_to_argv.c \ src/execute/pipe/exec_pipe_child.c \ diff --git a/src/execute/command/find_exec_path.c b/src/execute/command/find_exec_path.c new file mode 100644 index 0000000..7cca762 --- /dev/null +++ b/src/execute/command/find_exec_path.c @@ -0,0 +1,55 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* find_exec_path.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/16 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/04/16 00:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "execute.h" +#include "path.h" + +static char *find_in_path(const char *cmd, t_shell_table *shell_table) +{ + char **paths; + char *path_env; + char *full_path; + int i; + + path_env = st_search(shell_table, "PATH"); + if (!path_env) + return (NULL); + paths = ft_split(path_env, ':'); + if (!paths) + return (NULL); + i = 0; + while (paths[i]) + { + full_path = join_path(paths[i], cmd); + if (!full_path) + return (ft_free_array((void **)paths), NULL); + if (access(full_path, X_OK) == 0) + return (ft_free_array((void **)paths), full_path); + free(full_path); + i++; + } + ft_free_array((void **)paths); + return (NULL); +} + +char *find_exec_path(const char *cmd, t_shell_table *shell_table) +{ + if (!cmd || !*cmd) + return (NULL); + if (ft_strchr(cmd, '/')) + { + if (access(cmd, X_OK) == 0) + return (ft_strdup(cmd)); + return (NULL); + } + return (find_in_path(cmd, shell_table)); +} diff --git a/src/execute/exec_cmd.c b/src/execute/exec_cmd.c index 637c232..b03ccd2 100644 --- a/src/execute/exec_cmd.c +++ b/src/execute/exec_cmd.c @@ -11,47 +11,28 @@ /* ************************************************************************** */ #include "execute.h" -#include "path.h" -static char *find_in_path(const char *cmd, t_shell_table *shell_table) +static int cmd_not_found(char **argv) { - char **paths; - char *path_env; - char *full_path; - int i; - - path_env = st_search(shell_table, "PATH"); - if (!path_env) - return (NULL); - paths = ft_split(path_env, ':'); - if (!paths) - return (NULL); - i = 0; - while (paths[i]) - { - full_path = join_path(paths[i], cmd); - if (!full_path) - return (ft_free_array((void **)paths), NULL); - if (access(full_path, X_OK) == 0) - return (ft_free_array((void **)paths), full_path); - free(full_path); - i++; - } - ft_free_array((void **)paths); - return (NULL); -} - -char *find_exec_path(const char *cmd, t_shell_table *shell_table) -{ - if (!cmd || !*cmd) - return (NULL); - if (ft_strchr(cmd, '/')) + if (ft_strchr(argv[0], '/')) { - if (access(cmd, X_OK) == 0) - return (ft_strdup(cmd)); - return (NULL); + if (access(argv[0], F_OK) == 0) + { + ft_putstr_fd("jikussh: ", STDERR_FILENO); + perror(argv[0]); + ft_free_array((void **)argv); + return (126); + } + ft_putstr_fd("jikussh: ", STDERR_FILENO); + perror(argv[0]); + ft_free_array((void **)argv); + return (127); } - return (find_in_path(cmd, shell_table)); + ft_putstr_fd("jikussh: ", STDERR_FILENO); + ft_putstr_fd(argv[0], STDERR_FILENO); + ft_putstr_fd(": command not found\n", STDERR_FILENO); + ft_free_array((void **)argv); + return (127); } static int exec_external_cmd(char **argv, t_shell_table *shell_table) @@ -61,10 +42,7 @@ static int exec_external_cmd(char **argv, t_shell_table *shell_table) cmd_path = find_exec_path(argv[0], shell_table); if (!cmd_path) - { - ft_free_array((void **)argv); - return (126); - } + return (cmd_not_found(argv)); new_envp = export_envp(shell_table); if (!new_envp) { From 9782b299a29f341a2b3541a5ff1450ff17909bcf Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 16 Apr 2026 20:07:10 +0900 Subject: [PATCH 145/173] =?UTF-8?q?fix:=20=E3=83=91=E3=82=B9=E3=81=AA?= =?UTF-8?q?=E3=81=97=E3=83=AF=E3=82=A4=E3=83=AB=E3=83=89=E3=82=AB=E3=83=BC?= =?UTF-8?q?=E3=83=89=E3=81=8C=E3=83=95=E3=83=AB=E3=83=91=E3=82=B9=E3=81=A7?= =?UTF-8?q?=E5=B1=95=E9=96=8B=E3=81=95=E3=82=8C=E3=82=8B=E5=95=8F=E9=A1=8C?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit echo .* が /cursus/.git のようにフルパスで表示されていたのを bash と同様にファイル名のみ (. .. .git) で返すよう修正。 パス付きパターン (dir/*) の場合のみフルパスを構築する。 Co-Authored-By: Claude Opus 4.6 (1M context) --- src/expand/expand_wildcard/resolve_wildcard.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/expand/expand_wildcard/resolve_wildcard.c b/src/expand/expand_wildcard/resolve_wildcard.c index 29adef5..ae57717 100644 --- a/src/expand/expand_wildcard/resolve_wildcard.c +++ b/src/expand/expand_wildcard/resolve_wildcard.c @@ -39,6 +39,8 @@ t_list *resolve_wildcard(const char *token) result = get_matches(abs_dir, slash + 1); else result = get_matches(abs_dir, token); + if (slash && result) + result = build_full_paths(result, abs_dir); free(abs_dir); return (result); } @@ -46,15 +48,12 @@ t_list *resolve_wildcard(const char *token) static t_list *get_matches(const char *abs_dir, const char *pattern) { t_list *entries; - t_list *filtered_matches; t_list *result; if (list_directory(abs_dir, pattern[0] == '.', &entries) != SUCCESS) return (NULL); - filtered_matches = filter_pattern(entries, pattern); + result = filter_pattern(entries, pattern); ft_lstclear(&entries, free); - result = build_full_paths(filtered_matches, abs_dir); - ft_lstclear(&filtered_matches, free); return (result); } @@ -84,6 +83,7 @@ static t_list *build_full_paths(t_list *matches, const char *abs_dir) current = current->next; } free(dir_slash); + ft_lstclear(&matches, free); return (result); } From c2aee2b5f6926697a01aefc21aece125ee60b155 Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 16 Apr 2026 20:14:00 +0900 Subject: [PATCH 146/173] =?UTF-8?q?fix:=20=E3=82=AF=E3=82=A9=E3=83=BC?= =?UTF-8?q?=E3=83=88=E5=A2=83=E7=95=8C=E3=81=A7=E3=83=88=E3=83=BC=E3=82=AF?= =?UTF-8?q?=E3=83=B3=E3=81=8C=E5=88=86=E5=89=B2=E3=81=95=E3=82=8C=E3=82=8B?= =?UTF-8?q?=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit expand_parameter のクォート開始/終了時に push_token_expand を 呼んでいたため l"s" が [l, "s"] の2トークンに分割されていた。 クォート遷移時は buffer に文字を追加するだけに修正。 Co-Authored-By: Claude Opus 4.6 (1M context) --- Makefile | 1 + .../state/in_double_quote_expand.c | 4 +- .../expand_parameter/state/in_normal_expand.c | 4 +- .../state/in_single_quote_expand.c | 4 +- src/expand/expand_wildcard/match_wildcard.c | 56 ++++++++++++++ src/expand/expand_wildcard/resolve_wildcard.c | 77 +++++-------------- 6 files changed, 83 insertions(+), 63 deletions(-) create mode 100644 src/expand/expand_wildcard/match_wildcard.c diff --git a/Makefile b/Makefile index 3205be6..8af3c69 100644 --- a/Makefile +++ b/Makefile @@ -129,6 +129,7 @@ SRCS_MAND := src/main.c \ src/expand/expand_parameter/store/free_store_expand.c \ src/expand/expand_tilde/expand_tilde.c \ src/expand/expand_wildcard/resolve_wildcard.c \ + src/expand/expand_wildcard/match_wildcard.c \ src/expand/expand_wildcard/expand_wildcard.c \ src/expand/expand_remove_quotes/expand_remove_quotes.c \ src/signal/setup_signal_handlers.c \ diff --git a/src/expand/expand_parameter/state/in_double_quote_expand.c b/src/expand/expand_parameter/state/in_double_quote_expand.c index f10df32..2f3d673 100644 --- a/src/expand/expand_parameter/state/in_double_quote_expand.c +++ b/src/expand/expand_parameter/state/in_double_quote_expand.c @@ -64,8 +64,8 @@ static void by_dollar(t_shell_table *shell_table, t_expand_store *store, static void by_double_quote_end(t_shell_table *shell_table, t_expand_store *store, t_expand_state *state, char **current) { - if (add_buffer_expand(store, **current) == ERROR || push_token_expand(store, - shell_table) == ERROR) + (void)shell_table; + if (add_buffer_expand(store, **current) == ERROR) *state = EXPAND_ON_ERROR; else *state = EXPAND_IN_NORMAL; diff --git a/src/expand/expand_parameter/state/in_normal_expand.c b/src/expand/expand_parameter/state/in_normal_expand.c index 630ada7..e368ddb 100644 --- a/src/expand/expand_parameter/state/in_normal_expand.c +++ b/src/expand/expand_parameter/state/in_normal_expand.c @@ -48,8 +48,8 @@ static void by_last(t_shell_table *shell_table, t_expand_store *store, static void by_quote(t_shell_table *shell_table, t_expand_store *store, t_expand_state *state, char **current) { - if (push_token_expand(store, shell_table) == ERROR - || add_buffer_expand(store, **current) == ERROR) + (void)shell_table; + if (add_buffer_expand(store, **current) == ERROR) *state = EXPAND_ON_ERROR; else if (**current == '"') *state = EXPAND_IN_DOUBLE_QUOTE; diff --git a/src/expand/expand_parameter/state/in_single_quote_expand.c b/src/expand/expand_parameter/state/in_single_quote_expand.c index 1b4bbc2..19bee93 100644 --- a/src/expand/expand_parameter/state/in_single_quote_expand.c +++ b/src/expand/expand_parameter/state/in_single_quote_expand.c @@ -30,8 +30,8 @@ void in_single_quote_expand(t_shell_table *shell_table, static void by_single_quote_end(t_shell_table *shell_table, t_expand_store *store, t_expand_state *state, char **current) { - if (add_buffer_expand(store, **current) == ERROR || push_token_expand(store, - shell_table) == ERROR) + (void)shell_table; + if (add_buffer_expand(store, **current) == ERROR) *state = EXPAND_ON_ERROR; else *state = EXPAND_IN_NORMAL; diff --git a/src/expand/expand_wildcard/match_wildcard.c b/src/expand/expand_wildcard/match_wildcard.c new file mode 100644 index 0000000..dffa31c --- /dev/null +++ b/src/expand/expand_wildcard/match_wildcard.c @@ -0,0 +1,56 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* match_wildcard.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/16 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/04/16 00:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "expand_wildcard_internal.h" + +static bool match_pattern(const char *str, const char *pattern) +{ + if (*pattern == '\0') + return (*str == '\0'); + if (*pattern == WILDCARD) + { + while (*str) + { + if (match_pattern(str, pattern + 1)) + return (true); + str++; + } + return (match_pattern(str, pattern + 1)); + } + if (*str == *pattern) + return (match_pattern(str + 1, pattern + 1)); + return (false); +} + +t_list *filter_pattern(t_list *source, const char *pattern) +{ + t_list *result; + t_list *current; + t_list *new_node; + + if (!source || !pattern) + return (NULL); + result = NULL; + current = source; + while (current) + { + if (match_pattern((const char *)current->content, pattern)) + { + new_node = ft_lstnew(ft_strdup((const char *)current->content)); + if (!new_node) + return (ft_lstclear(&result, free), NULL); + ft_lstadd_back(&result, new_node); + } + current = current->next; + } + return (result); +} diff --git a/src/expand/expand_wildcard/resolve_wildcard.c b/src/expand/expand_wildcard/resolve_wildcard.c index ae57717..85e61a1 100644 --- a/src/expand/expand_wildcard/resolve_wildcard.c +++ b/src/expand/expand_wildcard/resolve_wildcard.c @@ -16,8 +16,7 @@ static t_list *get_matches(const char *abs_dir, const char *pattern); static t_list *build_full_paths(t_list *matches, const char *abs_dir); -static bool match_pattern(const char *str, const char *pattern); -static t_list *filter_pattern(t_list *source, const char *pattern); +t_list *filter_pattern(t_list *source, const char *pattern); t_list *resolve_wildcard(const char *token) { @@ -57,13 +56,29 @@ static t_list *get_matches(const char *abs_dir, const char *pattern) return (result); } +static void append_full_path(t_list **result, const char *prefix, + const char *name) +{ + char *full_path; + t_list *node; + + full_path = ft_strjoin(prefix, name); + if (!full_path) + return ; + node = ft_lstnew(full_path); + if (!node) + { + free(full_path); + return ; + } + ft_lstadd_back(result, node); +} + static t_list *build_full_paths(t_list *matches, const char *abs_dir) { t_list *result; t_list *current; - t_list *node; char *dir_slash; - char *full_path; result = NULL; dir_slash = ft_strjoin(abs_dir, "/"); @@ -72,14 +87,7 @@ static t_list *build_full_paths(t_list *matches, const char *abs_dir) current = matches; while (current) { - full_path = ft_strjoin(dir_slash, (char *)current->content); - node = ft_lstnew(full_path); - if (!node) - { - free(full_path); - break ; - } - ft_lstadd_back(&result, node); + append_full_path(&result, dir_slash, (char *)current->content); current = current->next; } free(dir_slash); @@ -87,48 +95,3 @@ static t_list *build_full_paths(t_list *matches, const char *abs_dir) return (result); } -static t_list *filter_pattern(t_list *source, const char *pattern) -{ - t_list *result; - t_list *current; - t_list *new_node; - - if (!source || !pattern) - return (NULL); - result = NULL; - current = source; - while (current) - { - if (match_pattern((const char *)current->content, pattern)) - { - new_node = ft_lstnew(ft_strdup((const char *)current->content)); - if (!new_node) - { - ft_lstclear(&result, free); - return (NULL); - } - ft_lstadd_back(&result, new_node); - } - current = current->next; - } - return (result); -} - -static bool match_pattern(const char *str, const char *pattern) -{ - if (*pattern == '\0') - return (*str == '\0'); - if (*pattern == WILDCARD) - { - while (*str) - { - if (match_pattern(str, pattern + 1)) - return (true); - str++; - } - return (match_pattern(str, pattern + 1)); - } - if (*str == *pattern) - return (match_pattern(str + 1, pattern + 1)); - return (false); -} From 83105bf939180deb798a1a9b6e6ab44f4ddf2e32 Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 16 Apr 2026 19:36:50 +0900 Subject: [PATCH 147/173] =?UTF-8?q?feat:=20=E3=82=B3=E3=83=9E=E3=83=B3?= =?UTF-8?q?=E3=83=89=E5=AE=9F=E8=A1=8C=E4=B8=AD=E3=81=AE=E3=82=B7=E3=82=B0?= =?UTF-8?q?=E3=83=8A=E3=83=AB=E3=83=8F=E3=83=B3=E3=83=89=E3=83=AA=E3=83=B3?= =?UTF-8?q?=E3=82=B0=E3=82=92=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 子プロセスで set_signal_default を呼び、SIGINT/SIGQUIT をデフォルト動作に - 親プロセスで子プロセス待機中は set_signal_ignore で SIGINT を無視 - waitpid 後に set_signal_interactive でプロンプト用ハンドラに復帰 - シグナルによる終了時の exit status を 128+signal に設定 Co-Authored-By: Claude Opus 4.6 (1M context) --- src/execute/exec_cmd.c | 6 +++++- src/execute/exec_pipe.c | 5 ++++- src/execute/pipe/exec_pipe_child.c | 3 +++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/execute/exec_cmd.c b/src/execute/exec_cmd.c index b03ccd2..059befa 100644 --- a/src/execute/exec_cmd.c +++ b/src/execute/exec_cmd.c @@ -11,6 +11,7 @@ /* ************************************************************************** */ #include "execute.h" +#include "signal_handler.h" static int cmd_not_found(char **argv) { @@ -70,6 +71,7 @@ static int fork_and_exec(t_ast *node, t_shell_table *shell_table) return (perror("fork"), 1); if (pid == 0) { + set_signal_default(); if (node->cmd->redirs) if (exec_redirs(node->cmd->redirs) != 0) exit(1); @@ -78,10 +80,12 @@ static int fork_and_exec(t_ast *node, t_shell_table *shell_table) exit(127); exit(exec_external_cmd(argv, shell_table)); } + set_signal_ignore(); waitpid(pid, &wstatus, 0); + set_signal_interactive(); if (ft_wifexited(wstatus)) return (ft_wexitstatus(wstatus)); - return (1); + return (128 + WTERMSIG(wstatus)); } int exec_cmd(t_ast *node, t_shell_table *shell_table) diff --git a/src/execute/exec_pipe.c b/src/execute/exec_pipe.c index 30ac237..c609587 100644 --- a/src/execute/exec_pipe.c +++ b/src/execute/exec_pipe.c @@ -11,6 +11,7 @@ /* ************************************************************************** */ #include "execute.h" +#include "signal_handler.h" static int exec_pipe_left(t_ast *node, t_shell_table *shell_table, \ pid_t *left, int fd[2]) @@ -62,9 +63,11 @@ int exec_pipe(t_ast *node, t_shell_table *shell_table) } close(fd[0]); close(fd[1]); + set_signal_ignore(); waitpid(left, &exit_status_left_child, 0); waitpid(right, &exit_status_right_child, 0); + set_signal_interactive(); if (ft_wifexited(exit_status_right_child)) return (ft_wexitstatus(exit_status_right_child)); - return (1); + return (128 + WTERMSIG(exit_status_right_child)); } diff --git a/src/execute/pipe/exec_pipe_child.c b/src/execute/pipe/exec_pipe_child.c index f3d9fc9..d359454 100644 --- a/src/execute/pipe/exec_pipe_child.c +++ b/src/execute/pipe/exec_pipe_child.c @@ -11,6 +11,7 @@ /* ************************************************************************** */ #include "execute.h" +#include "signal_handler.h" void exec_left_child(t_ast *node, t_shell_table *shell_table, int fd[2]) { @@ -26,6 +27,7 @@ void exec_left_child(t_ast *node, t_shell_table *shell_table, int fd[2]) } close(fd[0]); close(fd[1]); + set_signal_default(); left_node = node->left; right_node = node->right; free(node); @@ -49,6 +51,7 @@ void exec_right_child(t_ast *node, t_shell_table *shell_table, int fd[2]) } close(fd[1]); close(fd[0]); + set_signal_default(); left_node = node->left; right_node = node->right; free(node); From f3bd145346d4dd784c7bc6cbe7f6b939d014f1c9 Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 16 Apr 2026 18:15:34 +0900 Subject: [PATCH 148/173] =?UTF-8?q?feat:=20&&=20/=20||=20=E8=AB=96?= =?UTF-8?q?=E7=90=86=E6=BC=94=E7=AE=97=E5=AD=90=E3=81=AE=E3=83=91=E3=83=BC?= =?UTF-8?q?=E3=82=B5=E3=83=BB=E5=AE=9F=E8=A1=8C=E3=82=B5=E3=83=9D=E3=83=BC?= =?UTF-8?q?=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AST に AND / OR ノード型を追加し、再帰下降パーサを拡張。 parse_list が && / || でパイプラインを分割し、exec_ast で 短絡評価を実行する。 Co-Authored-By: Claude Opus 4.6 (1M context) --- Makefile | 1 + includes/parse.h | 5 ++- src/execute/exec_ast.c | 19 ++++++++++-- src/parse/parse.c | 16 +++------- src/parse/parse_list.c | 57 +++++++++++++++++++++++++++++++++++ src/parse/utils/token_check.c | 2 ++ 6 files changed, 84 insertions(+), 16 deletions(-) create mode 100644 src/parse/parse_list.c diff --git a/Makefile b/Makefile index 8af3c69..1e891be 100644 --- a/Makefile +++ b/Makefile @@ -83,6 +83,7 @@ SRCS_MAND := src/main.c \ src/tokenize/store/push_token.c \ src/tokenize/store/add_buffer.c \ src/parse/parse.c \ + src/parse/parse_list.c \ src/parse/utils/add_to_cmd.c \ src/parse/utils/new_ast_node.c \ src/parse/utils/new_cmd.c \ diff --git a/includes/parse.h b/includes/parse.h index 163e417..756bcda 100644 --- a/includes/parse.h +++ b/includes/parse.h @@ -27,7 +27,9 @@ typedef enum e_ast_type { PIPE, - CMD + CMD, + AND, + OR } t_ast_type; typedef enum e_redir_kind @@ -60,6 +62,7 @@ typedef struct s_ast /* main function------------------------------------------------------------- */ t_ast *parse(t_list *token_head); +t_ast *parse_pipeline(t_list **current); /* AST's token utils--------------------------------------------------------- */ bool is_word(const t_list *node); diff --git a/src/execute/exec_ast.c b/src/execute/exec_ast.c index f0e2947..6478d98 100644 --- a/src/execute/exec_ast.c +++ b/src/execute/exec_ast.c @@ -12,14 +12,27 @@ #include "execute.h" +static int exec_logical(t_ast *node, t_shell_table *shell_table) +{ + int status; + + status = exec_ast(node->left, shell_table); + if (node->type == AND && status == 0) + return (exec_ast(node->right, shell_table)); + if (node->type == OR && status != 0) + return (exec_ast(node->right, shell_table)); + return (status); +} + int exec_ast(t_ast *node, t_shell_table *shell_table) { if (!node) return (EXIT_FAILURE); if (node->type == PIPE) return (exec_pipe(node, shell_table)); - else if (node->type == CMD) + if (node->type == CMD) return (exec_cmd(node, shell_table)); - else - return (EXIT_FAILURE); + if (node->type == AND || node->type == OR) + return (exec_logical(node, shell_table)); + return (EXIT_FAILURE); } diff --git a/src/parse/parse.c b/src/parse/parse.c index 7553bc4..b5ea84d 100644 --- a/src/parse/parse.c +++ b/src/parse/parse.c @@ -47,7 +47,9 @@ static t_ast *parse_cmd(t_list **current) cmd = new_cmd(); if (!cmd) return (NULL); - while (*current && !is_symbol(*current, "|")) + while (*current && !is_symbol(*current, "|") + && !is_symbol(*current, "&&") + && !is_symbol(*current, "||")) { if (is_redir(*current)) { @@ -68,7 +70,7 @@ static t_ast *parse_cmd(t_list **current) return (ast); } -static t_ast *parse_pipeline(t_list **current) +t_ast *parse_pipeline(t_list **current) { t_ast *left; t_ast *pipe_node; @@ -90,13 +92,3 @@ static t_ast *parse_pipeline(t_list **current) } return (left); } - -t_ast *parse(t_list *token_head) -{ - t_list *current; - t_ast *root; - - current = token_head; - root = parse_pipeline(¤t); - return (root); -} diff --git a/src/parse/parse_list.c b/src/parse/parse_list.c new file mode 100644 index 0000000..227db0f --- /dev/null +++ b/src/parse/parse_list.c @@ -0,0 +1,57 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parse_list.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/16 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/04/16 00:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parse.h" + +static t_ast_type get_logical_type(t_list *current) +{ + if (is_symbol(current, "&&")) + return (AND); + if (is_symbol(current, "||")) + return (OR); + return (CMD); +} + +static t_ast *parse_list(t_list **current) +{ + t_ast *left; + t_ast *node; + t_ast_type type; + + left = parse_pipeline(current); + if (!left) + return (NULL); + while (*current) + { + type = get_logical_type(*current); + if (type != AND && type != OR) + break ; + *current = (*current)->next; + node = new_ast_node(type); + if (!node) + return (free_ast(left), NULL); + node->left = left; + node->right = parse_pipeline(current); + if (!node->right) + return (free_ast(node), NULL); + left = node; + } + return (left); +} + +t_ast *parse(t_list *token_head) +{ + t_list *current; + + current = token_head; + return (parse_list(¤t)); +} diff --git a/src/parse/utils/token_check.c b/src/parse/utils/token_check.c index 9ce37bd..7894090 100644 --- a/src/parse/utils/token_check.c +++ b/src/parse/utils/token_check.c @@ -23,6 +23,8 @@ bool is_word(const t_list *node) ft_strncmp(s, ">", 2) == 0 || \ ft_strncmp(s, ">>", 3) == 0 || \ ft_strncmp(s, "|", 2) == 0 || \ + ft_strncmp(s, "&&", 3) == 0 || \ + ft_strncmp(s, "||", 3) == 0 || \ ft_strncmp(s, "EOF", 4) == 0) return (false); return (true); From 57963754737265cdaaf1e815cfa3a3ed1cdcfe39 Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 16 Apr 2026 18:03:24 +0900 Subject: [PATCH 149/173] =?UTF-8?q?wip:=20exec=5Fast=20=E3=81=AE=E6=88=BB?= =?UTF-8?q?=E3=82=8A=E5=80=A4=E3=82=92=20$=3F=20=E3=81=A8=E3=81=97?= =?UTF-8?q?=E3=81=A6=20shell=5Ftable=20=E3=81=AB=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 (1M context) --- src/callback/on_input.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/callback/on_input.c b/src/callback/on_input.c index c4b0cfe..8dcfad1 100644 --- a/src/callback/on_input.c +++ b/src/callback/on_input.c @@ -12,10 +12,22 @@ #include "minishell.h" +static void update_exit_status(t_shell_table *shell_table, int status) +{ + char *status_str; + + status_str = ft_itoa(status); + if (!status_str) + return ; + st_insert(shell_table, "?", status_str, false); + free(status_str); +} + void on_input(char *input, t_shell_table *shell_table) { t_list *tokens; t_ast *ast; + int status; tokens = tokenize(input); if (!tokens) @@ -32,6 +44,7 @@ void on_input(char *input, t_shell_table *shell_table) ft_lstclear(&tokens, free); if (!ast) return ; - exec_ast(ast, shell_table); + status = exec_ast(ast, shell_table); free_ast(ast); + update_exit_status(shell_table, status); } From d190945fd190f45c7f09375b3b9327553f946e8b Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 16 Apr 2026 18:46:54 +0900 Subject: [PATCH 150/173] =?UTF-8?q?refactor:=20expand=20=E3=82=92=20execut?= =?UTF-8?q?or=20=E3=81=AB=E7=A7=BB=E5=8B=95=E3=81=97=E3=80=81=E3=82=B3?= =?UTF-8?q?=E3=83=9E=E3=83=B3=E3=83=89=E5=8D=98=E4=BD=8D=E3=81=A7=E5=B1=95?= =?UTF-8?q?=E9=96=8B=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit on_input から expand 呼び出しを削除し、exec_cmd 内で コマンド実行直前に expand を呼ぶよう変更。 redir filename も expand_redir_filenames で展開する。 これにより export FOO=bar && echo $FOO が正しく動作する。 Co-Authored-By: Claude Opus 4.6 (1M context) --- Makefile | 1 + includes/execute.h | 2 ++ src/callback/on_input.c | 3 -- src/execute/exec_cmd.c | 4 +++ src/execute/redirects/expand_redirs.c | 45 +++++++++++++++++++++++++++ 5 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 src/execute/redirects/expand_redirs.c diff --git a/Makefile b/Makefile index 1e891be..3dd94be 100644 --- a/Makefile +++ b/Makefile @@ -111,6 +111,7 @@ SRCS_MAND := src/main.c \ src/execute/command/list_to_argv.c \ src/execute/pipe/exec_pipe_child.c \ src/execute/redirects/exec_redirs.c \ + src/execute/redirects/expand_redirs.c \ src/component/directory/list_directory.c \ src/component/directory/list_directory_recursive.c \ src/component/path/to_absolute_path.c \ diff --git a/includes/execute.h b/includes/execute.h index 4e24a39..a1db226 100644 --- a/includes/execute.h +++ b/includes/execute.h @@ -30,6 +30,8 @@ void exec_left_child(t_ast *node, \ void exec_right_child(t_ast *node, \ t_shell_table *shell_table, int fd[2]); int exec_redirs(t_list *redirs); +void expand_redir_filenames(t_list *redirs, \ + t_shell_table *shell_table); char **list_to_argv(t_list *lst); int ft_wifexited(int exit_status); int ft_wexitstatus(int exit_status); diff --git a/src/callback/on_input.c b/src/callback/on_input.c index c4b0cfe..62d37a9 100644 --- a/src/callback/on_input.c +++ b/src/callback/on_input.c @@ -25,9 +25,6 @@ void on_input(char *input, t_shell_table *shell_table) ft_lstclear(&tokens, free); return ; } - tokens = expand(tokens, shell_table); - if (!tokens) - return ; ast = parse(tokens); ft_lstclear(&tokens, free); if (!ast) diff --git a/src/execute/exec_cmd.c b/src/execute/exec_cmd.c index b03ccd2..ca51c91 100644 --- a/src/execute/exec_cmd.c +++ b/src/execute/exec_cmd.c @@ -11,6 +11,7 @@ /* ************************************************************************** */ #include "execute.h" +#include "expand.h" static int cmd_not_found(char **argv) { @@ -88,6 +89,9 @@ int exec_cmd(t_ast *node, t_shell_table *shell_table) { int status; + node->cmd->argv = expand(node->cmd->argv, shell_table); + if (node->cmd->redirs) + expand_redir_filenames(node->cmd->redirs, shell_table); if (node->cmd->redirs) { if (exec_redirs(node->cmd->redirs) != 0) diff --git a/src/execute/redirects/expand_redirs.c b/src/execute/redirects/expand_redirs.c new file mode 100644 index 0000000..8dfbd68 --- /dev/null +++ b/src/execute/redirects/expand_redirs.c @@ -0,0 +1,45 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* expand_redirs.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/16 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/04/16 00:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "execute.h" +#include "expand.h" + +static void expand_one_filename(t_redir *redir, t_shell_table *st) +{ + t_list *tmp; + char *expanded; + + tmp = ft_lstnew(ft_strdup(redir->filename)); + if (!tmp) + return ; + tmp = expand(tmp, st); + if (!tmp) + return ; + expanded = ft_strdup((char *)tmp->content); + ft_lstclear(&tmp, free); + if (!expanded) + return ; + free(redir->filename); + redir->filename = expanded; +} + +void expand_redir_filenames(t_list *redirs, t_shell_table *st) +{ + t_redir *redir; + + while (redirs) + { + redir = (t_redir *)redirs->content; + expand_one_filename(redir, st); + redirs = redirs->next; + } +} From 3022d43046a13246151aab1914588717a98d37dd Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 16 Apr 2026 19:14:17 +0900 Subject: [PATCH 151/173] =?UTF-8?q?feat:=20=E3=82=B5=E3=83=96=E3=82=B7?= =?UTF-8?q?=E3=82=A7=E3=83=AB=20(cmd1=20&&=20cmd2)=20|=20cmd3=20=E3=81=AE?= =?UTF-8?q?=E3=83=91=E3=83=BC=E3=82=B5=E3=83=BB=E5=AE=9F=E8=A1=8C=E3=82=B5?= =?UTF-8?q?=E3=83=9D=E3=83=BC=E3=83=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - t_ast_type に SUBSHELL を追加 - parse_pipeline.c に parse_subshell/parse_primary を分離 - exec_ast に exec_subshell を追加(fork して子プロセスでサブツリー実行) - free_ast の AND/OR/SUBSHELL メモリリーク修正 - is_word から ( ) を除外 Co-Authored-By: Claude Opus 4.6 (1M context) --- Makefile | 1 + includes/parse.h | 5 +- src/execute/exec_ast.c | 18 ++++++ src/expand/expand_wildcard/resolve_wildcard.c | 1 - src/parse/parse.c | 27 +-------- src/parse/parse_list.c | 2 +- src/parse/parse_pipeline.c | 60 +++++++++++++++++++ src/parse/utils/free_ast.c | 8 +-- src/parse/utils/token_check.c | 2 + 9 files changed, 92 insertions(+), 32 deletions(-) create mode 100644 src/parse/parse_pipeline.c diff --git a/Makefile b/Makefile index 3dd94be..0040fbb 100644 --- a/Makefile +++ b/Makefile @@ -84,6 +84,7 @@ SRCS_MAND := src/main.c \ src/tokenize/store/add_buffer.c \ src/parse/parse.c \ src/parse/parse_list.c \ + src/parse/parse_pipeline.c \ src/parse/utils/add_to_cmd.c \ src/parse/utils/new_ast_node.c \ src/parse/utils/new_cmd.c \ diff --git a/includes/parse.h b/includes/parse.h index 756bcda..7ad5366 100644 --- a/includes/parse.h +++ b/includes/parse.h @@ -29,7 +29,8 @@ typedef enum e_ast_type PIPE, CMD, AND, - OR + OR, + SUBSHELL } t_ast_type; typedef enum e_redir_kind @@ -62,7 +63,9 @@ typedef struct s_ast /* main function------------------------------------------------------------- */ t_ast *parse(t_list *token_head); +t_ast *parse_cmd(t_list **current); t_ast *parse_pipeline(t_list **current); +t_ast *parse_list(t_list **current); /* AST's token utils--------------------------------------------------------- */ bool is_word(const t_list *node); diff --git a/src/execute/exec_ast.c b/src/execute/exec_ast.c index 6478d98..ae01a00 100644 --- a/src/execute/exec_ast.c +++ b/src/execute/exec_ast.c @@ -24,6 +24,22 @@ static int exec_logical(t_ast *node, t_shell_table *shell_table) return (status); } +static int exec_subshell(t_ast *node, t_shell_table *shell_table) +{ + pid_t pid; + int wstatus; + + pid = fork(); + if (pid < 0) + return (perror("fork"), 1); + if (pid == 0) + exit(exec_ast(node->right, shell_table)); + waitpid(pid, &wstatus, 0); + if (ft_wifexited(wstatus)) + return (ft_wexitstatus(wstatus)); + return (1); +} + int exec_ast(t_ast *node, t_shell_table *shell_table) { if (!node) @@ -34,5 +50,7 @@ int exec_ast(t_ast *node, t_shell_table *shell_table) return (exec_cmd(node, shell_table)); if (node->type == AND || node->type == OR) return (exec_logical(node, shell_table)); + if (node->type == SUBSHELL) + return (exec_subshell(node, shell_table)); return (EXIT_FAILURE); } diff --git a/src/expand/expand_wildcard/resolve_wildcard.c b/src/expand/expand_wildcard/resolve_wildcard.c index 85e61a1..edac7e5 100644 --- a/src/expand/expand_wildcard/resolve_wildcard.c +++ b/src/expand/expand_wildcard/resolve_wildcard.c @@ -94,4 +94,3 @@ static t_list *build_full_paths(t_list *matches, const char *abs_dir) ft_lstclear(&matches, free); return (result); } - diff --git a/src/parse/parse.c b/src/parse/parse.c index b5ea84d..f0758a1 100644 --- a/src/parse/parse.c +++ b/src/parse/parse.c @@ -39,7 +39,7 @@ static int parse_redir(t_list **current, t_cmd *cmd) return (SUCCESS); } -static t_ast *parse_cmd(t_list **current) +t_ast *parse_cmd(t_list **current) { t_ast *ast; t_cmd *cmd; @@ -49,7 +49,8 @@ static t_ast *parse_cmd(t_list **current) return (NULL); while (*current && !is_symbol(*current, "|") && !is_symbol(*current, "&&") - && !is_symbol(*current, "||")) + && !is_symbol(*current, "||") + && !is_symbol(*current, ")")) { if (is_redir(*current)) { @@ -70,25 +71,3 @@ static t_ast *parse_cmd(t_list **current) return (ast); } -t_ast *parse_pipeline(t_list **current) -{ - t_ast *left; - t_ast *pipe_node; - - left = parse_cmd(current); - if (!left) - return (NULL); - if (*current && is_symbol(*current, "|")) - { - *current = (*current)->next; - pipe_node = new_ast_node(PIPE); - if (!pipe_node) - return (free_ast(left), NULL); - pipe_node->left = left; - pipe_node->right = parse_pipeline(current); - if (!pipe_node->right) - return (free_ast(pipe_node), NULL); - return (pipe_node); - } - return (left); -} diff --git a/src/parse/parse_list.c b/src/parse/parse_list.c index 227db0f..a3a637a 100644 --- a/src/parse/parse_list.c +++ b/src/parse/parse_list.c @@ -21,7 +21,7 @@ static t_ast_type get_logical_type(t_list *current) return (CMD); } -static t_ast *parse_list(t_list **current) +t_ast *parse_list(t_list **current) { t_ast *left; t_ast *node; diff --git a/src/parse/parse_pipeline.c b/src/parse/parse_pipeline.c new file mode 100644 index 0000000..2aa2014 --- /dev/null +++ b/src/parse/parse_pipeline.c @@ -0,0 +1,60 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parse_pipeline.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/16 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/04/16 00:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parse.h" + +static t_ast *parse_subshell(t_list **current) +{ + t_ast *node; + + *current = (*current)->next; + node = new_ast_node(SUBSHELL); + if (!node) + return (NULL); + node->right = parse_list(current); + if (!node->right) + return (free_ast(node), NULL); + if (!*current || !is_symbol(*current, ")")) + return (free_ast(node), NULL); + *current = (*current)->next; + return (node); +} + +static t_ast *parse_primary(t_list **current) +{ + if (*current && is_symbol(*current, "(")) + return (parse_subshell(current)); + return (parse_cmd(current)); +} + +t_ast *parse_pipeline(t_list **current) +{ + t_ast *left; + t_ast *pipe_node; + + left = parse_primary(current); + if (!left) + return (NULL); + if (*current && is_symbol(*current, "|")) + { + *current = (*current)->next; + pipe_node = new_ast_node(PIPE); + if (!pipe_node) + return (free_ast(left), NULL); + pipe_node->left = left; + pipe_node->right = parse_pipeline(current); + if (!pipe_node->right) + return (free_ast(pipe_node), NULL); + return (pipe_node); + } + return (left); +} diff --git a/src/parse/utils/free_ast.c b/src/parse/utils/free_ast.c index 1a73608..041575a 100644 --- a/src/parse/utils/free_ast.c +++ b/src/parse/utils/free_ast.c @@ -37,14 +37,12 @@ void free_ast(t_ast *ast) { if (!ast) return ; - if (ast->type == PIPE) + if (ast->type == CMD) + free_cmd(ast->cmd); + else { free_ast(ast->left); free_ast(ast->right); } - else if (ast->type == CMD) - { - free_cmd(ast->cmd); - } free(ast); } diff --git a/src/parse/utils/token_check.c b/src/parse/utils/token_check.c index 7894090..3adfab6 100644 --- a/src/parse/utils/token_check.c +++ b/src/parse/utils/token_check.c @@ -25,6 +25,8 @@ bool is_word(const t_list *node) ft_strncmp(s, "|", 2) == 0 || \ ft_strncmp(s, "&&", 3) == 0 || \ ft_strncmp(s, "||", 3) == 0 || \ + ft_strncmp(s, "(", 2) == 0 || \ + ft_strncmp(s, ")", 2) == 0 || \ ft_strncmp(s, "EOF", 4) == 0) return (false); return (true); From 20f70cedb21d8d2f68a40141540090980b71a7bc Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 16 Apr 2026 20:14:00 +0900 Subject: [PATCH 152/173] =?UTF-8?q?fix:=20=E3=82=AF=E3=82=A9=E3=83=BC?= =?UTF-8?q?=E3=83=88=E5=A2=83=E7=95=8C=E3=81=A7=E3=83=88=E3=83=BC=E3=82=AF?= =?UTF-8?q?=E3=83=B3=E3=81=8C=E5=88=86=E5=89=B2=E3=81=95=E3=82=8C=E3=82=8B?= =?UTF-8?q?=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit expand_parameter のクォート開始/終了時に push_token_expand を 呼んでいたため l"s" が [l, "s"] の2トークンに分割されていた。 クォート遷移時は buffer に文字を追加するだけに修正。 Co-Authored-By: Claude Opus 4.6 (1M context) --- Makefile | 1 + .../state/in_double_quote_expand.c | 4 +- .../expand_parameter/state/in_normal_expand.c | 4 +- .../state/in_single_quote_expand.c | 4 +- src/expand/expand_wildcard/match_wildcard.c | 56 +++++++++++++ src/expand/expand_wildcard/resolve_wildcard.c | 78 +++++-------------- 6 files changed, 83 insertions(+), 64 deletions(-) create mode 100644 src/expand/expand_wildcard/match_wildcard.c diff --git a/Makefile b/Makefile index 3205be6..8af3c69 100644 --- a/Makefile +++ b/Makefile @@ -129,6 +129,7 @@ SRCS_MAND := src/main.c \ src/expand/expand_parameter/store/free_store_expand.c \ src/expand/expand_tilde/expand_tilde.c \ src/expand/expand_wildcard/resolve_wildcard.c \ + src/expand/expand_wildcard/match_wildcard.c \ src/expand/expand_wildcard/expand_wildcard.c \ src/expand/expand_remove_quotes/expand_remove_quotes.c \ src/signal/setup_signal_handlers.c \ diff --git a/src/expand/expand_parameter/state/in_double_quote_expand.c b/src/expand/expand_parameter/state/in_double_quote_expand.c index f10df32..2f3d673 100644 --- a/src/expand/expand_parameter/state/in_double_quote_expand.c +++ b/src/expand/expand_parameter/state/in_double_quote_expand.c @@ -64,8 +64,8 @@ static void by_dollar(t_shell_table *shell_table, t_expand_store *store, static void by_double_quote_end(t_shell_table *shell_table, t_expand_store *store, t_expand_state *state, char **current) { - if (add_buffer_expand(store, **current) == ERROR || push_token_expand(store, - shell_table) == ERROR) + (void)shell_table; + if (add_buffer_expand(store, **current) == ERROR) *state = EXPAND_ON_ERROR; else *state = EXPAND_IN_NORMAL; diff --git a/src/expand/expand_parameter/state/in_normal_expand.c b/src/expand/expand_parameter/state/in_normal_expand.c index 630ada7..e368ddb 100644 --- a/src/expand/expand_parameter/state/in_normal_expand.c +++ b/src/expand/expand_parameter/state/in_normal_expand.c @@ -48,8 +48,8 @@ static void by_last(t_shell_table *shell_table, t_expand_store *store, static void by_quote(t_shell_table *shell_table, t_expand_store *store, t_expand_state *state, char **current) { - if (push_token_expand(store, shell_table) == ERROR - || add_buffer_expand(store, **current) == ERROR) + (void)shell_table; + if (add_buffer_expand(store, **current) == ERROR) *state = EXPAND_ON_ERROR; else if (**current == '"') *state = EXPAND_IN_DOUBLE_QUOTE; diff --git a/src/expand/expand_parameter/state/in_single_quote_expand.c b/src/expand/expand_parameter/state/in_single_quote_expand.c index 1b4bbc2..19bee93 100644 --- a/src/expand/expand_parameter/state/in_single_quote_expand.c +++ b/src/expand/expand_parameter/state/in_single_quote_expand.c @@ -30,8 +30,8 @@ void in_single_quote_expand(t_shell_table *shell_table, static void by_single_quote_end(t_shell_table *shell_table, t_expand_store *store, t_expand_state *state, char **current) { - if (add_buffer_expand(store, **current) == ERROR || push_token_expand(store, - shell_table) == ERROR) + (void)shell_table; + if (add_buffer_expand(store, **current) == ERROR) *state = EXPAND_ON_ERROR; else *state = EXPAND_IN_NORMAL; diff --git a/src/expand/expand_wildcard/match_wildcard.c b/src/expand/expand_wildcard/match_wildcard.c new file mode 100644 index 0000000..dffa31c --- /dev/null +++ b/src/expand/expand_wildcard/match_wildcard.c @@ -0,0 +1,56 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* match_wildcard.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/16 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/04/16 00:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "expand_wildcard_internal.h" + +static bool match_pattern(const char *str, const char *pattern) +{ + if (*pattern == '\0') + return (*str == '\0'); + if (*pattern == WILDCARD) + { + while (*str) + { + if (match_pattern(str, pattern + 1)) + return (true); + str++; + } + return (match_pattern(str, pattern + 1)); + } + if (*str == *pattern) + return (match_pattern(str + 1, pattern + 1)); + return (false); +} + +t_list *filter_pattern(t_list *source, const char *pattern) +{ + t_list *result; + t_list *current; + t_list *new_node; + + if (!source || !pattern) + return (NULL); + result = NULL; + current = source; + while (current) + { + if (match_pattern((const char *)current->content, pattern)) + { + new_node = ft_lstnew(ft_strdup((const char *)current->content)); + if (!new_node) + return (ft_lstclear(&result, free), NULL); + ft_lstadd_back(&result, new_node); + } + current = current->next; + } + return (result); +} diff --git a/src/expand/expand_wildcard/resolve_wildcard.c b/src/expand/expand_wildcard/resolve_wildcard.c index ae57717..edac7e5 100644 --- a/src/expand/expand_wildcard/resolve_wildcard.c +++ b/src/expand/expand_wildcard/resolve_wildcard.c @@ -16,8 +16,7 @@ static t_list *get_matches(const char *abs_dir, const char *pattern); static t_list *build_full_paths(t_list *matches, const char *abs_dir); -static bool match_pattern(const char *str, const char *pattern); -static t_list *filter_pattern(t_list *source, const char *pattern); +t_list *filter_pattern(t_list *source, const char *pattern); t_list *resolve_wildcard(const char *token) { @@ -57,13 +56,29 @@ static t_list *get_matches(const char *abs_dir, const char *pattern) return (result); } +static void append_full_path(t_list **result, const char *prefix, + const char *name) +{ + char *full_path; + t_list *node; + + full_path = ft_strjoin(prefix, name); + if (!full_path) + return ; + node = ft_lstnew(full_path); + if (!node) + { + free(full_path); + return ; + } + ft_lstadd_back(result, node); +} + static t_list *build_full_paths(t_list *matches, const char *abs_dir) { t_list *result; t_list *current; - t_list *node; char *dir_slash; - char *full_path; result = NULL; dir_slash = ft_strjoin(abs_dir, "/"); @@ -72,63 +87,10 @@ static t_list *build_full_paths(t_list *matches, const char *abs_dir) current = matches; while (current) { - full_path = ft_strjoin(dir_slash, (char *)current->content); - node = ft_lstnew(full_path); - if (!node) - { - free(full_path); - break ; - } - ft_lstadd_back(&result, node); + append_full_path(&result, dir_slash, (char *)current->content); current = current->next; } free(dir_slash); ft_lstclear(&matches, free); return (result); } - -static t_list *filter_pattern(t_list *source, const char *pattern) -{ - t_list *result; - t_list *current; - t_list *new_node; - - if (!source || !pattern) - return (NULL); - result = NULL; - current = source; - while (current) - { - if (match_pattern((const char *)current->content, pattern)) - { - new_node = ft_lstnew(ft_strdup((const char *)current->content)); - if (!new_node) - { - ft_lstclear(&result, free); - return (NULL); - } - ft_lstadd_back(&result, new_node); - } - current = current->next; - } - return (result); -} - -static bool match_pattern(const char *str, const char *pattern) -{ - if (*pattern == '\0') - return (*str == '\0'); - if (*pattern == WILDCARD) - { - while (*str) - { - if (match_pattern(str, pattern + 1)) - return (true); - str++; - } - return (match_pattern(str, pattern + 1)); - } - if (*str == *pattern) - return (match_pattern(str + 1, pattern + 1)); - return (false); -} From aedc1ada32cfe7bc21379c1fa9fb673559b686a6 Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 16 Apr 2026 20:55:10 +0900 Subject: [PATCH 153/173] =?UTF-8?q?fix:=20=E3=82=AF=E3=82=A9=E3=83=BC?= =?UTF-8?q?=E3=83=88=E5=89=8A=E9=99=A4=E3=81=A7=E3=82=AF=E3=82=A9=E3=83=BC?= =?UTF-8?q?=E3=83=88=E3=81=AE=E9=96=8B=E9=96=89=E7=8A=B6=E6=85=8B=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E8=B7=A1=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 全てのクォート文字を無条件に削除していたため、 echo "hello 'world'" が hello world になっていた。 クォートの開閉を追跡し、外側のクォートのみ削除するよう修正。 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../expand_remove_quotes.c | 61 +++++++++---------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/src/expand/expand_remove_quotes/expand_remove_quotes.c b/src/expand/expand_remove_quotes/expand_remove_quotes.c index cdc8502..16a22cc 100644 --- a/src/expand/expand_remove_quotes/expand_remove_quotes.c +++ b/src/expand/expand_remove_quotes/expand_remove_quotes.c @@ -6,16 +6,15 @@ /* By: surayama +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/02/07 00:51:36 by surayama #+# #+# */ -/* Updated: 2026/02/13 23:29:35 by surayama ### ########.fr */ +/* Updated: 2026/04/16 00:00:00 by surayama ### ########.fr */ /* */ /* ************************************************************************** */ #include "expand.h" #include -static bool is_quote(char c); +static int count_unquoted_len(const char *str); static char *remove_quotes_from_string(const char *str); -static int excluded_quote_length(const char *str); t_list *expand_remove_quotes(t_list *tokens) { @@ -42,47 +41,47 @@ t_list *expand_remove_quotes(t_list *tokens) return (tokens); } -static int excluded_quote_length(const char *str) +static int count_unquoted_len(const char *str) { - size_t len; - size_t quote_count; + int len; + char quote; - len = ft_strlen(str); - quote_count = 0; + len = 0; + quote = 0; while (*str) { - if (is_quote(*str)) - quote_count++; + if (!quote && (*str == '\'' || *str == '"')) + quote = *str; + else if (*str == quote) + quote = 0; + else + len++; str++; } - return (len - quote_count); + return (len); } static char *remove_quotes_from_string(const char *str) { - char *removed_str; - int i; + char *result; + char quote; int j; - i = 0; - j = 0; - removed_str = malloc(sizeof(char) * (excluded_quote_length(str) + 1)); - if (!removed_str) + result = malloc(sizeof(char) * (count_unquoted_len(str) + 1)); + if (!result) return (NULL); - while (str[i]) + quote = 0; + j = 0; + while (*str) { - if (!is_quote(str[i])) - { - removed_str[j] = str[i]; - j++; - } - i++; + if (!quote && (*str == '\'' || *str == '"')) + quote = *str; + else if (*str == quote) + quote = 0; + else + result[j++] = *str; + str++; } - removed_str[j] = '\0'; - return (removed_str); -} - -static bool is_quote(char c) -{ - return (c == '\'' || c == '"' || c == '`'); + result[j] = '\0'; + return (result); } From 9871904150de7e76ce4d861ec91768138830adb1 Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 16 Apr 2026 21:00:38 +0900 Subject: [PATCH 154/173] =?UTF-8?q?feat:=20=E9=96=89=E3=81=98=E3=82=89?= =?UTF-8?q?=E3=82=8C=E3=81=A6=E3=81=84=E3=81=AA=E3=81=84=E3=82=AF=E3=82=A9?= =?UTF-8?q?=E3=83=BC=E3=83=88=E3=81=AE=E3=82=A8=E3=83=A9=E3=83=BC=E3=83=A1?= =?UTF-8?q?=E3=83=83=E3=82=BB=E3=83=BC=E3=82=B8=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ダブルクォート/シングルクォートが閉じられずに入力が終了した場合、 stderr にエラーメッセージを出力するようにした。 Co-Authored-By: Claude Opus 4.6 (1M context) --- src/tokenize/state/in_double_quote.c | 4 ++++ src/tokenize/state/in_single_quote.c | 4 ++++ src/tokenize/tokenize_private.h | 1 + 3 files changed, 9 insertions(+) diff --git a/src/tokenize/state/in_double_quote.c b/src/tokenize/state/in_double_quote.c index 20494f5..33f6aa1 100644 --- a/src/tokenize/state/in_double_quote.c +++ b/src/tokenize/state/in_double_quote.c @@ -16,7 +16,11 @@ void in_double_quote(t_token_store *store, t_token_state *state, char current) { if (current == '\0') + { + ft_putstr_fd("jikussh: unexpected EOF while looking" + " for matching `\"'\n", STDERR_FILENO); *state = ON_ERROR; + } else if (add_buffer(store, current) == ERROR) *state = ON_ERROR; else if (current == '"') diff --git a/src/tokenize/state/in_single_quote.c b/src/tokenize/state/in_single_quote.c index ad02a2e..7dcb7b3 100644 --- a/src/tokenize/state/in_single_quote.c +++ b/src/tokenize/state/in_single_quote.c @@ -16,7 +16,11 @@ void in_single_quote(t_token_store *store, t_token_state *state, char current) { if (current == '\0') + { + ft_putstr_fd("jikussh: unexpected EOF while looking" + " for matching `''\n", STDERR_FILENO); *state = ON_ERROR; + } else if (add_buffer(store, current) == ERROR) *state = ON_ERROR; else if (current == '\'') diff --git a/src/tokenize/tokenize_private.h b/src/tokenize/tokenize_private.h index bf3a4aa..393cf8a 100644 --- a/src/tokenize/tokenize_private.h +++ b/src/tokenize/tokenize_private.h @@ -15,6 +15,7 @@ # include "tokenize.h" # include "constants.h" +# include typedef enum e_token_state { From c1066fae8a3fa7b75450e4e460c19fe46407236c Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 16 Apr 2026 21:11:55 +0900 Subject: [PATCH 155/173] =?UTF-8?q?fix:=20heredoc=20=E5=85=A5=E5=8A=9B?= =?UTF-8?q?=E4=B8=AD=E3=81=AE=20Ctrl+C=20=E3=81=A7=E3=83=97=E3=83=AD?= =?UTF-8?q?=E3=83=B3=E3=83=97=E3=83=88=E3=81=AB=E6=88=BB=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit heredoc の入力を子プロセスで実行するよう変更。 Ctrl+C で子プロセスが SIGINT で終了し、親は waitpid で検知して tmpfile を削除しプロンプトに戻る。rl_done の信頼性問題を回避。 Co-Authored-By: Claude Opus 4.6 (1M context) --- includes/heredoc.h | 1 + src/component/heredoc/heredoc.c | 2 - src/component/heredoc/heredoc_prompt.c | 91 ++++++++++++++++---------- 3 files changed, 56 insertions(+), 38 deletions(-) diff --git a/includes/heredoc.h b/includes/heredoc.h index a8ea1e1..0c7db2b 100644 --- a/includes/heredoc.h +++ b/includes/heredoc.h @@ -18,6 +18,7 @@ # include # include # include +# include # include t_list *heredoc(t_list *tokens); diff --git a/src/component/heredoc/heredoc.c b/src/component/heredoc/heredoc.c index d33cfe9..428c48b 100644 --- a/src/component/heredoc/heredoc.c +++ b/src/component/heredoc/heredoc.c @@ -31,9 +31,7 @@ t_list *heredoc(t_list *tokens) eof_node = current->next; if (eof_node == NULL) return (NULL); - set_signal_heredoc(); tmpfile_path = heredoc_prompt((char *)eof_node->content); - set_signal_interactive(); if (tmpfile_path == NULL) return (NULL); if (rebuild_tokens(current, eof_node, tmpfile_path) == ERROR) diff --git a/src/component/heredoc/heredoc_prompt.c b/src/component/heredoc/heredoc_prompt.c index db8372d..bbb8c96 100644 --- a/src/component/heredoc/heredoc_prompt.c +++ b/src/component/heredoc/heredoc_prompt.c @@ -15,37 +15,79 @@ #include static int write_line_to_file(int fd, char *line); -static char *by_found_delimiter(char *line, int fd, char *tmpfile_path); -static void *by_fail_write_line_to_file(char *line, int fd, char *tmpfile_path); -static void *by_sigint(int fd, char *tmpfile_path); +static void heredoc_child(const char *delimiter, int fd); + +static int wait_heredoc_child(pid_t pid) +{ + int wstatus; + + waitpid(pid, &wstatus, 0); + if (WIFSIGNALED(wstatus) && WTERMSIG(wstatus) == SIGINT) + { + write(STDOUT_FILENO, "\n", 1); + return (-1); + } + if (WIFEXITED(wstatus)) + return (WEXITSTATUS(wstatus)); + return (-1); +} + +static void *heredoc_interrupted(char *tmpfile_path) +{ + unlink(tmpfile_path); + free(tmpfile_path); + set_signal_interactive(); + g_signal = SIGINT; + return (NULL); +} char *heredoc_prompt(const char *delimiter) { - char *line; char *tmpfile_path; int fd; + pid_t pid; tmpfile_path = create_tmpfile(); if (tmpfile_path == NULL) return (NULL); fd = open_tmpfile(tmpfile_path); if (fd == -1) - return (NULL); + return (free(tmpfile_path), NULL); + pid = fork(); + if (pid == 0) + { + set_signal_default(); + heredoc_child(delimiter, fd); + } + close(fd); + set_signal_ignore(); + if (wait_heredoc_child(pid) != 0) + return (heredoc_interrupted(tmpfile_path)); + set_signal_interactive(); + return (tmpfile_path); +} + +static void heredoc_child(const char *delimiter, int fd) +{ + char *line; + int status; + + status = 0; while (1) { line = readline(HEREDOC_PROMPT); - if (line == NULL && g_signal == SIGINT) - return (by_sigint(fd, tmpfile_path)); - if (line == NULL) + if (!line || ft_strncmp(line, delimiter, + ft_strlen(delimiter) + 1) == 0) break ; - if (ft_strncmp(line, delimiter, ft_strlen(delimiter) + 1) == 0) - return (by_found_delimiter(line, fd, tmpfile_path)); if (write_line_to_file(fd, line) == ERROR) - return (by_fail_write_line_to_file(line, fd, tmpfile_path)); + { + status = 1; + break ; + } free(line); } - close(fd); - return (tmpfile_path); + free(line); + exit(status); } static int write_line_to_file(int fd, char *line) @@ -59,26 +101,3 @@ static int write_line_to_file(int fd, char *line) return (ERROR); return (SUCCESS); } - -static char *by_found_delimiter(char *line, int fd, char *tmpfile_path) -{ - free(line); - close(fd); - return (tmpfile_path); -} - -static void *by_fail_write_line_to_file(char *line, int fd, char *tmpfile_path) -{ - free(line); - close(fd); - free(tmpfile_path); - return (NULL); -} - -static void *by_sigint(int fd, char *tmpfile_path) -{ - close(fd); - unlink(tmpfile_path); - free(tmpfile_path); - return (NULL); -} From 0a1555fcca0a97972fc9fe6586113071294c7326 Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 16 Apr 2026 21:21:58 +0900 Subject: [PATCH 156/173] =?UTF-8?q?fix:=20=E3=83=AA=E3=83=80=E3=82=A4?= =?UTF-8?q?=E3=83=AC=E3=82=AF=E3=83=88=E3=81=8C=E8=A6=AA=E3=83=97=E3=83=AD?= =?UTF-8?q?=E3=82=BB=E3=82=B9=E3=81=AE=20fd=20=E3=82=92=E5=A3=8A=E3=81=99?= =?UTF-8?q?=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 外部コマンドのリダイレクトは子プロセスのみで実行し、 ビルトインのリダイレクトは dup で fd を保存・復元するよう変更。 cmd_not_found と exec_external_cmd を find_exec_path.c に移動。 Co-Authored-By: Claude Opus 4.6 (1M context) --- Makefile | 1 + includes/execute.h | 2 + src/execute/command/exec_external_cmd.c | 60 ++++++++++++++++++ src/execute/exec_cmd.c | 84 ++++++++++--------------- 4 files changed, 95 insertions(+), 52 deletions(-) create mode 100644 src/execute/command/exec_external_cmd.c diff --git a/Makefile b/Makefile index 8af3c69..a7d4bfa 100644 --- a/Makefile +++ b/Makefile @@ -106,6 +106,7 @@ SRCS_MAND := src/main.c \ src/execute/utils/ft_wexitstatus.c \ src/execute/utils/ft_wifexited.c \ src/execute/command/find_exec_path.c \ + src/execute/command/exec_external_cmd.c \ src/execute/command/exec_builtin_cmd.c \ src/execute/command/list_to_argv.c \ src/execute/pipe/exec_pipe_child.c \ diff --git a/includes/execute.h b/includes/execute.h index 4e24a39..036acb6 100644 --- a/includes/execute.h +++ b/includes/execute.h @@ -24,6 +24,8 @@ int exec_builtin_cmd(t_ast *node, t_shell_table *shell_table); int exec_cmd(t_ast *node, t_shell_table *shell_table); char *find_exec_path(const char *cmd, \ t_shell_table *shell_table); +int exec_external_cmd(char **argv, \ + t_shell_table *shell_table); int exec_pipe(t_ast *node, t_shell_table *shell_table); void exec_left_child(t_ast *node, \ t_shell_table *shell_table, int fd[2]); diff --git a/src/execute/command/exec_external_cmd.c b/src/execute/command/exec_external_cmd.c new file mode 100644 index 0000000..190e410 --- /dev/null +++ b/src/execute/command/exec_external_cmd.c @@ -0,0 +1,60 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_external_cmd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/16 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/04/16 00:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "execute.h" + +static int cmd_not_found(char **argv) +{ + if (ft_strchr(argv[0], '/')) + { + if (access(argv[0], F_OK) == 0) + { + ft_putstr_fd("jikussh: ", STDERR_FILENO); + perror(argv[0]); + ft_free_array((void **)argv); + return (126); + } + ft_putstr_fd("jikussh: ", STDERR_FILENO); + perror(argv[0]); + ft_free_array((void **)argv); + return (127); + } + ft_putstr_fd("jikussh: ", STDERR_FILENO); + ft_putstr_fd(argv[0], STDERR_FILENO); + ft_putstr_fd(": command not found\n", STDERR_FILENO); + ft_free_array((void **)argv); + return (127); +} + +int exec_external_cmd(char **argv, t_shell_table *shell_table) +{ + char *cmd_path; + char **new_envp; + + cmd_path = find_exec_path(argv[0], shell_table); + if (!cmd_path) + return (cmd_not_found(argv)); + new_envp = export_envp(shell_table); + if (!new_envp) + { + free(cmd_path); + ft_free_array((void **)argv); + return (1); + } + execve(cmd_path, argv, new_envp); + perror(cmd_path); + free(cmd_path); + st_destroy(shell_table); + ft_free_array((void **)new_envp); + ft_free_array((void **)argv); + return (127); +} diff --git a/src/execute/exec_cmd.c b/src/execute/exec_cmd.c index b03ccd2..f1459e5 100644 --- a/src/execute/exec_cmd.c +++ b/src/execute/exec_cmd.c @@ -11,53 +11,7 @@ /* ************************************************************************** */ #include "execute.h" - -static int cmd_not_found(char **argv) -{ - if (ft_strchr(argv[0], '/')) - { - if (access(argv[0], F_OK) == 0) - { - ft_putstr_fd("jikussh: ", STDERR_FILENO); - perror(argv[0]); - ft_free_array((void **)argv); - return (126); - } - ft_putstr_fd("jikussh: ", STDERR_FILENO); - perror(argv[0]); - ft_free_array((void **)argv); - return (127); - } - ft_putstr_fd("jikussh: ", STDERR_FILENO); - ft_putstr_fd(argv[0], STDERR_FILENO); - ft_putstr_fd(": command not found\n", STDERR_FILENO); - ft_free_array((void **)argv); - return (127); -} - -static int exec_external_cmd(char **argv, t_shell_table *shell_table) -{ - char *cmd_path; - char **new_envp; - - cmd_path = find_exec_path(argv[0], shell_table); - if (!cmd_path) - return (cmd_not_found(argv)); - new_envp = export_envp(shell_table); - if (!new_envp) - { - free(cmd_path); - ft_free_array((void **)argv); - return (1); - } - execve(cmd_path, argv, new_envp); - perror(cmd_path); - free(cmd_path); - st_destroy(shell_table); - ft_free_array((void **)new_envp); - ft_free_array((void **)argv); - return (127); -} +#include "signal_handler.h" static int fork_and_exec(t_ast *node, t_shell_table *shell_table) { @@ -84,17 +38,43 @@ static int fork_and_exec(t_ast *node, t_shell_table *shell_table) return (1); } -int exec_cmd(t_ast *node, t_shell_table *shell_table) +static void restore_fds(int saved_in, int saved_out) { - int status; + dup2(saved_in, STDIN_FILENO); + dup2(saved_out, STDOUT_FILENO); + close(saved_in); + close(saved_out); +} + +static int exec_builtin_with_redir(t_ast *node, t_shell_table *st) +{ + int saved_in; + int saved_out; + int status; - if (node->cmd->redirs) + saved_in = dup(STDIN_FILENO); + saved_out = dup(STDOUT_FILENO); + if (node->cmd->redirs + && exec_redirs(node->cmd->redirs) != 0) { - if (exec_redirs(node->cmd->redirs) != 0) - return (1); + restore_fds(saved_in, saved_out); + return (1); } + status = exec_builtin_cmd(node, st); + restore_fds(saved_in, saved_out); + return (status); +} + +int exec_cmd(t_ast *node, t_shell_table *shell_table) +{ + int status; + status = exec_builtin_cmd(node, shell_table); if (status != -1) + { + if (node->cmd->redirs) + return (exec_builtin_with_redir(node, shell_table)); return (status); + } return (fork_and_exec(node, shell_table)); } From ccc444d7e17b2d4186033aba227727021b7c714a Mon Sep 17 00:00:00 2001 From: jiku Date: Fri, 17 Apr 2026 21:27:56 +0900 Subject: [PATCH 157/173] =?UTF-8?q?=E2=93=AA=20fix:=20on=5Finput=20?= =?UTF-8?q?=E3=81=AB=E3=83=91=E3=82=A4=E3=83=97=E3=83=A9=E3=82=A4=E3=83=B3?= =?UTF-8?q?=E5=AE=9F=E8=A3=85=E3=81=A8=20$=3F=20=E5=B1=95=E9=96=8B?= =?UTF-8?q?=E5=AF=BE=E5=BF=9C=20(#75)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: on_inputの終了ステータス処理を整理 * fix: statusをon_input内部で変更できるように関数シグネチャを変更した。 * add: expand層に$?を展開するexpand_question層を追加。 * fix: includes/prompt.hのNormを修正。 * fix: on_inputのlast_statusのSignitureを、int *->intに変更。 * chore: 可読性を上げるために、current_statusという一時変数を追加。 --- Makefile | 3 +- includes/expand.h | 7 +- includes/minishell.h | 6 +- includes/prompt.h | 6 +- src/callback/on_input.c | 18 +-- src/expand/expand.c | 10 +- src/expand/expand_question/expand_question.c | 128 +++++++++++++++++++ src/prompt/prompt.c | 10 +- 8 files changed, 163 insertions(+), 25 deletions(-) create mode 100644 src/expand/expand_question/expand_question.c diff --git a/Makefile b/Makefile index 8af3c69..45bf8a6 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # By: kjikuhar +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/05/18 21:11:39 by kjikuhar #+# #+# # -# Updated: 2026/03/03 20:32:45 by surayama ### ########.fr # +# Updated: 2026/04/17 21:12:31 by kjikuhar ### ########.fr # # # # **************************************************************************** # @@ -132,6 +132,7 @@ SRCS_MAND := src/main.c \ src/expand/expand_wildcard/match_wildcard.c \ src/expand/expand_wildcard/expand_wildcard.c \ src/expand/expand_remove_quotes/expand_remove_quotes.c \ + src/expand/expand_question/expand_question.c \ src/signal/setup_signal_handlers.c \ src/signal/set_signals.c \ diff --git a/includes/expand.h b/includes/expand.h index c6b51b6..408b22b 100644 --- a/includes/expand.h +++ b/includes/expand.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* expand.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/03/03 17:13:55 by surayama #+# #+# */ -/* Updated: 2026/03/03 18:00:00 by surayama ### ########.fr */ +/* Updated: 2026/04/17 21:11:14 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,10 +18,11 @@ # include "shell_table.h" # include -t_list *expand(t_list *tokens, t_shell_table *shell_table); +t_list *expand(t_list *tokens, t_shell_table *shell_table, int last_status); t_list *expand_parameter(t_list *tokens, t_shell_table *shell_table); t_list *expand_tilde(t_list *tokens, t_shell_table *shell_table); t_list *expand_wildcard(t_list *tokens); t_list *expand_remove_quotes(t_list *tokens); +t_list *expand_question(t_list *tokens, int last_exit_status); #endif diff --git a/includes/minishell.h b/includes/minishell.h index 255880f..6937684 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* minishell.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/29 15:14:22 by kjikuhar #+# #+# */ -/* Updated: 2026/04/16 00:00:00 by surayama ### ########.fr */ +/* Updated: 2026/04/17 21:21:52 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -26,6 +26,6 @@ # include "tokenize.h" // callbacks -void on_input(char *input, t_shell_table *shell_table); +int on_input(char *input, t_shell_table *shell_table, int last_status); #endif diff --git a/includes/prompt.h b/includes/prompt.h index 09fb593..aa86e82 100644 --- a/includes/prompt.h +++ b/includes/prompt.h @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/01 15:35:18 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:51 by kjikuhar ### ########.fr */ +/* Updated: 2026/04/17 21:22:24 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -21,7 +21,7 @@ # include # include -void prompt(void (*handler)(char *input, t_shell_table *shell_table), - t_shell_table *shell_table); +void prompt(int (*handler)(char *input, t_shell_table *shell_table, + int last_status), t_shell_table *shell_table); #endif diff --git a/src/callback/on_input.c b/src/callback/on_input.c index c4b0cfe..43525c3 100644 --- a/src/callback/on_input.c +++ b/src/callback/on_input.c @@ -6,32 +6,34 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/10 17:04:25 by surayama #+# #+# */ -/* Updated: 2026/04/16 00:00:00 by surayama ### ########.fr */ +/* Updated: 2026/04/17 21:23:54 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -void on_input(char *input, t_shell_table *shell_table) +int on_input(char *input, t_shell_table *shell_table, int last_status) { t_list *tokens; t_ast *ast; + int current_status; tokens = tokenize(input); if (!tokens) - return ; + return (2); if (!heredoc(tokens)) { ft_lstclear(&tokens, free); - return ; + return (130); } - tokens = expand(tokens, shell_table); + tokens = expand(tokens, shell_table, last_status); if (!tokens) - return ; + return (1); ast = parse(tokens); ft_lstclear(&tokens, free); if (!ast) - return ; - exec_ast(ast, shell_table); + return (2); + current_status = exec_ast(ast, shell_table); free_ast(ast); + return (current_status); } diff --git a/src/expand/expand.c b/src/expand/expand.c index ee342e4..1d0988b 100644 --- a/src/expand/expand.c +++ b/src/expand/expand.c @@ -3,18 +3,22 @@ /* ::: :::::::: */ /* expand.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ +/* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/03/03 17:16:33 by surayama #+# #+# */ -/* Updated: 2026/03/03 17:54:02 by surayama ### ########.fr */ +/* Updated: 2026/04/16 22:20:39 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ #include "expand.h" -t_list *expand(t_list *tokens, t_shell_table *shell_table) +t_list *expand(t_list *tokens, t_shell_table *shell_table, \ + int last_exit_status) { tokens = expand_tilde(tokens, shell_table); + if (!tokens) + return (NULL); + tokens = expand_question(tokens, last_exit_status); if (!tokens) return (NULL); tokens = expand_parameter(tokens, shell_table); diff --git a/src/expand/expand_question/expand_question.c b/src/expand/expand_question/expand_question.c new file mode 100644 index 0000000..91db1b8 --- /dev/null +++ b/src/expand/expand_question/expand_question.c @@ -0,0 +1,128 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* expand_question.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: kjikuhar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/16 22:21:07 by kjikuhar #+# #+# */ +/* Updated: 2026/04/16 22:37:34 by kjikuhar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "expand.h" + +static bool has_question(const char *tok); +static size_t count_question_len(const char *tok, size_t slen); +static char *copy_and_advance(char *p, const char *status, + size_t slen, const char **tok); +static char *expand_question_token(const char *tok, + const char *status, size_t slen); + +static bool has_question(const char *tok) +{ + char quote; + + quote = 0; + while (*tok) + { + if (!quote && ft_strchr("'\"", *tok)) + quote = *tok; + else if (*tok == quote) + quote = 0; + else if (quote != '\'' && ft_strncmp(tok, "$?", 2) == 0) + return (true); + tok++; + } + return (false); +} + +static size_t count_question_len(const char *tok, size_t slen) +{ + size_t len; + char quote; + + len = 0; + quote = 0; + while (*tok) + { + if (!quote && ft_strchr("'\"", *tok)) + quote = *tok; + else if (*tok == quote) + quote = 0; + else if (quote != '\'' && ft_strncmp(tok, "$?", 2) == 0) + { + len += slen; + tok++; + } + else + len++; + tok++; + } + return (len); +} + +static char *copy_and_advance(char *p, const char *status, + size_t slen, const char **tok) +{ + ft_memcpy(p, status, slen); + (*tok)++; + return (p + slen); +} + +static char *expand_question_token(const char *tok, + const char *status, size_t slen) +{ + char *result; + char *p; + char quote; + + result = malloc(count_question_len(tok, slen) + 1); + if (!result) + return (NULL); + p = result; + quote = 0; + while (*tok) + { + if (!quote && ft_strchr("'\"", *tok)) + quote = *tok; + else if (*tok == quote) + quote = 0; + else if (quote != '\'' && ft_strncmp(tok, "$?", 2) == 0) + p = copy_and_advance(p, status, slen, &tok); + else + *p++ = *tok; + tok++; + } + *p = '\0'; + return (result); +} + +t_list *expand_question(t_list *tokens, int last_exit_status) +{ + char *status; + size_t slen; + t_list *current; + char *expanded; + + status = ft_itoa(last_exit_status); + if (!status) + return (NULL); + slen = ft_strlen(status); + current = tokens; + while (current) + { + if (current->content && has_question(current->content)) + { + expanded = expand_question_token(current->content, status, slen); + if (expanded) + { + free(current->content); + current->content = expanded; + } + } + current = current->next; + } + free(status); + return (tokens); +} diff --git a/src/prompt/prompt.c b/src/prompt/prompt.c index ecd86b8..7fffc4c 100644 --- a/src/prompt/prompt.c +++ b/src/prompt/prompt.c @@ -6,18 +6,20 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/01 15:35:00 by surayama #+# #+# */ -/* Updated: 2026/01/16 13:59:52 by kjikuhar ### ########.fr */ +/* Updated: 2026/04/17 21:22:08 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ #include "prompt.h" #include "signal_handler.h" -void prompt(void (*handler)(char *input, t_shell_table *shell_table), - t_shell_table *shell_table) +void prompt(int (*handler)(char *input, t_shell_table *shell_table, + int last_status), t_shell_table *shell_table) { char *input; + int last_status; + last_status = 0; while (1) { input = readline(PROMPT); @@ -34,7 +36,7 @@ void prompt(void (*handler)(char *input, t_shell_table *shell_table), if (*input) add_history(input); if (handler) - handler(input, shell_table); + last_status = handler(input, shell_table, last_status); } rl_clear_history(); } From ede8631ace08541d4a1da2b8d19a90dba91a60e7 Mon Sep 17 00:00:00 2001 From: jiku0730 Date: Fri, 17 Apr 2026 21:32:03 +0900 Subject: [PATCH 158/173] =?UTF-8?q?chore:=20expand=E5=B1=A4=E3=81=A8Header?= =?UTF-8?q?=E3=81=AE=E9=96=A2=E6=95=B0=E3=81=AE=E9=A0=86=E7=95=AA=E3=82=92?= =?UTF-8?q?=E5=90=88=E3=82=8F=E3=81=9B=E3=81=9F=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- includes/expand.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/includes/expand.h b/includes/expand.h index 408b22b..9d39677 100644 --- a/includes/expand.h +++ b/includes/expand.h @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/03/03 17:13:55 by surayama #+# #+# */ -/* Updated: 2026/04/17 21:11:14 by kjikuhar ### ########.fr */ +/* Updated: 2026/04/17 21:31:58 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,8 +19,9 @@ # include t_list *expand(t_list *tokens, t_shell_table *shell_table, int last_status); -t_list *expand_parameter(t_list *tokens, t_shell_table *shell_table); t_list *expand_tilde(t_list *tokens, t_shell_table *shell_table); +t_list *expand_question(t_list *tokens, int last_exit_status); +t_list *expand_parameter(t_list *tokens, t_shell_table *shell_table); t_list *expand_wildcard(t_list *tokens); t_list *expand_remove_quotes(t_list *tokens); t_list *expand_question(t_list *tokens, int last_exit_status); From 873cf3590e44e9f9e04546d257053c5478f641c7 Mon Sep 17 00:00:00 2001 From: jiku0730 Date: Fri, 17 Apr 2026 21:34:12 +0900 Subject: [PATCH 159/173] =?UTF-8?q?fix:=20includes/prompt.h=E3=81=AENorm?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- includes/prompt.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/prompt.h b/includes/prompt.h index aa86e82..ae26d84 100644 --- a/includes/prompt.h +++ b/includes/prompt.h @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/01 15:35:18 by surayama #+# #+# */ -/* Updated: 2026/04/17 21:22:24 by kjikuhar ### ########.fr */ +/* Updated: 2026/04/17 21:35:51 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,6 +22,6 @@ # include void prompt(int (*handler)(char *input, t_shell_table *shell_table, - int last_status), t_shell_table *shell_table); + int last_status), t_shell_table *shell_table); #endif From 51b5d51b1192c069ab9035c751a071ef8f7208d5 Mon Sep 17 00:00:00 2001 From: urassh Date: Fri, 17 Apr 2026 22:08:57 +0900 Subject: [PATCH 160/173] =?UTF-8?q?feat:=20export=20=E3=82=B3=E3=83=9E?= =?UTF-8?q?=E3=83=B3=E3=83=89=E3=82=92=20bash=20=E4=BA=92=E6=8F=9B?= =?UTF-8?q?=E3=81=AB=E6=94=B9=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - declare -x プレフィックス付きで一覧表示 - export FOO (値なし) と export FOO= (空文字) を区別 - 不正な識別子にエラーメッセージを表示 Co-Authored-By: Claude Opus 4.6 (1M context) --- Makefile | 1 + includes/builtin.h | 1 + includes/prompt.h | 3 +- src/builtin/export/export.c | 53 +++++++++++------------- src/builtin/export/export_errors.c | 21 ++++++++++ src/component/shell_table/shell_insert.c | 15 ++++--- src/component/shell_table/shell_print.c | 7 ++-- 7 files changed, 61 insertions(+), 40 deletions(-) create mode 100644 src/builtin/export/export_errors.c diff --git a/Makefile b/Makefile index 45bf8a6..8cb6eb5 100644 --- a/Makefile +++ b/Makefile @@ -59,6 +59,7 @@ LIBFT_A := $(LIBFT_DIR)/libft.a SRCS_MAND := src/main.c \ src/builtin/echo/echo.c \ src/builtin/export/export.c \ + src/builtin/export/export_errors.c \ src/builtin/pwd/pwd.c \ src/builtin/unset/unset.c \ src/builtin/cd/cd.c \ diff --git a/includes/builtin.h b/includes/builtin.h index 4d0ce5a..68e3ef0 100644 --- a/includes/builtin.h +++ b/includes/builtin.h @@ -25,5 +25,6 @@ int export(t_list *argv, t_shell_table *shell_table); int unset(t_list *argv, t_shell_table *shell_table); int cd(t_list *argv, t_shell_table *shell_table); int builtin_exit(t_list *argv, t_shell_table *shell_table); +void print_export_error(const char *assignment); #endif diff --git a/includes/prompt.h b/includes/prompt.h index ae26d84..7d97419 100644 --- a/includes/prompt.h +++ b/includes/prompt.h @@ -6,7 +6,7 @@ /* By: kjikuhar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/10/01 15:35:18 by surayama #+# #+# */ -/* Updated: 2026/04/17 21:35:51 by kjikuhar ### ########.fr */ +/* Updated: 2026/04/17 21:33:50 by kjikuhar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -23,5 +23,4 @@ void prompt(int (*handler)(char *input, t_shell_table *shell_table, int last_status), t_shell_table *shell_table); - #endif diff --git a/src/builtin/export/export.c b/src/builtin/export/export.c index 8812355..65b92fd 100644 --- a/src/builtin/export/export.c +++ b/src/builtin/export/export.c @@ -15,8 +15,9 @@ static void skip_head_node(t_list **argv); static int insert_assignment(t_shell_table *shell_table, const char *assignment); +static int insert_key_value(t_shell_table *shell_table, + const char *key, const char *assignment); static char *get_key_from_assignment(const char *assignment); -static char *get_value_from_assignment(const char *assignment); int export(t_list *argv, t_shell_table *shell_table) { @@ -48,7 +49,6 @@ static int insert_assignment(t_shell_table *shell_table, const char *assignment) { char *key; - char *value; int result; if (!shell_table || !assignment) @@ -56,23 +56,35 @@ static int insert_assignment(t_shell_table *shell_table, key = get_key_from_assignment(assignment); if (!key) return (ERROR); - value = get_value_from_assignment(assignment); - if (!value) - { - free(key); - return (ERROR); - } - if (value[0] == '\0') + if (!ft_strchr(assignment, '=')) result = st_set_exported(shell_table, key); else - result = st_insert(shell_table, key, value, true); + result = insert_key_value(shell_table, key, assignment); free(key); - free(value); - if (!result) + if (result <= 0) + { + print_export_error(assignment); return (ERROR); + } return (SUCCESS); } +static int insert_key_value(t_shell_table *shell_table, + const char *key, const char *assignment) +{ + char *equal_pos; + char *value; + int result; + + equal_pos = ft_strchr(assignment, '='); + value = ft_strdup(equal_pos + 1); + if (!value) + return (ERROR); + result = st_insert(shell_table, key, value, true); + free(value); + return (result); +} + static char *get_key_from_assignment(const char *assignment) { char *equal_sign_pos; @@ -84,20 +96,3 @@ static char *get_key_from_assignment(const char *assignment) key_len = equal_sign_pos - assignment; return (ft_substr(assignment, 0, key_len)); } - -static char *get_value_from_assignment(const char *assignment) -{ - char *equal_sign_pos; - char *value; - - equal_sign_pos = ft_strchr(assignment, '='); - if (!equal_sign_pos) - { - value = (char *)ft_calloc(1, sizeof(char)); - if (!value) - return (NULL); - return (value); - } - value = ft_strdup(equal_sign_pos + 1); - return (value); -} diff --git a/src/builtin/export/export_errors.c b/src/builtin/export/export_errors.c new file mode 100644 index 0000000..0de2d80 --- /dev/null +++ b/src/builtin/export/export_errors.c @@ -0,0 +1,21 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* export_errors.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/17 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/04/17 00:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "builtin.h" + +void print_export_error(const char *assignment) +{ + ft_putstr_fd(SHELL_NAME, STDERR_FILENO); + ft_putstr_fd(": export: `", STDERR_FILENO); + ft_putstr_fd((char *)assignment, STDERR_FILENO); + ft_putendl_fd("': not a valid identifier", STDERR_FILENO); +} diff --git a/src/component/shell_table/shell_insert.c b/src/component/shell_table/shell_insert.c index f24873e..e06eb06 100644 --- a/src/component/shell_table/shell_insert.c +++ b/src/component/shell_table/shell_insert.c @@ -44,12 +44,15 @@ static t_shell_node *create_node(const char *key, const char *value, free(node); return (NULL); } - node->value = ft_strdup(value); - if (!node->value) + if (value) { - free(node->key); - free(node); - return (NULL); + node->value = ft_strdup(value); + if (!node->value) + { + free(node->key); + free(node); + return (NULL); + } } node->exported = exported; return (node); @@ -112,7 +115,7 @@ int st_set_exported(t_shell_table *table, const char *key) } node = node->next; } - new_node = create_node(key, "", true); + new_node = create_node(key, NULL, true); if (!new_node) return (0); new_node->next = table->buckets[index]; diff --git a/src/component/shell_table/shell_print.c b/src/component/shell_table/shell_print.c index abef1ea..a741d4b 100644 --- a/src/component/shell_table/shell_print.c +++ b/src/component/shell_table/shell_print.c @@ -25,10 +25,11 @@ void st_print_env(t_shell_table *table) { if (node->exported) { - if (node->value && node->value[0] != '\0') - printf("%s=%s\n", node->key, node->value); + if (node->value) + printf("declare -x %s=\"%s\"\n", + node->key, node->value); else - printf("%s=''\n", node->key); + printf("declare -x %s\n", node->key); } node = node->next; } From 8bf1ed2b7e0963d15c61e515d62817fa5823247b Mon Sep 17 00:00:00 2001 From: urassh Date: Thu, 16 Apr 2026 21:21:58 +0900 Subject: [PATCH 161/173] =?UTF-8?q?fix:=20=E3=83=AA=E3=83=80=E3=82=A4?= =?UTF-8?q?=E3=83=AC=E3=82=AF=E3=83=88=E3=81=8C=E8=A6=AA=E3=83=97=E3=83=AD?= =?UTF-8?q?=E3=82=BB=E3=82=B9=E3=81=AE=20fd=20=E3=82=92=E5=A3=8A=E3=81=99?= =?UTF-8?q?=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 外部コマンドのリダイレクトは子プロセスのみで実行し、 ビルトインのリダイレクトは dup で fd を保存・復元するよう変更。 cmd_not_found と exec_external_cmd を find_exec_path.c に移動。 Co-Authored-By: Claude Opus 4.6 (1M context) --- Makefile | 1 + includes/execute.h | 2 + src/execute/command/exec_external_cmd.c | 60 ++++++++++++++++++ src/execute/exec_cmd.c | 84 ++++++++++--------------- 4 files changed, 95 insertions(+), 52 deletions(-) create mode 100644 src/execute/command/exec_external_cmd.c diff --git a/Makefile b/Makefile index 8cb6eb5..7efe168 100644 --- a/Makefile +++ b/Makefile @@ -107,6 +107,7 @@ SRCS_MAND := src/main.c \ src/execute/utils/ft_wexitstatus.c \ src/execute/utils/ft_wifexited.c \ src/execute/command/find_exec_path.c \ + src/execute/command/exec_external_cmd.c \ src/execute/command/exec_builtin_cmd.c \ src/execute/command/list_to_argv.c \ src/execute/pipe/exec_pipe_child.c \ diff --git a/includes/execute.h b/includes/execute.h index 4e24a39..036acb6 100644 --- a/includes/execute.h +++ b/includes/execute.h @@ -24,6 +24,8 @@ int exec_builtin_cmd(t_ast *node, t_shell_table *shell_table); int exec_cmd(t_ast *node, t_shell_table *shell_table); char *find_exec_path(const char *cmd, \ t_shell_table *shell_table); +int exec_external_cmd(char **argv, \ + t_shell_table *shell_table); int exec_pipe(t_ast *node, t_shell_table *shell_table); void exec_left_child(t_ast *node, \ t_shell_table *shell_table, int fd[2]); diff --git a/src/execute/command/exec_external_cmd.c b/src/execute/command/exec_external_cmd.c new file mode 100644 index 0000000..190e410 --- /dev/null +++ b/src/execute/command/exec_external_cmd.c @@ -0,0 +1,60 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_external_cmd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/16 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/04/16 00:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "execute.h" + +static int cmd_not_found(char **argv) +{ + if (ft_strchr(argv[0], '/')) + { + if (access(argv[0], F_OK) == 0) + { + ft_putstr_fd("jikussh: ", STDERR_FILENO); + perror(argv[0]); + ft_free_array((void **)argv); + return (126); + } + ft_putstr_fd("jikussh: ", STDERR_FILENO); + perror(argv[0]); + ft_free_array((void **)argv); + return (127); + } + ft_putstr_fd("jikussh: ", STDERR_FILENO); + ft_putstr_fd(argv[0], STDERR_FILENO); + ft_putstr_fd(": command not found\n", STDERR_FILENO); + ft_free_array((void **)argv); + return (127); +} + +int exec_external_cmd(char **argv, t_shell_table *shell_table) +{ + char *cmd_path; + char **new_envp; + + cmd_path = find_exec_path(argv[0], shell_table); + if (!cmd_path) + return (cmd_not_found(argv)); + new_envp = export_envp(shell_table); + if (!new_envp) + { + free(cmd_path); + ft_free_array((void **)argv); + return (1); + } + execve(cmd_path, argv, new_envp); + perror(cmd_path); + free(cmd_path); + st_destroy(shell_table); + ft_free_array((void **)new_envp); + ft_free_array((void **)argv); + return (127); +} diff --git a/src/execute/exec_cmd.c b/src/execute/exec_cmd.c index b03ccd2..f1459e5 100644 --- a/src/execute/exec_cmd.c +++ b/src/execute/exec_cmd.c @@ -11,53 +11,7 @@ /* ************************************************************************** */ #include "execute.h" - -static int cmd_not_found(char **argv) -{ - if (ft_strchr(argv[0], '/')) - { - if (access(argv[0], F_OK) == 0) - { - ft_putstr_fd("jikussh: ", STDERR_FILENO); - perror(argv[0]); - ft_free_array((void **)argv); - return (126); - } - ft_putstr_fd("jikussh: ", STDERR_FILENO); - perror(argv[0]); - ft_free_array((void **)argv); - return (127); - } - ft_putstr_fd("jikussh: ", STDERR_FILENO); - ft_putstr_fd(argv[0], STDERR_FILENO); - ft_putstr_fd(": command not found\n", STDERR_FILENO); - ft_free_array((void **)argv); - return (127); -} - -static int exec_external_cmd(char **argv, t_shell_table *shell_table) -{ - char *cmd_path; - char **new_envp; - - cmd_path = find_exec_path(argv[0], shell_table); - if (!cmd_path) - return (cmd_not_found(argv)); - new_envp = export_envp(shell_table); - if (!new_envp) - { - free(cmd_path); - ft_free_array((void **)argv); - return (1); - } - execve(cmd_path, argv, new_envp); - perror(cmd_path); - free(cmd_path); - st_destroy(shell_table); - ft_free_array((void **)new_envp); - ft_free_array((void **)argv); - return (127); -} +#include "signal_handler.h" static int fork_and_exec(t_ast *node, t_shell_table *shell_table) { @@ -84,17 +38,43 @@ static int fork_and_exec(t_ast *node, t_shell_table *shell_table) return (1); } -int exec_cmd(t_ast *node, t_shell_table *shell_table) +static void restore_fds(int saved_in, int saved_out) { - int status; + dup2(saved_in, STDIN_FILENO); + dup2(saved_out, STDOUT_FILENO); + close(saved_in); + close(saved_out); +} + +static int exec_builtin_with_redir(t_ast *node, t_shell_table *st) +{ + int saved_in; + int saved_out; + int status; - if (node->cmd->redirs) + saved_in = dup(STDIN_FILENO); + saved_out = dup(STDOUT_FILENO); + if (node->cmd->redirs + && exec_redirs(node->cmd->redirs) != 0) { - if (exec_redirs(node->cmd->redirs) != 0) - return (1); + restore_fds(saved_in, saved_out); + return (1); } + status = exec_builtin_cmd(node, st); + restore_fds(saved_in, saved_out); + return (status); +} + +int exec_cmd(t_ast *node, t_shell_table *shell_table) +{ + int status; + status = exec_builtin_cmd(node, shell_table); if (status != -1) + { + if (node->cmd->redirs) + return (exec_builtin_with_redir(node, shell_table)); return (status); + } return (fork_and_exec(node, shell_table)); } From b50445f4af9b7cfb84d1b2d6e9639bec8cfe00c2 Mon Sep 17 00:00:00 2001 From: urassh Date: Fri, 17 Apr 2026 22:43:07 +0900 Subject: [PATCH 162/173] =?UTF-8?q?fix:=20=E3=83=93=E3=83=AB=E3=83=88?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E5=88=A4=E5=AE=9A=E3=82=92=E5=AE=9F=E8=A1=8C?= =?UTF-8?q?=E5=89=8D=E3=81=AB=E8=A1=8C=E3=81=84=E4=BA=8C=E9=87=8D=E5=AE=9F?= =?UTF-8?q?=E8=A1=8C=E3=82=92=E9=98=B2=E6=AD=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 (1M context) --- src/execute/exec_cmd.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/execute/exec_cmd.c b/src/execute/exec_cmd.c index f1459e5..4699843 100644 --- a/src/execute/exec_cmd.c +++ b/src/execute/exec_cmd.c @@ -65,16 +65,30 @@ static int exec_builtin_with_redir(t_ast *node, t_shell_table *st) return (status); } -int exec_cmd(t_ast *node, t_shell_table *shell_table) +static bool is_builtin(t_ast *node) { - int status; + static const char *builtins[] = {"echo", "pwd", "cd", + "export", "unset", "exit", NULL}; + int i; + char *name; - status = exec_builtin_cmd(node, shell_table); - if (status != -1) + if (!node->cmd->argv || !node->cmd->argv->content) + return (false); + name = (char *)node->cmd->argv->content; + i = 0; + while (builtins[i]) { - if (node->cmd->redirs) - return (exec_builtin_with_redir(node, shell_table)); - return (status); + if (ft_strncmp(name, builtins[i], + ft_strlen(builtins[i]) + 1) == 0) + return (true); + i++; } + return (false); +} + +int exec_cmd(t_ast *node, t_shell_table *shell_table) +{ + if (is_builtin(node)) + return (exec_builtin_with_redir(node, shell_table)); return (fork_and_exec(node, shell_table)); } From 73b182188796201522bfb1efd78345a67850560d Mon Sep 17 00:00:00 2001 From: urassh Date: Fri, 17 Apr 2026 23:00:16 +0900 Subject: [PATCH 163/173] =?UTF-8?q?fix:=20=E3=83=AA=E3=83=80=E3=82=A4?= =?UTF-8?q?=E3=83=AC=E3=82=AF=E3=83=88=E3=81=AE=E3=83=91=E3=83=BC=E3=82=B9?= =?UTF-8?q?=E5=88=A4=E5=AE=9A=E3=81=A8printf=20=E3=83=90=E3=83=83=E3=83=95?= =?UTF-8?q?=E3=82=A1=E3=83=95=E3=83=A9=E3=83=83=E3=82=B7=E3=83=A5=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - parse_redir の戻り値判定を !result から == ERROR に修正 - ビルトイン実行後に fflush(stdout) を追加し fd 復元前にバッファを確実にフラッシュ Co-Authored-By: Claude Opus 4.6 (1M context) --- src/execute/exec_cmd.c | 1 + src/parse/parse.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/execute/exec_cmd.c b/src/execute/exec_cmd.c index 4699843..ed93a03 100644 --- a/src/execute/exec_cmd.c +++ b/src/execute/exec_cmd.c @@ -61,6 +61,7 @@ static int exec_builtin_with_redir(t_ast *node, t_shell_table *st) return (1); } status = exec_builtin_cmd(node, st); + fflush(stdout); restore_fds(saved_in, saved_out); return (status); } diff --git a/src/parse/parse.c b/src/parse/parse.c index 7553bc4..2b29f77 100644 --- a/src/parse/parse.c +++ b/src/parse/parse.c @@ -51,7 +51,7 @@ static t_ast *parse_cmd(t_list **current) { if (is_redir(*current)) { - if (!parse_redir(current, cmd)) + if (parse_redir(current, cmd) == ERROR) return (free_cmd(cmd), NULL); } else if (is_word(*current)) From dbbac714316037d43d0c0884f15923db7528b7e5 Mon Sep 17 00:00:00 2001 From: urassh Date: Fri, 17 Apr 2026 23:30:59 +0900 Subject: [PATCH 164/173] =?UTF-8?q?refactor:=20exec=5Fcmd=20=E3=81=8B?= =?UTF-8?q?=E3=82=89=20expand=20=E5=91=BC=E3=81=B3=E5=87=BA=E3=81=97?= =?UTF-8?q?=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit on_input で展開済みのため exec_cmd 内の expand/expand_redir_filenames は不要。 expand_redirs.c も削除。 Co-Authored-By: Claude Opus 4.6 (1M context) --- Makefile | 1 - includes/execute.h | 2 -- src/execute/exec_cmd.c | 4 --- src/execute/redirects/expand_redirs.c | 45 --------------------------- 4 files changed, 52 deletions(-) delete mode 100644 src/execute/redirects/expand_redirs.c diff --git a/Makefile b/Makefile index 1d0bfea..5a9291e 100644 --- a/Makefile +++ b/Makefile @@ -112,7 +112,6 @@ SRCS_MAND := src/main.c \ src/execute/command/list_to_argv.c \ src/execute/pipe/exec_pipe_child.c \ src/execute/redirects/exec_redirs.c \ - src/execute/redirects/expand_redirs.c \ src/component/directory/list_directory.c \ src/component/directory/list_directory_recursive.c \ src/component/path/to_absolute_path.c \ diff --git a/includes/execute.h b/includes/execute.h index a1db226..4e24a39 100644 --- a/includes/execute.h +++ b/includes/execute.h @@ -30,8 +30,6 @@ void exec_left_child(t_ast *node, \ void exec_right_child(t_ast *node, \ t_shell_table *shell_table, int fd[2]); int exec_redirs(t_list *redirs); -void expand_redir_filenames(t_list *redirs, \ - t_shell_table *shell_table); char **list_to_argv(t_list *lst); int ft_wifexited(int exit_status); int ft_wexitstatus(int exit_status); diff --git a/src/execute/exec_cmd.c b/src/execute/exec_cmd.c index ca51c91..b03ccd2 100644 --- a/src/execute/exec_cmd.c +++ b/src/execute/exec_cmd.c @@ -11,7 +11,6 @@ /* ************************************************************************** */ #include "execute.h" -#include "expand.h" static int cmd_not_found(char **argv) { @@ -89,9 +88,6 @@ int exec_cmd(t_ast *node, t_shell_table *shell_table) { int status; - node->cmd->argv = expand(node->cmd->argv, shell_table); - if (node->cmd->redirs) - expand_redir_filenames(node->cmd->redirs, shell_table); if (node->cmd->redirs) { if (exec_redirs(node->cmd->redirs) != 0) diff --git a/src/execute/redirects/expand_redirs.c b/src/execute/redirects/expand_redirs.c deleted file mode 100644 index 8dfbd68..0000000 --- a/src/execute/redirects/expand_redirs.c +++ /dev/null @@ -1,45 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* expand_redirs.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: surayama +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2026/04/16 00:00:00 by surayama #+# #+# */ -/* Updated: 2026/04/16 00:00:00 by surayama ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "execute.h" -#include "expand.h" - -static void expand_one_filename(t_redir *redir, t_shell_table *st) -{ - t_list *tmp; - char *expanded; - - tmp = ft_lstnew(ft_strdup(redir->filename)); - if (!tmp) - return ; - tmp = expand(tmp, st); - if (!tmp) - return ; - expanded = ft_strdup((char *)tmp->content); - ft_lstclear(&tmp, free); - if (!expanded) - return ; - free(redir->filename); - redir->filename = expanded; -} - -void expand_redir_filenames(t_list *redirs, t_shell_table *st) -{ - t_redir *redir; - - while (redirs) - { - redir = (t_redir *)redirs->content; - expand_one_filename(redir, st); - redirs = redirs->next; - } -} From 2738a92003b742feda059e587a6e27e1da481542 Mon Sep 17 00:00:00 2001 From: urassh Date: Sat, 18 Apr 2026 12:16:55 +0900 Subject: [PATCH 165/173] =?UTF-8?q?fix:=20=E3=83=93=E3=83=AB=E3=83=88?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E5=87=BA=E5=8A=9B=E3=82=92write=E3=81=AB?= =?UTF-8?q?=E5=A4=89=E6=9B=B4=E3=81=97=E3=82=B5=E3=83=96=E3=82=B7=E3=82=A7?= =?UTF-8?q?=E3=83=AB=E3=81=AE=E3=82=B7=E3=82=B0=E3=83=8A=E3=83=AB=E5=88=B6?= =?UTF-8?q?=E5=BE=A1=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - echo/pwdのprintfをft_putstr_fd/writeに置換しリダイレクト時のバッファ問題を解消 - exec_subshellにシグナルハンドリング(default/ignore/interactive)を追加 - exec_builtin_with_redirから禁止関数fflushを削除 Co-Authored-By: Claude Opus 4.6 (1M context) --- src/builtin/echo/echo.c | 6 +++--- src/builtin/pwd/pwd.c | 3 ++- src/execute/exec_ast.c | 8 +++++++- src/execute/exec_cmd.c | 1 - 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/builtin/echo/echo.c b/src/builtin/echo/echo.c index b99f194..cd8c6aa 100644 --- a/src/builtin/echo/echo.c +++ b/src/builtin/echo/echo.c @@ -71,12 +71,12 @@ static void print_argv(t_list *to_print_argv, bool with_newline) { if (current->content) { - printf("%s", (char *)current->content); + ft_putstr_fd((char *)current->content, STDOUT_FILENO); if (current->next) - printf(" "); + write(STDOUT_FILENO, " ", 1); } current = current->next; } if (with_newline) - printf("\n"); + write(STDOUT_FILENO, "\n", 1); } diff --git a/src/builtin/pwd/pwd.c b/src/builtin/pwd/pwd.c index 8215c29..f4ee161 100644 --- a/src/builtin/pwd/pwd.c +++ b/src/builtin/pwd/pwd.c @@ -24,7 +24,8 @@ int pwd(t_list *argv, t_shell_table *shell_table) perror("pwd"); return (EXIT_FAILURE); } - printf("%s\n", pwd_path); + ft_putstr_fd(pwd_path, STDOUT_FILENO); + write(STDOUT_FILENO, "\n", 1); free(pwd_path); return (EXIT_SUCCESS); } diff --git a/src/execute/exec_ast.c b/src/execute/exec_ast.c index ae01a00..064398e 100644 --- a/src/execute/exec_ast.c +++ b/src/execute/exec_ast.c @@ -11,6 +11,7 @@ /* ************************************************************************** */ #include "execute.h" +#include "signal_handler.h" static int exec_logical(t_ast *node, t_shell_table *shell_table) { @@ -33,11 +34,16 @@ static int exec_subshell(t_ast *node, t_shell_table *shell_table) if (pid < 0) return (perror("fork"), 1); if (pid == 0) + { + set_signal_default(); exit(exec_ast(node->right, shell_table)); + } + set_signal_ignore(); waitpid(pid, &wstatus, 0); + set_signal_interactive(); if (ft_wifexited(wstatus)) return (ft_wexitstatus(wstatus)); - return (1); + return (128 + WTERMSIG(wstatus)); } int exec_ast(t_ast *node, t_shell_table *shell_table) diff --git a/src/execute/exec_cmd.c b/src/execute/exec_cmd.c index c83de59..9363cc8 100644 --- a/src/execute/exec_cmd.c +++ b/src/execute/exec_cmd.c @@ -64,7 +64,6 @@ static int exec_builtin_with_redir(t_ast *node, t_shell_table *st) return (1); } status = exec_builtin_cmd(node, st); - fflush(stdout); restore_fds(saved_in, saved_out); return (status); } From 7392b7f75eb11cab6069dfb6442c2a4e0f02eeda Mon Sep 17 00:00:00 2001 From: urassh Date: Sat, 18 Apr 2026 12:19:08 +0900 Subject: [PATCH 166/173] =?UTF-8?q?fix:=20parse=5Fcmd=E3=81=AEnorminette?= =?UTF-8?q?=E9=81=95=E5=8F=8D=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit parse_tokenとis_cmd_endを分離して25行制限に対応。 Co-Authored-By: Claude Opus 4.6 (1M context) --- src/parse/parse.c | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/src/parse/parse.c b/src/parse/parse.c index 0e132f9..b6bddae 100644 --- a/src/parse/parse.c +++ b/src/parse/parse.c @@ -39,6 +39,30 @@ static int parse_redir(t_list **current, t_cmd *cmd) return (SUCCESS); } +static int parse_token(t_list **current, t_cmd *cmd) +{ + if (is_redir(*current)) + { + if (parse_redir(current, cmd) == ERROR) + return (ERROR); + } + else if (is_word(*current)) + { + if (!add_argv_to_cmd(cmd, (*current)->content)) + return (ERROR); + } + *current = (*current)->next; + return (SUCCESS); +} + +static bool is_cmd_end(t_list *current) +{ + if (!current) + return (true); + return (is_symbol(current, "|") || is_symbol(current, "&&") + || is_symbol(current, "||") || is_symbol(current, ")")); +} + t_ast *parse_cmd(t_list **current) { t_ast *ast; @@ -47,22 +71,10 @@ t_ast *parse_cmd(t_list **current) cmd = new_cmd(); if (!cmd) return (NULL); - while (*current && !is_symbol(*current, "|") - && !is_symbol(*current, "&&") - && !is_symbol(*current, "||") - && !is_symbol(*current, ")")) + while (!is_cmd_end(*current)) { - if (is_redir(*current)) - { - if (parse_redir(current, cmd) == ERROR) - return (free_cmd(cmd), NULL); - } - else if (is_word(*current)) - { - if (!add_argv_to_cmd(cmd, (*current)->content)) - return (free_cmd(cmd), NULL); - } - *current = (*current)->next; + if (parse_token(current, cmd) == ERROR) + return (free_cmd(cmd), NULL); } ast = new_ast_node(CMD); if (!ast) @@ -70,4 +82,3 @@ t_ast *parse_cmd(t_list **current) ast->cmd = cmd; return (ast); } - From b0bd7f93d186ca262ebe0d6c85d4fa6b65349f2a Mon Sep 17 00:00:00 2001 From: urassh Date: Sat, 18 Apr 2026 12:45:29 +0900 Subject: [PATCH 167/173] =?UTF-8?q?fix:=20=E3=83=87=E3=82=A3=E3=83=AC?= =?UTF-8?q?=E3=82=AF=E3=83=88=E3=83=AA=E5=AE=9F=E8=A1=8C=E6=99=82=E3=81=AE?= =?UTF-8?q?=E3=82=A8=E3=83=A9=E3=83=BC=E5=87=A6=E7=90=86=E3=81=A8expand?= =?UTF-8?q?=E3=81=AE=E3=82=B3=E3=83=9E=E3=83=B3=E3=83=89=E5=8D=98=E4=BD=8D?= =?UTF-8?q?=E5=AE=9F=E8=A1=8C=E3=81=B8=E3=81=AE=E7=A7=BB=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ディレクトリをコマンドとして実行した際に "Is a directory" エラー(終了ステータス126)を 正しく返すように修正。また、変数展開をパイプライン全体の一括処理からコマンド単位の 実行時展開に変更し、export FOO=bar && echo $FOO が正しく動作するようにした。 Co-Authored-By: Claude Opus 4.6 (1M context) --- Makefile | 1 + includes/expand.h | 2 + includes/shell_table.h | 1 + src/callback/on_input.c | 4 +- src/execute/command/exec_external_cmd.c | 24 ++++++--- src/execute/command/find_exec_path.c | 12 ++++- src/execute/exec_cmd.c | 3 ++ src/expand/expand_cmd.c | 67 +++++++++++++++++++++++++ 8 files changed, 104 insertions(+), 10 deletions(-) create mode 100644 src/expand/expand_cmd.c diff --git a/Makefile b/Makefile index 178d117..d2d47eb 100644 --- a/Makefile +++ b/Makefile @@ -121,6 +121,7 @@ SRCS_MAND := src/main.c \ src/component/path/append_path.c \ src/component/path/resolve_relative_path.c \ src/expand/expand.c \ + src/expand/expand_cmd.c \ src/expand/expand_parameter/expand_parameter.c \ src/expand/expand_parameter/state/in_normal_expand.c \ src/expand/expand_parameter/state/in_double_quote_expand.c \ diff --git a/includes/expand.h b/includes/expand.h index 9d39677..5c93620 100644 --- a/includes/expand.h +++ b/includes/expand.h @@ -15,10 +15,12 @@ # include "constants.h" # include "libft.h" +# include "parse.h" # include "shell_table.h" # include t_list *expand(t_list *tokens, t_shell_table *shell_table, int last_status); +int expand_cmd(t_cmd *cmd, t_shell_table *shell_table); t_list *expand_tilde(t_list *tokens, t_shell_table *shell_table); t_list *expand_question(t_list *tokens, int last_exit_status); t_list *expand_parameter(t_list *tokens, t_shell_table *shell_table); diff --git a/includes/shell_table.h b/includes/shell_table.h index 6d127b4..2c91ebc 100644 --- a/includes/shell_table.h +++ b/includes/shell_table.h @@ -33,6 +33,7 @@ typedef struct s_shell_table t_shell_node **buckets; size_t size; size_t n_nodes; + int last_status; } t_shell_table; // shell_table operations diff --git a/src/callback/on_input.c b/src/callback/on_input.c index 43525c3..7d2e115 100644 --- a/src/callback/on_input.c +++ b/src/callback/on_input.c @@ -26,9 +26,7 @@ int on_input(char *input, t_shell_table *shell_table, int last_status) ft_lstclear(&tokens, free); return (130); } - tokens = expand(tokens, shell_table, last_status); - if (!tokens) - return (1); + shell_table->last_status = last_status; ast = parse(tokens); ft_lstclear(&tokens, free); if (!ast) diff --git a/src/execute/command/exec_external_cmd.c b/src/execute/command/exec_external_cmd.c index 190e410..0ecd222 100644 --- a/src/execute/command/exec_external_cmd.c +++ b/src/execute/command/exec_external_cmd.c @@ -11,18 +11,30 @@ /* ************************************************************************** */ #include "execute.h" +#include + +static int cmd_path_error(char **argv) +{ + struct stat sb; + + ft_putstr_fd("jikussh: ", STDERR_FILENO); + if (stat(argv[0], &sb) == 0 && S_ISDIR(sb.st_mode)) + { + ft_putstr_fd(argv[0], STDERR_FILENO); + ft_putstr_fd(": Is a directory\n", STDERR_FILENO); + } + else + perror(argv[0]); + ft_free_array((void **)argv); + return (126); +} static int cmd_not_found(char **argv) { if (ft_strchr(argv[0], '/')) { if (access(argv[0], F_OK) == 0) - { - ft_putstr_fd("jikussh: ", STDERR_FILENO); - perror(argv[0]); - ft_free_array((void **)argv); - return (126); - } + return (cmd_path_error(argv)); ft_putstr_fd("jikussh: ", STDERR_FILENO); perror(argv[0]); ft_free_array((void **)argv); diff --git a/src/execute/command/find_exec_path.c b/src/execute/command/find_exec_path.c index 7cca762..bfe86e5 100644 --- a/src/execute/command/find_exec_path.c +++ b/src/execute/command/find_exec_path.c @@ -12,6 +12,16 @@ #include "execute.h" #include "path.h" +#include + +static int is_directory(const char *path) +{ + struct stat sb; + + if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) + return (1); + return (0); +} static char *find_in_path(const char *cmd, t_shell_table *shell_table) { @@ -47,7 +57,7 @@ char *find_exec_path(const char *cmd, t_shell_table *shell_table) return (NULL); if (ft_strchr(cmd, '/')) { - if (access(cmd, X_OK) == 0) + if (access(cmd, X_OK) == 0 && !is_directory(cmd)) return (ft_strdup(cmd)); return (NULL); } diff --git a/src/execute/exec_cmd.c b/src/execute/exec_cmd.c index 9363cc8..1808d27 100644 --- a/src/execute/exec_cmd.c +++ b/src/execute/exec_cmd.c @@ -11,6 +11,7 @@ /* ************************************************************************** */ #include "execute.h" +#include "expand.h" #include "signal_handler.h" static int fork_and_exec(t_ast *node, t_shell_table *shell_table) @@ -91,6 +92,8 @@ static bool is_builtin(t_ast *node) int exec_cmd(t_ast *node, t_shell_table *shell_table) { + if (expand_cmd(node->cmd, shell_table) == ERROR) + return (1); if (is_builtin(node)) return (exec_builtin_with_redir(node, shell_table)); return (fork_and_exec(node, shell_table)); diff --git a/src/expand/expand_cmd.c b/src/expand/expand_cmd.c new file mode 100644 index 0000000..9a674be --- /dev/null +++ b/src/expand/expand_cmd.c @@ -0,0 +1,67 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* expand_cmd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/18 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/04/18 00:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "expand.h" +#include "parse.h" + +static int expand_redir_filename(t_redir *redir, t_shell_table *st) +{ + t_list *tmp; + char *dup; + + dup = ft_strdup(redir->filename); + if (!dup) + return (ERROR); + tmp = ft_lstnew(dup); + if (!tmp) + return (free(dup), ERROR); + tmp = expand(tmp, st, st->last_status); + if (!tmp) + return (ERROR); + free(redir->filename); + redir->filename = ft_strdup(tmp->content); + ft_lstclear(&tmp, free); + if (!redir->filename) + return (ERROR); + return (SUCCESS); +} + +static int expand_redirs(t_list *redirs, t_shell_table *st) +{ + t_list *current; + + current = redirs; + while (current) + { + if (expand_redir_filename(current->content, st) == ERROR) + return (ERROR); + current = current->next; + } + return (SUCCESS); +} + +int expand_cmd(t_cmd *cmd, t_shell_table *shell_table) +{ + if (cmd->argv) + { + cmd->argv = expand(cmd->argv, shell_table, + shell_table->last_status); + if (!cmd->argv) + return (ERROR); + } + if (cmd->redirs) + { + if (expand_redirs(cmd->redirs, shell_table) == ERROR) + return (ERROR); + } + return (SUCCESS); +} From ac492e87abec43c76cf81b5cad17621b9bbaa531 Mon Sep 17 00:00:00 2001 From: urassh Date: Sat, 18 Apr 2026 12:53:47 +0900 Subject: [PATCH 168/173] =?UTF-8?q?fix:=20expand=5Fcmd=E5=A4=B1=E6=95=97?= =?UTF-8?q?=E6=99=82=E3=81=AEreturn=E3=82=92-1=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit exit_status=1との混合を避けるため。 Co-Authored-By: Claude Opus 4.6 (1M context) --- src/execute/exec_cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/execute/exec_cmd.c b/src/execute/exec_cmd.c index 1808d27..f761b59 100644 --- a/src/execute/exec_cmd.c +++ b/src/execute/exec_cmd.c @@ -93,7 +93,7 @@ static bool is_builtin(t_ast *node) int exec_cmd(t_ast *node, t_shell_table *shell_table) { if (expand_cmd(node->cmd, shell_table) == ERROR) - return (1); + return (-1); if (is_builtin(node)) return (exec_builtin_with_redir(node, shell_table)); return (fork_and_exec(node, shell_table)); From 63c463d270cb57f753517664d06b1e61d5ae6611 Mon Sep 17 00:00:00 2001 From: urassh Date: Sat, 18 Apr 2026 13:03:46 +0900 Subject: [PATCH 169/173] =?UTF-8?q?fix:=20SIGQUIT=E6=99=82=E3=81=ABQuit:?= =?UTF-8?q?=203=E3=82=92=E8=A1=A8=E7=A4=BA=E3=81=99=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 (1M context) --- src/execute/exec_ast.c | 2 ++ src/execute/exec_cmd.c | 2 ++ src/execute/exec_pipe.c | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/execute/exec_ast.c b/src/execute/exec_ast.c index 064398e..edcc020 100644 --- a/src/execute/exec_ast.c +++ b/src/execute/exec_ast.c @@ -43,6 +43,8 @@ static int exec_subshell(t_ast *node, t_shell_table *shell_table) set_signal_interactive(); if (ft_wifexited(wstatus)) return (ft_wexitstatus(wstatus)); + if (WTERMSIG(wstatus) == SIGQUIT) + ft_putendl_fd("Quit: 3", STDERR_FILENO); return (128 + WTERMSIG(wstatus)); } diff --git a/src/execute/exec_cmd.c b/src/execute/exec_cmd.c index f761b59..395a624 100644 --- a/src/execute/exec_cmd.c +++ b/src/execute/exec_cmd.c @@ -39,6 +39,8 @@ static int fork_and_exec(t_ast *node, t_shell_table *shell_table) set_signal_interactive(); if (ft_wifexited(wstatus)) return (ft_wexitstatus(wstatus)); + if (WTERMSIG(wstatus) == SIGQUIT) + ft_putendl_fd("Quit: 3", STDERR_FILENO); return (128 + WTERMSIG(wstatus)); } diff --git a/src/execute/exec_pipe.c b/src/execute/exec_pipe.c index c609587..f3ff1cd 100644 --- a/src/execute/exec_pipe.c +++ b/src/execute/exec_pipe.c @@ -69,5 +69,7 @@ int exec_pipe(t_ast *node, t_shell_table *shell_table) set_signal_interactive(); if (ft_wifexited(exit_status_right_child)) return (ft_wexitstatus(exit_status_right_child)); + if (WTERMSIG(exit_status_right_child) == SIGQUIT) + ft_putendl_fd("Quit: 3", STDERR_FILENO); return (128 + WTERMSIG(exit_status_right_child)); } From 5748aa069b0cbd7802d7352a8dcff01abd70e514 Mon Sep 17 00:00:00 2001 From: jiku0730 Date: Sat, 18 Apr 2026 12:29:28 +0900 Subject: [PATCH 170/173] =?UTF-8?q?fix:=20Word=E6=84=8F=E5=A4=96=E3=82=92p?= =?UTF-8?q?arse=E3=82=A8=E3=83=A9=E3=83=BC=E3=81=8C=E5=87=BA=E3=82=8B?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E4=BF=AE=E6=AD=A3=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/parse/parse.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/parse/parse.c b/src/parse/parse.c index b6bddae..aefa86e 100644 --- a/src/parse/parse.c +++ b/src/parse/parse.c @@ -51,6 +51,8 @@ static int parse_token(t_list **current, t_cmd *cmd) if (!add_argv_to_cmd(cmd, (*current)->content)) return (ERROR); } + else + return (ERROR); *current = (*current)->next; return (SUCCESS); } From 9a1bb4195bd003817a62446beb6a9a82dbfcaf72 Mon Sep 17 00:00:00 2001 From: urassh Date: Sat, 18 Apr 2026 13:59:10 +0900 Subject: [PATCH 171/173] fix --- includes/prompt.h | 2 +- src/builtin/cd/cd.c | 6 +++- src/builtin/exit/exit.c | 63 +++++++++++++++++++++++++++++++++-------- src/execute/exec_cmd.c | 45 ++++++++++++++--------------- src/execute/exec_pipe.c | 33 ++++++++++++++------- src/main.c | 5 ++-- src/prompt/prompt.c | 3 +- 7 files changed, 106 insertions(+), 51 deletions(-) diff --git a/includes/prompt.h b/includes/prompt.h index 7d97419..f189078 100644 --- a/includes/prompt.h +++ b/includes/prompt.h @@ -21,6 +21,6 @@ # include # include -void prompt(int (*handler)(char *input, t_shell_table *shell_table, +int prompt(int (*handler)(char *input, t_shell_table *shell_table, int last_status), t_shell_table *shell_table); #endif diff --git a/src/builtin/cd/cd.c b/src/builtin/cd/cd.c index aca89ad..1f0f396 100644 --- a/src/builtin/cd/cd.c +++ b/src/builtin/cd/cd.c @@ -71,6 +71,7 @@ static int by_move_to_home(t_shell_table *shell_table) static int by_move_to_oldpwd(t_shell_table *shell_table) { char *oldpwd; + int result; oldpwd = st_search(shell_table, "OLDPWD"); if (!oldpwd) @@ -78,7 +79,10 @@ static int by_move_to_oldpwd(t_shell_table *shell_table) ft_putstr_fd("Error: cd OLDPWD not set\n", STDERR_FILENO); return (1); } - return (move_to_path(oldpwd, shell_table)); + result = move_to_path(oldpwd, shell_table); + if (result == 0) + ft_putendl_fd(oldpwd, STDOUT_FILENO); + return (result); } static int move_to_path(const char *absolute_path, t_shell_table *shell_table) diff --git a/src/builtin/exit/exit.c b/src/builtin/exit/exit.c index 9c87d0a..d0043b2 100644 --- a/src/builtin/exit/exit.c +++ b/src/builtin/exit/exit.c @@ -38,27 +38,66 @@ static void exit_numeric_error(const char *str) exit(2); } -int builtin_exit(t_list *argv, t_shell_table *shell_table) +static long long ft_atoll_check(const char *str, bool *ovf) +{ + long long num; + int sign; + int digit; + + *ovf = false; + sign = 1; + if (*str == '+' || *str == '-') + { + if (*str == '-') + sign = -1; + str++; + } + num = 0; + while (ft_isdigit((unsigned char)*str)) + { + digit = *str - '0'; + if (sign == 1 && num > (LLONG_MAX - digit) / 10) + return (*ovf = true, 0); + if (sign == -1 && num > -(LLONG_MIN + digit) / 10) + return (*ovf = true, 0); + num = num * 10 + digit; + str++; + } + return (num * sign); +} + +static void exit_no_args(t_shell_table *shell_table) { - t_list *args; char *str; + str = st_search(shell_table, "?"); + if (!str) + exit(0); + exit(ft_atoi(str) & 0xFF); +} + +int builtin_exit(t_list *argv, t_shell_table *shell_table) +{ + t_list *args; + char *str; + long long val; + bool ovf; + write(STDOUT_FILENO, "exit\n", 5); args = argv->next; if (!args) - { - str = st_search(shell_table, "?"); - if (!str) - exit(0); - exit(ft_atoi(str) & 0xFF); - } + exit_no_args(shell_table); + str = (char *)args->content; + if (!is_numeric(str)) + exit_numeric_error(str); if (args->next) { - ft_putstr_fd(SHELL_NAME ": exit: too many arguments\n", STDERR_FILENO); + ft_putstr_fd(SHELL_NAME ": exit: too many arguments\n", + STDERR_FILENO); return (1); } - str = (char *)args->content; - if (!is_numeric(str)) + val = ft_atoll_check(str, &ovf); + if (ovf) exit_numeric_error(str); - exit(ft_atoi(str) & 0xFF); + exit((unsigned char)val); } diff --git a/src/execute/exec_cmd.c b/src/execute/exec_cmd.c index 395a624..ee66f8f 100644 --- a/src/execute/exec_cmd.c +++ b/src/execute/exec_cmd.c @@ -14,10 +14,23 @@ #include "expand.h" #include "signal_handler.h" +static int wait_for_child(pid_t pid) +{ + int wstatus; + + set_signal_ignore(); + waitpid(pid, &wstatus, 0); + set_signal_interactive(); + if (ft_wifexited(wstatus)) + return (ft_wexitstatus(wstatus)); + if (WTERMSIG(wstatus) == SIGQUIT) + ft_putendl_fd("Quit: 3", STDERR_FILENO); + return (128 + WTERMSIG(wstatus)); +} + static int fork_and_exec(t_ast *node, t_shell_table *shell_table) { pid_t pid; - int wstatus; char **argv; pid = fork(); @@ -34,22 +47,7 @@ static int fork_and_exec(t_ast *node, t_shell_table *shell_table) exit(127); exit(exec_external_cmd(argv, shell_table)); } - set_signal_ignore(); - waitpid(pid, &wstatus, 0); - set_signal_interactive(); - if (ft_wifexited(wstatus)) - return (ft_wexitstatus(wstatus)); - if (WTERMSIG(wstatus) == SIGQUIT) - ft_putendl_fd("Quit: 3", STDERR_FILENO); - return (128 + WTERMSIG(wstatus)); -} - -static void restore_fds(int saved_in, int saved_out) -{ - dup2(saved_in, STDIN_FILENO); - dup2(saved_out, STDOUT_FILENO); - close(saved_in); - close(saved_out); + return (wait_for_child(pid)); } static int exec_builtin_with_redir(t_ast *node, t_shell_table *st) @@ -62,12 +60,13 @@ static int exec_builtin_with_redir(t_ast *node, t_shell_table *st) saved_out = dup(STDOUT_FILENO); if (node->cmd->redirs && exec_redirs(node->cmd->redirs) != 0) - { - restore_fds(saved_in, saved_out); - return (1); - } - status = exec_builtin_cmd(node, st); - restore_fds(saved_in, saved_out); + status = 1; + else + status = exec_builtin_cmd(node, st); + dup2(saved_in, STDIN_FILENO); + dup2(saved_out, STDOUT_FILENO); + close(saved_in); + close(saved_out); return (status); } diff --git a/src/execute/exec_pipe.c b/src/execute/exec_pipe.c index f3ff1cd..d041228 100644 --- a/src/execute/exec_pipe.c +++ b/src/execute/exec_pipe.c @@ -43,13 +43,32 @@ static int exec_pipe_right(t_ast *node, t_shell_table *shell_table, \ return (0); } +static int get_exit_status(int wstatus) +{ + if (ft_wifexited(wstatus)) + return (ft_wexitstatus(wstatus)); + if (WTERMSIG(wstatus) == SIGQUIT) + ft_putendl_fd("Quit: 3", STDERR_FILENO); + return (128 + WTERMSIG(wstatus)); +} + +static int wait_pipe_children(pid_t left, pid_t right) +{ + int wstatus_left; + int wstatus_right; + + set_signal_ignore(); + waitpid(left, &wstatus_left, 0); + waitpid(right, &wstatus_right, 0); + set_signal_interactive(); + return (get_exit_status(wstatus_right)); +} + int exec_pipe(t_ast *node, t_shell_table *shell_table) { int fd[2]; pid_t left; pid_t right; - int exit_status_left_child; - int exit_status_right_child; if (pipe(fd) == -1) return (1); @@ -63,13 +82,5 @@ int exec_pipe(t_ast *node, t_shell_table *shell_table) } close(fd[0]); close(fd[1]); - set_signal_ignore(); - waitpid(left, &exit_status_left_child, 0); - waitpid(right, &exit_status_right_child, 0); - set_signal_interactive(); - if (ft_wifexited(exit_status_right_child)) - return (ft_wexitstatus(exit_status_right_child)); - if (WTERMSIG(exit_status_right_child) == SIGQUIT) - ft_putendl_fd("Quit: 3", STDERR_FILENO); - return (128 + WTERMSIG(exit_status_right_child)); + return (wait_pipe_children(left, right)); } diff --git a/src/main.c b/src/main.c index 3a59797..9ef7abc 100644 --- a/src/main.c +++ b/src/main.c @@ -15,6 +15,7 @@ int main(int argc, char const **argv, char *const envp[]) { t_shell_table *shell_table; + int last_status; (void)argc; (void)argv; @@ -22,7 +23,7 @@ int main(int argc, char const **argv, char *const envp[]) if (!shell_table) return (1); setup_signal_handlers(); - prompt(on_input, shell_table); + last_status = prompt(on_input, shell_table); st_destroy(shell_table); - return (0); + return (last_status); } diff --git a/src/prompt/prompt.c b/src/prompt/prompt.c index 7fffc4c..3a95901 100644 --- a/src/prompt/prompt.c +++ b/src/prompt/prompt.c @@ -13,7 +13,7 @@ #include "prompt.h" #include "signal_handler.h" -void prompt(int (*handler)(char *input, t_shell_table *shell_table, +int prompt(int (*handler)(char *input, t_shell_table *shell_table, int last_status), t_shell_table *shell_table) { char *input; @@ -39,4 +39,5 @@ void prompt(int (*handler)(char *input, t_shell_table *shell_table, last_status = handler(input, shell_table, last_status); } rl_clear_history(); + return (last_status); } From 1ef65c5aea090153209bdc4d421f6480b23ae2e7 Mon Sep 17 00:00:00 2001 From: urassh Date: Sat, 18 Apr 2026 14:16:08 +0900 Subject: [PATCH 172/173] =?UTF-8?q?=E6=9C=80=E7=B5=82=E8=AA=BF=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 18 ----- Makefile | 11 +-- compose.yml | 7 -- includes/heredoc.h | 10 ++- src/builtin/unset/unset.c | 12 +-- src/callback/on_input.c | 19 ++++- src/component/heredoc/heredoc.c | 50 +++++++++--- src/component/heredoc/heredoc_expand.c | 108 +++++++++++++++++++++++++ src/component/heredoc/heredoc_prompt.c | 41 +++++++--- src/parse/parse.c | 4 +- 10 files changed, 208 insertions(+), 72 deletions(-) delete mode 100644 Dockerfile delete mode 100644 compose.yml create mode 100644 src/component/heredoc/heredoc_expand.c diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 688e704..0000000 --- a/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -FROM ubuntu:22.04 - -ENV DEBIAN_FRONTEND=noninteractive - -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - build-essential \ - libreadline-dev \ - clang \ - git \ - valgrind \ - python3 \ - python3-pip \ - && apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN python3 -m pip install --upgrade pip && \ - python3 -m pip install norminette==3.3.55 diff --git a/Makefile b/Makefile index d2d47eb..88d1995 100644 --- a/Makefile +++ b/Makefile @@ -94,6 +94,7 @@ SRCS_MAND := src/main.c \ src/parse/utils/free_ast.c \ src/component/heredoc/heredoc.c \ src/component/heredoc/heredoc_prompt.c \ + src/component/heredoc/heredoc_expand.c \ src/component/heredoc/tmpfile.c \ src/component/shell_table/shell_hash.c \ src/component/shell_table/shell_insert.c \ @@ -196,13 +197,3 @@ re: fclean all .PHONY: all clean fclean re bonus -#----------------------------------------------------------------------------- - -#▸ original rules - -#----------------------------------------------------------------------------- - -docker: - docker compose up -d && docker compose exec minishell bash - -.PHONY: docker diff --git a/compose.yml b/compose.yml deleted file mode 100644 index 4360743..0000000 --- a/compose.yml +++ /dev/null @@ -1,7 +0,0 @@ -services: - minishell: - build: . - volumes: - - .:/cursus - working_dir: /cursus - tty: true diff --git a/includes/heredoc.h b/includes/heredoc.h index 0c7db2b..e977035 100644 --- a/includes/heredoc.h +++ b/includes/heredoc.h @@ -21,8 +21,14 @@ # include # include -t_list *heredoc(t_list *tokens); -char *heredoc_prompt(const char *delimiter); +# include "shell_table.h" +# include + +t_list *heredoc(t_list *tokens, t_shell_table *st); +char *heredoc_prompt(const char *delim, bool expand, + t_shell_table *st); + +char *expand_heredoc_line(const char *line, t_shell_table *st); // tmpfile int open_tmpfile(char *tmpfile_path); diff --git a/src/builtin/unset/unset.c b/src/builtin/unset/unset.c index d0e506d..68d8b7d 100644 --- a/src/builtin/unset/unset.c +++ b/src/builtin/unset/unset.c @@ -20,20 +20,14 @@ int unset(t_list *argv, t_shell_table *shell_table) int result; if (!argv || !argv->content) - return (ERROR); + return (SUCCESS); result = SUCCESS; skip_head_node(&argv); while (argv) { key = (char *)argv->content; - if (!key) - { - result = ERROR; - skip_head_node(&argv); - continue ; - } - if (!st_delete(shell_table, key)) - result = ERROR; + if (key) + st_delete(shell_table, key); skip_head_node(&argv); } return (result); diff --git a/src/callback/on_input.c b/src/callback/on_input.c index 7d2e115..ba31414 100644 --- a/src/callback/on_input.c +++ b/src/callback/on_input.c @@ -12,6 +12,18 @@ #include "minishell.h" +static bool has_valid_heredoc(t_list *tokens) +{ + while (tokens) + { + if (ft_strncmp(tokens->content, "<<", 3) == 0) + if (!tokens->next || !tokens->next->content) + return (false); + tokens = tokens->next; + } + return (true); +} + int on_input(char *input, t_shell_table *shell_table, int last_status) { t_list *tokens; @@ -21,7 +33,12 @@ int on_input(char *input, t_shell_table *shell_table, int last_status) tokens = tokenize(input); if (!tokens) return (2); - if (!heredoc(tokens)) + if (!has_valid_heredoc(tokens)) + { + ft_lstclear(&tokens, free); + return (2); + } + if (!heredoc(tokens, shell_table)) { ft_lstclear(&tokens, free); return (130); diff --git a/src/component/heredoc/heredoc.c b/src/component/heredoc/heredoc.c index 428c48b..c1c099b 100644 --- a/src/component/heredoc/heredoc.c +++ b/src/component/heredoc/heredoc.c @@ -16,32 +16,60 @@ static bool is_heredoc_operator(const char *token); static int rebuild_tokens(t_list *current, t_list *eof_node, char *tmpfile_path); +static char *strip_quotes(const char *s, bool *was_quoted); -t_list *heredoc(t_list *tokens) +static char *process_heredoc(t_list *current, t_shell_table *st) { - t_list *current; t_list *eof_node; + bool quoted; + char *delim; char *tmpfile_path; + eof_node = current->next; + if (eof_node == NULL) + return (NULL); + delim = strip_quotes(eof_node->content, "ed); + if (!delim) + return (NULL); + tmpfile_path = heredoc_prompt(delim, !quoted, st); + free(delim); + if (!tmpfile_path) + return (NULL); + if (rebuild_tokens(current, eof_node, tmpfile_path) == ERROR) + return (NULL); + return (tmpfile_path); +} + +t_list *heredoc(t_list *tokens, t_shell_table *st) +{ + t_list *current; + current = tokens; while (current != NULL) { if (is_heredoc_operator((char *)current->content)) - { - eof_node = current->next; - if (eof_node == NULL) - return (NULL); - tmpfile_path = heredoc_prompt((char *)eof_node->content); - if (tmpfile_path == NULL) + if (!process_heredoc(current, st)) return (NULL); - if (rebuild_tokens(current, eof_node, tmpfile_path) == ERROR) - return (NULL); - } current = current->next; } return (tokens); } +static char *strip_quotes(const char *s, bool *was_quoted) +{ + size_t len; + + *was_quoted = false; + len = ft_strlen(s); + if (len >= 2 && ((s[0] == '\'' && s[len - 1] == '\'') + || (s[0] == '"' && s[len - 1] == '"'))) + { + *was_quoted = true; + return (ft_substr(s, 1, len - 2)); + } + return (ft_strdup(s)); +} + static bool is_heredoc_operator(const char *token) { if (token == NULL) diff --git a/src/component/heredoc/heredoc_expand.c b/src/component/heredoc/heredoc_expand.c new file mode 100644 index 0000000..803bb4a --- /dev/null +++ b/src/component/heredoc/heredoc_expand.c @@ -0,0 +1,108 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* heredoc_expand.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: surayama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/18 00:00:00 by surayama #+# #+# */ +/* Updated: 2026/04/18 00:00:00 by surayama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "heredoc.h" + +char *heredoc_append_str(char *dst, const char *src) +{ + char *result; + + if (!dst) + return (ft_strdup(src)); + result = ft_strjoin(dst, src); + free(dst); + return (result); +} + +static char *expand_var(const char *s, size_t *i, + t_shell_table *st) +{ + char *key; + char *val; + size_t len; + + len = 0; + while (s[*i + 1 + len] + && (ft_isalnum(s[*i + 1 + len]) || s[*i + 1 + len] == '_')) + len++; + if (len == 0) + return (ft_strdup("$")); + key = ft_substr(s, *i + 1, len); + if (!key) + return (NULL); + *i += len; + val = st_search(st, key); + free(key); + if (!val) + return (ft_strdup("")); + return (ft_strdup(val)); +} + +static char *expand_dollar(const char *s, size_t *i, + t_shell_table *st) +{ + char *val; + + if (!s[*i + 1] || s[*i + 1] == ' ' || s[*i + 1] == '\n') + return (ft_strdup("$")); + if (s[*i + 1] == '?') + { + *i += 1; + val = st_search(st, "?"); + if (!val) + return (ft_strdup("0")); + return (ft_strdup(val)); + } + return (expand_var(s, i, st)); +} + +static char *expand_one_char(char *result, const char *line, + size_t *i, t_shell_table *st) +{ + char *expanded; + char buf[2]; + + if (line[*i] == '$') + { + expanded = expand_dollar(line, i, st); + if (!expanded) + return (free(result), NULL); + result = heredoc_append_str(result, expanded); + free(expanded); + } + else + { + buf[0] = line[*i]; + buf[1] = '\0'; + result = heredoc_append_str(result, buf); + } + return (result); +} + +char *expand_heredoc_line(const char *line, t_shell_table *st) +{ + char *result; + size_t i; + + result = ft_strdup(""); + if (!result) + return (NULL); + i = 0; + while (line[i]) + { + result = expand_one_char(result, line, &i, st); + if (!result) + return (NULL); + i++; + } + return (result); +} diff --git a/src/component/heredoc/heredoc_prompt.c b/src/component/heredoc/heredoc_prompt.c index bbb8c96..6a1a15f 100644 --- a/src/component/heredoc/heredoc_prompt.c +++ b/src/component/heredoc/heredoc_prompt.c @@ -14,8 +14,10 @@ #include "signal_handler.h" #include -static int write_line_to_file(int fd, char *line); -static void heredoc_child(const char *delimiter, int fd); +static int write_line(int fd, char *line, bool expand, + t_shell_table *st); +static void heredoc_child(const char *delim, int fd, + bool expand, t_shell_table *st); static int wait_heredoc_child(pid_t pid) { @@ -41,7 +43,8 @@ static void *heredoc_interrupted(char *tmpfile_path) return (NULL); } -char *heredoc_prompt(const char *delimiter) +char *heredoc_prompt(const char *delim, bool expand, + t_shell_table *st) { char *tmpfile_path; int fd; @@ -57,7 +60,7 @@ char *heredoc_prompt(const char *delimiter) if (pid == 0) { set_signal_default(); - heredoc_child(delimiter, fd); + heredoc_child(delim, fd, expand, st); } close(fd); set_signal_ignore(); @@ -67,7 +70,8 @@ char *heredoc_prompt(const char *delimiter) return (tmpfile_path); } -static void heredoc_child(const char *delimiter, int fd) +static void heredoc_child(const char *delim, int fd, + bool expand, t_shell_table *st) { char *line; int status; @@ -76,10 +80,10 @@ static void heredoc_child(const char *delimiter, int fd) while (1) { line = readline(HEREDOC_PROMPT); - if (!line || ft_strncmp(line, delimiter, - ft_strlen(delimiter) + 1) == 0) + if (!line || ft_strncmp(line, delim, + ft_strlen(delim) + 1) == 0) break ; - if (write_line_to_file(fd, line) == ERROR) + if (write_line(fd, line, expand, st) == ERROR) { status = 1; break ; @@ -90,14 +94,25 @@ static void heredoc_child(const char *delimiter, int fd) exit(status); } -static int write_line_to_file(int fd, char *line) +static int write_line(int fd, char *line, bool expand, + t_shell_table *st) { - size_t len; + char *out; - len = ft_strlen(line); - if (write(fd, line, len) == -1) + if (expand) + out = expand_heredoc_line(line, st); + else + out = line; + if (!out) return (ERROR); - if (write(fd, "\n", 1) == -1) + if (write(fd, out, ft_strlen(out)) == -1 + || write(fd, "\n", 1) == -1) + { + if (expand) + free(out); return (ERROR); + } + if (expand) + free(out); return (SUCCESS); } diff --git a/src/parse/parse.c b/src/parse/parse.c index aefa86e..094fbf4 100644 --- a/src/parse/parse.c +++ b/src/parse/parse.c @@ -32,7 +32,7 @@ static int parse_redir(t_list **current, t_cmd *cmd) if (kind == R_NOT_FOUND) return (ERROR); *current = (*current)->next; - if (!*current) + if (!*current || !is_word(*current)) return (ERROR); if (!add_redir_to_cmd(cmd, kind, (*current)->content)) return (ERROR); @@ -78,6 +78,8 @@ t_ast *parse_cmd(t_list **current) if (parse_token(current, cmd) == ERROR) return (free_cmd(cmd), NULL); } + if (!cmd->argv && !cmd->redirs) + return (free_cmd(cmd), NULL); ast = new_ast_node(CMD); if (!ast) return (free_cmd(cmd), NULL); From 51e6784637016a64da39f3f064934f77e544c219 Mon Sep 17 00:00:00 2001 From: urassh Date: Sat, 18 Apr 2026 14:19:11 +0900 Subject: [PATCH 173/173] delete claude, github --- .claude/CLAUDE.md | 86 ------ .claude/commands/code-review.md | 30 --- .claude/commands/pr-creation.md | 11 - .claude/hooks/post-edit-norminette.sh | 23 -- .claude/hooks/pre-bash-safety-check.sh | 25 -- .claude/hooks/session-start-branch-check.sh | 15 -- .claude/rules/c.md | 98 ------- .claude/settings.json | 36 --- .github/pull_request_template.md | 33 --- .github/workflows/build.yml | 79 ------ .github/workflows/leak-check-all-checker.yml | 260 ------------------- .github/workflows/leak-check.yml | 196 -------------- .github/workflows/norminette.yml | 40 --- 13 files changed, 932 deletions(-) delete mode 100644 .claude/CLAUDE.md delete mode 100644 .claude/commands/code-review.md delete mode 100644 .claude/commands/pr-creation.md delete mode 100644 .claude/hooks/post-edit-norminette.sh delete mode 100644 .claude/hooks/pre-bash-safety-check.sh delete mode 100644 .claude/hooks/session-start-branch-check.sh delete mode 100644 .claude/rules/c.md delete mode 100644 .claude/settings.json delete mode 100644 .github/pull_request_template.md delete mode 100644 .github/workflows/build.yml delete mode 100644 .github/workflows/leak-check-all-checker.yml delete mode 100644 .github/workflows/leak-check.yml delete mode 100644 .github/workflows/norminette.yml diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md deleted file mode 100644 index 3bd9f39..0000000 --- a/.claude/CLAUDE.md +++ /dev/null @@ -1,86 +0,0 @@ -# CLAUDE.md - -このファイルは Claude Code (claude.ai/code) がこのリポジトリで作業する際のガイダンスを提供する。 - -## プロジェクト概要 - -42 Tokyo の minishell プロジェクト。C言語による最小限の POSIX シェル実装。開発者: surayama, kjikuhar。 - -## ビルドコマンド - -```bash -make # ビルド (libft → ソースを -Wall -Wextra -Werror でコンパイル) -make re # クリーンビルド -make clean # オブジェクトファイル削除 -make fclean # オブジェクトファイルとバイナリ削除 -make norm # norminette スタイルチェック -make valgrind # リビルド後 valgrind でメモリリーク検出 (readline.supp 使用) -make test # norminette + valgrind 両方実行 -make docker # Docker コンテナをビルドして入る -``` - -## 実行方法 - -ビルド・実行は必ずDocker環境内で行うこと。 - -```bash -make docker # Docker コンテナをビルドして入る -make # コンテナ内でビルド -./minishell # 通常モード (対話シェル) -./minishell --dev # 開発モード (expand_checker でパイプラインデバッグ) -``` - -## Architecture - -シェルは以下のインタープリタパイプラインに従う: - -``` -Input → tokenize() → heredoc() → variable_expand() → remove_quotes() → parse() → AST → execute -``` - -### パイプラインの各段階 - -1. **tokenize** (`src/tokenize/`) — 状態機械による字句解析。状態: `IN_NORMAL`, `IN_SINGLE_QUOTE`, `IN_DOUBLE_QUOTE`, `IN_OPERATOR`, `ON_SUCCESS`, `ON_ERROR`。演算子・スペース・クォート境界で `t_list` のトークン文字列に分割する。 - -2. **変数展開** (`src/component/variable_expand/`) — `$VAR` 構文を展開。クォート文脈を尊重し、シングルクォート内では展開しない。トークナイザと同様の状態機械パターンを使用。 - -3. **クォート削除** (`src/component/remove_quotes/`) — 展開後のトークンからクォート文字を除去。 - -4. **parse** (`src/parse/`) — 再帰下降パーサ。二分木ASTを生成。ノード型: `PIPE`(内部ノード)、`CMD`(葉ノード、`t_cmd` に argv リストとリダイレクションリストを持つ)。 - -5. **実行** — 未実装。エントリポイントは `src/callback/on_input.c`。 - -### 主要コンポーネント - -- **Shell Table** (`src/component/shell_table/`) — 環境変数のハッシュテーブル。export 状態を追跡。関数プレフィックス: `st_*`。 -- **ビルトイン** (`src/builtin/`) — echo, pwd, export, unset, cd。全て `(t_list *argv, t_shell_table *shell_table)` を引数に取る。 -- **ヒアドキュメント** (`src/component/heredoc/`) — `<<` リダイレクションを処理。一時ファイルを `/tmp/minishell_heredoc_*` に作成。 -- **チェッカー** (`src/checker/`) — 各パイプライン段階のデバッグ・テスト用ハーネス。個別に呼び出し可能。 - -### 主要データ構造 (`includes/`) - -- `t_shell_table` / `t_shell_node` — 環境変数ハッシュテーブル (`shell_table.h`) -- `t_ast` — AST木。`t_ast_type` (PIPE/CMD) と left/right 子ノード (`parse.h`) -- `t_cmd` — コマンド。`t_list *argv` と `t_list *redirs` を持つ (`parse.h`) -- `t_redir` — リダイレクション。`t_redir_kind` (R_IN, R_OUT_TRUNC, R_OUT_APPEND) と filename (`parse.h`) -- `t_list` — libft のリンクリスト。トークンリストや引数リストとして全体で使用 - -## Critical Rules - -### コーディング規約 (42 Norminette) - -- 1行最大80文字、関数本体最大25行、関数の引数最大4つ -- 変数宣言は関数の先頭、全て snake_case -- typedef: `typedef struct s_name { ... } t_name;` -- 公開ヘッダは `includes/`、非公開ヘッダ (例: `tokenize_private.h`) はソースファイルと同階層 -- 全ファイルに 42 ヘッダコメントブロックが必要 -- 新規ソースファイルは Makefile の `SRCS_MAND` に追加すること - -### メモリリークチェック - -- メモリリークの検出は必ず valgrind で行うこと (`make valgrind`) - -## 依存関係 - -- **libft** (`libft/`) — カスタムCライブラリ。Makefile で自動コンパイル -- **readline** — GNU readline。対話入力用 (`-lreadline`) diff --git a/.claude/commands/code-review.md b/.claude/commands/code-review.md deleted file mode 100644 index bcef153..0000000 --- a/.claude/commands/code-review.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -description: 変更コードの自動レビュー ---- - - -# 変更コードの自動レビュー - -## 実行手順 - -### Step 1: 並列レビューエージェントの起動 -以下の 3 つのエージェントを並列で起動してください: - - -#### エージェント 1: コーディング規約チェック - -- 1行最大80文字、関数本体最大25行、関数の引数最大4つ -- 変数宣言は関数の先頭、全て snake_case -- typedef: `typedef struct s_name { ... } t_name;` -- 公開ヘッダは `includes/`、非公開ヘッダ (例: `tokenize_private.h`) はソースファイルと同階層 -- 全ファイルに 42 ヘッダコメントブロックが必要 - -#### エージェント 2: 命名・可読性チェック - -- 変数名・メソッド名の適切さ -- マジックナンバー - -#### エージェント 3: メモリリークチェック - -- `malloc`などのメモリ確保が行われた場合に、全てのパターンにおいて`free`解放が行われているか検証する。 -- 入力パターンで再現性があれば、それもユーザに報告する。 diff --git a/.claude/commands/pr-creation.md b/.claude/commands/pr-creation.md deleted file mode 100644 index 56d38cc..0000000 --- a/.claude/commands/pr-creation.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -description: PR 作成 ---- - -## 実行手順 - -### 1. コミット状態の確認 -### 2. 変更内容の分析 -### 3. norminette 最終確認(変更ファイルのみ) -### 4. PR 説明文の生成(テンプレートに従う) -### 5. PR 作成(gh pr create) diff --git a/.claude/hooks/post-edit-norminette.sh b/.claude/hooks/post-edit-norminette.sh deleted file mode 100644 index 6a26635..0000000 --- a/.claude/hooks/post-edit-norminette.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -# post-edit-norminette.sh - -INPUT=$(cat) -FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty') - -# C/H ファイルでない場合はスキップ -if [[ ! "$FILE_PATH" =~ \.(c|h)$ ]]; then - exit 0 -fi - -# norminette 実行 -NORM_OUTPUT=$(norminette "$FILE_PATH" 2>&1 || true) - -if echo "$NORM_OUTPUT" | grep -q "Error"; then - ERRORS=$(echo "$NORM_OUTPUT" | grep "Error" | head -20) - cat << EOF -{ - "decision": "block", - "reason": "norminette エラー:\n$ERRORS" -} -EOF -fi diff --git a/.claude/hooks/pre-bash-safety-check.sh b/.claude/hooks/pre-bash-safety-check.sh deleted file mode 100644 index a79252e..0000000 --- a/.claude/hooks/pre-bash-safety-check.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash -# pre-bash-safety-check.sh - -INPUT=$(cat) -COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty') - -DANGEROUS_PATTERNS=( - "rm -rf /" - "git push --force.*main" - "git push --force.*develop" -) - -for pattern in "${DANGEROUS_PATTERNS[@]}"; do - if echo "$COMMAND" | grep -qE "$pattern"; then - cat << EOF -{ - "decision": "Reject", - "feedback": "🚨 危険なコマンドがブロックされました - -コマンド: \`$COMMAND\`" -} -EOF - exit 0 - fi -done diff --git a/.claude/hooks/session-start-branch-check.sh b/.claude/hooks/session-start-branch-check.sh deleted file mode 100644 index 8b10313..0000000 --- a/.claude/hooks/session-start-branch-check.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -# session-start-branch-check.sh - -CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) - -if [ "$CURRENT_BRANCH" = "develop" ] || [ "$CURRENT_BRANCH" = "main" ]; then - cat << EOF -{ - "decision": "Proceed", - "feedback": "⚠️ 現在のブランチ: **$CURRENT_BRANCH** - -開発作業は feature ブランチでおこなってください。" -} -EOF -fi diff --git a/.claude/rules/c.md b/.claude/rules/c.md deleted file mode 100644 index 7d47cd8..0000000 --- a/.claude/rules/c.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -paths: - - "src/**/*.c" ---- - -# C Code Guidelines - -### Code Style - -- Use snake_case for variable and function names. -- Limit lines to a maximum of 80 characters. -- Your project must be written in accordance with the Norminette. -- All heap-allocated memory must be properly freed when necessary. Memory leaks will not be tolerated. - -### Allowable External Functions - -以下の関数のみ使用可能。それ以外の外部関数は使用禁止。 - -#### readline -- `char *readline(const char *prompt)` — プロンプトを表示し、ユーザ入力を返す -- `void rl_clear_history(void)` — 履歴リストを全削除 -- `void rl_on_new_line(void)` — カーソルが新しい行に移動したことを通知 -- `void rl_replace_line(const char *text, int clear_undo)` — 現在の入力行を置換 -- `void rl_redisplay(void)` — プロンプトと入力行を再描画 -- `void add_history(const char *string)` — 履歴リストに追加 - -#### stdio / stdlib -- `int printf(const char *format, ...)` — フォーマット出力 -- `void *malloc(size_t size)` — メモリ確保 -- `void free(void *ptr)` — メモリ解放 - -#### I/O -- `ssize_t write(int fd, const void *buf, size_t count)` — ファイルディスクリプタへ書き込み -- `int access(const char *pathname, int mode)` — ファイルのアクセス権確認 -- `int open(const char *pathname, int flags, ...)` — ファイルを開く -- `ssize_t read(int fd, void *buf, size_t count)` — ファイルディスクリプタから読み込み -- `int close(int fd)` — ファイルディスクリプタを閉じる - -#### プロセス制御 -- `pid_t fork(void)` — 子プロセスを生成 -- `pid_t wait(int *wstatus)` — 子プロセスの終了を待つ -- `pid_t waitpid(pid_t pid, int *wstatus, int options)` — 指定子プロセスの終了を待つ -- `pid_t wait3(int *wstatus, int options, struct rusage *rusage)` — リソース使用情報付きwait -- `pid_t wait4(pid_t pid, int *wstatus, int options, struct rusage *rusage)` — リソース使用情報付きwaitpid - -#### シグナル -- `sighandler_t signal(int signum, sighandler_t handler)` — シグナルハンドラを設定 -- `int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)` — シグナルアクションを設定 -- `int sigemptyset(sigset_t *set)` — シグナルセットを空にする -- `int sigaddset(sigset_t *set, int signum)` — シグナルセットにシグナルを追加 -- `int kill(pid_t pid, int sig)` — プロセスにシグナルを送信 - -#### プロセス終了・実行 -- `void exit(int status)` — プロセスを終了 -- `int execve(const char *pathname, char *const argv[], char *const envp[])` — プログラムを実行 - -#### ファイルシステム -- `char *getcwd(char *buf, size_t size)` — カレントディレクトリを取得 -- `int chdir(const char *path)` — カレントディレクトリを変更 -- `int stat(const char *pathname, struct stat *statbuf)` — ファイル情報を取得 -- `int lstat(const char *pathname, struct stat *statbuf)` — シンボリックリンク情報を取得 -- `int fstat(int fd, struct stat *statbuf)` — fdからファイル情報を取得 -- `int unlink(const char *pathname)` — ファイルを削除 - -#### パイプ・ファイルディスクリプタ -- `int dup(int oldfd)` — ファイルディスクリプタを複製 -- `int dup2(int oldfd, int newfd)` — ファイルディスクリプタを指定番号に複製 -- `int pipe(int pipefd[2])` — パイプを作成 - -#### ディレクトリ操作 -- `DIR *opendir(const char *name)` — ディレクトリを開く -- `struct dirent *readdir(DIR *dirp)` — ディレクトリエントリを読む -- `int closedir(DIR *dirp)` — ディレクトリを閉じる - -#### エラー処理 -- `char *strerror(int errnum)` — エラー番号に対応する文字列を返す -- `void perror(const char *s)` — エラーメッセージを出力 - -#### ターミナル -- `int isatty(int fd)` — fdが端末か判定 -- `char *ttyname(int fd)` — 端末名を返す -- `int ttyslot(void)` — 端末スロット番号を返す -- `int ioctl(int fd, unsigned long request, ...)` — デバイス制御 - -#### 環境変数 -- `char *getenv(const char *name)` — 環境変数の値を取得 - -#### termios -- `int tcsetattr(int fd, int optional_actions, const struct termios *termios_p)` — 端末属性を設定 -- `int tcgetattr(int fd, struct termios *termios_p)` — 端末属性を取得 - -#### termcap -- `int tgetent(char *bp, const char *name)` — termcapエントリを取得 -- `int tgetflag(const char *id)` — ブール型ケーパビリティを取得 -- `int tgetnum(const char *id)` — 数値型ケーパビリティを取得 -- `char *tgetstr(const char *id, char **area)` — 文字列型ケーパビリティを取得 -- `char *tgoto(const char *cap, int col, int row)` — カーソル移動文字列を生成 -- `int tputs(const char *str, int affcnt, int (*putc)(int))` — ケーパビリティ文字列を出力 diff --git a/.claude/settings.json b/.claude/settings.json deleted file mode 100644 index 39d0fa9..0000000 --- a/.claude/settings.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "hooks": { - "SessionStart": [ - { - "hooks": [ - { - "type": "command", - "command": ".claude/hooks/session-start-branch-check.sh" - } - ] - } - ], - "PostToolUse": [ - { - "matcher": "Write|Edit", - "hooks": [ - { - "type": "command", - "command": ".claude/hooks/post-edit-norminette.sh" - } - ] - } - ], - "PreToolUse": [ - { - "matcher": "Bash", - "hooks": [ - { - "type": "command", - "command": ".claude/hooks/pre-bash-safety-check.sh" - } - ] - } - ] - } -} diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index 31dfa30..0000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,33 +0,0 @@ -## やったこと - -- -- - -## 懸念点 / レビューしてほしいポイント - -- - -## 動作確認 - -- [] norminetteを通過している。 -- [] makeコマンドでビルドできる。 -- [] valgrindでリークチェックをした。(`valgrind --leak-check=full --suppressions=readline.supp --show-leak-kinds=all -s -q ./minishell`) -- [] ~~~ -- [] ~~~ -- [] ~~~ - -## ひとこと - diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index bd9e072..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,79 +0,0 @@ -name: Build - -on: - pull_request: - branches: [ "master", "develop" ] - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Install build dependencies - run: | - sudo apt-get update - sudo apt-get install -y build-essential libreadline-dev - - - name: Build project with make - run: | - echo "Building project..." - make - - - name: Verify minishell binary creation - run: | - echo "Checking if minishell binary was created..." - if [ -f "./minishell" ]; then - echo "✅ minishell binary was successfully created" - ls -la ./minishell - file ./minishell - else - echo "❌ ERROR: minishell binary was not created" - exit 1 - fi - - - name: Test minishell execution - run: | - echo "Testing if minishell is executable..." - if [ -x "./minishell" ]; then - echo "✅ minishell is executable" - # 基本的なテスト(シェルが起動するかどうか) - echo "Testing basic shell functionality..." - timeout 5s ./minishell --help || echo "Help command test completed" - else - echo "❌ ERROR: minishell is not executable" - exit 1 - fi - - - name: Test make clean functionality - run: | - echo "Testing make clean..." - make clean - if [ ! -d "./obj" ]; then - echo "✅ Object files cleaned successfully" - else - echo "⚠️ WARNING: Object directory still exists after clean" - fi - - - name: Test make fclean functionality - run: | - echo "Testing make fclean..." - make fclean - if [ ! -f "./minishell" ]; then - echo "✅ Binary cleaned successfully" - else - echo "❌ ERROR: Binary still exists after fclean" - exit 1 - fi - - - name: Test make re functionality - run: | - echo "Testing make re (rebuild)..." - make re - if [ -f "./minishell" ] && [ -x "./minishell" ]; then - echo "✅ Rebuild successful" - else - echo "❌ ERROR: Rebuild failed" - exit 1 - fi diff --git a/.github/workflows/leak-check-all-checker.yml b/.github/workflows/leak-check-all-checker.yml deleted file mode 100644 index c711179..0000000 --- a/.github/workflows/leak-check-all-checker.yml +++ /dev/null @@ -1,260 +0,0 @@ -name: Memory Leak Check (All Checkers) - -on: - pull_request: - branches: [ "master", "develop" ] - push: - branches: [ "master", "develop" ] - -jobs: - leak-check-all-checker: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - checker: - - tokenize - - heredoc - - expand - - remove-quotes - - parse - - builtin - - directory - - path - - relative-path - - wildcard - - steps: - - uses: actions/checkout@v4 - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y build-essential libreadline-dev valgrind - - - name: Build project - run: | - echo "Building minishell..." - make - - - name: Verify binary exists - run: | - if [ ! -f "./minishell" ]; then - echo "ERROR: minishell binary not found" - exit 1 - fi - echo "minishell binary found" - ls -la ./minishell - - - name: Generate test input for ${{ matrix.checker }} - run: | - CHECKER="${{ matrix.checker }}" - case "$CHECKER" in - tokenize) - cat << 'TESTEOF' > test_input.txt - - echo hello - echo "'nested'" - cmd|cat>file>out - || && - "unclosed - echo "hello world" | cat -e > output.txt - TESTEOF - ;; - heredoc) - cat << 'TESTEOF' > test_input.txt - cat << EOF - hello world - EOF - echo hello - cat << 'DELIM' - no expand $VAR - DELIM - cat << EOF | grep hello - hello world - EOF - - cat << EOF > /tmp/test_heredoc_out - test - EOF - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - cat << EOF - $HOME - EOF - TESTEOF - ;; - expand) - cat << 'TESTEOF' > test_input.txt - echo $PATH - echo $UNDEFINED - echo '$NO_EXPAND' - echo "$HOME" - echo $? - echo $A$B$C - echo $ - echo $AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - echo "" - echo "$?" - TESTEOF - ;; - remove-quotes) - cat << 'TESTEOF' > test_input.txt - echo "" - echo '' - echo "'nested'" - echo 'hello world' - echo "he said \"hi\"" - echo "a"'b'"c" - echo "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - echo hello - echo "hello"'world'"!" - TESTEOF - ;; - parse) - cat << 'TESTEOF' > test_input.txt - echo hello - cat | grep | wc - echo > out.txt - < in cat | grep > out - echo a | echo b | echo c | echo d | echo e | echo f | echo g | echo h | echo i | echo j - echo "hello | world" - echo hello > out.txt < in.txt >> append.txt - echo hello world foo bar baz - cat | grep pattern | sort | uniq - TESTEOF - ;; - builtin) - cat << 'TESTEOF' > test_input.txt - export A=1 - export A=1 B=2 C=3 - export EMPTY= - export - unset A - export LONG_VAR=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - export SPECIAL="hello world" - export A=1 - export A=2 - unset NONEXISTENT - TESTEOF - ;; - directory) - cat << 'TESTEOF' > test_input.txt - . - .. - /tmp - /nonexistent - / - - /usr/local/bin - /a/b/c/d/e/f/g/h/i/j - /tmp/test dir - TESTEOF - ;; - path) - cat << 'TESTEOF' > test_input.txt - ../src - ./file.c - /usr/bin - ../../.. - //tmp///file - . - / - /tmp/ - ./a/b/c/d - TESTEOF - ;; - relative-path) - cat << 'TESTEOF' > test_input.txt - ./file - ../dir - ../../file - ./a/b/../c - . - .. - hello - ./aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - ../a/b/c - TESTEOF - ;; - wildcard) - cat << 'TESTEOF' > test_input.txt - *.c - src/*.h - ? - nonexistent*.xyz - "*.c" - src/*/*.c - [a-z]* - * - *.o - TESTEOF - ;; - esac - - echo "exit" >> test_input.txt - - echo "=== Test input for $CHECKER ===" - cat -n test_input.txt - - - name: Run valgrind leak check for ${{ matrix.checker }} - run: | - CHECKER="${{ matrix.checker }}" - echo "Running valgrind for --${CHECKER} checker..." - - cat test_input.txt | timeout 10 valgrind \ - --leak-check=full \ - --show-leak-kinds=all \ - --track-origins=yes \ - --suppressions=./readline.supp \ - --error-exitcode=42 \ - --log-file=valgrind_result.txt \ - ./minishell --${CHECKER} 2>&1 || true - - VALGRIND_EXIT=${PIPESTATUS[1]:-$?} - - echo "" - echo "==========================================" - echo "Valgrind Output (--${CHECKER}):" - echo "==========================================" - cat valgrind_result.txt - echo "==========================================" - - if [ "$VALGRIND_EXIT" -eq 42 ]; then - echo "" - echo "MEMORY LEAK DETECTED in --${CHECKER} checker!" - echo "" - echo "Summary of leaks:" - grep "definitely lost" valgrind_result.txt || echo "No definitely lost blocks" - grep "indirectly lost" valgrind_result.txt || echo "No indirectly lost blocks" - grep "possibly lost" valgrind_result.txt || echo "No possibly lost blocks" - exit 1 - else - echo "" - echo "NO MEMORY LEAKS DETECTED in --${CHECKER} checker" - echo "" - echo "Leak Summary:" - grep "LEAK SUMMARY" valgrind_result.txt -A 5 || true - - if grep -q "All heap blocks were freed -- no leaks are possible" valgrind_result.txt; then - echo "All heap blocks were freed" - elif grep -q "definitely lost: 0 bytes in 0 blocks" valgrind_result.txt && \ - grep -q "indirectly lost: 0 bytes in 0 blocks" valgrind_result.txt && \ - grep -q "possibly lost: 0 bytes in 0 blocks" valgrind_result.txt; then - echo "No definite, indirect, or possible leaks" - else - echo "Warning: Some reachable memory detected (this is usually OK for readline)" - fi - - exit 0 - fi - - - name: Upload valgrind report - if: always() - uses: actions/upload-artifact@v4 - with: - name: valgrind-report-${{ matrix.checker }} - path: valgrind_result.txt - retention-days: 30 diff --git a/.github/workflows/leak-check.yml b/.github/workflows/leak-check.yml deleted file mode 100644 index 1e4cd94..0000000 --- a/.github/workflows/leak-check.yml +++ /dev/null @@ -1,196 +0,0 @@ -name: Memory Leak Check - -on: - pull_request: - branches: [ "master", "develop" ] - push: - branches: [ "master", "develop" ] - -jobs: - leak-check: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y build-essential libreadline-dev valgrind - - - name: Build project - run: | - echo "Building minishell..." - make - - - name: Verify binary exists - run: | - if [ ! -f "./minishell" ]; then - echo "❌ ERROR: minishell binary not found" - exit 1 - fi - echo "✅ minishell binary found" - ls -la ./minishell - - - name: Create test script for production mode - run: | - cat << 'EOF' > test_prod.sh - #!/bin/bash - - echo "==========================================" - echo "🚀 Testing PRODUCTION mode" - echo "==========================================" - - # minishellにコマンドを送信してメモリリークをチェック - echo "Starting memory leak test for production mode..." - - # expectスタイルでインタラクティブな入力をシミュレート - ( - sleep 0.5 - echo "ec'c'o \"hello\"&&cat -e" - sleep 0.5 - echo "exit" - sleep 0.5 - ) | valgrind --leak-check=full \ - --show-leak-kinds=all \ - --track-origins=yes \ - --suppressions=./readline.supp \ - --error-exitcode=42 \ - --log-file=valgrind_prod.txt \ - ./minishell 2>&1 - - VALGRIND_EXIT=$? - - echo "" - echo "==========================================" - echo "Valgrind Output (Production):" - echo "==========================================" - cat valgrind_prod.txt - echo "==========================================" - - # Valgrindの結果を解析 - if [ $VALGRIND_EXIT -eq 42 ]; then - echo "" - echo "❌ MEMORY LEAK DETECTED in PRODUCTION mode!" - echo "" - echo "Summary of leaks:" - grep "definitely lost" valgrind_prod.txt || echo "No definitely lost blocks" - grep "indirectly lost" valgrind_prod.txt || echo "No indirectly lost blocks" - grep "possibly lost" valgrind_prod.txt || echo "No possibly lost blocks" - exit 1 - else - echo "" - echo "✅ NO MEMORY LEAKS DETECTED in PRODUCTION mode" - - # リークサマリーを表示 - echo "" - echo "Leak Summary:" - grep "LEAK SUMMARY" valgrind_prod.txt -A 5 || true - - # 全てのヒープブロックが解放されたかチェック - if grep -q "All heap blocks were freed -- no leaks are possible" valgrind_prod.txt; then - echo "✅ All heap blocks were freed" - elif grep -q "definitely lost: 0 bytes in 0 blocks" valgrind_prod.txt && \ - grep -q "indirectly lost: 0 bytes in 0 blocks" valgrind_prod.txt && \ - grep -q "possibly lost: 0 bytes in 0 blocks" valgrind_prod.txt; then - echo "✅ No definite, indirect, or possible leaks" - else - echo "⚠️ Warning: Some reachable memory detected (this is usually OK for readline)" - fi - - exit 0 - fi - EOF - - chmod +x test_prod.sh - - - name: Create test script for development mode - run: | - cat << 'EOF' > test_dev.sh - #!/bin/bash - - echo "" - echo "==========================================" - echo "🔧 Testing DEVELOPMENT mode" - echo "==========================================" - - # minishellにコマンドを送信してメモリリークをチェック - echo "Starting memory leak test for development mode..." - - # expectスタイルでインタラクティブな入力をシミュレート - ( - sleep 0.5 - echo "ec'c'o \"hello\"&&cat -e" - sleep 0.5 - echo "exit" - sleep 0.5 - ) | valgrind --leak-check=full \ - --show-leak-kinds=all \ - --track-origins=yes \ - --suppressions=./readline.supp \ - --error-exitcode=42 \ - --log-file=valgrind_dev.txt \ - ./minishell --dev 2>&1 - - VALGRIND_EXIT=$? - - echo "" - echo "==========================================" - echo "Valgrind Output (Development):" - echo "==========================================" - cat valgrind_dev.txt - echo "==========================================" - - # Valgrindの結果を解析 - if [ $VALGRIND_EXIT -eq 42 ]; then - echo "" - echo "❌ MEMORY LEAK DETECTED in DEVELOPMENT mode!" - echo "" - echo "Summary of leaks:" - grep "definitely lost" valgrind_dev.txt || echo "No definitely lost blocks" - grep "indirectly lost" valgrind_dev.txt || echo "No indirectly lost blocks" - grep "possibly lost" valgrind_dev.txt || echo "No possibly lost blocks" - exit 1 - else - echo "" - echo "✅ NO MEMORY LEAKS DETECTED in DEVELOPMENT mode" - - # リークサマリーを表示 - echo "" - echo "Leak Summary:" - grep "LEAK SUMMARY" valgrind_dev.txt -A 5 || true - - # 全てのヒープブロックが解放されたかチェック - if grep -q "All heap blocks were freed -- no leaks are possible" valgrind_dev.txt; then - echo "✅ All heap blocks were freed" - elif grep -q "definitely lost: 0 bytes in 0 blocks" valgrind_dev.txt && \ - grep -q "indirectly lost: 0 bytes in 0 blocks" valgrind_dev.txt && \ - grep -q "possibly lost: 0 bytes in 0 blocks" valgrind_dev.txt; then - echo "✅ No definite, indirect, or possible leaks" - else - echo "⚠️ Warning: Some reachable memory detected (this is usually OK for readline)" - fi - - exit 0 - fi - EOF - - chmod +x test_dev.sh - - - name: Run memory leak test (Production mode) - run: | - ./test_prod.sh - - - name: Run memory leak test (Development mode) - run: | - ./test_dev.sh - - - name: Upload valgrind output as artifact - if: always() - uses: actions/upload-artifact@v4 - with: - name: valgrind-report - path: | - valgrind_prod.txt - valgrind_dev.txt - retention-days: 30 diff --git a/.github/workflows/norminette.yml b/.github/workflows/norminette.yml deleted file mode 100644 index e92a6bf..0000000 --- a/.github/workflows/norminette.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Norminette Check - -on: - pull_request: - branches: [ "master", "develop" ] - push: - branches: [ "master", "develop" ] - -jobs: - norminette: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Set up Python 3.8 - uses: actions/setup-python@v4 - with: - python-version: '3.8' - - - name: Install norminette - run: | - python -m pip install --upgrade pip - pip install norminette=="3.3.55" - - - name: Check norminette version - run: norminette --version - - - name: Run norminette on C files - run: | - echo "Checking C and header files..." - find . -name "*.c" -o -name "*.h" | grep -E "\.(c|h)$" | while read file; do - echo "Checking: $file" - norminette "$file" - done - - - name: Run norminette summary - run: | - echo "Running norminette on all C and header files..." - norminette $(find . -name "*.c" -o -name "*.h")