fix: now compiles and works for simple commands + clang format

This commit is contained in:
matteo 2026-01-17 19:11:55 +01:00
parent 6099bbb9e3
commit 352c122549
23 changed files with 168 additions and 150 deletions

View file

@ -7,26 +7,22 @@
TODO
### Build
run theses commands:
`autoreconf --force --verbose --install && ./configure`
run this command:
`autoreconf --force --verbose --install`
### Test
run this command:
`./configure CFLAGS='-std=c99 -Werror -Wall -Wextra -Wvla'`
then:
`make`
`./src/42sh --help`
### Testing
#### asan
run this command:
`./configure CFLAGS='-std=c99 -Werror -Wall -Wextra -Wvla -g -fsanitize=address'`
then:
`make check`
#### debug (asan)
run this command:
`./src/debug`
#### testsuite
run this command:
`./src/testsuite`
## Authors
- Matteo Flebus

View file

@ -28,8 +28,8 @@ bin_PROGRAMS = 42sh
check_PROGRAMS = testsuite
testsuite_CFLAGS = $(42sh_CFLAGS)
testsuite_CFLAGS += $(CRITERION_CFLAGS)
#testsuite_CFLAGS = $(42sh_CFLAGS)
#testsuite_CFLAGS += $(CRITERION_CFLAGS)
testsuite_SOURCES = ../tests/unit/lexer/lexer_tests.c \
../tests/unit/utils/utils_tests.c
@ -42,8 +42,8 @@ testsuite_LDADD = $(42sh_LDADD) $(CRITERION_LIBS)
check_PROGRAMS += debug
debug_CFLAGS = $(42sh_CFLAGS)
debug_CFLAGS += -fsanitize=address -g
#debug_CFLAGS = $(42sh_CFLAGS)
#debug_CFLAGS += -fsanitize=address -g
debug_SOURCES = $(42sh_SOURCES)

View file

@ -1,13 +1,13 @@
#include "execution.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include "../utils/ast/ast.h"
@ -262,7 +262,9 @@ int execution(struct ast *ast)
int fd_target = redir->io_number;
if (fd_target == -1)
{
if (redir->type == AST_REDIR_TYPE_LESS || redir->type == AST_REDIR_TYPE_DLESS || redir->type == AST_REDIR_TYPE_LESSAND)
if (redir->type == AST_REDIR_TYPE_LESS
|| redir->type == AST_REDIR_TYPE_DLESS
|| redir->type == AST_REDIR_TYPE_LESSAND)
fd_target = 0;
else
fd_target = 1;
@ -274,22 +276,24 @@ int execution(struct ast *ast)
int flags = 0;
int mode = 0644;
if (redir->type == AST_REDIR_TYPE_GREAT || redir->type == AST_REDIR_TYPE_CLOBBER)
if (redir->type == AST_REDIR_TYPE_GREAT
|| redir->type == AST_REDIR_TYPE_CLOBBER)
{
flags = O_WRONLY | O_CREAT | O_TRUNC;
new_fd = open(redir->filename, flags, mode);
}
else if (redir->type == AST_REDIR_TYPE_DGREAT)
{
flags = O_WRONLY | O_CREAT | O_APPEND;
new_fd = open(redir->filename, flags, mode);
flags = O_WRONLY | O_CREAT | O_APPEND;
new_fd = open(redir->filename, flags, mode);
}
else if (redir->type == AST_REDIR_TYPE_LESS)
{
flags = O_RDONLY;
new_fd = open(redir->filename, flags);
flags = O_RDONLY;
new_fd = open(redir->filename, flags);
}
else if (redir->type == AST_REDIR_TYPE_GREATAND || redir->type == AST_REDIR_TYPE_LESSAND)
else if (redir->type == AST_REDIR_TYPE_GREATAND
|| redir->type == AST_REDIR_TYPE_LESSAND)
{
// Simple fd duplication
new_fd = atoi(redir->filename);
@ -297,7 +301,8 @@ int execution(struct ast *ast)
if (dup2(new_fd, fd_target) == -1)
{
perror("dup2");
if (saved_fd != -1) close(saved_fd);
if (saved_fd != -1)
close(saved_fd);
return 1;
}
new_fd = -2; // Mark as "already duped"
@ -306,7 +311,8 @@ int execution(struct ast *ast)
if (new_fd == -1)
{
perror("open");
if (saved_fd != -1) close(saved_fd);
if (saved_fd != -1)
close(saved_fd);
return 1;
}
@ -316,7 +322,8 @@ int execution(struct ast *ast)
{
perror("dup2");
close(new_fd);
if (saved_fd != -1) close(saved_fd);
if (saved_fd != -1)
close(saved_fd);
return 1;
}
close(new_fd);

View file

@ -2,6 +2,7 @@
#define IO_BACKEND_H
#include <sys/types.h>
#include "utils/args/args.h"
// Error codes

View file

@ -69,62 +69,62 @@ static void set_token_spechar(struct token *tok, char *begin, ssize_t size)
return;
switch (begin[0])
{
case EOF:
tok->type = TOKEN_EOF;
break;
case ';':
tok->type = TOKEN_SEMICOLON;
break;
case '\n':
tok->type = TOKEN_NEWLINE;
break;
case '\'':
tok->type = TOKEN_QUOTE;
break;
case '"':
tok->type = TOKEN_DOUBLE_QUOTE;
break;
case '`':
tok->type = TOKEN_GRAVE;
break;
case '#':
tok->type = TOKEN_COMMENT;
break;
case '|':
tok->type = TOKEN_PIPE;
break;
case '&':
tok->type = TOKEN_AMPERSAND;
break;
case '\\':
tok->type = TOKEN_BACKSLASH;
break;
case '$':
tok->type = TOKEN_DOLLAR;
break;
case '(':
tok->type = TOKEN_LEFT_PAREN;
break;
case ')':
tok->type = TOKEN_RIGHT_PAREN;
break;
case '{':
tok->type = TOKEN_LEFT_BRACKET;
break;
case '}':
tok->type = TOKEN_RIGHT_BRACKET;
break;
case '<':
tok->type = TOKEN_LESS;
break;
case '>':
tok->type = TOKEN_GREATER;
break;
case '*':
tok->type = TOKEN_STAR;
break;
default:
break;
case EOF:
tok->type = TOKEN_EOF;
break;
case ';':
tok->type = TOKEN_SEMICOLON;
break;
case '\n':
tok->type = TOKEN_NEWLINE;
break;
case '\'':
tok->type = TOKEN_QUOTE;
break;
case '"':
tok->type = TOKEN_DOUBLE_QUOTE;
break;
case '`':
tok->type = TOKEN_GRAVE;
break;
case '#':
tok->type = TOKEN_COMMENT;
break;
case '|':
tok->type = TOKEN_PIPE;
break;
case '&':
tok->type = TOKEN_AMPERSAND;
break;
case '\\':
tok->type = TOKEN_BACKSLASH;
break;
case '$':
tok->type = TOKEN_DOLLAR;
break;
case '(':
tok->type = TOKEN_LEFT_PAREN;
break;
case ')':
tok->type = TOKEN_RIGHT_PAREN;
break;
case '{':
tok->type = TOKEN_LEFT_BRACKET;
break;
case '}':
tok->type = TOKEN_RIGHT_BRACKET;
break;
case '<':
tok->type = TOKEN_LESS;
break;
case '>':
tok->type = TOKEN_GREATER;
break;
case '*':
tok->type = TOKEN_STAR;
break;
default:
break;
}
}

View file

@ -69,9 +69,14 @@ int main(int argc, char **argv)
// Execute AST
return_code = execution(command_ast);
ast_free(&command_ast);
// Retrieve and build next AST
command_ast = get_ast();
}
ast_free(&command_ast);
if (command_ast == NULL)
return ERR_INPUT_PROCESSING;

View file

@ -7,8 +7,8 @@
#include <string.h>
#include "lexer/lexer.h"
#include "utils/lists/lists.h"
#include "parser/parsing_utils.h"
#include "utils/lists/lists.h"
// === Static functions
// ...

View file

@ -1,9 +1,11 @@
#define _POSIX_C_SOURCE 200809L
// === Includes
#include "parsing_utils.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include "lexer/lexer.h"
#include "utils/ast/ast.h"
@ -58,7 +60,8 @@ struct ast *parse_simple_command(void)
while (!isterminator(token))
{
token = POP_TOKEN();
command_elements = list_append(command_elements, token->data);
char *word = strdup(token->data);
command_elements = list_append(command_elements, word);
token = PEEK_TOKEN();
}
@ -86,6 +89,7 @@ struct ast *parse_list(void)
}
token = PEEK_TOKEN();
}
result_list = list_append(result_list, current_node);
return ast_create_list(result_list);
}
@ -163,7 +167,9 @@ struct ast *parse_compound_list(void)
return NULL;
}
command_elements = list_append(command_elements, token->data);
char *word = strdup(token->data);
command_elements = list_append(command_elements, word);
token = POP_TOKEN();
}

View file

@ -39,14 +39,14 @@ struct ast *parse_shell_command(void);
/* @brief parses commands inside if/else clauses and returns the corresponding
* AST list
*/
struct ast* parse_compound_list(void);
struct ast *parse_compound_list(void);
/*
*/
struct ast* parse_and_or(void);
struct ast *parse_and_or(void);
/*
*/
struct ast* parse_else_clause(void);
struct ast *parse_else_clause(void);
#endif /* ! PARSING_UTILS_H */

View file

@ -1,13 +1,13 @@
#ifndef AST_H
#define AST_H
#include "utils/ast/ast_and_or.h"
#include "utils/ast/ast_base.h"
#include "utils/ast/ast_command.h"
#include "utils/ast/ast_if.h"
#include "utils/ast/ast_and_or.h"
#include "utils/ast/ast_redir.h"
#include "utils/ast/ast_list.h"
#include "utils/ast/ast_end.h"
#include "utils/ast/ast_if.h"
#include "utils/ast/ast_list.h"
#include "utils/ast/ast_redir.h"
#include "utils/ast/ast_void.h"
#endif /* ! AST_H */

View file

@ -1,4 +1,5 @@
#include "utils/ast/ast_and_or.h"
#include <stdlib.h>
bool ast_is_and_or(struct ast *node)
@ -13,7 +14,8 @@ struct ast_and_or *ast_get_and_or(struct ast *node)
return NULL;
}
struct ast *ast_create_and_or(struct ast *left, struct ast *right, enum ast_and_or_type type)
struct ast *ast_create_and_or(struct ast *left, struct ast *right,
enum ast_and_or_type type)
{
struct ast_and_or *and_or = malloc(sizeof(struct ast_and_or));
if (!and_or)

View file

@ -2,14 +2,17 @@
#define AST_AND_OR_H
#include <stdbool.h>
#include "utils/ast/ast_base.h"
enum ast_and_or_type {
enum ast_and_or_type
{
AST_AND_OR_TYPE_AND,
AST_AND_OR_TYPE_OR
};
struct ast_and_or {
struct ast_and_or
{
struct ast *left;
struct ast *right;
enum ast_and_or_type type;
@ -17,7 +20,8 @@ struct ast_and_or {
bool ast_is_and_or(struct ast *node);
struct ast_and_or *ast_get_and_or(struct ast *node);
struct ast *ast_create_and_or(struct ast *left, struct ast *right, enum ast_and_or_type type);
struct ast *ast_create_and_or(struct ast *left, struct ast *right,
enum ast_and_or_type type);
void ast_free_and_or(struct ast_and_or *and_or);
#endif /* ! AST_AND_OR_H */

View file

@ -1,8 +1,8 @@
#include "utils/ast/ast_command.h"
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include "utils/lists/lists.h"

View file

@ -3,8 +3,8 @@
#include <stdbool.h>
#include "utils/lists/lists.h"
#include "utils/ast/ast_base.h"
#include "utils/lists/lists.h"
struct ast_command
{

View file

@ -1,8 +1,8 @@
#include "utils/ast/ast_end.h"
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
bool ast_is_end(struct ast *node)
{

View file

@ -3,8 +3,8 @@
#include <stdbool.h>
#include "utils/lists/lists.h"
#include "utils/ast/ast_base.h"
#include "utils/lists/lists.h"
/**
* Checks if the given AST node is of type AST_END.

View file

@ -1,8 +1,8 @@
#include "utils/ast/ast_if.h"
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
struct ast *ast_create_if(struct ast *condition, struct ast *then_clause,
struct ast *else_clause)

View file

@ -1,7 +1,7 @@
#include "utils/ast/ast.h"
#include <assert.h>
#include "utils/ast/ast.h"
struct ast *ast_create_list(struct list *list)
{
struct ast_list *ast_list = malloc(sizeof(struct ast_list));
@ -16,7 +16,7 @@ struct ast *ast_create_list(struct list *list)
struct ast_list *ast_get_list(struct ast *node)
{
assert(node != NULL);
return (struct ast_list*)node->data;
return (struct ast_list *)node->data;
}
bool ast_is_list(struct ast *node)

View file

@ -1,4 +1,5 @@
#include "utils/ast/ast_redir.h"
#include <stdlib.h>
bool ast_is_redir(struct ast *node)
@ -13,13 +14,16 @@ struct ast_redir *ast_get_redir(struct ast *node)
return NULL;
}
struct ast *ast_create_redir(struct ast *child, char *filename, int io_number, enum ast_redir_type type)
struct ast *ast_create_redir(struct ast *child, char *filename, int io_number,
enum ast_redir_type type)
{
struct ast_redir *redir = malloc(sizeof(struct ast_redir));
if (!redir)
return NULL;
redir->child = child;
redir->filename = filename; // Takes ownership? Usually yes in simple ASTs, or dup. Let's assume pointer copy for now, but user must manage memory.
redir->filename =
filename; // Takes ownership? Usually yes in simple ASTs, or dup. Let's
// assume pointer copy for now, but user must manage memory.
redir->io_number = io_number;
redir->type = type;

View file

@ -2,28 +2,33 @@
#define AST_REDIR_H
#include <stdbool.h>
#include "utils/ast/ast_base.h"
enum ast_redir_type {
AST_REDIR_TYPE_LESS, // <
AST_REDIR_TYPE_GREAT, // >
AST_REDIR_TYPE_DLESS, // <<
AST_REDIR_TYPE_DGREAT, // >>
AST_REDIR_TYPE_LESSAND, // <&
AST_REDIR_TYPE_GREATAND, // >&
AST_REDIR_TYPE_CLOBBER // >|
enum ast_redir_type
{
AST_REDIR_TYPE_LESS, // <
AST_REDIR_TYPE_GREAT, // >
AST_REDIR_TYPE_DLESS, // <<
AST_REDIR_TYPE_DGREAT, // >>
AST_REDIR_TYPE_LESSAND, // <&
AST_REDIR_TYPE_GREATAND, // >&
AST_REDIR_TYPE_CLOBBER // >|
};
struct ast_redir {
struct ast_redir
{
struct ast *child;
char *filename;
int io_number; // The FD being redirected (default -1 if not specified, implies 0 or 1 based on type)
int io_number; // The FD being redirected (default -1 if not specified,
// implies 0 or 1 based on type)
enum ast_redir_type type;
};
bool ast_is_redir(struct ast *node);
struct ast_redir *ast_get_redir(struct ast *node);
struct ast *ast_create_redir(struct ast *child, char *filename, int io_number, enum ast_redir_type type);
struct ast *ast_create_redir(struct ast *child, char *filename, int io_number,
enum ast_redir_type type);
void ast_free_redir(struct ast_redir *redir);
#endif /* ! AST_REDIR_H */

View file

@ -1,8 +1,8 @@
#include "utils/ast/ast_void.h"
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
bool ast_is_void(struct ast *node)
{

View file

@ -3,8 +3,8 @@
#include <stdbool.h>
#include "utils/lists/lists.h"
#include "utils/ast/ast_base.h"
#include "utils/lists/lists.h"
/**
* Checks if the given AST node is of type AST_VOID.

View file

@ -5,8 +5,8 @@
#include <string.h>
#include <sys/types.h>
#include "lexer/lexer.h"
#include "io_backend/io_backend.h"
#include "lexer/lexer.h"
TestSuite(peek_token);
@ -14,11 +14,7 @@ Test(peek_token, basic_empty)
{
// simulates input
char command[] = "";
struct iob_context context =
{
IOB_MODE_CMD,
command
};
struct iob_context context = { IOB_MODE_CMD, command };
iob_init(&context);
// test
@ -38,11 +34,7 @@ Test(peek_token, basic_word)
{
// simulates input
char command[] = "hello";
struct iob_context context =
{
IOB_MODE_CMD,
command
};
struct iob_context context = { IOB_MODE_CMD, command };
iob_init(&context);
// test
@ -60,11 +52,7 @@ Test(peek_token, basic_words)
{
// simulates input
char command[] = "echo hello there";
struct iob_context context =
{
IOB_MODE_CMD,
command
};
struct iob_context context = { IOB_MODE_CMD, command };
iob_init(&context);
// ======= echo