save commit
This commit is contained in:
113
minishell-codex/src/parser/expand.c
Normal file
113
minishell-codex/src/parser/expand.c
Normal file
@@ -0,0 +1,113 @@
|
||||
#include "minishell.h"
|
||||
|
||||
static void buf_append(char **buf, size_t *len, size_t *cap, const char *s)
|
||||
{
|
||||
size_t slen;
|
||||
char *newbuf;
|
||||
|
||||
if (!s)
|
||||
return;
|
||||
slen = strlen(s);
|
||||
if (*len + slen + 1 > *cap)
|
||||
{
|
||||
*cap = (*len + slen + 1) * 2;
|
||||
newbuf = (char *)realloc(*buf, *cap);
|
||||
if (!newbuf)
|
||||
return;
|
||||
*buf = newbuf;
|
||||
}
|
||||
memcpy(*buf + *len, s, slen);
|
||||
*len += slen;
|
||||
(*buf)[*len] = '\0';
|
||||
}
|
||||
|
||||
static void buf_append_char(char **buf, size_t *len, size_t *cap, char c)
|
||||
{
|
||||
char tmp[2];
|
||||
tmp[0] = c;
|
||||
tmp[1] = '\0';
|
||||
buf_append(buf, len, cap, tmp);
|
||||
}
|
||||
|
||||
static char *expand_word(const char *word, t_shell *sh)
|
||||
{
|
||||
int in_single = 0;
|
||||
int in_double = 0;
|
||||
size_t i = 0;
|
||||
char *out = NULL;
|
||||
size_t len = 0, cap = 0;
|
||||
|
||||
while (word && word[i])
|
||||
{
|
||||
if (word[i] == '\'' && !in_double)
|
||||
{
|
||||
in_single = !in_single;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (word[i] == '"' && !in_single)
|
||||
{
|
||||
in_double = !in_double;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (word[i] == '$' && !in_single)
|
||||
{
|
||||
if (word[i + 1] == '?')
|
||||
{
|
||||
char *v = ms_itoa(sh->last_status);
|
||||
buf_append(&out, &len, &cap, v);
|
||||
free(v);
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
if (ms_is_alpha((unsigned char)word[i + 1]))
|
||||
{
|
||||
size_t j = i + 1;
|
||||
while (word[j] && ms_is_alnum((unsigned char)word[j]))
|
||||
j++;
|
||||
char *name = ms_strndup(word + i + 1, j - (i + 1));
|
||||
char *val = env_get(sh, name);
|
||||
buf_append(&out, &len, &cap, val ? val : "");
|
||||
free(name);
|
||||
i = j;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
buf_append_char(&out, &len, &cap, word[i]);
|
||||
i++;
|
||||
}
|
||||
if (!out)
|
||||
out = ms_strdup("");
|
||||
return out;
|
||||
}
|
||||
|
||||
int expand_pipeline(t_pipeline *p, t_shell *sh)
|
||||
{
|
||||
size_t i;
|
||||
int j;
|
||||
for (i = 0; i < p->count; i++)
|
||||
{
|
||||
for (j = 0; p->cmds[i]->argv && p->cmds[i]->argv[j]; j++)
|
||||
{
|
||||
char *neww = expand_word(p->cmds[i]->argv[j], sh);
|
||||
free(p->cmds[i]->argv[j]);
|
||||
p->cmds[i]->argv[j] = neww;
|
||||
}
|
||||
if (p->cmds[i]->redirs)
|
||||
{
|
||||
t_redir *r = p->cmds[i]->redirs;
|
||||
while (r)
|
||||
{
|
||||
if (r->target)
|
||||
{
|
||||
char *nt = expand_word(r->target, sh);
|
||||
free(r->target);
|
||||
r->target = nt;
|
||||
}
|
||||
r = r->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
131
minishell-codex/src/parser/lexer.c
Normal file
131
minishell-codex/src/parser/lexer.c
Normal file
@@ -0,0 +1,131 @@
|
||||
#include "minishell.h"
|
||||
|
||||
static t_token *token_new(t_tokentype type, const char *text, size_t len)
|
||||
{
|
||||
t_token *t = (t_token *)calloc(1, sizeof(t_token));
|
||||
if (!t)
|
||||
return NULL;
|
||||
t->type = type;
|
||||
if (text)
|
||||
t->text = ms_strndup(text, len);
|
||||
return t;
|
||||
}
|
||||
|
||||
static void token_add(t_token **head, t_token *new)
|
||||
{
|
||||
t_token *cur;
|
||||
if (!new)
|
||||
return;
|
||||
if (!*head)
|
||||
{
|
||||
*head = new;
|
||||
return;
|
||||
}
|
||||
cur = *head;
|
||||
while (cur->next)
|
||||
cur = cur->next;
|
||||
cur->next = new;
|
||||
}
|
||||
|
||||
void free_tokens(t_token *toks)
|
||||
{
|
||||
t_token *n;
|
||||
while (toks)
|
||||
{
|
||||
n = toks->next;
|
||||
free(toks->text);
|
||||
free(toks);
|
||||
toks = n;
|
||||
}
|
||||
}
|
||||
|
||||
static int is_meta(char c)
|
||||
{
|
||||
return (c == '|' || c == '<' || c == '>');
|
||||
}
|
||||
|
||||
static int read_word(const char *line, size_t *i, t_token **out)
|
||||
{
|
||||
size_t start = *i;
|
||||
int in_single = 0;
|
||||
int in_double = 0;
|
||||
|
||||
while (line[*i])
|
||||
{
|
||||
if (line[*i] == '\'' && !in_double)
|
||||
in_single = !in_single;
|
||||
else if (line[*i] == '"' && !in_single)
|
||||
in_double = !in_double;
|
||||
else if (!in_single && !in_double)
|
||||
{
|
||||
if (ms_is_space(line[*i]) || is_meta(line[*i]))
|
||||
break;
|
||||
}
|
||||
(*i)++;
|
||||
}
|
||||
if (in_single || in_double)
|
||||
return 1;
|
||||
*out = token_new(TOK_WORD, line + start, *i - start);
|
||||
return 0;
|
||||
}
|
||||
|
||||
t_token *lex_line(const char *line, int *error)
|
||||
{
|
||||
t_token *toks = NULL;
|
||||
size_t i = 0;
|
||||
|
||||
*error = 0;
|
||||
while (line[i])
|
||||
{
|
||||
if (ms_is_space(line[i]))
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (line[i] == '|')
|
||||
{
|
||||
token_add(&toks, token_new(TOK_PIPE, "|", 1));
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (line[i] == '<')
|
||||
{
|
||||
if (line[i + 1] == '<')
|
||||
{
|
||||
token_add(&toks, token_new(TOK_HEREDOC, "<<", 2));
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
token_add(&toks, token_new(TOK_REDIR_IN, "<", 1));
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (line[i] == '>')
|
||||
{
|
||||
if (line[i + 1] == '>')
|
||||
{
|
||||
token_add(&toks, token_new(TOK_REDIR_APPEND, ">>", 2));
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
token_add(&toks, token_new(TOK_REDIR_OUT, ">", 1));
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
{
|
||||
t_token *w = NULL;
|
||||
if (read_word(line, &i, &w))
|
||||
{
|
||||
*error = 1;
|
||||
free_tokens(toks);
|
||||
return NULL;
|
||||
}
|
||||
token_add(&toks, w);
|
||||
}
|
||||
}
|
||||
return toks;
|
||||
}
|
||||
175
minishell-codex/src/parser/parser.c
Normal file
175
minishell-codex/src/parser/parser.c
Normal file
@@ -0,0 +1,175 @@
|
||||
#include "minishell.h"
|
||||
|
||||
static t_command *command_new(void)
|
||||
{
|
||||
t_command *cmd = (t_command *)calloc(1, sizeof(t_command));
|
||||
return cmd;
|
||||
}
|
||||
|
||||
static void command_add_arg(t_command *cmd, const char *text)
|
||||
{
|
||||
char **new_argv;
|
||||
int i;
|
||||
|
||||
if (!cmd || !text)
|
||||
return;
|
||||
i = cmd->argc;
|
||||
new_argv = (char **)calloc((size_t)i + 2, sizeof(char *));
|
||||
if (!new_argv)
|
||||
return;
|
||||
for (int j = 0; j < i; j++)
|
||||
new_argv[j] = cmd->argv[j];
|
||||
new_argv[i] = ms_strdup(text);
|
||||
new_argv[i + 1] = NULL;
|
||||
free(cmd->argv);
|
||||
cmd->argv = new_argv;
|
||||
cmd->argc += 1;
|
||||
}
|
||||
|
||||
static void command_add_redir(t_command *cmd, t_redirtype type, const char *target)
|
||||
{
|
||||
t_redir *r = (t_redir *)calloc(1, sizeof(t_redir));
|
||||
t_redir *cur;
|
||||
if (!r)
|
||||
return;
|
||||
r->type = type;
|
||||
r->target = ms_strdup(target);
|
||||
r->fd = -1;
|
||||
r->next = NULL;
|
||||
if (!cmd->redirs)
|
||||
{
|
||||
cmd->redirs = r;
|
||||
return;
|
||||
}
|
||||
cur = cmd->redirs;
|
||||
while (cur->next)
|
||||
cur = cur->next;
|
||||
cur->next = r;
|
||||
}
|
||||
|
||||
static void free_redirs(t_redir *r)
|
||||
{
|
||||
t_redir *n;
|
||||
while (r)
|
||||
{
|
||||
n = r->next;
|
||||
if (r->fd != -1)
|
||||
close(r->fd);
|
||||
free(r->target);
|
||||
free(r);
|
||||
r = n;
|
||||
}
|
||||
}
|
||||
|
||||
void free_pipeline(t_pipeline *p)
|
||||
{
|
||||
size_t i;
|
||||
if (!p)
|
||||
return;
|
||||
for (i = 0; i < p->count; i++)
|
||||
{
|
||||
if (p->cmds[i])
|
||||
{
|
||||
for (int j = 0; p->cmds[i]->argv && p->cmds[i]->argv[j]; j++)
|
||||
free(p->cmds[i]->argv[j]);
|
||||
free(p->cmds[i]->argv);
|
||||
free(p->cmds[i]->path);
|
||||
free_redirs(p->cmds[i]->redirs);
|
||||
free(p->cmds[i]);
|
||||
}
|
||||
}
|
||||
free(p->cmds);
|
||||
free(p);
|
||||
}
|
||||
|
||||
static int pipeline_add_cmd(t_pipeline *p, t_command *cmd)
|
||||
{
|
||||
t_command **new_cmds;
|
||||
size_t i;
|
||||
|
||||
new_cmds = (t_command **)calloc(p->count + 1, sizeof(t_command *));
|
||||
if (!new_cmds)
|
||||
return 1;
|
||||
for (i = 0; i < p->count; i++)
|
||||
new_cmds[i] = p->cmds[i];
|
||||
new_cmds[p->count] = cmd;
|
||||
free(p->cmds);
|
||||
p->cmds = new_cmds;
|
||||
p->count += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
t_pipeline *parse_tokens(t_token *toks, int *error)
|
||||
{
|
||||
t_pipeline *p;
|
||||
t_command *cmd;
|
||||
t_token *cur;
|
||||
|
||||
*error = 0;
|
||||
p = (t_pipeline *)calloc(1, sizeof(t_pipeline));
|
||||
if (!p)
|
||||
return NULL;
|
||||
cmd = command_new();
|
||||
if (!cmd)
|
||||
{
|
||||
free(p);
|
||||
return NULL;
|
||||
}
|
||||
cur = toks;
|
||||
while (cur)
|
||||
{
|
||||
if (cur->type == TOK_PIPE)
|
||||
{
|
||||
if (cmd->argc == 0)
|
||||
{
|
||||
*error = 1;
|
||||
free_pipeline(p);
|
||||
free(cmd);
|
||||
return NULL;
|
||||
}
|
||||
pipeline_add_cmd(p, cmd);
|
||||
cmd = command_new();
|
||||
if (!cmd)
|
||||
{
|
||||
*error = 1;
|
||||
free_pipeline(p);
|
||||
return NULL;
|
||||
}
|
||||
cur = cur->next;
|
||||
continue;
|
||||
}
|
||||
if (cur->type == TOK_REDIR_IN || cur->type == TOK_REDIR_OUT
|
||||
|| cur->type == TOK_REDIR_APPEND || cur->type == TOK_HEREDOC)
|
||||
{
|
||||
if (!cur->next || cur->next->type != TOK_WORD)
|
||||
{
|
||||
*error = 1;
|
||||
free_pipeline(p);
|
||||
free(cmd);
|
||||
return NULL;
|
||||
}
|
||||
if (cur->type == TOK_REDIR_IN)
|
||||
command_add_redir(cmd, REDIR_IN, cur->next->text);
|
||||
else if (cur->type == TOK_REDIR_OUT)
|
||||
command_add_redir(cmd, REDIR_OUT, cur->next->text);
|
||||
else if (cur->type == TOK_REDIR_APPEND)
|
||||
command_add_redir(cmd, REDIR_APPEND, cur->next->text);
|
||||
else if (cur->type == TOK_HEREDOC)
|
||||
command_add_redir(cmd, REDIR_HEREDOC, cur->next->text);
|
||||
cur = cur->next->next;
|
||||
continue;
|
||||
}
|
||||
if (cur->type == TOK_WORD)
|
||||
command_add_arg(cmd, cur->text);
|
||||
cur = cur->next;
|
||||
}
|
||||
if (cmd->argc == 0)
|
||||
{
|
||||
*error = 1;
|
||||
free_pipeline(p);
|
||||
free(cmd);
|
||||
return NULL;
|
||||
}
|
||||
pipeline_add_cmd(p, cmd);
|
||||
return p;
|
||||
}
|
||||
Reference in New Issue
Block a user