1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* interpolation.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: cacharle <me@cacharle.xyz> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2020/10/09 15:27:46 by cacharle #+# #+# */
/* Updated: 2020/10/10 10:26:43 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));
}
#define BEFORE 0
#define MATCH 1
#define AFTER 2
static bool st_make_strs(char *strs[3], t_env env, char *str, size_t i)
{
size_t var_len;
var_len = env_key_len(&str[i + 1], true) + 1;
if ((strs[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 (false);
}
str[i] = '\0';
strs[BEFORE] = str;
strs[AFTER] = &str[i + var_len];
return (true);
}
static size_t st_merge_fields_in_curr(
char *strs[3], t_tok_lst **curr, t_tok_lst *fields, size_t len)
{
t_tok_lst *last;
last = tok_lst_last(fields);
last->tag = (*curr)->tag;
(*curr)->tag = TAG_STR;
(*curr)->content = ft_strjoinf_snd(strs[BEFORE], fields->content);
last->content = ft_strjoinf_fst(last->content, strs[AFTER]);
free(strs[BEFORE]);
last->next = (*curr)->next;
(*curr)->next = fields->next;
(*curr) = last;
free(fields);
return (len);
}
static size_t st_interpolate_non_quoted(
char *strs[3], t_tok_lst **curr, size_t i, enum e_tok prev_tag)
{
t_tok_lst *fields;
size_t len;
fields = st_field_split(strs[MATCH]);
if (fields == NULL)
return (i);
len = ft_strlen(tok_lst_last(fields)->content);
if (!(prev_tag & TAG_STICK) && *strs[BEFORE] == '\0' &&
*fields->content == '\0')
ft_lstpop_front((t_ftlst **)&fields, free);
if (!((*curr)->tag & TAG_STICK) && *strs[AFTER] == '\0' &&
*tok_lst_last(fields)->content == '\0')
ft_lstpop_back((t_ftlst **)&fields, free);
if (fields != NULL && fields->next == NULL)
{
(*curr)->content =
ft_strjoin3(strs[BEFORE], fields->content, strs[AFTER]);
free(strs[BEFORE]);
tok_lst_destroy(&fields, free);
return (i + len);
}
else if (fields != NULL)
return (st_merge_fields_in_curr(strs, curr, fields, len));
return (i);
}
size_t interpolate(
void *ptrs[2], size_t i, enum e_tok prev_tag, t_env env)
{
char *strs[3];
char *str;
t_tok_lst **curr;
str = ptrs[INTERPOLATION_STR];
curr = ptrs[INTERPOLATION_CURR];
if (!st_make_strs(strs, env, str, i))
return (i);
if ((*curr)->tag & TAG_STR_DOUBLE)
{
(*curr)->content = ft_strjoin3(strs[BEFORE], strs[MATCH], strs[AFTER]);
free(strs[BEFORE]);
return (i + ft_strlen(strs[MATCH]));
}
return (st_interpolate_non_quoted(strs, curr, i, prev_tag));
}
|