From 452d35acdf14b68fad00b71457e530666c4dcf27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kha=C3=AFs=20COLIN?= Date: Mon, 17 Feb 2025 14:00:01 +0100 Subject: [PATCH] wordsplit: handle mixed quotes --- src/parser/wordsplit/wordsplit.c | 18 +++++++++++------- tests/word_splitting.c | 28 +++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/parser/wordsplit/wordsplit.c b/src/parser/wordsplit/wordsplit.c index d8eee47..ee4cbc5 100644 --- a/src/parser/wordsplit/wordsplit.c +++ b/src/parser/wordsplit/wordsplit.c @@ -6,7 +6,7 @@ /* By: khais +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/02/13 17:02:32 by khais #+# #+# */ -/* Updated: 2025/02/17 13:54:58 by khais ### ########.fr */ +/* Updated: 2025/02/17 14:20:45 by khais ### ########.fr */ /* */ /* ************************************************************************** */ @@ -41,10 +41,14 @@ static t_buffer *new_word(t_buffer *token, char c, bool *currently_in_word) return (token); } -static bool quote_flip(t_buffer **token, char c, bool currently_in_quotes) +static char quote_flip(t_buffer **token, char c, char quote) { + if (quote == '\0') + quote = c; + else if (quote == c) + quote = '\0'; (*token) = push_char((*token), c); - return (!currently_in_quotes); + return (quote); } /* @@ -63,13 +67,13 @@ t_wordlist *minishell_wordsplit(char *original) t_wordlist *wordlist; t_buffer *token; bool currently_in_word; - bool currently_in_quotes; + char quote; idx = 0; wordlist = NULL; token = NULL; currently_in_word = false; - currently_in_quotes = false; + quote = '\0'; while (true) { // If the end of input is recognized, the current token (if any) shall @@ -85,11 +89,11 @@ t_wordlist *minishell_wordsplit(char *original) // the end of the quoted text. The token shall not be delimited by the // end of the quoted field. else if (original[idx] == '\'' || original[idx] == '"') - currently_in_quotes = quote_flip(&token, original[idx], currently_in_quotes); + quote = quote_flip(&token, original[idx], quote); // 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]) && !currently_in_quotes) + else if (is_blank(original[idx]) && quote == '\0') 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. diff --git a/tests/word_splitting.c b/tests/word_splitting.c index 0dcd588..74786b2 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/17 13:52:55 by khais ### ########.fr */ +/* Updated: 2025/02/17 14:27:45 by khais ### ########.fr */ /* */ /* ************************************************************************** */ @@ -76,11 +76,37 @@ static void test_wordsplit_multiword_with_double_quotes(void) wordlist_destroy(words); } +static void test_wordsplit_mixed_single_in_double(void) +{ + t_wordlist *words; + + words = minishell_wordsplit("hello \"mixed ' \tquotes \t'\" there"); + assert_strequal("hello", wordlist_get(words, 0)->word); + assert_strequal("\"mixed ' \tquotes \t'\"", wordlist_get(words, 1)->word); + assert_strequal("there", wordlist_get(words, 2)->word); + assert(NULL == wordlist_get(words, 3)); + wordlist_destroy(words); +} + +static void test_wordsplit_mixed_double_in_single(void) +{ + t_wordlist *words; + + words = minishell_wordsplit("hello 'mixed \" quotes \"' there"); + assert_strequal("hello", wordlist_get(words, 0)->word); + assert_strequal("'mixed \" quotes \"'", wordlist_get(words, 1)->word); + assert_strequal("there", wordlist_get(words, 2)->word); + assert(NULL == wordlist_get(words, 3)); + wordlist_destroy(words); +} + int main(void) { test_wordsplit_singleword(); test_wordsplit_singleword_with_blanks(); test_wordsplit_multiword(); test_wordsplit_multiword_with_single_quotes(); test_wordsplit_multiword_with_double_quotes(); + test_wordsplit_mixed_single_in_double(); + test_wordsplit_mixed_double_in_single(); return (0); }