2025-02-28 18:48:30 +01:00
|
|
|
/* ************************************************************************** */
|
|
|
|
|
/* */
|
|
|
|
|
/* ::: :::::::: */
|
|
|
|
|
/* variable_subst.c :+: :+: :+: */
|
|
|
|
|
/* +:+ +:+ +:+ */
|
2025-03-19 17:58:46 +01:00
|
|
|
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
|
2025-02-28 18:48:30 +01:00
|
|
|
/* +#+#+#+#+#+ +#+ */
|
2025-03-19 17:58:46 +01:00
|
|
|
/* Created: 2025/03/19 17:28/29 by khais #+# #+# */
|
2025-03-24 10:53:02 +01:00
|
|
|
/* Updated: 2025/03/24 10:52:10 by jguelen ### ########.fr */
|
2025-02-28 18:48:30 +01:00
|
|
|
/* */
|
|
|
|
|
/* ************************************************************************** */
|
|
|
|
|
|
|
|
|
|
#include "subst.h"
|
2025-03-01 17:03:15 +01:00
|
|
|
#include "../minishell.h"
|
2025-02-28 18:48:30 +01:00
|
|
|
#include "replace_substr.h"
|
|
|
|
|
#include "../env/env_manip.h"
|
|
|
|
|
|
2025-03-08 17:32:47 +01:00
|
|
|
/*
|
|
|
|
|
** @Param
|
|
|
|
|
** word: the worddesc to be modified
|
|
|
|
|
** i: the index at which the $ marking the start of expansion is located
|
|
|
|
|
** id_len: the length of the string that constitutes a valid bash
|
|
|
|
|
** identifier (it is to be noted that it can be zero and yet still
|
|
|
|
|
** conduct to a replacement of more that just $ if $ is immediately
|
|
|
|
|
** followed by a digit -- this cans be modified as it is not strictly
|
|
|
|
|
** required to consider positionnal arguments at all or indeed treat
|
|
|
|
|
** them as holding no value)
|
|
|
|
|
** rep: a malloc-allocated string previously calculated to correspond to
|
|
|
|
|
** the actual value to set as the expansion
|
|
|
|
|
** This function exists to actually modify the worddesc word by modifying the
|
|
|
|
|
** word proper inside but also keep the marker string coherent with these
|
|
|
|
|
** modifications so that further steps can act properly with the type of
|
|
|
|
|
** expansion and properly field split (word split in the manual) the result or
|
|
|
|
|
** not. To this end if an expansion occurs outside quotes every character
|
|
|
|
|
** resulting from it is marked simply with a '$' character and is subject to
|
|
|
|
|
** future field splitting. If however, the expansion occurs within double quotes
|
|
|
|
|
** it is not to be subjected to field splitting in the future and every
|
|
|
|
|
** character resulting from such an expansion is marked with a '&'.
|
|
|
|
|
**
|
|
|
|
|
** cf. https://www.gnu.org/software/bash/manual/bash.html#Quoting
|
|
|
|
|
** section 3.5.7
|
|
|
|
|
** The shell scans the results of parameter expansion, command substitution, and
|
|
|
|
|
** arithmetic expansion that did not occur within double quotes for word
|
|
|
|
|
** splitting.
|
|
|
|
|
**
|
|
|
|
|
** NOTE: It frees the malloc-allocated string rep.
|
|
|
|
|
**
|
|
|
|
|
** @RETURN In case of allocation error returns NULL, oterwise returns word
|
|
|
|
|
** itself.
|
|
|
|
|
*/
|
|
|
|
|
static t_worddesc *word_update(t_worddesc *word, size_t i, size_t id_len,
|
|
|
|
|
char *rep)
|
2025-02-28 18:48:30 +01:00
|
|
|
{
|
2025-03-01 17:03:15 +01:00
|
|
|
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;
|
2025-03-08 17:32:47 +01:00
|
|
|
if (word->marker[i] == '"')
|
|
|
|
|
rep = construct_repeting_char_string('&', rep_len);
|
|
|
|
|
else
|
|
|
|
|
rep = construct_repeting_char_string('$', rep_len);
|
2025-03-01 17:03:15 +01:00
|
|
|
if (!rep)
|
|
|
|
|
return (NULL);
|
2025-03-08 17:32:47 +01:00
|
|
|
new_word = replace_in_str(word->marker, i, i + id_len + digit, rep);
|
2025-03-01 17:03:15 +01:00
|
|
|
free(rep);
|
|
|
|
|
if (!new_word)
|
|
|
|
|
return (NULL);
|
2025-03-08 17:32:47 +01:00
|
|
|
free(word->marker);
|
|
|
|
|
word->marker = new_word;
|
|
|
|
|
return (word);
|
2025-02-28 18:48:30 +01:00
|
|
|
}
|
|
|
|
|
|
2025-03-08 17:32:47 +01:00
|
|
|
/*
|
|
|
|
|
** Calculates the string corresponding to the value of the variable to be
|
|
|
|
|
** expanded in the word proper and returns it.
|
2025-03-14 18:47:14 +01:00
|
|
|
** The string returned is always malloc-allocated or NULL.
|
2025-03-08 17:32:47 +01:00
|
|
|
*/
|
2025-03-01 17:03:15 +01:00
|
|
|
static char *calculate_replacement(t_worddesc *word, t_minishell *app, size_t i,
|
|
|
|
|
size_t *id_len)
|
2025-02-28 18:48:30 +01:00
|
|
|
{
|
2025-03-01 17:03:15 +01:00
|
|
|
char *rep;
|
|
|
|
|
char *id;
|
2025-02-28 18:48:30 +01:00
|
|
|
|
2025-03-01 17:03:15 +01:00
|
|
|
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] == '?')
|
2025-02-28 18:48:30 +01:00
|
|
|
{
|
2025-03-24 10:48:05 +01:00
|
|
|
*id_len = 1;
|
2025-03-01 17:03:15 +01:00
|
|
|
rep = expand_question_mark(app);
|
|
|
|
|
if (!rep)
|
|
|
|
|
return (NULL);
|
2025-02-28 18:48:30 +01:00
|
|
|
}
|
2025-03-01 17:03:15 +01:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rep = env_get_val(app->env, id);
|
|
|
|
|
if (!rep)
|
2025-03-21 18:54:10 +01:00
|
|
|
rep = ft_strdup("");
|
2025-03-01 17:03:15 +01:00
|
|
|
else
|
2025-03-21 18:54:10 +01:00
|
|
|
rep = ft_strdup(rep);
|
2025-03-01 17:03:15 +01:00
|
|
|
if (!rep)
|
|
|
|
|
return (NULL);
|
|
|
|
|
}
|
2025-03-24 10:48:05 +01:00
|
|
|
return (free(id), rep);
|
2025-02-28 18:48:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2025-03-01 17:03:15 +01:00
|
|
|
** @Param word should NOT be NULL.
|
2025-02-28 18:48:30 +01:00
|
|
|
** 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
|
2025-03-24 10:53:02 +01:00
|
|
|
** identifier with the corresponding value if present in env, the return value
|
|
|
|
|
** of the last foreground executed pipeline in the case of $? or nothing if
|
2025-02-28 18:48:30 +01:00
|
|
|
** 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.
|
2025-03-01 17:03:15 +01:00
|
|
|
** Returns NULL in case of error, or the worddesc pointer word itself if
|
|
|
|
|
** everything went normally.
|
2025-02-28 18:48:30 +01:00
|
|
|
*/
|
2025-03-01 17:03:15 +01:00
|
|
|
t_worddesc *word_var_expansion(t_worddesc *word, t_minishell *app)
|
2025-02-28 18:48:30 +01:00
|
|
|
{
|
|
|
|
|
size_t i;
|
2025-03-01 17:03:15 +01:00
|
|
|
size_t id_len;
|
|
|
|
|
size_t rep_len;
|
2025-02-28 18:48:30 +01:00
|
|
|
char *rep;
|
|
|
|
|
|
|
|
|
|
i = 0;
|
2025-03-01 17:03:15 +01:00
|
|
|
while (word->word[i] && word->word[i + 1])
|
2025-02-28 18:48:30 +01:00
|
|
|
{
|
2025-03-19 17:58:46 +01:00
|
|
|
rep_len = 1;
|
2025-03-10 17:17:02 +01:00
|
|
|
if (word->marker[i] != '\'' && word->word[i] == '$')
|
2025-02-28 18:48:30 +01:00
|
|
|
{
|
2025-03-01 17:03:15 +01:00
|
|
|
rep = calculate_replacement(word, app, i, &id_len);
|
|
|
|
|
if (!rep)
|
2025-02-28 18:48:30 +01:00
|
|
|
return (NULL);
|
2025-03-01 17:03:15 +01:00
|
|
|
rep_len = ft_strlen(rep);
|
|
|
|
|
if (word_update(word, i, id_len, rep) == NULL)
|
2025-02-28 18:48:30 +01:00
|
|
|
return (NULL);
|
|
|
|
|
}
|
2025-03-01 17:03:15 +01:00
|
|
|
i += rep_len;
|
2025-02-28 18:48:30 +01:00
|
|
|
}
|
2025-03-01 17:03:15 +01:00
|
|
|
return (word);
|
2025-02-28 18:48:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
** Returns the t_wordlist passed as a parameter where the words have been
|
2025-03-08 17:32:47 +01:00
|
|
|
** modified to contain strings that represent the result of parameter expansion
|
2025-02-28 18:48:30 +01:00
|
|
|
** where the introductory '$' character was not single quoted.
|
2025-03-08 17:32:47 +01:00
|
|
|
** We DO NOT take the '\' character into account as an escape character here
|
2025-02-28 18:48:30 +01:00
|
|
|
** under any circumstance per subject requirement.
|
|
|
|
|
*/
|
2025-03-01 17:03:15 +01:00
|
|
|
t_wordlist *wordlist_var_expansion(t_wordlist *list, t_minishell *app)
|
2025-02-28 18:48:30 +01:00
|
|
|
{
|
|
|
|
|
t_wordlist *tmp_list;
|
|
|
|
|
|
|
|
|
|
tmp_list = list;
|
|
|
|
|
while (tmp_list)
|
|
|
|
|
{
|
|
|
|
|
if ((tmp_list->word->flags & W_HASDOLLAR)
|
2025-03-01 17:03:15 +01:00
|
|
|
&& word_var_expansion(tmp_list->word, app) == NULL)
|
2025-02-28 18:48:30 +01:00
|
|
|
return (NULL);
|
|
|
|
|
tmp_list = tmp_list->next;
|
|
|
|
|
}
|
|
|
|
|
return (list);
|
|
|
|
|
}
|