mirror of
https://codeberg.org/la-chouette/minishell.git
synced 2025-12-06 07:28:09 +01:00
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:
parent
e348040ea4
commit
fa383c4f17
7 changed files with 152 additions and 82 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -31,3 +31,4 @@ mallocfail_hashes
|
||||||
bash.txt
|
bash.txt
|
||||||
.cache/
|
.cache/
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
|
.vscode
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,19 @@
|
||||||
/* ::: :::::::: */
|
/* ::: :::::::: */
|
||||||
/* minishell.h :+: :+: :+: */
|
/* minishell.h :+: :+: :+: */
|
||||||
/* +:+ +:+ +:+ */
|
/* +:+ +:+ +:+ */
|
||||||
/* By: jguelen <marvin@42.fr> +#+ +:+ +#+ */
|
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2025/02/24 12:51:21 by jguelen #+# #+# */
|
/* 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
|
#ifndef MINISHELL_H
|
||||||
# define MINISHELL_H
|
# define MINISHELL_H
|
||||||
|
|
||||||
typedef struct s_minishell
|
typedef struct s_minishell
|
||||||
{
|
{
|
||||||
|
t_env *env;
|
||||||
int last_return_value;
|
int last_return_value;
|
||||||
} t_minishell;
|
} t_minishell;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@
|
||||||
/* ::: :::::::: */
|
/* ::: :::::::: */
|
||||||
/* worddesc.h :+: :+: :+: */
|
/* worddesc.h :+: :+: :+: */
|
||||||
/* +:+ +:+ +:+ */
|
/* +:+ +:+ +:+ */
|
||||||
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2025/03/11 11:13/50 by khais #+# #+# */
|
/* Created: 2025/02/13 15:47:58 by khais #+# #+# */
|
||||||
/* Updated: 2025/03/11 11:13:50 by khais ### ########.fr */
|
/* Updated: 2025/03/21 10:09:06 by jguelen ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2025/02/23 15:01:40 by jguelen #+# #+# */
|
/* 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 "../parser/wordlist/wordlist.h"
|
||||||
# include "../minishell.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 *wordlist_var_expansion(t_wordlist *list, t_env *env);
|
||||||
t_wordlist *expand_star(char *file_pattern);
|
t_wordlist *expand_star(char *file_pattern);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,56 +6,72 @@
|
||||||
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2025/02/23 15:02:37 by jguelen #+# #+# */
|
/* 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 "subst.h"
|
||||||
|
#include "../minishell.h"
|
||||||
#include "replace_substr.h"
|
#include "replace_substr.h"
|
||||||
#include "../env/env.h"
|
#include "../env/env.h"
|
||||||
#include "../env/env_manip.h"
|
#include "../env/env_manip.h"
|
||||||
|
|
||||||
/*
|
static char *word_update(t_worddesc *word, size_t i, size_t id_len, char *rep)
|
||||||
** @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));
|
char *new_word;
|
||||||
}
|
size_t rep_len;
|
||||||
|
size_t digit;
|
||||||
|
|
||||||
/*
|
digit = ft_isdigit(word->word[i + 1]);
|
||||||
** Returns the longest possible substring present in str starting at the
|
rep_len = ft_strlen(rep);
|
||||||
** beginning that follows the definition of a valid bash identifier.
|
new_word = replace_in_str(word->word, i, i + id_len + digit, rep);
|
||||||
** NOTE(reminder): a valid bash identifier (name) is a non-empty string
|
free(rep);
|
||||||
** starting with a '_' or an alphabetic character and composed only of '_'s or
|
free(word->word);
|
||||||
** alphanumerical characters.
|
word->word = new_word;
|
||||||
** The returned string is malloc-allocated.
|
rep = construct_repeting_char_string('$', rep_len);
|
||||||
** In case of an allocation error, NULL is returned.
|
if (!rep)
|
||||||
*/
|
|
||||||
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);
|
return (NULL);
|
||||||
ft_memcpy(key, str, i);
|
new_word = replace_in_str(word->mark_string, i, i + id_len + digit, rep);
|
||||||
key[i] = '\0';
|
free(rep);
|
||||||
return (key);
|
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
|
** 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
|
** corresponding to the replacement of the '$' followed by a valid bash
|
||||||
** identifier with the corresponding value if present in env or nothing if
|
** 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
|
** Similarly if the character following the '$' is neither '_' or
|
||||||
** alphanumerical the dollar is removed except for the appearance of a '\0'
|
** alphanumerical the dollar is removed except for the appearance of a '\0'
|
||||||
** signaling the end of the word.
|
** 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;
|
size_t i;
|
||||||
char *id;
|
size_t id_len;
|
||||||
char *tmp;
|
size_t rep_len;
|
||||||
char *rep;
|
char *rep;
|
||||||
|
|
||||||
i = 0;
|
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);
|
rep = calculate_replacement(word, app, i, &id_len);
|
||||||
if (!id)
|
if (!rep)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
id_len = ft_strlen(id);
|
rep_len = ft_strlen(rep);
|
||||||
if ((id_len == 0 && (word->word[i + 1] == '\0'
|
if (word_update(word, i, id_len, rep) == NULL)
|
||||||
|| 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)
|
|
||||||
return (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
|
** We do NOT take the '\' character into account as an escape character here
|
||||||
** under any circumstance per subject requirement.
|
** 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;
|
t_wordlist *tmp_list;
|
||||||
char *tmp_word;
|
|
||||||
ssize_t idx_start;
|
|
||||||
char *value;
|
|
||||||
|
|
||||||
tmp_list = list;
|
tmp_list = list;
|
||||||
while (tmp_list)
|
while (tmp_list)
|
||||||
{
|
{
|
||||||
if ((tmp_list->word->flags & W_HASDOLLAR)
|
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);
|
return (NULL);
|
||||||
tmp_list = tmp_list->next;
|
tmp_list = tmp_list->next;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
73
src/subst/variable_subst_utils.c
Normal file
73
src/subst/variable_subst_utils.c
Normal 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);
|
||||||
|
}
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2025/02/23 15:00:18 by jguelen #+# #+# */
|
/* 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);
|
free(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Test to be remade since structures changed in the function calls and returns.
|
||||||
static void test_env_variable_expansion(void)
|
static void test_env_variable_expansion(void)
|
||||||
{
|
{
|
||||||
char *token;
|
char *token;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue