diff options
| author | Charles Cabergs <me@cacharle.xyz> | 2020-10-09 16:13:50 +0200 |
|---|---|---|
| committer | Charles Cabergs <me@cacharle.xyz> | 2020-10-09 16:13:50 +0200 |
| commit | 00bce5ad1d5ac92d20617a9eb2647365bf87cab2 (patch) | |
| tree | aaad5cbb6cdb6372f5809d50cdc65b912695956f /src | |
| parent | e8075fcf93873149593ccd141f99d65a4db40f4f (diff) | |
| download | minishell-00bce5ad1d5ac92d20617a9eb2647365bf87cab2.tar.gz minishell-00bce5ad1d5ac92d20617a9eb2647365bf87cab2.tar.bz2 minishell-00bce5ad1d5ac92d20617a9eb2647365bf87cab2.zip | |
Splitting preprocessing, Added parsed error helper
Diffstat (limited to 'src')
| -rw-r--r-- | src/eval/eval.c | 4 | ||||
| -rw-r--r-- | src/eval/operation.c | 4 | ||||
| -rw-r--r-- | src/lexer/lexer.c | 12 | ||||
| -rw-r--r-- | src/lexer/tok_lst.c | 16 | ||||
| -rw-r--r-- | src/lexer/trim.c | 6 | ||||
| -rw-r--r-- | src/lexer/utils.c | 26 | ||||
| -rw-r--r-- | src/main.c | 34 | ||||
| -rw-r--r-- | src/parser/parsed.c | 18 | ||||
| -rw-r--r-- | src/parser/parser.c | 42 | ||||
| -rw-r--r-- | src/preprocess.c | 215 | ||||
| -rw-r--r-- | src/preprocess/filename.c | 35 | ||||
| -rw-r--r-- | src/preprocess/interpolation.c | 110 | ||||
| -rw-r--r-- | src/preprocess/preprocess.c | 98 |
13 files changed, 332 insertions, 288 deletions
diff --git a/src/eval/eval.c b/src/eval/eval.c index 0df8b85..032fc30 100644 --- a/src/eval/eval.c +++ b/src/eval/eval.c @@ -6,7 +6,7 @@ /* By: charles <me@cacharle.xyz> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/09/13 20:38:06 by charles #+# #+# */ -/* Updated: 2020/10/09 14:03:31 by cacharle ### ########.fr */ +/* Updated: 2020/10/09 16:12:27 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -64,7 +64,7 @@ int eval(int fds[2], t_env env, t_ast *ast) if (ast->tag == AST_CMD) return (eval_cmd(fds, env, ast)); if (ast->tag == AST_PIPELINE) - return (eval_pipeline(fds, env, ast)); + return (eval_pipeline(env, ast)); if (ast->tag == AST_PARENT) return (eval_parenthesis(fds, env, ast)); return (EVAL_FATAL); diff --git a/src/eval/operation.c b/src/eval/operation.c index 19ecec7..f1daa0b 100644 --- a/src/eval/operation.c +++ b/src/eval/operation.c @@ -6,7 +6,7 @@ /* By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/06/17 15:27:22 by charles #+# #+# */ -/* Updated: 2020/10/09 14:54:43 by cacharle ### ########.fr */ +/* Updated: 2020/10/09 16:12:14 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -62,7 +62,7 @@ static int st_run_piped( return (pid); } -int eval_pipeline(int fds[2], t_env env, t_ast *ast) +int eval_pipeline(t_env env, t_ast *ast) { t_ftlst *curr; int pipes[3]; diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index 9b947f4..5df63ba 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -6,15 +6,14 @@ /* By: nahaddac <nahaddac@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/07/16 08:18:25 by nahaddac #+# #+# */ -/* Updated: 2020/10/09 12:29:32 by cacharle ### ########.fr */ +/* Updated: 2020/10/09 15:12:51 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ #include "lexer.h" #include <stdio.h> -// len until meaningful character for non quoted str -int len_until_sep(char *input) +int len_until_sep(char *input) { int i; @@ -40,7 +39,6 @@ int len_until_sep(char *input) return (i); } -// token content length int tok_len(char *input) { int i; @@ -74,10 +72,10 @@ int tok_len(char *input) ** return all token */ -t_tok_lst *create_token_list(char *input, t_tok_lst **lst) +t_tok_lst *create_token_list(char *input, t_tok_lst **lst) { t_tok_lst *tok; - size_t i; + size_t i; size_t j; size_t len; @@ -105,7 +103,7 @@ t_tok_lst *create_token_list(char *input, t_tok_lst **lst) ** \return The created tokens or NULL on error */ -int lexer(char *input, t_tok_lst **out) +int lexer(char *input, t_tok_lst **out) { int status; diff --git a/src/lexer/tok_lst.c b/src/lexer/tok_lst.c index 9ae0ce1..89ab120 100644 --- a/src/lexer/tok_lst.c +++ b/src/lexer/tok_lst.c @@ -6,7 +6,7 @@ /* By: charles <me@cacharle.xyz> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/08/27 09:32:58 by charles #+# #+# */ -/* Updated: 2020/10/08 17:38:59 by cacharle ### ########.fr */ +/* Updated: 2020/10/09 15:14:38 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,7 +14,8 @@ t_tok_lst *tok_lst_new(enum e_tok tag, char *content) { - return (tok_lst_new_until(tag, content, content == NULL ? 0 : ft_strlen(content))); + return (tok_lst_new_until( + tag, content, content == NULL ? 0 : ft_strlen(content))); } /* @@ -25,14 +26,15 @@ t_tok_lst *tok_lst_new(enum e_tok tag, char *content) ** \return An allocated tok_lst or NULL on error */ -t_tok_lst *tok_lst_new_until(enum e_tok tag, char *content, size_t n) +t_tok_lst *tok_lst_new_until( + enum e_tok tag, char *content, size_t n) { t_tok_lst *ret; if ((ret = malloc(sizeof(t_tok_lst))) == NULL) return (NULL); if (content == NULL) - ret->content = NULL; + ret->content = NULL; else if ((ret->content = ft_strndup(content, n)) == NULL) { free(ret); @@ -48,7 +50,8 @@ void tok_lst_push_back(t_tok_lst **tokens, t_tok_lst *pushed) ft_lstpush_back((t_ftlst**)tokens, (t_ftlst*)pushed); } -t_tok_lst *tok_lst_push_front(t_tok_lst **tokens, t_tok_lst *pushed) +t_tok_lst *tok_lst_push_front( + t_tok_lst **tokens, t_tok_lst *pushed) { if (pushed == NULL) return (NULL); @@ -56,7 +59,8 @@ t_tok_lst *tok_lst_push_front(t_tok_lst **tokens, t_tok_lst *pushed) return (*tokens); } -void tok_lst_pop_front(t_tok_lst **tokens, void (*del)(void*)) +void tok_lst_pop_front( + t_tok_lst **tokens, void (*del)(void*)) { ft_lstpop_front((t_ftlst**)tokens, del); } diff --git a/src/lexer/trim.c b/src/lexer/trim.c index 0f3279b..d0ba90a 100644 --- a/src/lexer/trim.c +++ b/src/lexer/trim.c @@ -6,13 +6,11 @@ /* By: nahaddac <nahaddac@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/07/16 08:18:36 by nahaddac #+# #+# */ -/* Updated: 2020/10/07 10:36:41 by cacharle ### ########.fr */ +/* Updated: 2020/10/09 15:17:45 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ - #include "lexer.h" -#include <stdio.h> void del_space(char *str) { @@ -32,7 +30,7 @@ void del_space(char *str) } } -int del_quote(char *str) +int del_quote(char *str) { size_t i; size_t quote_counter; diff --git a/src/lexer/utils.c b/src/lexer/utils.c index 0b7baa3..624b460 100644 --- a/src/lexer/utils.c +++ b/src/lexer/utils.c @@ -6,14 +6,13 @@ /* By: nahaddac <nahaddac@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/07/16 08:18:15 by nahaddac #+# #+# */ -/* Updated: 2020/10/08 14:11:51 by cacharle ### ########.fr */ +/* Updated: 2020/10/09 15:24:31 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ #include "lexer.h" -// return token tag corresponding to string id -enum e_tok tok_assign_tag(char *content) +enum e_tok tok_assign_tag(char *content) { if (content[0] == ';') return (TAG_END); @@ -21,7 +20,7 @@ enum e_tok tok_assign_tag(char *content) return (TAG_AND); if (ft_strncmp(content, "||", 2) == 0) return (TAG_OR); - if(content[0] == '|') + if (content[0] == '|') return (TAG_PIPE); if (content[0] == '>') return (TAG_REDIR_OUT); @@ -42,14 +41,13 @@ enum e_tok tok_assign_tag(char *content) ** a la fin (char *)tk->tok ne figure pas d'espace. */ -enum e_tok tok_assign_stick(t_tok_lst *tok) +enum e_tok tok_assign_stick(t_tok_lst *tok) { int i; i = ft_strlen(tok->content); - if (i > 0) - if (ft_isblank(tok->content[i - 1])) - return (tok->tag); + if (i > 0 && ft_isblank(tok->content[i - 1])) + return (tok->tag); return (tok->tag | TAG_STICK); } @@ -58,7 +56,8 @@ enum e_tok tok_assign_stick(t_tok_lst *tok) ** la chaine de character est un str où '' où '' ** \note the loop after ft_strpbrk is to search again if the quote was escaped */ -enum e_tok tok_assign_str(t_tok_lst *tok) + +enum e_tok tok_assign_str(t_tok_lst *tok) { char *found; @@ -74,20 +73,17 @@ enum e_tok tok_assign_str(t_tok_lst *tok) return (tok_assign_stick(tok)); } - -// check is char is separator -int lexer_sep(char c) +int lexer_sep(char c) { return (ft_strchr(";&|><()", c) != NULL); } -// number of starting space character -int lexer_space(char *input) +int lexer_space(char *input) { return (ft_strspn(input, " \t")); } -int quote_len(char *input, int i) +int quote_len(char *input, int i) { char quote_type; @@ -6,7 +6,7 @@ /* By: cacharle <cacharle@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/02/28 11:45:44 by cacharle #+# #+# */ -/* Updated: 2020/10/09 13:57:22 by cacharle ### ########.fr */ +/* Updated: 2020/10/09 15:51:00 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -25,12 +25,27 @@ int debug_parser(char *input); t_state g_state; +int run_eval(t_env env, t_parsed *parser_out) +{ + int status; + int fds[2]; + + fds[0] = FD_NONE; + fds[1] = FD_NONE; + status = eval(fds, env, parser_out->ast); + ast_destroy(parser_out->ast); + free(parser_out); + if (status == EVAL_FATAL) + exit(1); + g_state.last_status = status; + return (status); +} + int execute(t_env env, char *input) { t_tok_lst *lexer_out; int status; t_parsed *parser_out; - int fds[2]; if (utils_strisblank(input)) return (0); @@ -46,15 +61,7 @@ int execute(t_env env, char *input) free(parser_out); return (2); } - fds[0] = FD_NONE; - fds[1] = FD_NONE; - status = eval(fds, env, parser_out->ast); - ast_destroy(parser_out->ast); - free(parser_out); - if (status == EVAL_FATAL) - exit(1); - g_state.last_status = status; - return (status); + return (run_eval(env, parser_out)); } int repl(t_env env) @@ -65,11 +72,6 @@ int repl(t_env env) print_prompt(); while ((ret = ft_getline(STDIN_FILENO, &line)) == FTGL_OK) { - if (*line == '\0') - { - print_prompt(); - continue ; - } g_state.killed = false; if (execute(env, line) == EVAL_FATAL) return (2); diff --git a/src/parser/parsed.c b/src/parser/parsed.c index a2b569a..7b82832 100644 --- a/src/parser/parsed.c +++ b/src/parser/parsed.c @@ -6,7 +6,7 @@ /* By: charles <me@cacharle.xyz> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/08/27 20:27:42 by charles #+# #+# */ -/* Updated: 2020/10/09 14:08:46 by cacharle ### ########.fr */ +/* Updated: 2020/10/09 16:00:02 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -38,3 +38,19 @@ t_parsed *parsed_error(const char *format, ...) ft_putchar_fd('\n', STDERR_FILENO); return (err); } + +t_parsed *parsed_expected(void) +{ + return (parsed_error("syntax error expected token")); +} + +t_parsed *parsed_unexpected(char *content) +{ + return (parsed_error("syntax error near unexpected token `%s'", content)); +} + +void parsed_destroy(t_parsed *parsed) +{ + ast_destroy(parsed->ast); + free(parsed); +} diff --git a/src/parser/parser.c b/src/parser/parser.c index 8d5a0aa..be71097 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -6,7 +6,7 @@ /* By: nahaddac <nahaddac@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/06/17 18:09:04 by nahaddac #+# #+# */ -/* Updated: 2020/10/09 14:30:29 by cacharle ### ########.fr */ +/* Updated: 2020/10/09 16:10:31 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -20,12 +20,12 @@ static char *g_sep_str_lookup[] = { [TAG_END] = ";", - [TAG_AND] = "&&", [TAG_OR] = "||", - [TAG_PIPE] = "|", [TAG_REDIR_IN] = "<", [TAG_REDIR_APPEND] = ">>", [TAG_PARENT_CLOSE] = ")", + [TAG_AND] = "&&", + [TAG_PIPE] = "|", [TAG_REDIR_OUT] = ">", [TAG_PARENT_OPEN] = "(", }; @@ -38,17 +38,18 @@ static char *g_sep_str_lookup[] = { t_parsed *parse_redir(t_tok_lst *input, t_tok_lst **redirs) { - t_parsed *ret; + t_parsed *ret; tok_lst_push_back(redirs, tok_lst_uncons(&input)); - while (input != NULL && input->tag & TAG_IS_STR && input->tag & TAG_STICK && + while (input != NULL && input->tag & TAG_IS_STR && + input->tag & TAG_STICK && input->next != NULL && input->next->tag & TAG_IS_STR) tok_lst_push_back(redirs, tok_lst_uncons(&input)); if (input == NULL) - return (parsed_error("syntax error near unexpected token `newline'")); + return (parsed_unexpected("newline")); if (!(input->tag & TAG_IS_STR)) { - ret = parsed_error("syntax error near unexpected token `%s'", input->content); + ret = parsed_unexpected(input->content); tok_lst_destroy(&input, free); return (ret); } @@ -60,12 +61,14 @@ t_parsed *parse_cmd(t_tok_lst *input) { t_ast *ast; t_parsed *tmp; + t_parsed *ret; - if (input->tag & TAG_IS_SEP || input->tag == TAG_PIPE || input->tag == TAG_PARENT_CLOSE) + if (input->tag & TAG_IS_SEP || input->tag == TAG_PIPE || + input->tag == TAG_PARENT_CLOSE) { - tmp = parsed_error("syntax error near unexpected token `%s'", input->content); + ret = parsed_unexpected(input->content); tok_lst_destroy(&input, free); - return (tmp); + return (ret); } if ((ast = ast_new(AST_CMD)) == NULL) return (NULL); @@ -99,14 +102,15 @@ t_parsed *parse_pipeline(t_tok_lst *input) t_ast *pipeline_ast; expr = parse_expr(input); - if (expr == NULL || expr->syntax_error || expr->rest == NULL || expr->rest->tag != TAG_PIPE) + if (expr == NULL || expr->syntax_error || + expr->rest == NULL || expr->rest->tag != TAG_PIPE) return (expr); tok_lst_pop_front(&expr->rest, free); if (expr->rest == NULL) { ast_destroy(expr->ast); free(expr); - return (parsed_error("syntax error expected token")); + return (parsed_expected()); } tail = parse_pipeline(expr->rest); if (tail == NULL || tail->syntax_error) @@ -154,8 +158,7 @@ t_parsed *parse_op(t_tok_lst *input) ast_destroy(left->ast); tok_lst_destroy(&left->rest, free); free(left); - return (parsed_error( - "syntax error near unexpected token `%s'", g_sep_str_lookup[sep_tag])); + return (parsed_unexpected(g_sep_str_lookup[sep_tag])); } tok_lst_pop_front(&input, free); if (input == NULL && sep_tag == TAG_END) @@ -167,7 +170,7 @@ t_parsed *parse_op(t_tok_lst *input) { ast_destroy(left->ast); free(left); - return (parsed_error("syntax error expected token")); + return (parsed_expected()); } right = parse_op(input); if (right == NULL || right->syntax_error) @@ -202,7 +205,7 @@ t_parsed *parse_expr(t_tok_lst *input) { tok_lst_pop_front(&input, free); if (input == NULL) - return (parsed_error("syntax error expected token")); + return (parsed_expected()); parsed = parse_op(input); if (parsed == NULL || parsed->syntax_error) return (parsed); @@ -211,7 +214,7 @@ t_parsed *parse_expr(t_tok_lst *input) { ast_destroy(parsed->ast); free(parsed); - return (parsed_error("syntax error expected token")); + return (parsed_expected()); } tok_lst_pop_front(&input, free); if ((ast = ast_new(AST_PARENT)) == NULL) @@ -223,8 +226,8 @@ t_parsed *parse_expr(t_tok_lst *input) tmp = parse_redir(input, &parsed->ast->redirs); if (tmp == NULL || tmp->syntax_error) return (tmp); - input = tmp->rest; free(tmp); + input = tmp->rest; } parsed->rest = input; return (parsed); @@ -244,8 +247,7 @@ t_parsed *parse(t_tok_lst *input) return (parsed); if (parsed->rest != NULL) { - ret = parsed_error( - "syntax error near unexpected token `%s'", parsed->rest->content); + ret = parsed_unexpected(parsed->rest->content); tok_lst_destroy(&parsed->rest, free); ast_destroy(parsed->ast); free(parsed); diff --git a/src/preprocess.c b/src/preprocess.c deleted file mode 100644 index 7f37a97..0000000 --- a/src/preprocess.c +++ /dev/null @@ -1,215 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* preprocess.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: charles <charles@student.42.fr> +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2020/04/03 08:58:49 by charles #+# #+# */ -/* Updated: 2020/10/08 09:58:48 by cacharle ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "minishell.h" -#include "lexer.h" -#include "eval.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)); -} - - -t_tok_lst *st_stick_tokens(t_tok_lst *tokens) -{ - t_tok_lst *curr; - - curr = tokens; - while (curr != NULL) - { - // curr->next shouldn't be null - if (curr->tag & TAG_STICK && curr->next != NULL) - { - curr->content = ft_strjoinf_fst(curr->content, curr->next->content); - t_tok_lst *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); -} - -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; - - 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); - - t_tok_lst *tmp = curr->next; - curr->next = fields->next; - (*curr_addr) = last; - (*curr_addr)->next = tmp; - free(fields); - return len; - } - } - return i; -} - -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)); -} - -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/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)); +} |
