| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | ** EPITECH PROJECT, 2024 | ||
| 3 | ** 42sh | ||
| 4 | ** File description: | ||
| 5 | ** The file containing the replace_variable functions | ||
| 6 | */ | ||
| 7 | /** | ||
| 8 | * @file replace_variable.c | ||
| 9 | * @brief The file containing the replace_variable functions | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include "../../include/myshell.h" | ||
| 13 | |||
| 14 | /** | ||
| 15 | * @brief Find the first valid variable in a string | ||
| 16 | * @param line The string | ||
| 17 | * @return <b>char *</b> The variable | ||
| 18 | */ | ||
| 19 | 148 | static char *find_valid_variable(char *line) | |
| 20 | { | ||
| 21 |
2/2✓ Branch 1 taken 139 times.
✓ Branch 2 taken 9 times.
|
148 | while (my_strstr(line, "$") != NULL) { |
| 22 |
2/4✓ Branch 1 taken 139 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 139 times.
|
278 | if (*(my_strstr(line, "$") + 1) == '\0' || |
| 23 | 139 | my_char_is(*(my_strstr(line, "$") + 1), " \t\n")) { | |
| 24 | ✗ | line = my_strstr(line, "$") + 1; | |
| 25 | ✗ | continue; | |
| 26 | } | ||
| 27 | 139 | return my_strstr(line, "$"); | |
| 28 | } | ||
| 29 | 9 | return NULL; | |
| 30 | } | ||
| 31 | |||
| 32 | /** | ||
| 33 | * @brief Display an error message | ||
| 34 | * @param variable The variable | ||
| 35 | * @param type The type of error | ||
| 36 | * @return <b>int</b> The exit status | ||
| 37 | */ | ||
| 38 | 13 | static int display_error(char *variable, int type) | |
| 39 | { | ||
| 40 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 8 times.
|
13 | if (type == 1) { |
| 41 | 5 | my_fprintf(2, "Illegal variable name.\n"); | |
| 42 | 5 | return -1; | |
| 43 | } | ||
| 44 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
|
8 | if (type == 2) { |
| 45 | 1 | my_fprintf(2, "Missing '}'.\n"); | |
| 46 | 1 | return -1; | |
| 47 | } | ||
| 48 | 7 | my_fprintf(2, "%s: Undefined variable.\n", variable); | |
| 49 | 7 | FREE(variable); | |
| 50 | 7 | return 1; | |
| 51 | } | ||
| 52 | |||
| 53 | /** | ||
| 54 | * @brief Get the value of a variable | ||
| 55 | * @param mysh The shell structure | ||
| 56 | * @param variable The variable | ||
| 57 | * @param value The value | ||
| 58 | * @return <b>int</b> The exit status | ||
| 59 | */ | ||
| 60 | 19 | static int get_variables_value(mysh_t *mysh, char *variable, char **value) | |
| 61 | { | ||
| 62 | 19 | char *tmp = NULL; | |
| 63 | |||
| 64 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 7 times.
|
35 | for (node_t *node = mysh->variable_list; node; node = node->next) { |
| 65 |
2/2✓ Branch 1 taken 12 times.
✓ Branch 2 taken 16 times.
|
28 | if (my_strcmp(((variable_t *)node->data)->name, variable) == 0) { |
| 66 | 12 | *value = ((variable_t *)node->data)->value; | |
| 67 | 12 | return 1; | |
| 68 | } | ||
| 69 | } | ||
| 70 | 7 | tmp = get_env_var(mysh->env, variable); | |
| 71 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (tmp != NULL) { |
| 72 | ✗ | *value = tmp; | |
| 73 | ✗ | return 1; | |
| 74 | } | ||
| 75 | 7 | return 0; | |
| 76 | } | ||
| 77 | |||
| 78 | /** | ||
| 79 | * @brief Get the new line | ||
| 80 | * @param line The line | ||
| 81 | * @param value The value | ||
| 82 | * @param nb_letters The number of letters | ||
| 83 | * @return <b>char *</b> The new line | ||
| 84 | */ | ||
| 85 | 12 | static char *get_new_line(char **line, char *value, int *nb_letters) | |
| 86 | { | ||
| 87 | 12 | char *new_line = NULL; | |
| 88 | |||
| 89 | 12 | new_line = calloc(find_valid_variable(*line) - *line + | |
| 90 | 12 | my_strlen(value) + my_strlen(&((*line)[find_valid_variable(*line) | |
| 91 | 12 | - *line + 1 + *nb_letters])) + 2, sizeof(char)); | |
| 92 | 12 | my_strncpy(new_line, *line, | |
| 93 | 12 | find_valid_variable(*line) - *line); | |
| 94 | 12 | my_strcat(new_line, value); | |
| 95 | 12 | my_strcat(new_line, &((*line)[find_valid_variable(*line) | |
| 96 | 12 | - *line + *nb_letters + 1])); | |
| 97 | 12 | FREE(*line); | |
| 98 | 12 | *nb_letters = 0; | |
| 99 | 12 | return new_line; | |
| 100 | } | ||
| 101 | |||
| 102 | /** | ||
| 103 | * @brief Clear the variable | ||
| 104 | * @param variable The variable | ||
| 105 | * @return <b>char *</b> The cleared variable | ||
| 106 | */ | ||
| 107 | 19 | char *clear_var(char *variable) | |
| 108 | { | ||
| 109 | 19 | char *tmp = variable; | |
| 110 | |||
| 111 |
3/4✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 15 times.
|
19 | if (variable[0] && variable[0] == '{') { |
| 112 | 4 | tmp = my_strdup(&variable[1]); | |
| 113 | 4 | FREE(variable); | |
| 114 | } | ||
| 115 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 14 times.
|
19 | if (tmp[my_strlen(tmp) - 1] == '}') |
| 116 | 5 | tmp[my_strlen(tmp) - 1] = '\0'; | |
| 117 | 19 | return tmp; | |
| 118 | } | ||
| 119 | |||
| 120 | /** | ||
| 121 | * @brief Count the number of letters in a variable | ||
| 122 | * @param line The line | ||
| 123 | * @return <b>int</b> The number of letters | ||
| 124 | */ | ||
| 125 | 25 | static int count_letter(char *line) | |
| 126 | { | ||
| 127 | 25 | int nb_letters = 0; | |
| 128 | 25 | int bracket = 0; | |
| 129 | 25 | int index = find_valid_variable(line) - line + 1; | |
| 130 | |||
| 131 |
6/6✓ Branch 1 taken 53 times.
✓ Branch 2 taken 45 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 39 times.
✓ Branch 6 taken 21 times.
✓ Branch 7 taken 18 times.
|
137 | for (; my_char_is_alpha(line[index]) || my_char_is_num(line[index]) || |
| 132 | 112 | my_char_is(line[index], "_{}?"); index++) { | |
| 133 | 80 | nb_letters++; | |
| 134 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 73 times.
|
80 | if (line[index] == '}') |
| 135 | 7 | break; | |
| 136 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 65 times.
|
73 | if (line[index] == '{') |
| 137 | 8 | bracket = 1; | |
| 138 | } | ||
| 139 |
5/6✓ Branch 0 taken 8 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 3 times.
✓ Branch 5 taken 22 times.
✗ Branch 6 not taken.
|
25 | if ((bracket && nb_letters < 2) || my_count_letter(line, '{') > 1 |
| 140 |
7/8✓ Branch 0 taken 7 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9 times.
✓ Branch 7 taken 13 times.
|
22 | || (line[index] == '}' && bracket && nb_letters == 2) || |
| 141 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
|
9 | (nb_letters == 1 && line[index] == '}')) |
| 142 | 5 | return display_error(NULL, 1); | |
| 143 |
4/4✓ Branch 0 taken 5 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 4 times.
|
20 | if (bracket && line[index] != '}') |
| 144 | 1 | return display_error(NULL, 2); | |
| 145 | 19 | return nb_letters; | |
| 146 | } | ||
| 147 | |||
| 148 | /** | ||
| 149 | * @brief Change the line | ||
| 150 | * @param mysh The shell structure | ||
| 151 | * @param line The line | ||
| 152 | * @return <b>int</b> The exit status | ||
| 153 | */ | ||
| 154 | 22 | static int change_line(mysh_t *mysh, char **line) | |
| 155 | { | ||
| 156 | 22 | char *variable = NULL; | |
| 157 | 22 | int nb_letters = 0; | |
| 158 | 22 | char *value = NULL; | |
| 159 | |||
| 160 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
|
22 | if (find_valid_variable(*line) == NULL) |
| 161 | ✗ | return 0; | |
| 162 |
2/2✓ Branch 1 taken 25 times.
✓ Branch 2 taken 9 times.
|
34 | while (find_valid_variable(*line) != NULL) { |
| 163 | 25 | nb_letters = count_letter(*line); | |
| 164 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 19 times.
|
25 | if (nb_letters == -1) |
| 165 | 6 | return 1; | |
| 166 | 19 | variable = clear_var(my_strndup(find_valid_variable(*line) + 1, | |
| 167 | nb_letters)); | ||
| 168 |
2/2✓ Branch 1 taken 7 times.
✓ Branch 2 taken 12 times.
|
19 | if (get_variables_value(mysh, variable, &value) == 0) |
| 169 | 7 | return display_error(variable, 3); | |
| 170 | 12 | FREE(variable); | |
| 171 | 12 | *line = get_new_line(line, value, &nb_letters); | |
| 172 | } | ||
| 173 | 9 | return 0; | |
| 174 | } | ||
| 175 | |||
| 176 | /** | ||
| 177 | * @brief Replace the variables in the command arguments | ||
| 178 | * @param mysh The shell structure | ||
| 179 | * @return <b>int/b> The new command arguments | ||
| 180 | */ | ||
| 181 | 4712 | int replace_variables(mysh_t *mysh) | |
| 182 | { | ||
| 183 | 4712 | char *exit_status = NULL; | |
| 184 | |||
| 185 |
2/2✓ Branch 1 taken 4690 times.
✓ Branch 2 taken 22 times.
|
4712 | if (my_str_contains(mysh->line, "$") == 0) |
| 186 | 4690 | return 0; | |
| 187 | 22 | exit_status = my_str_nbr(mysh->exit_status); | |
| 188 | 22 | add_variable(mysh, "?", my_malloc_strdup(exit_status)); | |
| 189 | 22 | FREE(exit_status); | |
| 190 |
2/2✓ Branch 1 taken 13 times.
✓ Branch 2 taken 9 times.
|
22 | if (change_line(mysh, &mysh->line)) { |
| 191 | 13 | mysh->exit_status = 1; | |
| 192 | 13 | return 1; | |
| 193 | } | ||
| 194 | 9 | return 0; | |
| 195 | } | ||
| 196 |