aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2019-03-10 16:52:53 +0100
committerdec05eba <dec05eba@protonmail.com>2020-07-25 14:36:46 +0200
commit79bf40f909cefdc611bfa13f70ae55b52ac41d23 (patch)
treea022cbf8e0548aab677aabb5a9138619cb9aa562
parent470a60a3ea8723852568df2ecf7587303b250664 (diff)
Load @import files relative to the file that uses @import
-rw-r--r--include/std/file.h4
-rw-r--r--src/parser.c36
-rw-r--r--src/std/file.c54
-rw-r--r--tests/main.amal4
4 files changed, 84 insertions, 14 deletions
diff --git a/include/std/file.h b/include/std/file.h
index 4224346..8be0c66 100644
--- a/include/std/file.h
+++ b/include/std/file.h
@@ -3,6 +3,7 @@
#include "misc.h"
#include "types.h"
+#include "buffer_view.h"
/* Return bool_true if you want to continue scanning, otherwise return bool_false */
typedef bool (*scan_dir_callback_func)(const char *filepath, int filepath_length, void *userdata);
@@ -26,4 +27,7 @@ CHECK_RESULT int mapped_file_deinit(MappedFile *self);
CHECK_RESULT int read_whole_file(const char *filepath, char **data, usize *size);
+BufferView file_get_parent_directory(BufferView filepath);
+BufferView file_get_name(BufferView filepath);
+
#endif
diff --git a/src/parser.c b/src/parser.c
index 22c8b77..f531705 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -478,24 +478,27 @@ int parser_parse_file(Parser *self, BufferView filepath) {
int result;
char *file_data;
usize file_size;
- char *filepath_tmp;
amal_log_debug("Parsing %.*s", (int)filepath.size, filepath.data);
assert(!self->started && "Parser can't be reused. Create a new parser.");
self->started = bool_true;
- /* TODO: Somehow free this... */
- /*return_if_error(scoped_allocator_alloc(self->allocator, filepath.size + 1, (void**)&filepath_tmp));*/
- filepath_tmp = malloc(filepath.size + 1);
- am_memcpy(filepath_tmp, filepath.data, filepath.size);
- filepath_tmp[filepath.size] = '\0';
- result = read_whole_file(filepath_tmp, &file_data, &file_size);
+ assert(filepath.size > 0 && filepath.data[filepath.size] == '\0');
+ result = read_whole_file(filepath.data, &file_data, &file_size);
if(result != 0) return result;
- result = parser_parse_buffer(self, create_buffer_view(file_data, file_size), create_buffer_view(filepath_tmp, filepath.size));
- /* TODO: Somehow free this.. causes issue where filepath becomes corrupt */
- /*am_free(file_data);*/
+ result = parser_parse_buffer(self, create_buffer_view(file_data, file_size), filepath);
return result;
}
+static CHECK_RESULT int file_path_join(BufferView directory, BufferView file, ScopedAllocator *allocator, Buffer *result) {
+ return_if_error(buffer_init(result, allocator));
+ return_if_error(buffer_append(result, NULL, directory.size + 1 + file.size + 1));
+ am_memcpy(result->data, directory.data, directory.size);
+ result->data[directory.size] = '/';
+ am_memcpy(result->data + directory.size + 1, file.data, file.size);
+ result->data[directory.size + 1 + file.size] = '\0';
+ return 0;
+}
+
/*
Path can be path to included library path (or system library path) in which case
the path separator is a dot, otherwise the path separator is forward slash '/'
@@ -503,7 +506,16 @@ the path separator is a dot, otherwise the path separator is forward slash '/'
int parser_queue_file(Parser *self, BufferView path) {
/* TODO: Do not load same path twice or the compile will fail (and it can have recursive import) also for performance reasons */
/* TODO: Parse special path (to include library path with dots) */
- /* TODO: Path should be relative to the file that uses @import */
- throw_if_error(amal_compiler_load_file(self->compiler, path));
+ BufferView file_directory;
+ BufferView filename;
+ Buffer file_to_parse;
+ file_directory = file_get_parent_directory(self->tokenizer.code_name);
+ filename = file_get_name(path);
+ return_if_error(file_path_join(file_directory, filename, self->allocator, &file_to_parse));
+ /*
+ We want buffer to be null terminated but null terminated character
+ should not be included for the length.
+ */
+ throw_if_error(amal_compiler_load_file(self->compiler, create_buffer_view(file_to_parse.data, file_to_parse.size - 1)));
return PARSER_OK;
}
diff --git a/src/std/file.c b/src/std/file.c
index 46099b4..098b18f 100644
--- a/src/std/file.c
+++ b/src/std/file.c
@@ -14,6 +14,7 @@
#include <unistd.h>
#define SCANDIR_PATH_LENGTH 4096
+#define MAX_FILE_SIZE 1024*1024*48 /* 48 mb */
static int scan_dir_recursive_internal(char *dir_path, int path_length, scan_dir_callback_func callback_func, void *userdata) {
DIR *dir;
@@ -165,11 +166,40 @@ int mapped_file_deinit(MappedFile *self) {
return 0;
}
+typedef enum {
+ REGULAR,
+ DIRECTORY,
+ OTHER
+} FileType;
+
+static CHECK_RESULT int file_get_type(const char *filepath, FileType *type) {
+ struct stat file_stats;
+ if(stat(filepath, &file_stats) == -1) {
+ amal_log_perror(filepath);
+ return -1;
+ }
+
+ if(file_stats.st_mode & S_IFDIR)
+ *type = DIRECTORY;
+ else if(file_stats.st_mode & S_IFREG)
+ *type = REGULAR;
+ else
+ *type = OTHER;
+ return 0;
+}
+
int read_whole_file(const char *filepath, char **data, usize *size) {
+ FileType file_type;
FILE *file;
int result;
usize bytes_read;
+ return_if_error(file_get_type(filepath, &file_type));
+ if(file_type != REGULAR) {
+ amal_log_error("Expected file %s to be a regular file", filepath);
+ return -2;
+ }
+
result = 0;
file = fopen(filepath, "rb");
if(!file) {
@@ -192,6 +222,12 @@ int read_whole_file(const char *filepath, char **data, usize *size) {
goto cleanup;
}
+ if(*size > MAX_FILE_SIZE) {
+ amal_log_error("File %s is too large (larger than 48 megabytes)", filepath);
+ result = -1;
+ goto cleanup;
+ }
+
cleanup_if_error(am_malloc(*size, (void**)data));
bytes_read = fread(*data, 1, *size, file);
if(bytes_read != *size) {
@@ -202,3 +238,21 @@ int read_whole_file(const char *filepath, char **data, usize *size) {
fclose(file);
return result;
}
+
+BufferView file_get_parent_directory(BufferView filepath) {
+ int i;
+ for(i = filepath.size - 1; i >= 0; --i) {
+ if(filepath.data[i] == '/')
+ return create_buffer_view(filepath.data, i);
+ }
+ return create_buffer_view(filepath.data, 0);
+}
+
+BufferView file_get_name(BufferView filepath) {
+ int i;
+ for(i = filepath.size - 1; i >= 0; --i) {
+ if(filepath.data[i] == '/')
+ return create_buffer_view(filepath.data + i, filepath.size - i);
+ }
+ return filepath;
+}
diff --git a/tests/main.amal b/tests/main.amal
index 990dc26..ba6247b 100644
--- a/tests/main.amal
+++ b/tests/main.amal
@@ -1,4 +1,4 @@
-const io = @import("tests/io.amal");
+const io = @import("io.amal");
const main = fn {
var hello = fn {
@@ -10,7 +10,7 @@ const main = fn {
const num2 = 23232;
const num3 = num1 + num2 * 30;
const num4 = (num1 + num2) * num3 * ((34 + 32) / 234.345);
- const num4 = 23;
+ //const num4 = 23;
/*
episfjpseifipesf
*/