Bsh/src/lexer/alias.c

279 lines
7.9 KiB
C

#include "bsh.h"
#include "lexer_tools.h"
extern struct shell *shell;
struct lexer_alias *get_alias(char *name)
{
struct lexer_alias *head = shell->alias_list;
while (head)
{
if (head->name && !strcmp(head->name, name))
return head;
head = head->next;
}
return NULL;
}
static char *get_token_string(enum token_type type)
{
char *token_string[] = { "",
"if",
"else",
"elif",
"fi",
"then",
"do",
"done",
"while",
"until",
"for",
"in",
"&&",
"||",
";",
"\n",
"REDIR",
"IONUMBER",
"|",
"!",
"ASSIGNMENT_WORD",
"(",
"$(",
"`",
")",
"{",
"}",
"$",
"case",
"esac",
"WORD",
"WORD_DOUBLE_QUOTE",
"WORD_SINGLE_QUOTE",
"EOF",
" " };
return strdup(token_string[type]);
}
static char *get_alias_value(struct lexer_token *head)
{
char *res = NULL;
while (head)
{
size_t len = res ? strlen(res) : 0;
char *to_append =
head->value ? head->value : get_token_string(head->type);
res = realloc(res, sizeof(char) * (len + strlen(to_append) + 1));
res[len] = '\0';
strcat(res, to_append);
if (!head->value)
free(to_append);
head = head->next;
}
return res;
}
void lexer_append_alias(struct lexer *lexer, struct lexer_alias *alias)
{
struct lexer_token *token = alias->value;
while (token)
{
struct lexer_token *new = calloc(1, sizeof(struct lexer_token));
new->type = token->type;
if (token->value)
new->value = strdup(token->value);
else
new->value = NULL;
lexer_append(lexer, new);
token = token->next;
}
}
struct lexer_token *copy_lexer_alias(struct lexer_token *head)
{
struct lexer_token *new_head = calloc(1, sizeof(struct lexer_token));
new_head->type = head->type;
if (head->value)
new_head->value = strdup(head->value);
head = head->next;
struct lexer_token *current_tail = head;
while (head)
{
struct lexer_token *new_token = calloc(1, sizeof(struct lexer_token));
new_token->type = head->type;
if (head->value)
new_token->value = strdup(head->value);
current_tail->next = new_token;
current_tail = new_token;
head = head->next;
}
return new_head;
}
static void process_single_alias(struct lexer *lexer, char *name,
struct lexer_token *value)
{
if (value)
{
struct lexer_alias *alias = calloc(1, sizeof(struct lexer_alias));
alias->name = strdup(name);
if (value->type != TOKEN_NEWLINE && value->type != TOKEN_SEMICOLON
&& value->type != TOKEN_EOF)
alias->value = value;
else
{
struct lexer_token *token = calloc(1, sizeof(struct lexer_token));
token->type = TOKEN_WORD;
token->value = strdup("");
alias->value = token;
}
alias->next = lexer->alias_list;
lexer->alias_list = alias;
shell->return_code = 0;
}
else
{
struct lexer_alias *alias = get_alias(name);
if (!alias)
{
shell->return_code = 1;
fprintf(stderr, "bsh: alias: %s: not found\n", name);
}
else
{
char *a_value = get_alias_value(alias->value);
printf("%s='%s'\n", alias->name, a_value);
free(a_value);
shell->return_code = 0;
}
}
}
void process_alias(struct lexer_token *prev, struct lexer_token *head,
struct lexer *lexer)
{
shell->return_code = 0;
if (!head
|| (head->type != TOKEN_ALIAS && head->type != TOKEN_SPACE
&& head->type != TOKEN_ASSIGNMENT_WORD && head->type != TOKEN_WORD
&& head->type != TOKEN_WORD_SINGLE_QUOTE
&& head->type != TOKEN_WORD_DOUBLE_QUOTE))
{
if (head
&& (head->type == TOKEN_SEMICOLON || head->type == TOKEN_NEWLINE))
{
if (prev)
prev->next = head->next;
else
lexer->tokens = head->next;
lexer_token_free(head);
}
return;
}
struct lexer_token *name = head;
if (head->type == TOKEN_ALIAS && head->next)
{
name = head->next;
lexer_token_free(head);
}
while (name->type == TOKEN_SPACE)
{
struct lexer_token *next = name->next;
lexer_token_free(name);
name = next;
}
head = name;
if (!name || !name->value)
{
if (prev)
prev->next = NULL;
else
lexer->tokens = NULL;
return;
}
struct lexer_token *value = NULL;
struct lexer_token *end = head->next ? head->next : head;
if (name->type == TOKEN_ASSIGNMENT_WORD)
{
value = head->next;
while (value->type == TOKEN_SPACE)
{
struct lexer_token *next = value->next;
lexer_token_free(value);
value = next;
}
end = value;
if (value->next)
end = value->next;
struct lexer_token *previous = value;
while (end && end->type != TOKEN_SPACE && end->type != TOKEN_NEWLINE
&& end->type != TOKEN_EOF && end->type != TOKEN_SEMICOLON)
{
previous = end;
end = end->next;
}
previous->next = NULL;
if (prev)
prev->next = end;
else
lexer->tokens = end;
}
else
{
if (prev)
prev->next = end;
else
lexer->tokens = end;
}
process_single_alias(lexer, name->value, value);
lexer_token_free(name);
if (end && end->type == TOKEN_SEMICOLON)
end->type = TOKEN_SPACE;
process_alias(end, end ? end->next : NULL, lexer);
}
void process_unalias(struct lexer_token *prev, struct lexer_token *head,
struct lexer *lexer)
{
shell->return_code = 0;
while (head && head->type != TOKEN_SEMICOLON && head->type != TOKEN_NEWLINE
&& head->type != TOKEN_EOF)
{
if (head->type < TOKEN_WORD || head->type > TOKEN_WORD_DOUBLE_QUOTE)
{
struct lexer_token *next = head->next;
lexer_token_free(head);
head = next;
continue;
}
bool to_free = false;
if (!head->value)
{
head->value = get_token_string(head->type);
to_free = true;
}
struct lexer_alias *alias = get_alias(head->value);
if (alias)
{
free(alias->name);
alias->name = calloc(1, sizeof(char));
}
else
{
shell->return_code = 1;
fprintf(stderr, "bsh: alias: %s: not found\n", head->value);
}
if (to_free)
free(head->value);
struct lexer_token *next = head->next;
lexer_token_free(head);
head = next;
}
if (head && head->type == TOKEN_SEMICOLON)
head->type = TOKEN_SPACE;
if (prev)
prev->next = head;
else
lexer->tokens = head;
}