diff --git a/src/parser/wordsplit/wordsplit.c b/src/parser/wordsplit/wordsplit.c index eb32315..0f5d709 100644 --- a/src/parser/wordsplit/wordsplit.c +++ b/src/parser/wordsplit/wordsplit.c @@ -6,14 +6,14 @@ /* By: khais +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/02/13 17:02:32 by khais #+# #+# */ -/* Updated: 2025/02/14 18:06:44 by khais ### ########.fr */ +/* Updated: 2025/02/14 18:45:45 by khais ### ########.fr */ /* */ /* ************************************************************************** */ #include "wordsplit.h" -#include "libft.h" #include "../../buffer/buffer.h" #include "../matchers/blank.h" +#include static t_wordlist *delimit(t_wordlist *wordlist, t_buffer **token, bool *currently_in_word) { @@ -28,20 +28,25 @@ static t_wordlist *delimit(t_wordlist *wordlist, t_buffer **token, bool *current static t_buffer *push_char(t_buffer *token, char c) { + if (token == NULL) + token = ft_buffer_new(); return (ft_buffer_pushchar(token, c)); } -static t_buffer *new_word(char c, bool *currently_in_word) +static t_buffer *new_word(t_buffer *token, char c, bool *currently_in_word) { - t_buffer *token; - - token = ft_buffer_new(); - ft_buffer_pushchar(token, c); + token = push_char(token, c); (*currently_in_word) = true; return (token); } +static bool quote_flip(t_buffer **token, char c, bool currently_in_quotes) +{ + (*token) = push_char((*token), c); + return (!currently_in_quotes); +} + /* ** split a string into words, respecting quotes etc. ** @@ -58,21 +63,25 @@ t_wordlist *minishell_wordsplit(char *original) t_wordlist *wordlist; t_buffer *token; bool currently_in_word; + bool currently_in_quotes; idx = 0; wordlist = NULL; token = NULL; currently_in_word = false; + currently_in_quotes = false; while (true) { // If the end of input is recognized, the current token (if any) shall // be delimited. if (original[idx] == '\0') wordlist = delimit(wordlist, &token, ¤tly_in_word); + else if (original[idx] == '\'') + currently_in_quotes = quote_flip(&token, original[idx], currently_in_quotes); // If the current character is an unquoted , any token containing // the previous character is delimited and the current character shall // be discarded. - else if (is_blank(original[idx])) + else if (is_blank(original[idx]) && !currently_in_quotes) wordlist = delimit(wordlist, &token, ¤tly_in_word); // If the previous character was part of a word, the current character // shall be appended to that word. @@ -80,7 +89,7 @@ t_wordlist *minishell_wordsplit(char *original) token = push_char(token, original[idx]); // The current character is used as the start of a new word. else - token = new_word(original[idx], ¤tly_in_word); + token = new_word(token, original[idx], ¤tly_in_word); if (original[idx] == '\0') break ; idx++; diff --git a/tests/word_splitting.c b/tests/word_splitting.c index b20aed4..fa6e0b3 100644 --- a/tests/word_splitting.c +++ b/tests/word_splitting.c @@ -6,7 +6,7 @@ /* By: khais +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/02/13 15:17:56 by khais #+# #+# */ -/* Updated: 2025/02/14 16:16:14 by khais ### ########.fr */ +/* Updated: 2025/02/14 17:37:46 by khais ### ########.fr */ /* */ /* ************************************************************************** */ @@ -54,9 +54,21 @@ void test_wordsplit_multiword(void) wordlist_destroy(words); } +void test_wordsplit_multiword_with_single_quotes(void) +{ + t_wordlist *words; + + words = minishell_wordsplit("\t echo\t' \t The file is named $MYFILE ' \t"); + assert_strequal("echo", wordlist_get(words, 0)->word); + assert_strequal("' \t The file is named $MYFILE '", wordlist_get(words, 1)->word); + assert(NULL == wordlist_get(words, 2)); + wordlist_destroy(words); +} + int main(void) { test_wordsplit_singleword(); test_wordsplit_singleword_with_blanks(); test_wordsplit_multiword(); + test_wordsplit_multiword_with_single_quotes(); return (0); }