wordsplit: handle single quotes

This commit is contained in:
Khaïs COLIN 2025-02-14 17:50:56 +01:00
parent 81d28c15d4
commit 5276aba278
Signed by: logistic-bot
SSH key fingerprint: SHA256:RlpiqKeXpcPFZZ4y9Ou4xi2M8OhRJovIwDlbCaMsuAo
2 changed files with 31 additions and 10 deletions

View file

@ -6,14 +6,14 @@
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */ /* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/13 17:02:32 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 "wordsplit.h"
#include "libft.h"
#include "../../buffer/buffer.h" #include "../../buffer/buffer.h"
#include "../matchers/blank.h" #include "../matchers/blank.h"
#include <stdlib.h>
static t_wordlist *delimit(t_wordlist *wordlist, t_buffer **token, bool *currently_in_word) 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) static t_buffer *push_char(t_buffer *token, char c)
{ {
if (token == NULL)
token = ft_buffer_new();
return (ft_buffer_pushchar(token, c)); 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 = push_char(token, c);
token = ft_buffer_new();
ft_buffer_pushchar(token, c);
(*currently_in_word) = true; (*currently_in_word) = true;
return (token); 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. ** split a string into words, respecting quotes etc.
** **
@ -58,21 +63,25 @@ t_wordlist *minishell_wordsplit(char *original)
t_wordlist *wordlist; t_wordlist *wordlist;
t_buffer *token; t_buffer *token;
bool currently_in_word; bool currently_in_word;
bool currently_in_quotes;
idx = 0; idx = 0;
wordlist = NULL; wordlist = NULL;
token = NULL; token = NULL;
currently_in_word = false; currently_in_word = false;
currently_in_quotes = false;
while (true) while (true)
{ {
// If the end of input is recognized, the current token (if any) shall // If the end of input is recognized, the current token (if any) shall
// be delimited. // be delimited.
if (original[idx] == '\0') if (original[idx] == '\0')
wordlist = delimit(wordlist, &token, &currently_in_word); wordlist = delimit(wordlist, &token, &currently_in_word);
else if (original[idx] == '\'')
currently_in_quotes = quote_flip(&token, original[idx], currently_in_quotes);
// If the current character is an unquoted <blank>, any token containing // If the current character is an unquoted <blank>, any token containing
// the previous character is delimited and the current character shall // the previous character is delimited and the current character shall
// be discarded. // be discarded.
else if (is_blank(original[idx])) else if (is_blank(original[idx]) && !currently_in_quotes)
wordlist = delimit(wordlist, &token, &currently_in_word); wordlist = delimit(wordlist, &token, &currently_in_word);
// If the previous character was part of a word, the current character // If the previous character was part of a word, the current character
// shall be appended to that word. // shall be appended to that word.
@ -80,7 +89,7 @@ t_wordlist *minishell_wordsplit(char *original)
token = push_char(token, original[idx]); token = push_char(token, original[idx]);
// The current character is used as the start of a new word. // The current character is used as the start of a new word.
else else
token = new_word(original[idx], &currently_in_word); token = new_word(token, original[idx], &currently_in_word);
if (original[idx] == '\0') if (original[idx] == '\0')
break ; break ;
idx++; idx++;

View file

@ -6,7 +6,7 @@
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */ /* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/13 15:17:56 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); 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) { int main(void) {
test_wordsplit_singleword(); test_wordsplit_singleword();
test_wordsplit_singleword_with_blanks(); test_wordsplit_singleword_with_blanks();
test_wordsplit_multiword(); test_wordsplit_multiword();
test_wordsplit_multiword_with_single_quotes();
return (0); return (0);
} }