Skip to content

Commit 9b5c06e

Browse files
committed
Add heredoc
1 parent 2920814 commit 9b5c06e

File tree

8 files changed

+122
-48
lines changed

8 files changed

+122
-48
lines changed

src/ast.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ ast_t *parse_arg(ast_ctx_t *ctx, ast_t *node)
2020
ctx->act_tok = get_next_token(ctx);
2121
if (ctx->act_tok.type == T_SEMICOLON)
2222
return node;
23-
if (ctx->act_tok.type & (T_ARG | T_REDIRECT | T_APPEND | T_IN_REDIRECT)) {
23+
if (ctx->act_tok.type & (T_ARG | T_REDIRECT | T_APPEND |
24+
T_IN_REDIRECT | T_HEREDOC)) {
2425
if (!ensure_node_cap(node))
2526
return NULL;
2627
node->vector.tokens[node->vector.sz] = ctx->act_tok;

src/ast.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@ typedef enum {
2929
T_PREV_CMD = 1 << 9, // !!
3030
T_VAR = 1 << 10, // $
3131
T_REDIRECT = 1 << 11, // >
32-
T_IN_REDIRECT = 1 << 12, // <
33-
T_APPEND = 1 << 13, // >>
34-
T_EOF = 1 << 14, // \0
35-
T_ARG = 1 << 15,
36-
T_INVALID = 1 << 16
32+
T_APPEND = 1 << 12, // >>
33+
T_HEREDOC = 1 << 13, // <
34+
T_IN_REDIRECT = 1 << 14, // <
35+
T_EOF = 1 << 15, // \0
36+
T_ARG = 1 << 16,
37+
T_INVALID = 1 << 17
3738
} token_type_t;
3839

3940
typedef enum {

src/redirects.c

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
** EPITECH PROJECT, 2025
3+
** __
4+
** File description:
5+
** _
6+
*/
7+
8+
#include <fcntl.h>
9+
#include <stdbool.h>
10+
#include <stdio.h>
11+
#include <stdlib.h>
12+
#include <string.h>
13+
#include <unistd.h>
14+
15+
#include "exec.h"
16+
#include "u_str.h"
17+
18+
bool handle_out_redirect(ef_t *ef, ast_t *node, size_t i, size_t sz)
19+
{
20+
if (!(node->vector.tokens[i].type & (T_REDIRECT | T_APPEND)))
21+
return true;
22+
if (i >= sz || node->vector.tokens[i + 1].type != T_ARG)
23+
return (WRITE_CONST(STDERR_FILENO,
24+
"Missing name for redirect.\n"), false);
25+
ef->skip_i = ef->skip_i ?: i;
26+
ef->skip_sz += 2;
27+
node->vector.tokens[i + 1].str[node->vector.tokens[i + 1].sz] = '\0';
28+
ef->rout_fd = open(node->vector.tokens[i + 1].str, O_CREAT | O_WRONLY |
29+
(node->vector.tokens[i].type == T_APPEND ? O_APPEND : O_TRUNC), 0644);
30+
if (ef->rout_fd < 0)
31+
return (puterror(node->vector.tokens[i + 1].str), false);
32+
ef->out_fd = ef->rout_fd;
33+
return true;
34+
}
35+
36+
bool handle_in_redirect(ef_t *ef, ast_t *node, size_t i, size_t sz)
37+
{
38+
if (node->vector.tokens[i].type != T_IN_REDIRECT)
39+
return true;
40+
if (i >= sz || node->vector.tokens[i + 1].type != T_ARG)
41+
return (WRITE_CONST(STDERR_FILENO,
42+
"Missing name for redirect.\n"), false);
43+
ef->skip_i = ef->skip_i ?: i;
44+
ef->skip_sz += 2;
45+
node->vector.tokens[i + 1].str[node->vector.tokens[i + 1].sz] = '\0';
46+
ef->rin_fd = open(node->vector.tokens[i + 1].str, O_RDONLY);
47+
if (ef->rin_fd < 0)
48+
return (puterror(node->vector.tokens[i + 1].str), false);
49+
ef->in_fd = ef->rin_fd;
50+
return true;
51+
}
52+
53+
int handle_heredoc_loop(ast_t *node, size_t i)
54+
{
55+
int fds[2];
56+
buff_t buffer = { .str = NULL };
57+
58+
if (pipe(fds) < 0)
59+
return (puterror("pipe"), -1);
60+
node->vector.tokens[i + 1].str[node->vector.tokens[i + 1].sz] = '\0';
61+
WRITE_CONST(STDOUT_FILENO, "? ");
62+
while (getline(&buffer.str, &buffer.sz, stdin) != -1) {
63+
buffer.str[u_strlen(buffer.str) - 1] = '\0';
64+
if (u_strcmp(buffer.str, node->vector.tokens[i + 1].str) == 0)
65+
break;
66+
write(fds[1], buffer.str, u_strlen(buffer.str));
67+
write(fds[1], "\n", 1);
68+
WRITE_CONST(STDOUT_FILENO, "? ");
69+
}
70+
free(buffer.str);
71+
close(fds[1]);
72+
return fds[0];
73+
}
74+
75+
bool handle_heredoc(ef_t *ef, ast_t *node, size_t i, size_t sz)
76+
{
77+
if (node->vector.tokens[i].type != T_HEREDOC)
78+
return true;
79+
if (i >= sz || node->vector.tokens[i + 1].type != T_ARG)
80+
return (WRITE_CONST(STDERR_FILENO,
81+
"Missing name for redirect.\n"), false);
82+
ef->skip_i = ef->skip_i ?: i;
83+
ef->skip_sz += 2;
84+
ef->in_fd = handle_heredoc_loop(node, i);
85+
if (ef->in_fd == -1)
86+
return false;
87+
return true;
88+
}

src/redirects.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
** EPITECH PROJECT, 2025
3+
** __
4+
** File description:
5+
** _
6+
*/
7+
8+
#ifndef REDIRECTS_H
9+
#define REDIRECTS_H
10+
#include <stdbool.h>
11+
12+
#include "exec.h"
13+
14+
bool handle_out_redirect(ef_t *ef, ast_t *node, size_t i, size_t sz);
15+
bool handle_in_redirect(ef_t *ef, ast_t *node, size_t i, size_t sz);
16+
int handle_heredoc_loop(ast_t *node, size_t i);
17+
bool handle_heredoc(ef_t *ef, ast_t *node, size_t i, size_t sz);
18+
#endif /* REDIRECTS_H */

src/tokeniser.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const tokens_list_t TOKENS_LIST[] = {
2525
{ T_VAR, "$", 1, "T_VAR" },
2626
{ T_APPEND, ">>", 2, "T_APPEND" },
2727
{ T_REDIRECT, ">", 1, "T_REDIRECT" },
28+
{ T_HEREDOC, "<<", 2, "T_HEREDOC" },
2829
{ T_IN_REDIRECT, "<", 1, "T_IN_REDIRECT" },
2930
{ T_EOF, "\0", 1, "T_EOF" }
3031
};

src/visitor.c

Lines changed: 5 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,52 +6,17 @@
66
*/
77

88
#include <fcntl.h>
9+
#include <stdio.h>
910
#include <stdlib.h>
1011
#include <unistd.h>
1112

1213
#include "ast.h"
1314
#include "builtins.h"
1415
#include "common.h"
1516
#include "exec.h"
17+
#include "redirects.h"
1618
#include "u_str.h"
1719

18-
static
19-
bool handle_out_redirect(ef_t *ef, ast_t *node, size_t i, size_t sz)
20-
{
21-
if (!(node->vector.tokens[i].type & (T_REDIRECT | T_APPEND)))
22-
return true;
23-
if (i >= sz || node->vector.tokens[i + 1].type != T_ARG)
24-
return (WRITE_CONST(STDERR_FILENO,
25-
"Missing name for redirect.\n"), false);
26-
ef->skip_i = ef->skip_i ?: i;
27-
ef->skip_sz += 2;
28-
node->vector.tokens[i + 1].str[node->vector.tokens[i + 1].sz] = '\0';
29-
ef->rout_fd = open(node->vector.tokens[i + 1].str, O_CREAT | O_WRONLY |
30-
(node->vector.tokens[i].type == T_APPEND ? O_APPEND : O_TRUNC), 0644);
31-
if (ef->rout_fd < 0)
32-
return (puterror(node->vector.tokens[i + 1].str), false);
33-
ef->out_fd = ef->rout_fd;
34-
return true;
35-
}
36-
37-
static
38-
bool handle_in_redirect(ef_t *ef, ast_t *node, size_t i, size_t sz)
39-
{
40-
if (node->vector.tokens[i].type != T_IN_REDIRECT)
41-
return true;
42-
if (i >= sz || node->vector.tokens[i + 1].type != T_ARG)
43-
return (WRITE_CONST(STDERR_FILENO,
44-
"Missing name for redirect.\n"), false);
45-
ef->skip_i = ef->skip_i ?: i;
46-
ef->skip_sz += 2;
47-
node->vector.tokens[i + 1].str[node->vector.tokens[i + 1].sz] = '\0';
48-
ef->rin_fd = open(node->vector.tokens[i + 1].str, O_RDONLY);
49-
if (ef->rin_fd < 0)
50-
return (puterror(node->vector.tokens[i + 1].str), false);
51-
ef->in_fd = ef->rin_fd;
52-
return true;
53-
}
54-
5520
/*
5621
* ef->in_fd = ef->pin_fd;
5722
* ef->out_fd = ef->out_fd;
@@ -69,9 +34,9 @@ int visit_cmd(ef_t *ef)
6934
ef->rout_fd = 0;
7035
ef->rin_fd = 0;
7136
for (size_t i = 0; i < ef->act_node->vector.sz; i++) {
72-
if (!handle_in_redirect(ef, ef->act_node, i, ef->act_node->vector.sz))
73-
return -1;
74-
if (!handle_out_redirect(ef, ef->act_node, i, ef->act_node->vector.sz))
37+
if (!handle_in_redirect(ef, ef->act_node, i, ef->act_node->vector.sz)
38+
|| !handle_out_redirect(ef, ef->act_node, i, ef->act_node->vector.sz)
39+
|| !handle_heredoc(ef, ef->act_node, i, ef->act_node->vector.sz))
7540
return -1;
7641
}
7742
result = execute(ef);

ulib/str/puterror.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
#include "u_str.h"
1313

14-
void puterror(char *prefix)
14+
void puterror(char const *prefix)
1515
{
1616
char const *error_msg = strerror(errno);
1717
size_t len;

ulib/u_str.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,6 @@ int u_spacelen(char const *str);
3333
int u_strcspn(char *str, char c);
3434
bool u_str_is_alnum(char *str);
3535
bool u_str_is_only_alnum(char *str);
36-
void puterror(char *prefix);
36+
void puterror(char const *prefix);
3737

3838
#endif /* STRING_H */

0 commit comments

Comments
 (0)