mirror of
https://codeberg.org/la-chouette/minishell.git
synced 2025-12-06 07:28:09 +01:00
Norm has been checked, test are not up to date. Wildcard management and filename expansions still to be done.
132 lines
4 KiB
C
132 lines
4 KiB
C
/* ************************************************************************** */
|
|
/* */
|
|
/* ::: :::::::: */
|
|
/* variable_subst.c :+: :+: :+: */
|
|
/* +:+ +:+ +:+ */
|
|
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
|
/* +#+#+#+#+#+ +#+ */
|
|
/* Created: 2025/02/23 15:02:37 by jguelen #+# #+# */
|
|
/* 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"
|
|
|
|
static char *word_update(t_worddesc *word, size_t i, size_t id_len, char *rep)
|
|
{
|
|
char *new_word;
|
|
size_t rep_len;
|
|
size_t digit;
|
|
|
|
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);
|
|
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
|
|
** the corresponding identifier does not have an entry in env.
|
|
** Additionnally if the first character following is a digit both the '$'
|
|
** and digit are removed even though we do not deal with those type of bash
|
|
** parameters (we consider them to never hold a value).
|
|
** 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, or the worddesc pointer word itself if
|
|
** everything went normally.
|
|
*/
|
|
t_worddesc *word_var_expansion(t_worddesc *word, t_minishell *app)
|
|
{
|
|
size_t i;
|
|
size_t id_len;
|
|
size_t rep_len;
|
|
char *rep;
|
|
|
|
i = 0;
|
|
while (word->word[i] && word->word[i + 1])
|
|
{
|
|
if (word->mark_string[i] != '\'' && word->word[i] == '$')
|
|
{
|
|
rep = calculate_replacement(word, app, i, &id_len);
|
|
if (!rep)
|
|
return (NULL);
|
|
rep_len = ft_strlen(rep);
|
|
if (word_update(word, i, id_len, rep) == NULL)
|
|
return (NULL);
|
|
}
|
|
i += rep_len;
|
|
}
|
|
return (word);
|
|
}
|
|
|
|
/*
|
|
** Returns the t_wordlist passed as a parameter where the words have been
|
|
** modified to contain string that represent the result of parameter expansion
|
|
** where the introductory '$' character was not single quoted.
|
|
** 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_minishell *app)
|
|
{
|
|
t_wordlist *tmp_list;
|
|
|
|
tmp_list = list;
|
|
while (tmp_list)
|
|
{
|
|
if ((tmp_list->word->flags & W_HASDOLLAR)
|
|
&& word_var_expansion(tmp_list->word, app) == NULL)
|
|
return (NULL);
|
|
tmp_list = tmp_list->next;
|
|
}
|
|
return (list);
|
|
}
|