From 00bce5ad1d5ac92d20617a9eb2647365bf87cab2 Mon Sep 17 00:00:00 2001 From: Charles Cabergs Date: Fri, 9 Oct 2020 16:13:50 +0200 Subject: Splitting preprocessing, Added parsed error helper --- src/preprocess/filename.c | 35 +++++++++++++ src/preprocess/interpolation.c | 110 +++++++++++++++++++++++++++++++++++++++++ src/preprocess/preprocess.c | 98 ++++++++++++++++++++++++++++++++++++ 3 files changed, 243 insertions(+) create mode 100644 src/preprocess/filename.c create mode 100644 src/preprocess/interpolation.c create mode 100644 src/preprocess/preprocess.c (limited to 'src/preprocess') diff --git a/src/preprocess/filename.c b/src/preprocess/filename.c new file mode 100644 index 0000000..0470554 --- /dev/null +++ b/src/preprocess/filename.c @@ -0,0 +1,35 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* filename.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: cacharle +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/10/09 15:29:04 by cacharle #+# #+# */ +/* Updated: 2020/10/09 15:30:03 by cacharle ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "eval.h" +#include "lexer.h" +#include "minishell.h" + +int preprocess_filename(t_tok_lst **tokens, t_env env, char **filename) +{ + char **strs; + + if ((strs = preprocess(tokens, env)) == NULL || strs[0] == NULL) + { + free(strs); + return (EVAL_FATAL); + } + if (strs[1] != NULL) + { + errorf("%s: ambiguous redidrect\n", strs[1]); + ft_split_destroy(strs); + return (1); + } + *filename = strs[0]; + free(strs); + return (*filename == NULL ? EVAL_FATAL : 0); +} diff --git a/src/preprocess/interpolation.c b/src/preprocess/interpolation.c new file mode 100644 index 0000000..8845cb2 --- /dev/null +++ b/src/preprocess/interpolation.c @@ -0,0 +1,110 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* interpolation.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: cacharle +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/10/09 15:27:46 by cacharle #+# #+# */ +/* Updated: 2020/10/09 15:32:33 by cacharle ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "eval.h" +#include "lexer.h" +#include "minishell.h" + +static t_tok_lst *st_field_split(char *str) +{ + t_tok_lst *ret; + char *match; + + ret = NULL; + while (*str != '\0') + { + if ((match = ft_strchr(str, ' ')) == NULL) + { + if (tok_lst_push_front(&ret, tok_lst_new(TAG_STR, str)) == NULL) + return (tok_lst_destroy(&ret, free)); + break ; + } + if (tok_lst_push_front(&ret, + tok_lst_new_until(TAG_STR, str, match - str)) == NULL) + return (tok_lst_destroy(&ret, free)); + while (*++match == ' ') + ; + str = match; + if (*str == '\0' && tok_lst_push_front(&ret, + tok_lst_new(TAG_STR, str)) == NULL) + return (tok_lst_destroy(&ret, free)); + } + return ((t_tok_lst *)ft_lstreverse_ret((t_ftlst *)ret)); +} + +size_t interpolate( + char *str, size_t i, t_tok_lst **curr_addr, enum e_tok prev_tag, t_env env) +{ + char *match; + size_t var_len; + t_tok_lst *curr; + char *before; + char *after; + size_t len; + t_tok_lst *fields; + t_tok_lst *last; + t_tok_lst *tmp; + + curr = *curr_addr; + var_len = env_key_len(&str[i + 1], true) + 1; + if ((match = env_search_first_match(env, &str[i + 1])) == NULL) + { + ft_memmove(&str[i], &str[i + var_len], ft_strlen(&str[i + var_len]) + 1); + return (i); + } + str[i] = '\0'; + before = str; + after = &str[i + var_len]; + if (curr->tag & TAG_STR_DOUBLE) + { + curr->content = ft_strjoin3(before, match, after); + free(before); + return (i + ft_strlen(match)); + } + if (curr->tag & TAG_STR) + { + fields = st_field_split(match); + if (fields == NULL) + return (i); + last = tok_lst_last(fields); + len = ft_strlen(last->content); + if (!(prev_tag & TAG_STICK) && *before == '\0' && *fields->content == '\0') + ft_lstpop_front((t_ftlst **)&fields, free); + if (!(curr->tag & TAG_STICK) && *after == '\0' && *last->content == '\0') + ft_lstpop_back((t_ftlst **)&fields, free); + if (fields == NULL) + ; + else if (fields->next == NULL) + { + curr->content = ft_strjoin3(before, fields->content, after); + free(before); + tok_lst_destroy(&fields, free); + return (i + len); + } + else + { + last = tok_lst_last(fields); + last->tag = curr->tag; + curr->tag = TAG_STR; + curr->content = ft_strjoinf_snd(before, fields->content); + last->content = ft_strjoinf_fst(last->content, after); + free(before); + tmp = curr->next; + curr->next = fields->next; + (*curr_addr) = last; + (*curr_addr)->next = tmp; + free(fields); + return (len); + } + } + return (i); +} diff --git a/src/preprocess/preprocess.c b/src/preprocess/preprocess.c new file mode 100644 index 0000000..03ae203 --- /dev/null +++ b/src/preprocess/preprocess.c @@ -0,0 +1,98 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* preprocess.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: charles +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/04/03 08:58:49 by charles #+# #+# */ +/* Updated: 2020/10/09 15:31:33 by cacharle ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "eval.h" +#include "lexer.h" +#include "minishell.h" + +t_tok_lst *st_stick_tokens(t_tok_lst *tokens) +{ + t_tok_lst *curr; + t_tok_lst *tmp; + + curr = tokens; + while (curr != NULL) + { + if (curr->tag & TAG_STICK && curr->next != NULL) + { + curr->content = ft_strjoinf_fst(curr->content, curr->next->content); + tmp = curr->next->next; + curr->tag = curr->next->tag; + ft_lstdelone((t_ftlst *)curr->next, free); + curr->next = tmp; + continue; + } + curr = curr->next; + } + return (tokens); +} + +char **st_tokens_to_argv(t_tok_lst **tokens) +{ + char **ret; + size_t i; + t_tok_lst *curr; + + curr = *tokens; + ret = ft_calloc(ft_lstsize((t_ftlst *)curr) + 1, sizeof(char *)); + if (ret == NULL) + return (NULL); + i = 0; + while (curr != NULL) + { + ret[i++] = curr->content; + curr = curr->next; + } + tok_lst_destroy(tokens, NULL); + return (ret); +} + +bool escape(char *str, enum e_tok tag) +{ + if (str[0] == '\\' && + (tag & TAG_STR || ((tag & TAG_STR_DOUBLE) + && ft_strchr("\\\"$", str[1])))) + { + ft_memmove(str, str + 1, ft_strlen(str + 1) + 1); + return (true); + } + return (false); +} + +char **preprocess(t_tok_lst **tokens, t_env env) +{ + t_tok_lst *curr; + enum e_tok prev_tag; + char *str; + size_t i; + + prev_tag = 0; + curr = *tokens; + while (curr != NULL) + { + if (curr->tag & (TAG_STR | TAG_STR_DOUBLE)) + { + i = -1; + while ((str = curr->content) != NULL && str[++i] != '\0') + { + if (escape(str + i, curr->tag)) + continue; + if (str[i] == '$') + i = interpolate(str, i, &curr, prev_tag, env) - 1; + } + } + prev_tag = curr->tag; + curr = curr->next; + } + st_stick_tokens(*tokens); + return (st_tokens_to_argv(tokens)); +} -- cgit