feat(expansion): expand_var and expand

This commit is contained in:
william.valenduc 2026-01-18 01:27:31 +00:00
parent a16712e802
commit 34c741d86e
4 changed files with 276 additions and 14 deletions

View file

@ -6,6 +6,9 @@
#include <string.h>
#include "../utils/ast/ast.h"
#include "../utils/hash_map/hash_map.h"
#include "../utils/string_utils/string_utils.h"
#include "../utils/vars/vars.h"
static bool is_var_start_char(char c)
{
@ -77,14 +80,39 @@ size_t parse_var_name(char *str, char **res)
return i;
}
struct ast_command *expand(struct ast_command *command)
static bool expand_var(char **str, size_t pos, const struct hash_map *vars)
{
char *var_name = NULL;
size_t r = parse_var_name(*str + pos, &var_name);
if (r > 0 && var_name != NULL)
{
char *value = get_var_or_env(vars, var_name);
if (value == NULL)
// Undefined variable: expand to empty string
value = "";
char *p = insert_into(*str, value, pos, r);
free(var_name);
if (p == NULL)
{
// error: insertion failed
return false;
}
*str = p;
return true;
}
return false;
}
struct ast_command *expand(struct ast_command *command,
const struct hash_map *vars)
{
if (command == NULL)
return NULL;
bool in_quotes = false;
char *str;
size_t len;
bool in_quotes;
struct list *l = command->command;
while (l != NULL)
@ -93,28 +121,35 @@ struct ast_command *expand(struct ast_command *command)
str = (char *)l->data;
len = strlen(str);
for (size_t i = 0; str[i] != '\0'; i++)
for (size_t i = 0; str[i] != 0; i++)
{
if (in_quotes)
{
continue; // do nothing
}
else if (str[i] == '\'')
if (str[i] == '\'')
{
// remove quote
in_quotes = !in_quotes;
memmove(&str[i], &str[i + 1], strlen(&str[i + 1]) + 1);
memmove(str + i, str + i + 1, strlen(str + i + 1) + 1);
i--;
}
else if (in_quotes)
{
continue; // do nothing
}
else if (str[i] == '$' && str[i + 1] != 0 && !isspace(str[i + 1]))
{
// variable expansion
bool r = expand_var(&str, i, vars);
if (r == false || str == NULL)
return NULL;
i--; // -1 because loop will increment i
}
}
if (in_quotes)
{
// error: quote not closed
fprintf(stderr, "Error: quote not closed in string: %s\n", str);
return NULL;
}
if (len != strlen(str))
@ -123,6 +158,7 @@ struct ast_command *expand(struct ast_command *command)
if (new_str == NULL)
{
// error: realloc fail
return NULL;
}
l->data = new_str;
}

View file

@ -3,6 +3,8 @@
#include <stddef.h>
#include "../utils/hash_map/hash_map.h"
/**
* Parse a variable from a string starting with '$'.
* @param str The input string starting with '$'. It must start with '$'.
@ -12,4 +14,13 @@
*/
size_t parse_var_name(char *str, char **res);
/**
* Expand variables in an AST command using the provided variable map.
* @param command The AST command to expand.
* @param vars The hash map containing variables.
* @return A new AST command with variables expanded, or NULL on error.
*/
struct ast_command *expand(struct ast_command *command,
const struct hash_map *vars);
#endif /* ! EXPANSION_H */