feat(dev): expansion

This commit is contained in:
william.valenduc 2026-01-22 12:09:18 +00:00
parent 609c1667af
commit 4fc43e4678
8 changed files with 36 additions and 32 deletions

View file

@ -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 ================

View file

@ -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)
{ {

View file

@ -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 */

View file

@ -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;
} }

View file

@ -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 */

View file

@ -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);

View file

@ -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;

View file

@ -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]).
*/ */