aboutsummaryrefslogtreecommitdiff
path: root/src/preprocess
diff options
context:
space:
mode:
authorCharles Cabergs <me@cacharle.xyz>2020-10-09 16:13:50 +0200
committerCharles Cabergs <me@cacharle.xyz>2020-10-09 16:13:50 +0200
commit00bce5ad1d5ac92d20617a9eb2647365bf87cab2 (patch)
treeaaad5cbb6cdb6372f5809d50cdc65b912695956f /src/preprocess
parente8075fcf93873149593ccd141f99d65a4db40f4f (diff)
downloadminishell-00bce5ad1d5ac92d20617a9eb2647365bf87cab2.tar.gz
minishell-00bce5ad1d5ac92d20617a9eb2647365bf87cab2.tar.bz2
minishell-00bce5ad1d5ac92d20617a9eb2647365bf87cab2.zip
Splitting preprocessing, Added parsed error helper
Diffstat (limited to 'src/preprocess')
-rw-r--r--src/preprocess/filename.c35
-rw-r--r--src/preprocess/interpolation.c110
-rw-r--r--src/preprocess/preprocess.c98
3 files changed, 243 insertions, 0 deletions
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 <me@cacharle.xyz> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* 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 <me@cacharle.xyz> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* 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 <charles@student.42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* 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));
+}