feat(dev): expansion
This commit is contained in:
parent
609c1667af
commit
4fc43e4678
8 changed files with 36 additions and 32 deletions
|
|
@ -18,8 +18,8 @@ bin_PROGRAMS = 42sh
|
||||||
parser/libparser.a \
|
parser/libparser.a \
|
||||||
lexer/liblexer.a \
|
lexer/liblexer.a \
|
||||||
io_backend/libio_backend.a \
|
io_backend/libio_backend.a \
|
||||||
expansion/libexpansion.a \
|
|
||||||
execution/libexecution.a \
|
execution/libexecution.a \
|
||||||
|
expansion/libexpansion.a \
|
||||||
utils/libutils.a
|
utils/libutils.a
|
||||||
|
|
||||||
# ================ TESTS ================
|
# ================ TESTS ================
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,9 @@
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "../expansion/expansion.h"
|
||||||
#include "../utils/ast/ast.h"
|
#include "../utils/ast/ast.h"
|
||||||
|
#include "../utils/hash_map/hash_map.h"
|
||||||
|
|
||||||
// --- Helpers ---
|
// --- Helpers ---
|
||||||
|
|
||||||
|
|
@ -205,7 +207,7 @@ static int exec_command(struct ast_command *command)
|
||||||
* @param ast The AST to execute
|
* @param ast The AST to execute
|
||||||
* @return int The exit status of the last executed command.
|
* @return int The exit status of the last executed command.
|
||||||
*/
|
*/
|
||||||
int execution(struct ast *ast)
|
int execution(struct ast *ast, struct hash_map *vars)
|
||||||
{
|
{
|
||||||
if (!ast)
|
if (!ast)
|
||||||
{
|
{
|
||||||
|
|
@ -219,18 +221,20 @@ int execution(struct ast *ast)
|
||||||
}
|
}
|
||||||
case AST_CMD: {
|
case AST_CMD: {
|
||||||
struct ast_command *command = ast_get_command(ast);
|
struct ast_command *command = ast_get_command(ast);
|
||||||
|
if (!expand(command, vars))
|
||||||
|
fprintf(stderr, "Error: Variable expansion failed\n");
|
||||||
return exec_command(command);
|
return exec_command(command);
|
||||||
}
|
}
|
||||||
case AST_IF: {
|
case AST_IF: {
|
||||||
struct ast_if *if_node = ast_get_if(ast);
|
struct ast_if *if_node = ast_get_if(ast);
|
||||||
int cond = execution(if_node->condition);
|
int cond = execution(if_node->condition, vars);
|
||||||
if (cond == 0) // True
|
if (cond == 0) // True
|
||||||
{
|
{
|
||||||
return execution(if_node->then_clause);
|
return execution(if_node->then_clause, vars);
|
||||||
}
|
}
|
||||||
else // False
|
else // False
|
||||||
{
|
{
|
||||||
return execution(if_node->else_clause);
|
return execution(if_node->else_clause, vars);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case AST_LIST: {
|
case AST_LIST: {
|
||||||
|
|
@ -240,25 +244,25 @@ int execution(struct ast *ast)
|
||||||
while (cur)
|
while (cur)
|
||||||
{
|
{
|
||||||
struct ast *child = (struct ast *)cur->data;
|
struct ast *child = (struct ast *)cur->data;
|
||||||
ret = execution(child);
|
ret = execution(child, vars);
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
case AST_AND_OR: {
|
case AST_AND_OR: {
|
||||||
struct ast_and_or *ao_node = ast_get_and_or(ast);
|
struct ast_and_or *ao_node = ast_get_and_or(ast);
|
||||||
int left_ret = execution(ao_node->left);
|
int left_ret = execution(ao_node->left, vars);
|
||||||
|
|
||||||
if (ao_node->type == AST_AND_OR_TYPE_AND)
|
if (ao_node->type == AST_AND_OR_TYPE_AND)
|
||||||
{
|
{
|
||||||
if (left_ret == 0)
|
if (left_ret == 0)
|
||||||
return execution(ao_node->right);
|
return execution(ao_node->right, vars);
|
||||||
return left_ret;
|
return left_ret;
|
||||||
}
|
}
|
||||||
else // OR
|
else // OR
|
||||||
{
|
{
|
||||||
if (left_ret != 0)
|
if (left_ret != 0)
|
||||||
return execution(ao_node->right);
|
return execution(ao_node->right, vars);
|
||||||
return left_ret;
|
return left_ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -335,7 +339,7 @@ int execution(struct ast *ast)
|
||||||
close(new_fd);
|
close(new_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = execution(redir->child);
|
int ret = execution(redir->child, vars);
|
||||||
|
|
||||||
if (saved_fd != -1)
|
if (saved_fd != -1)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "../utils/ast/ast.h"
|
#include "../utils/ast/ast.h"
|
||||||
#include "../utils/lists/lists.h"
|
#include "../utils/lists/lists.h"
|
||||||
|
#include "../utils/hash_map/hash_map.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Execute the AST
|
* @brief Execute the AST
|
||||||
|
|
@ -10,6 +11,6 @@
|
||||||
* @param ast Pointer to the AST structure
|
* @param ast Pointer to the AST structure
|
||||||
* @return int Execution status code of the last command
|
* @return int Execution status code of the last command
|
||||||
*/
|
*/
|
||||||
int execution(struct ast *ast);
|
int execution(struct ast *ast, struct hash_map *vars);
|
||||||
|
|
||||||
#endif /* ! EXECUTION_H */
|
#endif /* ! EXECUTION_H */
|
||||||
|
|
|
||||||
|
|
@ -115,11 +115,10 @@ static bool expand_var(char **str, size_t pos, const struct hash_map *vars)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ast_command *expand(struct ast_command *command,
|
bool expand(struct ast_command *command, const struct hash_map *vars)
|
||||||
const struct hash_map *vars)
|
|
||||||
{
|
{
|
||||||
if (command == NULL)
|
if (command == NULL)
|
||||||
return NULL;
|
return false;
|
||||||
|
|
||||||
char *str;
|
char *str;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
@ -150,7 +149,7 @@ struct ast_command *expand(struct ast_command *command,
|
||||||
// variable expansion
|
// variable expansion
|
||||||
bool r = expand_var(&str, i, vars);
|
bool r = expand_var(&str, i, vars);
|
||||||
if (r == false || str == NULL)
|
if (r == false || str == NULL)
|
||||||
return NULL;
|
return false;
|
||||||
|
|
||||||
i--; // -1 because loop will increment i
|
i--; // -1 because loop will increment i
|
||||||
}
|
}
|
||||||
|
|
@ -160,7 +159,7 @@ struct ast_command *expand(struct ast_command *command,
|
||||||
{
|
{
|
||||||
// error: quote not closed
|
// error: quote not closed
|
||||||
fprintf(stderr, "Error: quote not closed in string: %s\n", str);
|
fprintf(stderr, "Error: quote not closed in string: %s\n", str);
|
||||||
return NULL;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len != strlen(str))
|
if (len != strlen(str))
|
||||||
|
|
@ -169,12 +168,12 @@ struct ast_command *expand(struct ast_command *command,
|
||||||
if (new_str == NULL)
|
if (new_str == NULL)
|
||||||
{
|
{
|
||||||
// error: realloc fail
|
// error: realloc fail
|
||||||
return NULL;
|
return false;
|
||||||
}
|
}
|
||||||
l->data = new_str;
|
l->data = new_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
l = l->next;
|
l = l->next;
|
||||||
}
|
}
|
||||||
return command;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef EXPANSION_H
|
#ifndef EXPANSION_H
|
||||||
#define EXPANSION_H
|
#define EXPANSION_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "../utils/hash_map/hash_map.h"
|
#include "../utils/hash_map/hash_map.h"
|
||||||
|
|
@ -20,7 +21,6 @@ size_t parse_var_name(char *str, char **res);
|
||||||
* @param vars The hash map containing variables.
|
* @param vars The hash map containing variables.
|
||||||
* @return A new AST command with variables expanded, or NULL on error.
|
* @return A new AST command with variables expanded, or NULL on error.
|
||||||
*/
|
*/
|
||||||
struct ast_command *expand(struct ast_command *command,
|
bool expand(struct ast_command *command, const struct hash_map *vars);
|
||||||
const struct hash_map *vars);
|
|
||||||
|
|
||||||
#endif /* ! EXPANSION_H */
|
#endif /* ! EXPANSION_H */
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,9 @@ int main(int argc, char **argv)
|
||||||
while (command_ast != NULL && command_ast->type != AST_END)
|
while (command_ast != NULL && command_ast->type != AST_END)
|
||||||
{
|
{
|
||||||
// Execute AST
|
// Execute AST
|
||||||
return_code = execution(command_ast);
|
return_code = execution(command_ast, vars);
|
||||||
|
|
||||||
|
// set $? variable
|
||||||
|
|
||||||
ast_free(&command_ast);
|
ast_free(&command_ast);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,7 @@
|
||||||
|
|
||||||
#define VARS_INITIAL_SIZE 16
|
#define VARS_INITIAL_SIZE 16
|
||||||
|
|
||||||
struct hash_map *vars_init(void)
|
static void vars_default(struct hash_map *vars)
|
||||||
{
|
|
||||||
return hash_map_init(VARS_INITIAL_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void vars_default(struct hash_map *vars)
|
|
||||||
{
|
{
|
||||||
set_var_copy(vars, "?", "0");
|
set_var_copy(vars, "?", "0");
|
||||||
pid_t pid = getpid();
|
pid_t pid = getpid();
|
||||||
|
|
@ -26,6 +21,14 @@ void vars_default(struct hash_map *vars)
|
||||||
set_var_copy(vars, "$", pid_str);
|
set_var_copy(vars, "$", pid_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct hash_map *vars_init(void)
|
||||||
|
{
|
||||||
|
struct hash_map *vars = hash_map_init(VARS_INITIAL_SIZE);
|
||||||
|
if (vars != NULL)
|
||||||
|
vars_default(vars);
|
||||||
|
return vars;
|
||||||
|
}
|
||||||
|
|
||||||
short short_random(void)
|
short short_random(void)
|
||||||
{
|
{
|
||||||
static bool seeded = false;
|
static bool seeded = false;
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,6 @@
|
||||||
*/
|
*/
|
||||||
struct hash_map *vars_init(void);
|
struct hash_map *vars_init(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* Set default variables.
|
|
||||||
*/
|
|
||||||
void vars_default(struct hash_map *vars);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a random short integer (16 bits positive [0-32767]).
|
* Generate a random short integer (16 bits positive [0-32767]).
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue