Expansion: variable substitution V1 attempt

Norm has been checked, test are not up to date. Wildcard management and
filename expansions still to be done.
This commit is contained in:
Jérôme Guélen 2025-03-01 17:03:15 +01:00
parent e348040ea4
commit fa383c4f17
No known key found for this signature in database
7 changed files with 152 additions and 82 deletions

1
.gitignore vendored
View file

@ -31,3 +31,4 @@ mallocfail_hashes
bash.txt
.cache/
compile_commands.json
.vscode

View file

@ -3,18 +3,19 @@
/* ::: :::::::: */
/* minishell.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jguelen <marvin@42.fr> +#+ +:+ +#+ */
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/24 12:51:21 by jguelen #+# #+# */
/* Updated: 2025/02/24 13:04:32 by jguelen ### ########.fr */
/* Updated: 2025/03/01 16:59:30 by jguelen ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef MINISHELL_H
# define MINISHELL_H
typedef struct s_minishell
typedef struct s_minishell
{
t_env *env;
int last_return_value;
} t_minishell;

View file

@ -3,10 +3,10 @@
/* ::: :::::::: */
/* worddesc.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/03/11 11:13/50 by khais #+# #+# */
/* Updated: 2025/03/11 11:13:50 by khais ### ########.fr */
/* Created: 2025/02/13 15:47:58 by khais #+# #+# */
/* Updated: 2025/03/21 10:09:06 by jguelen ### ########.fr */
/* */
/* ************************************************************************** */

View file

@ -6,7 +6,7 @@
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/23 15:01:40 by jguelen #+# #+# */
/* Updated: 2025/02/28 13:43:23 by jguelen ### ########.fr */
/* Updated: 2025/03/01 17:00:52 by jguelen ### ########.fr */
/* */
/* ************************************************************************** */
@ -17,7 +17,7 @@
# include "../parser/wordlist/wordlist.h"
# include "../minishell.h"
int expand_question_mark(t_minishell *app);
int expand_question_mark(t_minishell *app);
t_wordlist *wordlist_var_expansion(t_wordlist *list, t_env *env);
t_wordlist *expand_star(char *file_pattern);

View file

@ -6,56 +6,72 @@
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/23 15:02:37 by jguelen #+# #+# */
/* Updated: 2025/02/28 18:48:15 by jguelen ### ########.fr */
/* Updated: 2025/03/01 17:01:47 by jguelen ### ########.fr */
/* */
/* ************************************************************************** */
#include "subst.h"
#include "../minishell.h"
#include "replace_substr.h"
#include "../env/env.h"
#include "../env/env_manip.h"
/*
** @RETURN Returns a malloc-allocated string representing the return value of
** the last foreground executed pipeline.
*/
char *expand_question_mark(t_minishell *app)
static char *word_update(t_worddesc *word, size_t i, size_t id_len, char *rep)
{
return (ft_itoa(app->last_return_value));
}
char *new_word;
size_t rep_len;
size_t digit;
/*
** Returns the longest possible substring present in str starting at the
** beginning that follows the definition of a valid bash identifier.
** NOTE(reminder): a valid bash identifier (name) is a non-empty string
** starting with a '_' or an alphabetic character and composed only of '_'s or
** alphanumerical characters.
** The returned string is malloc-allocated.
** In case of an allocation error, NULL is returned.
*/
char *ft_get_longest_identifier(char *str)
{
char *key;
size_t i;
if (!str || (*str != '_' && !ft_isalpha(*str)))
return (ft_strdup(""));
i = 1;
while (str[i])
{
if (!ft_isalpha(str[i]) && !ft_isdigit(str[i]) && str[i] != '_')
break ;
i++;
}
key = malloc((i + 1)* sizeof(char));
if (!key)
digit = ft_isdigit(word->word[i + 1]);
rep_len = ft_strlen(rep);
new_word = replace_in_str(word->word, i, i + id_len + digit, rep);
free(rep);
free(word->word);
word->word = new_word;
rep = construct_repeting_char_string('$', rep_len);
if (!rep)
return (NULL);
ft_memcpy(key, str, i);
key[i] = '\0';
return (key);
new_word = replace_in_str(word->mark_string, i, i + id_len + digit, rep);
free(rep);
if (!new_word)
return (NULL);
free(word->mark_string);
word->mark_string = new_word;
return (new_word);
}
static char *calculate_replacement(t_worddesc *word, t_minishell *app, size_t i,
size_t *id_len)
{
char *rep;
char *id;
id = ft_get_longest_identifier(word->word + i + 1);
if (!id)
return (NULL);
*id_len = ft_strlen(id);
if (*id_len == 0 && word->word[i + 1] == '?')
{
rep = expand_question_mark(app);
if (!rep)
return (NULL);
}
else
{
rep = env_get_val(app->env, id);
if (!rep)
rep = strdup("");
else
rep = strdup(rep);
if (!rep)
return (NULL);
}
free(id);
return (rep);
}
/*
** @Param word should NOT be NULL.
** Replace the word field of the t_worddesc pointer word with a new string
** corresponding to the replacement of the '$' followed by a valid bash
** identifier with the corresponding value if present in env or nothing if
@ -66,50 +82,31 @@ char *ft_get_longest_identifier(char *str)
** Similarly if the character following the '$' is neither '_' or
** alphanumerical the dollar is removed except for the appearance of a '\0'
** signaling the end of the word.
** Returns NULL in case of error.
** Returns NULL in case of error, or the worddesc pointer word itself if
** everything went normally.
*/
t_worddesc *word_var_expansion(t_worddesc *word, t_env *env)
t_worddesc *word_var_expansion(t_worddesc *word, t_minishell *app)
{
size_t i;
char *id;
char *tmp;
size_t id_len;
size_t rep_len;
char *rep;
i = 0;
while (((*word)->word)[i])
while (word->word[i] && word->word[i + 1])
{
if (word->flags[i] != '\'' && word->word[i] == '$')
if (word->mark_string[i] != '\'' && word->word[i] == '$')
{
id = ft_get_longest_identifier((word->word) + i + 1);
if (!id)
rep = calculate_replacement(word, app, i, &id_len);
if (!rep)
return (NULL);
id_len = ft_strlen(id);
if ((id_len == 0 && (word->word[i + 1] == '\0'
|| word->word[i + 1] == '"' || word->word[i + 1] == '\''))
|| (id_len == 1 && ft_isdigit(*id)))
{
free(id);
if (word->word[i + 1] == '\0')
continue ;
tmp = replace_in_str(word->word, i, i, NULL);
free(word->word);
word->word = tmp;
/////flags update
continue ;
}
rep = env_get_val(env, id);
free(id);
tmp = replace_in_str(word->word, i, i + id_len, rep);
free(rep);
if (!tmp)
rep_len = ft_strlen(rep);
if (word_update(word, i, id_len, rep) == NULL)
return (NULL);
free(word->word);
word->word = tmp;
////flags update
}
i++;
i += rep_len;
}
return (*word);
return (word);
}
/*
@ -119,18 +116,15 @@ t_worddesc *word_var_expansion(t_worddesc *word, t_env *env)
** We do NOT take the '\' character into account as an escape character here
** under any circumstance per subject requirement.
*/
t_wordlist *wordlist_var_expansion(t_wordlist *list, t_env *env)
t_wordlist *wordlist_var_expansion(t_wordlist *list, t_minishell *app)
{
t_wordlist *tmp_list;
char *tmp_word;
ssize_t idx_start;
char *value;
tmp_list = list;
while (tmp_list)
{
if ((tmp_list->word->flags & W_HASDOLLAR)
&& word_var_expansion(tmp_list->word, env) == NULL)
&& word_var_expansion(tmp_list->word, app) == NULL)
return (NULL);
tmp_list = tmp_list->next;
}

View file

@ -0,0 +1,73 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* variable_subst_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/03/01 13:04:27 by jguelen #+# #+# */
/* Updated: 2025/03/01 17:02:27 by jguelen ### ########.fr */
/* */
/* ************************************************************************** */
#include "subst.h"
#include "../minishell.h"
#include "replace_substr.h"
#include "../env/env.h"
#include "../env/env_manip.h"
/*
** Returns a C-compliant malloc-allocated string of length len and complosed
** only of the character c except for the teerminating NULL-byte or NULL in
** case of an allocation error.
*/
char *construct_repeting_char_string(char c, size_t len)
{
char *new;
new = ft_calloc(len + 1, sizeof(char));
if (!new)
return (NULL);
ft_memset(new, c, len);
return (new);
}
/*
** @RETURN Returns a malloc-allocated string representing the return value of
** the last foreground executed pipeline.
*/
char *expand_question_mark(t_minishell *app)
{
return (ft_itoa(app->last_return_value));
}
/*
** Returns the longest possible substring present in str starting at the
** beginning that follows the definition of a valid bash identifier.
** NOTE(reminder): a valid bash identifier (name) is a non-empty string
** starting with a '_' or an alphabetic character and composed only of '_'s or
** alphanumerical characters.
** The returned string is malloc-allocated.
** In case of an allocation error, NULL is returned.
*/
char *ft_get_longest_identifier(char *str)
{
char *key;
size_t i;
if (!str || (*str != '_' && !ft_isalpha(*str)))
return (ft_strdup(""));
i = 1;
while (str[i])
{
if (!ft_isalpha(str[i]) && !ft_isdigit(str[i]) && str[i] != '_')
break ;
i++;
}
key = malloc((i + 1) * sizeof(char));
if (!key)
return (NULL);
ft_memcpy(key, str, i);
key[i] = '\0';
return (key);
}

View file

@ -6,7 +6,7 @@
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/23 15:00:18 by jguelen #+# #+# */
/* Updated: 2025/02/28 14:23:30 by jguelen ### ########.fr */
/* Updated: 2025/03/01 11:07:17 by jguelen ### ########.fr */
/* */
/* ************************************************************************** */
@ -43,6 +43,7 @@ static void test_insert_instr(void)
free(line);
}
//Test to be remade since structures changed in the function calls and returns.
static void test_env_variable_expansion(void)
{
char *token;